2 * drivers/video/ubicom32lcd.c
3 * LCD initilization code
5 * (C) Copyright 2009, Ubicom, Inc.
7 * This file is part of the Ubicom32 Linux Kernel Port.
9 * The Ubicom32 Linux Kernel Port is free software: you can redistribute
10 * it and/or modify it under the terms of the GNU General Public License
11 * as published by the Free Software Foundation, either version 2 of the
12 * License, or (at your option) any later version.
14 * The Ubicom32 Linux Kernel Port is distributed in the hope that it
15 * will be useful, but WITHOUT ANY WARRANTY; without even the implied
16 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
17 * the GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with the Ubicom32 Linux Kernel Port. If not,
21 * see <http://www.gnu.org/licenses/>.
23 #include <linux/init.h>
24 #include <linux/kernel.h>
25 #include <linux/module.h>
26 #include <linux/platform_device.h>
27 #include <linux/delay.h>
29 #include <asm/ip5000.h>
31 #include <asm/ubicom32lcd.h>
33 #include "ubicom32lcd.h"
35 #define DRIVER_NAME "ubicom32lcd"
37 struct ubicom32lcd_data
{
38 const struct ubicom32lcd_panel
*panel
;
45 struct ubicom32_io_port
*port_data
;
51 * Performs a write cycle on the bus (assumes CS asserted, RD & WR set)
53 static void ubicom32lcd_write(struct ubicom32lcd_data
*ud
, int command
, u16 data
)
56 UBICOM32_GPIO_SET_PIN_LOW(ud
->pin_rs
);
58 UBICOM32_GPIO_SET_PIN_HIGH(ud
->pin_rs
);
62 "or.4 4(%[port]), 4(%[port]), %[mask] \n\t"
63 "not.4 %[mask], %[mask] \n\t"
64 "and.4 8(%[port]), 8(%[port]), %[mask] \n\t"
65 "or.4 8(%[port]), 8(%[port]), %[cmd] \n\t"
67 : [port
] "a" (ud
->port_data
),
68 [mask
] "d" (0xFFFF << ud
->data_shift
),
69 [cmd
] "d" (data
<< ud
->data_shift
)
73 UBICOM32_GPIO_SET_PIN_LOW(ud
->pin_wr
);
78 UBICOM32_GPIO_SET_PIN_HIGH(ud
->pin_wr
);
85 * ubicom32lcd_read_data
86 * Performs a read cycle on the bus (assumes CS asserted, RD & WR set)
88 static u16
ubicom32lcd_read_data(struct ubicom32lcd_data
*ud
)
92 UBICOM32_GPIO_SET_PIN_HIGH(ud
->pin_rs
);
95 "and.4 4(%[port]), 4(%[port]), %[mask]\n\t"
97 : [port
] "a" (ud
->port_data
),
98 [mask
] "d" (~(0xFFFF << ud
->data_shift
))
102 UBICOM32_GPIO_SET_PIN_LOW(ud
->pin_rd
);
107 "lsr.4 %[data], 12(%[port]), %[shamt] \n\t"
108 "and.4 %[data], %[data], %[mask] \n\t"
110 : [port
] "a" (ud
->port_data
),
112 [shamt
] "d" (ud
->data_shift
)
118 UBICOM32_GPIO_SET_PIN_HIGH(ud
->pin_rd
);
126 * ubicom32lcd_execute
127 * Executes a script for performing operations on the LCD (assumes CS set)
129 static void ubicom32lcd_execute(struct ubicom32lcd_data
*ud
, const struct ubicom32lcd_step
*script
)
132 switch (script
->op
) {
134 ubicom32lcd_write(ud
, 1, script
->cmd
);
138 ubicom32lcd_write(ud
, 0, script
->data
);
141 case LCD_STEP_CMD_DATA
:
142 ubicom32lcd_write(ud
, 1, script
->cmd
);
143 ubicom32lcd_write(ud
, 0, script
->data
);
147 udelay(script
->data
);
159 * Places the gram pointer at a specific X, Y address
161 static void ubicom32lcd_goto(struct ubicom32lcd_data
*ud
, int x
, int y
)
163 ubicom32lcd_write(ud
, 1, ud
->panel
->horz_reg
);
164 ubicom32lcd_write(ud
, 0, x
);
165 ubicom32lcd_write(ud
, 1, ud
->panel
->vert_reg
);
166 ubicom32lcd_write(ud
, 0, y
);
167 ubicom32lcd_write(ud
, 1, ud
->panel
->gram_reg
);
171 * ubicom32lcd_panel_init
172 * Initializes the lcd panel.
174 static int ubicom32lcd_panel_init(struct ubicom32lcd_data
*ud
)
178 UBICOM32_GPIO_SET_PIN_LOW(ud
->pin_reset
);
179 UBICOM32_GPIO_SET_PIN_OUTPUT(ud
->pin_reset
);
180 UBICOM32_GPIO_ENABLE(ud
->pin_reset
);
183 "or.4 0x50(%[port]), 0x50(%[port]), %[mask] \n\t"
184 "not.4 %[mask], %[mask] \n\t"
185 "and.4 0x04(%[port]), 0x04(%[port]), %[mask] \n\t"
187 : [port
] "a" (ud
->port_data
),
188 [mask
] "d" (0xFFFF << ud
->data_shift
)
192 UBICOM32_GPIO_SET_PIN_HIGH(ud
->pin_rs
);
193 UBICOM32_GPIO_SET_PIN_HIGH(ud
->pin_rd
);
194 UBICOM32_GPIO_SET_PIN_HIGH(ud
->pin_wr
);
195 UBICOM32_GPIO_SET_PIN_HIGH(ud
->pin_cs
);
197 UBICOM32_GPIO_SET_PIN_OUTPUT(ud
->pin_rs
);
198 UBICOM32_GPIO_SET_PIN_OUTPUT(ud
->pin_rd
);
199 UBICOM32_GPIO_SET_PIN_OUTPUT(ud
->pin_wr
);
200 UBICOM32_GPIO_SET_PIN_OUTPUT(ud
->pin_cs
);
202 UBICOM32_GPIO_ENABLE(ud
->pin_rs
);
203 UBICOM32_GPIO_ENABLE(ud
->pin_rd
);
204 UBICOM32_GPIO_ENABLE(ud
->pin_wr
);
205 UBICOM32_GPIO_ENABLE(ud
->pin_cs
);
209 UBICOM32_GPIO_SET_PIN_HIGH(ud
->pin_reset
);
213 UBICOM32_GPIO_SET_PIN_LOW(ud
->pin_cs
);
215 id
= ubicom32lcd_read_data(ud
);
218 * We will try to figure out what kind of panel we have if we were not told.
221 const struct ubicom32lcd_panel
**p
= ubicom32lcd_panels
;
223 if ((*p
)->id
&& ((*p
)->id
== id
)) {
229 printk(KERN_WARNING DRIVER_NAME
":Could not find compatible panel, id=%x\n", id
);
236 * Make sure panel ID matches if we were supplied a panel type
238 if (ud
->panel
->id
&& (ud
->panel
->id
!= id
)) {
239 UBICOM32_GPIO_SET_PIN_HIGH(ud
->pin_cs
);
244 ubicom32lcd_execute(ud
, ud
->panel
->init_seq
);
246 ubicom32lcd_goto(ud
, 0, 0);
248 UBICOM32_GPIO_SET_PIN_HIGH(ud
->pin_cs
);
249 UBICOM32_GPIO_SET_PIN_HIGH(ud
->pin_rd
);
250 UBICOM32_GPIO_SET_PIN_HIGH(ud
->pin_wr
);
251 UBICOM32_GPIO_SET_PIN_HIGH(ud
->pin_rs
);
253 printk(KERN_INFO DRIVER_NAME
": Initialized panel %s\n", ud
->panel
->desc
);
261 static int ubicom32lcd_probe(struct platform_device
*pdev
)
263 const struct ubicom32lcd_platform_data
*pdata
= pdev
->dev
.platform_data
;
264 struct ubicom32lcd_data
*ud
;
268 * Allocate our private data
270 ud
= kzalloc(sizeof(struct ubicom32lcd_data
), GFP_KERNEL
);
276 ud
->pin_cs
= pdata
->pin_cs
;
277 ud
->pin_rd
= pdata
->pin_rd
;
278 ud
->pin_wr
= pdata
->pin_wr
;
279 ud
->pin_rs
= pdata
->pin_rs
;
280 ud
->pin_reset
= pdata
->pin_reset
;
281 ud
->port_data
= pdata
->port_data
;
282 ud
->data_shift
= pdata
->data_shift
;
287 ud
->pin_cs
= GPIO_RD_4
;
288 ud
->pin_rd
= GPIO_RD_5
;
289 ud
->pin_rs
= GPIO_RD_3
;
290 ud
->pin_wr
= GPIO_RD_2
;
291 ud
->pin_reset
= GPIO_RD_7
;
292 ud
->port_data
= (struct ubicom32_io_port
*)RI
;
297 * Initialize the display
299 retval
= ubicom32lcd_panel_init(ud
);
305 printk(KERN_INFO DRIVER_NAME
": LCD initialized\n");
313 static int __exit
ubicom32lcd_remove(struct platform_device
*pdev
)
315 struct ubicom32lcd_data
*ud
= platform_get_drvdata(pdev
);
322 static struct platform_driver ubicom32lcd_driver
= {
323 .probe
= ubicom32lcd_probe
,
324 .remove
= ubicom32lcd_remove
,
328 .owner
= THIS_MODULE
,
331 .remove
= __exit_p(ubicom32lcd_remove
),
334 static struct platform_device
*ubicom32lcd_device
;
339 static int __init
ubicom32lcd_init(void)
343 res
= platform_driver_register(&ubicom32lcd_driver
);
345 ubicom32lcd_device
= platform_device_alloc(DRIVER_NAME
, 0);
346 if (ubicom32lcd_device
) {
347 res
= platform_device_add(ubicom32lcd_device
);
352 platform_device_put(ubicom32lcd_device
);
353 platform_driver_unregister(&ubicom32lcd_driver
);
358 module_init(ubicom32lcd_init
);
363 static void __exit
ubicom32lcd_exit(void)
365 platform_device_unregister(ubicom32lcd_device
);
366 platform_driver_unregister(&ubicom32lcd_driver
);
368 module_exit(ubicom32lcd_exit
);
370 MODULE_AUTHOR("Patrick Tjin <@ubicom.com>");
371 MODULE_DESCRIPTION("Ubicom32 LCD driver");
372 MODULE_LICENSE("GPL");