summaryrefslogtreecommitdiffstats
path: root/meta/recipes-kernel/linux/linux-omap-2.6.29/dss2/0006-DSS2-HACK-Add-DSS2-support-for-N800.patch
diff options
context:
space:
mode:
Diffstat (limited to 'meta/recipes-kernel/linux/linux-omap-2.6.29/dss2/0006-DSS2-HACK-Add-DSS2-support-for-N800.patch')
-rw-r--r--meta/recipes-kernel/linux/linux-omap-2.6.29/dss2/0006-DSS2-HACK-Add-DSS2-support-for-N800.patch1079
1 files changed, 1079 insertions, 0 deletions
diff --git a/meta/recipes-kernel/linux/linux-omap-2.6.29/dss2/0006-DSS2-HACK-Add-DSS2-support-for-N800.patch b/meta/recipes-kernel/linux/linux-omap-2.6.29/dss2/0006-DSS2-HACK-Add-DSS2-support-for-N800.patch
new file mode 100644
index 0000000000..0025f1aa8b
--- /dev/null
+++ b/meta/recipes-kernel/linux/linux-omap-2.6.29/dss2/0006-DSS2-HACK-Add-DSS2-support-for-N800.patch
@@ -0,0 +1,1079 @@
1From 18a25382e81c03230e022ca2eb7e0fce24479d6a Mon Sep 17 00:00:00 2001
2From: Tomi Valkeinen <tomi.valkeinen@nokia.com>
3Date: Thu, 2 Apr 2009 10:31:57 +0300
4Subject: [PATCH] DSS2: HACK: Add DSS2 support for N800
5
6Works, but it an ugly quick hack.
7
8Signed-off-by: Tomi Valkeinen <tomi.valkeinen@nokia.com>
9---
10 arch/arm/mach-omap2/board-n800.c | 216 +++++++++++---
11 drivers/video/omap2/displays/Kconfig | 10 +
12 drivers/video/omap2/displays/Makefile | 3 +
13 drivers/video/omap2/displays/ctrl-blizzard.c | 279 +++++++++++++++++
14 drivers/video/omap2/displays/panel-n800.c | 435 ++++++++++++++++++++++++++
15 5 files changed, 905 insertions(+), 38 deletions(-)
16 create mode 100644 drivers/video/omap2/displays/ctrl-blizzard.c
17 create mode 100644 drivers/video/omap2/displays/panel-n800.c
18
19diff --git a/arch/arm/mach-omap2/board-n800.c b/arch/arm/mach-omap2/board-n800.c
20index f6f6571..6de60ae 100644
21--- a/arch/arm/mach-omap2/board-n800.c
22+++ b/arch/arm/mach-omap2/board-n800.c
23@@ -41,6 +41,8 @@
24 #include <mach/clock.h>
25 #include <mach/gpio-switch.h>
26 #include <mach/blizzard.h>
27+#include <mach/display.h>
28+#include <mach/vram.h>
29
30 #include <../drivers/cbus/tahvo.h>
31 #include <../drivers/media/video/tcm825x.h>
32@@ -161,23 +163,176 @@ static struct omap_uart_config n800_uart_config __initdata = {
33
34 #include "../../../drivers/cbus/retu.h"
35
36-static struct omap_fbmem_config n800_fbmem0_config __initdata = {
37- .size = 752 * 1024,
38+static struct omap_tmp105_config n800_tmp105_config __initdata = {
39+ .tmp105_irq_pin = 125,
40+ .set_power = n800_tmp105_set_power,
41 };
42
43-static struct omap_fbmem_config n800_fbmem1_config __initdata = {
44- .size = 752 * 1024,
45-};
46
47-static struct omap_fbmem_config n800_fbmem2_config __initdata = {
48- .size = 752 * 1024,
49+
50+
51+/* DISPLAY */
52+static struct {
53+ struct clk *sys_ck;
54+} blizzard;
55+
56+static int blizzard_get_clocks(void)
57+{
58+ blizzard.sys_ck = clk_get(0, "osc_ck");
59+ if (IS_ERR(blizzard.sys_ck)) {
60+ printk(KERN_ERR "can't get Blizzard clock\n");
61+ return PTR_ERR(blizzard.sys_ck);
62+ }
63+ return 0;
64+}
65+
66+static unsigned long blizzard_get_clock_rate(void)
67+{
68+ return clk_get_rate(blizzard.sys_ck);
69+}
70+
71+static int n800_pn800_enable(struct omap_display *display)
72+{
73+ if (display->hw_config.panel_reset_gpio != -1) {
74+ printk("enabling panel gpio\n");
75+ gpio_direction_output(display->hw_config.panel_reset_gpio, 1);
76+ }
77+
78+ return 0;
79+}
80+
81+static void n800_pn800_disable(struct omap_display *display)
82+{
83+ if (display->hw_config.panel_reset_gpio != -1) {
84+ printk("disabling panel gpio\n");
85+ gpio_direction_output(display->hw_config.panel_reset_gpio, 0);
86+ msleep(120);
87+ }
88+}
89+
90+static int n800_blizzard_enable(struct omap_display *display)
91+{
92+ printk("enabling bliz powers\n");
93+
94+ /* Vcore to 1.475V */
95+ tahvo_set_clear_reg_bits(0x07, 0, 0xf);
96+ msleep(10);
97+
98+ clk_enable(blizzard.sys_ck);
99+
100+ if (display->hw_config.ctrl_reset_gpio != -1)
101+ gpio_direction_output(display->hw_config.ctrl_reset_gpio, 1);
102+
103+ printk("osc_ck %lu\n", blizzard_get_clock_rate());
104+
105+ return 0;
106+}
107+
108+static void n800_blizzard_disable(struct omap_display *display)
109+{
110+ printk("disabling bliz powers\n");
111+
112+ if (display->hw_config.ctrl_reset_gpio != -1)
113+ gpio_direction_output(display->hw_config.ctrl_reset_gpio, 0);
114+
115+ clk_disable(blizzard.sys_ck);
116+
117+ /* Vcore to 1.005V */
118+ tahvo_set_clear_reg_bits(0x07, 0xf, 0);
119+}
120+
121+static int n800_set_backlight_level(struct omap_display *display, int level)
122+{
123+ return 0;
124+}
125+
126+static struct omap_dss_display_config n800_dsi_display_data = {
127+ .type = OMAP_DISPLAY_TYPE_DBI,
128+ .name = "lcd",
129+ .ctrl_name = "ctrl-blizzard",
130+ .panel_name = "panel-pn800",
131+ .panel_reset_gpio = -1,
132+ .ctrl_reset_gpio = N800_BLIZZARD_POWERDOWN_GPIO,
133+ .panel_enable = n800_pn800_enable,
134+ .panel_disable = n800_pn800_disable,
135+ .ctrl_enable = n800_blizzard_enable,
136+ .ctrl_disable = n800_blizzard_disable,
137+ .set_backlight = n800_set_backlight_level,
138+ .u.rfbi = {
139+ .channel = 0,
140+ /* 8 for cmd mode, 16 for pixel data. ctrl-blizzard handles switching */
141+ .data_lines = 8,
142+ },
143+ .panel_data = 0, // XXX used for panel datalines
144+};
145+static struct omap_dss_board_info n800_dss_data = {
146+ .num_displays = 1,
147+ .displays = {
148+ &n800_dsi_display_data,
149+ },
150 };
151
152-static struct omap_tmp105_config n800_tmp105_config __initdata = {
153- .tmp105_irq_pin = 125,
154- .set_power = n800_tmp105_set_power,
155+static struct platform_device n800_dss_device = {
156+ .name = "omapdss",
157+ .id = -1,
158+ .dev = {
159+ .platform_data = &n800_dss_data,
160+ },
161 };
162
163+static void __init n800_display_init(void)
164+{
165+ int r;
166+ const struct omap_lcd_config *conf;
167+
168+ conf = omap_get_config(OMAP_TAG_LCD, struct omap_lcd_config);
169+ if (conf != NULL) {
170+ n800_dsi_display_data.panel_reset_gpio = conf->nreset_gpio;
171+ n800_dsi_display_data.panel_data =
172+ (void*)(u32)conf->data_lines; // XXX
173+ //printk("\n\nTULI %d\n\n", conf->data_lines);
174+ } else {
175+ printk("\n\nEI TULLU MIOTÄÄÄ\n\n");
176+ }
177+
178+ blizzard_get_clocks();
179+ clk_enable(blizzard.sys_ck); // XXX always enable
180+
181+ //omapfb_set_ctrl_platform_data(&n800_blizzard_data);
182+ //
183+ if (n800_dsi_display_data.ctrl_reset_gpio != -1) {
184+ r = gpio_request(n800_dsi_display_data.ctrl_reset_gpio,
185+ "Blizzard pd");
186+ if (r < 0) {
187+ n800_dsi_display_data.ctrl_reset_gpio = -1;
188+ printk(KERN_ERR "Unable to get Blizzard GPIO\n");
189+ } else {
190+ gpio_direction_output(n800_dsi_display_data.ctrl_reset_gpio,
191+ 1);
192+ // XXX always enable
193+ }
194+ }
195+
196+ if (n800_dsi_display_data.panel_reset_gpio != -1) {
197+ r = gpio_request(n800_dsi_display_data.panel_reset_gpio,
198+ "panel reset");
199+ if (r < 0) {
200+ n800_dsi_display_data.panel_reset_gpio = -1;
201+ printk(KERN_ERR "Unable to get pn800 GPIO\n");
202+ } else {
203+ gpio_direction_output(n800_dsi_display_data.panel_reset_gpio,
204+ 1);
205+ // XXX always enable
206+ }
207+ }
208+}
209+
210+/* DISPLAY END */
211+
212+
213+
214+
215+
216 static void mipid_shutdown(struct mipid_platform_data *pdata)
217 {
218 if (pdata->nreset_gpio != -1) {
219@@ -191,6 +346,7 @@ static struct mipid_platform_data n800_mipid_platform_data = {
220 .shutdown = mipid_shutdown,
221 };
222
223+#if 0
224 static void __init mipid_dev_init(void)
225 {
226 const struct omap_lcd_config *conf;
227@@ -201,26 +357,9 @@ static void __init mipid_dev_init(void)
228 n800_mipid_platform_data.data_lines = conf->data_lines;
229 }
230 }
231+#endif
232
233-static struct {
234- struct clk *sys_ck;
235-} blizzard;
236-
237-static int blizzard_get_clocks(void)
238-{
239- blizzard.sys_ck = clk_get(0, "osc_ck");
240- if (IS_ERR(blizzard.sys_ck)) {
241- printk(KERN_ERR "can't get Blizzard clock\n");
242- return PTR_ERR(blizzard.sys_ck);
243- }
244- return 0;
245-}
246-
247-static unsigned long blizzard_get_clock_rate(struct device *dev)
248-{
249- return clk_get_rate(blizzard.sys_ck);
250-}
251-
252+#if 0
253 static void blizzard_enable_clocks(int enable)
254 {
255 if (enable)
256@@ -265,14 +404,12 @@ static void __init blizzard_dev_init(void)
257 gpio_direction_output(N800_BLIZZARD_POWERDOWN_GPIO, 1);
258
259 blizzard_get_clocks();
260- omapfb_set_ctrl_platform_data(&n800_blizzard_data);
261+ //omapfb_set_ctrl_platform_data(&n800_blizzard_data);
262 }
263+#endif
264
265 static struct omap_board_config_kernel n800_config[] __initdata = {
266 { OMAP_TAG_UART, &n800_uart_config },
267- { OMAP_TAG_FBMEM, &n800_fbmem0_config },
268- { OMAP_TAG_FBMEM, &n800_fbmem1_config },
269- { OMAP_TAG_FBMEM, &n800_fbmem2_config },
270 { OMAP_TAG_TMP105, &n800_tmp105_config },
271 };
272
273@@ -379,7 +516,7 @@ static struct omap2_mcspi_device_config tsc2005_mcspi_config = {
274
275 static struct spi_board_info n800_spi_board_info[] __initdata = {
276 {
277- .modalias = "lcd_mipid",
278+ .modalias = "panel-n800",
279 .bus_num = 1,
280 .chip_select = 1,
281 .max_speed_hz = 4000000,
282@@ -404,7 +541,7 @@ static struct spi_board_info n800_spi_board_info[] __initdata = {
283
284 static struct spi_board_info n810_spi_board_info[] __initdata = {
285 {
286- .modalias = "lcd_mipid",
287+ .modalias = "panel-n800",
288 .bus_num = 1,
289 .chip_select = 1,
290 .max_speed_hz = 4000000,
291@@ -582,6 +719,7 @@ static struct platform_device *n800_devices[] __initdata = {
292 #if defined(CONFIG_CBUS_RETU_HEADSET)
293 &retu_headset_device,
294 #endif
295+ &n800_dss_device,
296 };
297
298 #ifdef CONFIG_MENELAUS
299@@ -713,9 +851,10 @@ void __init nokia_n800_common_init(void)
300 if (machine_is_nokia_n810())
301 i2c_register_board_info(2, n810_i2c_board_info_2,
302 ARRAY_SIZE(n810_i2c_board_info_2));
303-
304- mipid_dev_init();
305- blizzard_dev_init();
306+
307+ //mipid_dev_init();
308+ //blizzard_dev_init();
309+ n800_display_init();
310 }
311
312 static void __init nokia_n800_init(void)
313@@ -735,6 +874,7 @@ void __init nokia_n800_map_io(void)
314 omap_board_config_size = ARRAY_SIZE(n800_config);
315
316 omap2_set_globals_242x();
317+ omap2_set_sdram_vram(800 * 480 * 2 * 3, 0);
318 omap2_map_common_io();
319 }
320
321diff --git a/drivers/video/omap2/displays/Kconfig b/drivers/video/omap2/displays/Kconfig
322index 0419ec8..356ceb1 100644
323--- a/drivers/video/omap2/displays/Kconfig
324+++ b/drivers/video/omap2/displays/Kconfig
325@@ -18,4 +18,14 @@ config PANEL_SHARP_LS037V7DW01
326 depends on OMAP2_DSS
327 help
328 LCD Panel used in TI's SDP3430 and EVM boards
329+
330+config PANEL_N800
331+ tristate "Panel N8x0"
332+ help
333+ N8x0 LCD (hack)
334+
335+config CTRL_BLIZZARD
336+ tristate "Blizzard Controller"
337+ help
338+ Blizzard Controller (hack)
339 endmenu
340diff --git a/drivers/video/omap2/displays/Makefile b/drivers/video/omap2/displays/Makefile
341index a26bbd2..1b74b7e 100644
342--- a/drivers/video/omap2/displays/Makefile
343+++ b/drivers/video/omap2/displays/Makefile
344@@ -1,3 +1,6 @@
345 obj-$(CONFIG_PANEL_GENERIC) += panel-generic.o
346 obj-$(CONFIG_PANEL_SAMSUNG_LTE430WQ_F0C) += panel-samsung-lte430wq-f0c.o
347 obj-$(CONFIG_PANEL_SHARP_LS037V7DW01) += panel-sharp-ls037v7dw01.o
348+
349+obj-$(CONFIG_CTRL_BLIZZARD) += ctrl-blizzard.o
350+obj-$(CONFIG_PANEL_N800) += panel-n800.o
351diff --git a/drivers/video/omap2/displays/ctrl-blizzard.c b/drivers/video/omap2/displays/ctrl-blizzard.c
352new file mode 100644
353index 0000000..6698e4d
354--- /dev/null
355+++ b/drivers/video/omap2/displays/ctrl-blizzard.c
356@@ -0,0 +1,279 @@
357+
358+//#define DEBUG
359+
360+#include <linux/kernel.h>
361+#include <linux/module.h>
362+#include <linux/clk.h>
363+#include <linux/delay.h>
364+#include <linux/err.h>
365+
366+#include <mach/display.h>
367+#include <mach/dma.h>
368+
369+#ifdef DEBUG
370+#define DBG(format, ...) printk(KERN_DEBUG "Blizzard: " format, ## __VA_ARGS__)
371+#else
372+#define DBG(format, ...)
373+#endif
374+
375+#define BLIZZARD_REV_CODE 0x00
376+#define BLIZZARD_CONFIG 0x02
377+#define BLIZZARD_PLL_DIV 0x04
378+#define BLIZZARD_PLL_LOCK_RANGE 0x06
379+#define BLIZZARD_PLL_CLOCK_SYNTH_0 0x08
380+#define BLIZZARD_PLL_CLOCK_SYNTH_1 0x0a
381+#define BLIZZARD_PLL_MODE 0x0c
382+#define BLIZZARD_CLK_SRC 0x0e
383+#define BLIZZARD_MEM_BANK0_ACTIVATE 0x10
384+#define BLIZZARD_MEM_BANK0_STATUS 0x14
385+#define BLIZZARD_PANEL_CONFIGURATION 0x28
386+#define BLIZZARD_HDISP 0x2a
387+#define BLIZZARD_HNDP 0x2c
388+#define BLIZZARD_VDISP0 0x2e
389+#define BLIZZARD_VDISP1 0x30
390+#define BLIZZARD_VNDP 0x32
391+#define BLIZZARD_HSW 0x34
392+#define BLIZZARD_VSW 0x38
393+#define BLIZZARD_DISPLAY_MODE 0x68
394+#define BLIZZARD_INPUT_WIN_X_START_0 0x6c
395+#define BLIZZARD_DATA_SOURCE_SELECT 0x8e
396+#define BLIZZARD_DISP_MEM_DATA_PORT 0x90
397+#define BLIZZARD_DISP_MEM_READ_ADDR0 0x92
398+#define BLIZZARD_POWER_SAVE 0xE6
399+#define BLIZZARD_NDISP_CTRL_STATUS 0xE8
400+
401+/* Data source select */
402+/* For S1D13745 */
403+#define BLIZZARD_SRC_WRITE_LCD_BACKGROUND 0x00
404+#define BLIZZARD_SRC_WRITE_LCD_DESTRUCTIVE 0x01
405+#define BLIZZARD_SRC_WRITE_OVERLAY_ENABLE 0x04
406+#define BLIZZARD_SRC_DISABLE_OVERLAY 0x05
407+/* For S1D13744 */
408+#define BLIZZARD_SRC_WRITE_LCD 0x00
409+#define BLIZZARD_SRC_BLT_LCD 0x06
410+
411+#define BLIZZARD_COLOR_RGB565 0x01
412+#define BLIZZARD_COLOR_YUV420 0x09
413+
414+#define BLIZZARD_VERSION_S1D13745 0x01 /* Hailstorm */
415+#define BLIZZARD_VERSION_S1D13744 0x02 /* Blizzard */
416+
417+#define BLIZZARD_AUTO_UPDATE_TIME (HZ / 20)
418+
419+
420+
421+static struct {
422+ int version;
423+} blizzard;
424+
425+
426+static inline void blizzard_cmd(u8 cmd)
427+{
428+ omap_rfbi_write_command(&cmd, 1);
429+}
430+
431+static inline void blizzard_write(u8 cmd, const u8 *buf, int len)
432+{
433+ omap_rfbi_write_command(&cmd, 1);
434+ omap_rfbi_write_data(buf, len);
435+}
436+
437+static inline void blizzard_read(u8 cmd, u8 *buf, int len)
438+{
439+ omap_rfbi_write_command(&cmd, 1);
440+ omap_rfbi_read_data(buf, len);
441+}
442+
443+static u8 blizzard_read_reg(u8 cmd)
444+{
445+ u8 data;
446+ blizzard_read(cmd, &data, 1);
447+ return data;
448+}
449+
450+static int blizzard_ctrl_init(struct omap_display *display)
451+{
452+ DBG("blizzard_ctrl_init\n");
453+
454+ return 0;
455+}
456+
457+
458+static int blizzard_ctrl_enable(struct omap_display *display)
459+{
460+ int r = 0;
461+ u8 rev, conf;
462+
463+ DBG("blizzard_ctrl_enable\n");
464+
465+ if (display->hw_config.ctrl_enable) {
466+ r = display->hw_config.ctrl_enable(display);
467+ if (r)
468+ return r;
469+ }
470+
471+ msleep(100);
472+
473+ rev = blizzard_read_reg(BLIZZARD_CLK_SRC);
474+ printk("CLK_SRC %x\n", rev);
475+
476+ rev = blizzard_read_reg(BLIZZARD_PLL_DIV);
477+ printk("PLLDIV %x\n", rev);
478+
479+ rev = blizzard_read_reg(BLIZZARD_REV_CODE);
480+ conf = blizzard_read_reg(BLIZZARD_CONFIG);
481+
482+ printk("rev %x, conf %x\n", rev, conf);
483+
484+ switch (rev & 0xfc) {
485+ case 0x9c:
486+ blizzard.version = BLIZZARD_VERSION_S1D13744;
487+ pr_info("omapfb: s1d13744 LCD controller rev %d "
488+ "initialized (CNF pins %x)\n", rev & 0x03, conf & 0x07);
489+ break;
490+ case 0xa4:
491+ blizzard.version = BLIZZARD_VERSION_S1D13745;
492+ pr_info("omapfb: s1d13745 LCD controller rev %d "
493+ "initialized (CNF pins %x)\n", rev & 0x03, conf & 0x07);
494+ break;
495+ default:
496+ printk("invalid s1d1374x revision %02x\n",
497+ rev);
498+ r = -ENODEV;
499+ }
500+
501+ return r;
502+}
503+
504+static void blizzard_ctrl_disable(struct omap_display *display)
505+{
506+ DBG("blizzard_ctrl_disable\n");
507+
508+ if (display->hw_config.ctrl_disable)
509+ display->hw_config.ctrl_disable(display);
510+}
511+
512+int rfbi_configure(int rfbi_module, int bpp, int lines);
513+
514+static void blizzard_ctrl_setup_update(struct omap_display *display,
515+ u16 x, u16 y, u16 w, u16 h)
516+{
517+ u8 tmp[18];
518+ int x_end, y_end;
519+
520+ DBG("blizzard_ctrl_setup_update\n");
521+
522+ x_end = x + w - 1;
523+ y_end = y + h - 1;
524+
525+ tmp[0] = x;
526+ tmp[1] = x >> 8;
527+ tmp[2] = y;
528+ tmp[3] = y >> 8;
529+ tmp[4] = x_end;
530+ tmp[5] = x_end >> 8;
531+ tmp[6] = y_end;
532+ tmp[7] = y_end >> 8;
533+
534+ /* scaling? */
535+ tmp[8] = x;
536+ tmp[9] = x >> 8;
537+ tmp[10] = y;
538+ tmp[11] = y >> 8;
539+ tmp[12] = x_end;
540+ tmp[13] = x_end >> 8;
541+ tmp[14] = y_end;
542+ tmp[15] = y_end >> 8;
543+
544+ tmp[16] = BLIZZARD_COLOR_RGB565; //color_mode;
545+
546+ if (blizzard.version == BLIZZARD_VERSION_S1D13745)
547+ tmp[17] = BLIZZARD_SRC_WRITE_LCD_BACKGROUND;
548+ else
549+ tmp[17] = blizzard.version == BLIZZARD_VERSION_S1D13744 ?
550+ BLIZZARD_SRC_WRITE_LCD :
551+ BLIZZARD_SRC_WRITE_LCD_DESTRUCTIVE;
552+
553+ rfbi_configure(display->hw_config.u.rfbi.channel,
554+ 16,
555+ 8);
556+
557+ blizzard_write(BLIZZARD_INPUT_WIN_X_START_0, tmp, 18);
558+
559+ rfbi_configure(display->hw_config.u.rfbi.channel,
560+ 16,
561+ 16);
562+}
563+
564+static int blizzard_ctrl_enable_te(struct omap_display *display, bool enable)
565+{
566+ return 0;
567+}
568+
569+static int blizzard_ctrl_rotate(struct omap_display *display, u8 rotate)
570+{
571+ return 0;
572+}
573+
574+static int blizzard_ctrl_mirror(struct omap_display *display, bool enable)
575+{
576+ return 0;
577+}
578+
579+static int blizzard_run_test(struct omap_display *display, int test_num)
580+{
581+ return 0;
582+}
583+
584+static struct omap_ctrl blizzard_ctrl = {
585+ .owner = THIS_MODULE,
586+ .name = "ctrl-blizzard",
587+ .init = blizzard_ctrl_init,
588+ .enable = blizzard_ctrl_enable,
589+ .disable = blizzard_ctrl_disable,
590+ .setup_update = blizzard_ctrl_setup_update,
591+ .enable_te = blizzard_ctrl_enable_te,
592+ .set_rotate = blizzard_ctrl_rotate,
593+ .set_mirror = blizzard_ctrl_mirror,
594+ .run_test = blizzard_run_test,
595+ .pixel_size = 16,
596+
597+ .timings = {
598+ .cs_on_time = 0,
599+
600+ .we_on_time = 9000,
601+ .we_off_time = 18000,
602+ .we_cycle_time = 36000,
603+
604+ .re_on_time = 9000,
605+ .re_off_time = 27000,
606+ .re_cycle_time = 36000,
607+
608+ .access_time = 27000,
609+ .cs_off_time = 36000,
610+
611+ .cs_pulse_width = 0,
612+ },
613+};
614+
615+
616+static int __init blizzard_init(void)
617+{
618+ DBG("blizzard_init\n");
619+ omap_dss_register_ctrl(&blizzard_ctrl);
620+ return 0;
621+}
622+
623+static void __exit blizzard_exit(void)
624+{
625+ DBG("blizzard_exit\n");
626+
627+ omap_dss_unregister_ctrl(&blizzard_ctrl);
628+}
629+
630+module_init(blizzard_init);
631+module_exit(blizzard_exit);
632+
633+MODULE_AUTHOR("Tomi Valkeinen <tomi.valkeinen@nokia.com>");
634+MODULE_DESCRIPTION("Blizzard Driver");
635+MODULE_LICENSE("GPL");
636diff --git a/drivers/video/omap2/displays/panel-n800.c b/drivers/video/omap2/displays/panel-n800.c
637new file mode 100644
638index 0000000..91d3e37
639--- /dev/null
640+++ b/drivers/video/omap2/displays/panel-n800.c
641@@ -0,0 +1,435 @@
642+
643+/*#define DEBUG*/
644+
645+#include <linux/kernel.h>
646+#include <linux/module.h>
647+#include <linux/clk.h>
648+#include <linux/platform_device.h>
649+#include <linux/delay.h>
650+#include <linux/spi/spi.h>
651+#include <linux/jiffies.h>
652+#include <linux/sched.h>
653+#include <linux/backlight.h>
654+#include <linux/fb.h>
655+
656+#include <mach/display.h>
657+#include <mach/dma.h>
658+
659+#define MIPID_CMD_READ_DISP_ID 0x04
660+#define MIPID_CMD_READ_RED 0x06
661+#define MIPID_CMD_READ_GREEN 0x07
662+#define MIPID_CMD_READ_BLUE 0x08
663+#define MIPID_CMD_READ_DISP_STATUS 0x09
664+#define MIPID_CMD_RDDSDR 0x0F
665+#define MIPID_CMD_SLEEP_IN 0x10
666+#define MIPID_CMD_SLEEP_OUT 0x11
667+#define MIPID_CMD_DISP_OFF 0x28
668+#define MIPID_CMD_DISP_ON 0x29
669+
670+#define MIPID_VER_LPH8923 3
671+#define MIPID_VER_LS041Y3 4
672+
673+#define MIPID_ESD_CHECK_PERIOD msecs_to_jiffies(5000)
674+
675+#ifdef DEBUG
676+#define DBG(format, ...) printk(KERN_DEBUG "PN800: " format, ## __VA_ARGS__)
677+#else
678+#define DBG(format, ...)
679+#endif
680+
681+struct pn800_device {
682+ struct backlight_device *bl_dev;
683+ int enabled;
684+ int model;
685+ int revision;
686+ u8 display_id[3];
687+ unsigned int saved_bklight_level;
688+ unsigned long hw_guard_end; /* next value of jiffies
689+ when we can issue the
690+ next sleep in/out command */
691+ unsigned long hw_guard_wait; /* max guard time in jiffies */
692+
693+ struct spi_device *spi;
694+ struct mutex mutex;
695+ struct omap_panel panel;
696+ struct omap_display *display;
697+};
698+
699+
700+static void pn800_transfer(struct pn800_device *md, int cmd,
701+ const u8 *wbuf, int wlen, u8 *rbuf, int rlen)
702+{
703+ struct spi_message m;
704+ struct spi_transfer *x, xfer[4];
705+ u16 w;
706+ int r;
707+
708+ BUG_ON(md->spi == NULL);
709+
710+ spi_message_init(&m);
711+
712+ memset(xfer, 0, sizeof(xfer));
713+ x = &xfer[0];
714+
715+ cmd &= 0xff;
716+ x->tx_buf = &cmd;
717+ x->bits_per_word = 9;
718+ x->len = 2;
719+ spi_message_add_tail(x, &m);
720+
721+ if (wlen) {
722+ x++;
723+ x->tx_buf = wbuf;
724+ x->len = wlen;
725+ x->bits_per_word = 9;
726+ spi_message_add_tail(x, &m);
727+ }
728+
729+ if (rlen) {
730+ x++;
731+ x->rx_buf = &w;
732+ x->len = 1;
733+ spi_message_add_tail(x, &m);
734+
735+ if (rlen > 1) {
736+ /* Arrange for the extra clock before the first
737+ * data bit.
738+ */
739+ x->bits_per_word = 9;
740+ x->len = 2;
741+
742+ x++;
743+ x->rx_buf = &rbuf[1];
744+ x->len = rlen - 1;
745+ spi_message_add_tail(x, &m);
746+ }
747+ }
748+
749+ r = spi_sync(md->spi, &m);
750+ if (r < 0)
751+ dev_dbg(&md->spi->dev, "spi_sync %d\n", r);
752+
753+ if (rlen)
754+ rbuf[0] = w & 0xff;
755+}
756+
757+static inline void pn800_cmd(struct pn800_device *md, int cmd)
758+{
759+ pn800_transfer(md, cmd, NULL, 0, NULL, 0);
760+}
761+
762+static inline void pn800_write(struct pn800_device *md,
763+ int reg, const u8 *buf, int len)
764+{
765+ pn800_transfer(md, reg, buf, len, NULL, 0);
766+}
767+
768+static inline void pn800_read(struct pn800_device *md,
769+ int reg, u8 *buf, int len)
770+{
771+ pn800_transfer(md, reg, NULL, 0, buf, len);
772+}
773+
774+static void set_data_lines(struct pn800_device *md, int data_lines)
775+{
776+ u16 par;
777+
778+ switch (data_lines) {
779+ case 16:
780+ par = 0x150;
781+ break;
782+ case 18:
783+ par = 0x160;
784+ break;
785+ case 24:
786+ par = 0x170;
787+ break;
788+ }
789+ pn800_write(md, 0x3a, (u8 *)&par, 2);
790+}
791+
792+static void send_init_string(struct pn800_device *md)
793+{
794+ u16 initpar[] = { 0x0102, 0x0100, 0x0100 };
795+ int data_lines;
796+
797+ pn800_write(md, 0xc2, (u8 *)initpar, sizeof(initpar));
798+
799+ data_lines = (int)md->display->hw_config.panel_data; // XXX
800+
801+ set_data_lines(md, data_lines);
802+}
803+
804+static void hw_guard_start(struct pn800_device *md, int guard_msec)
805+{
806+ md->hw_guard_wait = msecs_to_jiffies(guard_msec);
807+ md->hw_guard_end = jiffies + md->hw_guard_wait;
808+}
809+
810+static void hw_guard_wait(struct pn800_device *md)
811+{
812+ unsigned long wait = md->hw_guard_end - jiffies;
813+
814+ if ((long)wait > 0 && wait <= md->hw_guard_wait) {
815+ set_current_state(TASK_UNINTERRUPTIBLE);
816+ schedule_timeout(wait);
817+ }
818+}
819+
820+static void set_sleep_mode(struct pn800_device *md, int on)
821+{
822+ int cmd, sleep_time = 50;
823+
824+ if (on)
825+ cmd = MIPID_CMD_SLEEP_IN;
826+ else
827+ cmd = MIPID_CMD_SLEEP_OUT;
828+ hw_guard_wait(md);
829+ pn800_cmd(md, cmd);
830+ hw_guard_start(md, 120);
831+ /*
832+ * When we enable the panel, it seems we _have_ to sleep
833+ * 120 ms before sending the init string. When disabling the
834+ * panel we'll sleep for the duration of 2 frames, so that the
835+ * controller can still provide the PCLK,HS,VS signals. */
836+ if (!on)
837+ sleep_time = 120;
838+ msleep(sleep_time);
839+}
840+
841+static void set_display_state(struct pn800_device *md, int enabled)
842+{
843+ int cmd = enabled ? MIPID_CMD_DISP_ON : MIPID_CMD_DISP_OFF;
844+
845+ pn800_cmd(md, cmd);
846+}
847+
848+static int panel_enabled(struct pn800_device *md)
849+{
850+ u32 disp_status;
851+ int enabled;
852+
853+ pn800_read(md, MIPID_CMD_READ_DISP_STATUS, (u8 *)&disp_status, 4);
854+ disp_status = __be32_to_cpu(disp_status);
855+ enabled = (disp_status & (1 << 17)) && (disp_status & (1 << 10));
856+ dev_dbg(&md->spi->dev,
857+ "LCD panel %s enabled by bootloader (status 0x%04x)\n",
858+ enabled ? "" : "not ", disp_status);
859+ DBG("status %#08x\n", disp_status);
860+ return enabled;
861+}
862+
863+static int panel_detect(struct pn800_device *md)
864+{
865+ pn800_read(md, MIPID_CMD_READ_DISP_ID, md->display_id, 3);
866+ dev_dbg(&md->spi->dev, "MIPI display ID: %02x%02x%02x\n",
867+ md->display_id[0], md->display_id[1], md->display_id[2]);
868+
869+ switch (md->display_id[0]) {
870+ case 0x45:
871+ md->model = MIPID_VER_LPH8923;
872+ md->panel.name = "lph8923";
873+ break;
874+ case 0x83:
875+ md->model = MIPID_VER_LS041Y3;
876+ md->panel.name = "ls041y3";
877+ //md->esd_check = ls041y3_esd_check;
878+ break;
879+ default:
880+ md->panel.name = "unknown";
881+ dev_err(&md->spi->dev, "invalid display ID\n");
882+ return -ENODEV;
883+ }
884+
885+ md->revision = md->display_id[1];
886+ pr_info("omapfb: %s rev %02x LCD detected\n",
887+ md->panel.name, md->revision);
888+
889+ return 0;
890+}
891+
892+
893+
894+static int pn800_panel_enable(struct omap_display *display)
895+{
896+ int r;
897+ struct pn800_device *md =
898+ (struct pn800_device *)display->panel->priv;
899+
900+ DBG("pn800_panel_enable\n");
901+
902+ mutex_lock(&md->mutex);
903+
904+ if (display->hw_config.panel_enable)
905+ display->hw_config.panel_enable(display);
906+
907+ msleep(50); // wait for power up
908+
909+ r = panel_detect(md);
910+ if (r) {
911+ mutex_unlock(&md->mutex);
912+ return r;
913+ }
914+
915+ md->enabled = panel_enabled(md);
916+
917+ if (md->enabled) {
918+ DBG("panel already enabled\n");
919+ ; /*pn800_esd_start_check(md);*/
920+ } else {
921+ ; /*md->saved_bklight_level = pn800_get_bklight_level(panel);*/
922+ }
923+
924+
925+ if (md->enabled) {
926+ mutex_unlock(&md->mutex);
927+ return 0;
928+ }
929+
930+ set_sleep_mode(md, 0);
931+ md->enabled = 1;
932+ send_init_string(md);
933+ set_display_state(md, 1);
934+ //mipid_set_bklight_level(panel, md->saved_bklight_level);
935+ //mipid_esd_start_check(md);
936+
937+ mutex_unlock(&md->mutex);
938+ return 0;
939+}
940+
941+static void pn800_panel_disable(struct omap_display *display)
942+{
943+ struct pn800_device *md =
944+ (struct pn800_device *)display->panel->priv;
945+
946+ DBG("pn800_panel_disable\n");
947+
948+ mutex_lock(&md->mutex);
949+
950+ if (!md->enabled) {
951+ mutex_unlock(&md->mutex);
952+ return;
953+ }
954+ /*md->saved_bklight_level = pn800_get_bklight_level(panel);*/
955+ /*pn800_set_bklight_level(panel, 0);*/
956+
957+ set_display_state(md, 0);
958+ set_sleep_mode(md, 1);
959+ md->enabled = 0;
960+
961+
962+ if (display->hw_config.panel_disable)
963+ display->hw_config.panel_disable(display);
964+
965+ mutex_unlock(&md->mutex);
966+}
967+
968+static int pn800_panel_init(struct omap_display *display)
969+{
970+ struct pn800_device *md =
971+ (struct pn800_device *)display->panel->priv;
972+
973+ DBG("pn800_panel_init\n");
974+
975+ mutex_init(&md->mutex);
976+ md->display = display;
977+
978+ return 0;
979+}
980+
981+static int pn800_run_test(struct omap_display *display, int test_num)
982+{
983+ return 0;
984+}
985+
986+static struct omap_panel pn800_panel = {
987+ .owner = THIS_MODULE,
988+ .name = "panel-pn800",
989+ .init = pn800_panel_init,
990+ /*.remove = pn800_cleanup,*/
991+ .enable = pn800_panel_enable,
992+ .disable = pn800_panel_disable,
993+ //.set_mode = pn800_set_mode,
994+ .run_test = pn800_run_test,
995+
996+ .timings = {
997+ .x_res = 800,
998+ .y_res = 480,
999+
1000+ .pixel_clock = 21940,
1001+ .hsw = 50,
1002+ .hfp = 20,
1003+ .hbp = 15,
1004+
1005+ .vsw = 2,
1006+ .vfp = 1,
1007+ .vbp = 3,
1008+ },
1009+ .config = OMAP_DSS_LCD_TFT,
1010+};
1011+
1012+static int pn800_spi_probe(struct spi_device *spi)
1013+{
1014+ struct pn800_device *md;
1015+
1016+ DBG("pn800_spi_probe\n");
1017+
1018+ md = kzalloc(sizeof(*md), GFP_KERNEL);
1019+ if (md == NULL) {
1020+ dev_err(&spi->dev, "out of memory\n");
1021+ return -ENOMEM;
1022+ }
1023+
1024+ spi->mode = SPI_MODE_0;
1025+ md->spi = spi;
1026+ dev_set_drvdata(&spi->dev, md);
1027+ md->panel = pn800_panel;
1028+ pn800_panel.priv = md;
1029+
1030+ omap_dss_register_panel(&pn800_panel);
1031+
1032+ return 0;
1033+}
1034+
1035+static int pn800_spi_remove(struct spi_device *spi)
1036+{
1037+ struct pn800_device *md = dev_get_drvdata(&spi->dev);
1038+
1039+ DBG("pn800_spi_remove\n");
1040+
1041+ omap_dss_unregister_panel(&pn800_panel);
1042+
1043+ /*pn800_disable(&md->panel);*/
1044+ kfree(md);
1045+
1046+ return 0;
1047+}
1048+
1049+static struct spi_driver pn800_spi_driver = {
1050+ .driver = {
1051+ .name = "panel-n800",
1052+ .bus = &spi_bus_type,
1053+ .owner = THIS_MODULE,
1054+ },
1055+ .probe = pn800_spi_probe,
1056+ .remove = __devexit_p(pn800_spi_remove),
1057+};
1058+
1059+static int __init pn800_init(void)
1060+{
1061+ DBG("pn800_init\n");
1062+ return spi_register_driver(&pn800_spi_driver);
1063+}
1064+
1065+static void __exit pn800_exit(void)
1066+{
1067+ DBG("pn800_exit\n");
1068+ spi_unregister_driver(&pn800_spi_driver);
1069+}
1070+
1071+module_init(pn800_init);
1072+module_exit(pn800_exit);
1073+
1074+MODULE_AUTHOR("Tomi Valkeinen <tomi.valkeinen@nokia.com>");
1075+MODULE_DESCRIPTION("N800 LCD Driver");
1076+MODULE_LICENSE("GPL");
1077--
10781.5.6.5
1079