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:
authorRichard Purdie <rpurdie@linux.intel.com>2010-08-27 15:14:24 +0100
committerRichard Purdie <rpurdie@linux.intel.com>2010-08-27 15:29:45 +0100
commit29d6678fd546377459ef75cf54abeef5b969b5cf (patch)
tree8edd65790e37a00d01c3f203f773fe4b5012db18 /meta/recipes-kernel/linux/linux-omap-2.6.29/dss2/0006-DSS2-HACK-Add-DSS2-support-for-N800.patch
parentda49de6885ee1bc424e70bc02f21f6ab920efb55 (diff)
downloadpoky-29d6678fd546377459ef75cf54abeef5b969b5cf.tar.gz
Major layout change to the packages directory
Having one monolithic packages directory makes it hard to find things and is generally overwhelming. This commit splits it into several logical sections roughly based on function, recipes.txt gives more information about the classifications used. The opportunity is also used to switch from "packages" to "recipes" as used in OpenEmbedded as the term "packages" can be confusing to people and has many different meanings. Not all recipes have been classified yet, this is just a first pass at separating things out. Some packages are moved to meta-extras as they're no longer actively used or maintained. Signed-off-by: Richard Purdie <rpurdie@linux.intel.com>
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