summaryrefslogtreecommitdiffstats
path: root/meta/recipes-kernel/linux/linux-omap-2.6.29/dss2/0009-DSS2-Add-acx565akm-panel.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/0009-DSS2-Add-acx565akm-panel.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/0009-DSS2-Add-acx565akm-panel.patch')
-rw-r--r--meta/recipes-kernel/linux/linux-omap-2.6.29/dss2/0009-DSS2-Add-acx565akm-panel.patch778
1 files changed, 778 insertions, 0 deletions
diff --git a/meta/recipes-kernel/linux/linux-omap-2.6.29/dss2/0009-DSS2-Add-acx565akm-panel.patch b/meta/recipes-kernel/linux/linux-omap-2.6.29/dss2/0009-DSS2-Add-acx565akm-panel.patch
new file mode 100644
index 0000000000..3f55f04460
--- /dev/null
+++ b/meta/recipes-kernel/linux/linux-omap-2.6.29/dss2/0009-DSS2-Add-acx565akm-panel.patch
@@ -0,0 +1,778 @@
1From 66e16f86d3f4c5b34b37e965c65102b7192371de Mon Sep 17 00:00:00 2001
2From: Imre Deak <imre.deak@nokia.com>
3Date: Thu, 2 Apr 2009 11:47:13 +0300
4Subject: [PATCH] DSS2: Add acx565akm panel
5
6Signed-off-by: Imre Deak <imre.deak@nokia.com>
7---
8 drivers/video/omap2/displays/Kconfig | 8 +
9 drivers/video/omap2/displays/Makefile | 2 +
10 drivers/video/omap2/displays/panel-acx565akm.c | 712 ++++++++++++++++++++++++
11 drivers/video/omap2/displays/panel-acx565akm.h | 9 +
12 4 files changed, 731 insertions(+), 0 deletions(-)
13 create mode 100644 drivers/video/omap2/displays/panel-acx565akm.c
14 create mode 100644 drivers/video/omap2/displays/panel-acx565akm.h
15
16diff --git a/drivers/video/omap2/displays/Kconfig b/drivers/video/omap2/displays/Kconfig
17index 356ceb1..3feecee 100644
18--- a/drivers/video/omap2/displays/Kconfig
19+++ b/drivers/video/omap2/displays/Kconfig
20@@ -28,4 +28,12 @@ config CTRL_BLIZZARD
21 tristate "Blizzard Controller"
22 help
23 Blizzard Controller (hack)
24+
25+config PANEL_ACX565AKM
26+ tristate "ACX565AKM LCD Panel"
27+ depends on OMAP2_DSS_SDI
28+ select BACKLIGHT_CLASS_DEVICE
29+ help
30+ LCD Panel used in RX51
31+
32 endmenu
33diff --git a/drivers/video/omap2/displays/Makefile b/drivers/video/omap2/displays/Makefile
34index 1b74b7e..9bafcb6 100644
35--- a/drivers/video/omap2/displays/Makefile
36+++ b/drivers/video/omap2/displays/Makefile
37@@ -4,3 +4,5 @@ obj-$(CONFIG_PANEL_SHARP_LS037V7DW01) += panel-sharp-ls037v7dw01.o
38
39 obj-$(CONFIG_CTRL_BLIZZARD) += ctrl-blizzard.o
40 obj-$(CONFIG_PANEL_N800) += panel-n800.o
41+
42+obj-$(CONFIG_PANEL_ACX565AKM) += panel-acx565akm.o
43diff --git a/drivers/video/omap2/displays/panel-acx565akm.c b/drivers/video/omap2/displays/panel-acx565akm.c
44new file mode 100644
45index 0000000..2679d6c
46--- /dev/null
47+++ b/drivers/video/omap2/displays/panel-acx565akm.c
48@@ -0,0 +1,712 @@
49+#include <linux/kernel.h>
50+#include <linux/module.h>
51+#include <linux/clk.h>
52+#include <linux/platform_device.h>
53+#include <linux/delay.h>
54+#include <linux/spi/spi.h>
55+#include <linux/jiffies.h>
56+#include <linux/sched.h>
57+#include <linux/backlight.h>
58+#include <linux/fb.h>
59+
60+#include <mach/display.h>
61+#include <mach/dma.h>
62+
63+#include "panel-acx565akm.h"
64+
65+#define MIPID_CMD_READ_DISP_ID 0x04
66+#define MIPID_CMD_READ_RED 0x06
67+#define MIPID_CMD_READ_GREEN 0x07
68+#define MIPID_CMD_READ_BLUE 0x08
69+#define MIPID_CMD_READ_DISP_STATUS 0x09
70+#define MIPID_CMD_RDDSDR 0x0F
71+#define MIPID_CMD_SLEEP_IN 0x10
72+#define MIPID_CMD_SLEEP_OUT 0x11
73+#define MIPID_CMD_DISP_OFF 0x28
74+#define MIPID_CMD_DISP_ON 0x29
75+#define MIPID_CMD_WRITE_DISP_BRIGHTNESS 0x51
76+#define MIPID_CMD_READ_DISP_BRIGHTNESS 0x52
77+#define MIPID_CMD_WRITE_CTRL_DISP 0x53
78+
79+#define CTRL_DISP_BRIGHTNESS_CTRL_ON (1 << 5)
80+#define CTRL_DISP_AMBIENT_LIGHT_CTRL_ON (1 << 4)
81+#define CTRL_DISP_BACKLIGHT_ON (1 << 2)
82+#define CTRL_DISP_AUTO_BRIGHTNESS_ON (1 << 1)
83+
84+#define MIPID_CMD_READ_CTRL_DISP 0x54
85+#define MIPID_CMD_WRITE_CABC 0x55
86+#define MIPID_CMD_READ_CABC 0x56
87+
88+#define MIPID_VER_LPH8923 3
89+#define MIPID_VER_LS041Y3 4
90+#define MIPID_VER_L4F00311 8
91+#define MIPID_VER_ACX565AKM 9
92+
93+struct acx565akm_device {
94+ struct backlight_device *bl_dev;
95+ int enabled;
96+ int model;
97+ int revision;
98+ u8 display_id[3];
99+ int has_bc:1;
100+ int has_cabc:1;
101+ unsigned int saved_bklight_level;
102+ unsigned long hw_guard_end; /* next value of jiffies
103+ when we can issue the
104+ next sleep in/out command */
105+ unsigned long hw_guard_wait; /* max guard time in jiffies */
106+
107+ struct spi_device *spi;
108+ struct mutex mutex;
109+ struct omap_panel panel;
110+ struct omap_display *display;
111+};
112+
113+static int acx565akm_bl_update_status(struct backlight_device *dev);
114+
115+static void acx565akm_transfer(struct acx565akm_device *md, int cmd,
116+ const u8 *wbuf, int wlen, u8 *rbuf, int rlen)
117+{
118+ struct spi_message m;
119+ struct spi_transfer *x, xfer[5];
120+ int r;
121+
122+ BUG_ON(md->spi == NULL);
123+
124+ spi_message_init(&m);
125+
126+ memset(xfer, 0, sizeof(xfer));
127+ x = &xfer[0];
128+
129+ cmd &= 0xff;
130+ x->tx_buf = &cmd;
131+ x->bits_per_word = 9;
132+ x->len = 2;
133+
134+ if (rlen > 1 && wlen == 0) {
135+ /*
136+ * Between the command and the response data there is a
137+ * dummy clock cycle. Add an extra bit after the command
138+ * word to account for this.
139+ */
140+ x->bits_per_word = 10;
141+ cmd <<= 1;
142+ }
143+ spi_message_add_tail(x, &m);
144+
145+ if (wlen) {
146+ x++;
147+ x->tx_buf = wbuf;
148+ x->len = wlen;
149+ x->bits_per_word = 9;
150+ spi_message_add_tail(x, &m);
151+ }
152+
153+ if (rlen) {
154+ x++;
155+ x->rx_buf = rbuf;
156+ x->len = rlen;
157+ spi_message_add_tail(x, &m);
158+ }
159+
160+ r = spi_sync(md->spi, &m);
161+ if (r < 0)
162+ dev_dbg(&md->spi->dev, "spi_sync %d\n", r);
163+}
164+
165+static inline void acx565akm_cmd(struct acx565akm_device *md, int cmd)
166+{
167+ acx565akm_transfer(md, cmd, NULL, 0, NULL, 0);
168+}
169+
170+static inline void acx565akm_write(struct acx565akm_device *md,
171+ int reg, const u8 *buf, int len)
172+{
173+ acx565akm_transfer(md, reg, buf, len, NULL, 0);
174+}
175+
176+static inline void acx565akm_read(struct acx565akm_device *md,
177+ int reg, u8 *buf, int len)
178+{
179+ acx565akm_transfer(md, reg, NULL, 0, buf, len);
180+}
181+
182+static void hw_guard_start(struct acx565akm_device *md, int guard_msec)
183+{
184+ md->hw_guard_wait = msecs_to_jiffies(guard_msec);
185+ md->hw_guard_end = jiffies + md->hw_guard_wait;
186+}
187+
188+static void hw_guard_wait(struct acx565akm_device *md)
189+{
190+ unsigned long wait = md->hw_guard_end - jiffies;
191+
192+ if ((long)wait > 0 && wait <= md->hw_guard_wait) {
193+ set_current_state(TASK_UNINTERRUPTIBLE);
194+ schedule_timeout(wait);
195+ }
196+}
197+
198+static void set_sleep_mode(struct acx565akm_device *md, int on)
199+{
200+ int cmd, sleep_time = 50;
201+
202+ if (on)
203+ cmd = MIPID_CMD_SLEEP_IN;
204+ else
205+ cmd = MIPID_CMD_SLEEP_OUT;
206+ hw_guard_wait(md);
207+ acx565akm_cmd(md, cmd);
208+ hw_guard_start(md, 120);
209+ /*
210+ * When we enable the panel, it seems we _have_ to sleep
211+ * 120 ms before sending the init string. When disabling the
212+ * panel we'll sleep for the duration of 2 frames, so that the
213+ * controller can still provide the PCLK,HS,VS signals. */
214+ if (!on)
215+ sleep_time = 120;
216+ msleep(sleep_time);
217+}
218+
219+static void set_display_state(struct acx565akm_device *md, int enabled)
220+{
221+ int cmd = enabled ? MIPID_CMD_DISP_ON : MIPID_CMD_DISP_OFF;
222+
223+ acx565akm_cmd(md, cmd);
224+}
225+
226+static int panel_enabled(struct acx565akm_device *md)
227+{
228+ u32 disp_status;
229+ int enabled;
230+
231+ acx565akm_read(md, MIPID_CMD_READ_DISP_STATUS, (u8 *)&disp_status, 4);
232+ disp_status = __be32_to_cpu(disp_status);
233+ enabled = (disp_status & (1 << 17)) && (disp_status & (1 << 10));
234+ dev_dbg(&md->spi->dev,
235+ "LCD panel %senabled by bootloader (status 0x%04x)\n",
236+ enabled ? "" : "not ", disp_status);
237+ return enabled;
238+}
239+
240+static void enable_backlight_ctrl(struct acx565akm_device *md, int enable)
241+{
242+ u16 ctrl;
243+
244+ acx565akm_read(md, MIPID_CMD_READ_CTRL_DISP, (u8 *)&ctrl, 1);
245+ if (enable) {
246+ ctrl |= CTRL_DISP_BRIGHTNESS_CTRL_ON |
247+ CTRL_DISP_BACKLIGHT_ON;
248+ } else {
249+ ctrl &= ~(CTRL_DISP_BRIGHTNESS_CTRL_ON |
250+ CTRL_DISP_BACKLIGHT_ON);
251+ }
252+
253+ ctrl |= 1 << 8;
254+ acx565akm_write(md, MIPID_CMD_WRITE_CTRL_DISP, (u8 *)&ctrl, 2);
255+}
256+
257+static void set_cabc_mode(struct acx565akm_device *md, int mode)
258+{
259+ u16 cabc_ctrl;
260+
261+ cabc_ctrl = 0;
262+ acx565akm_read(md, MIPID_CMD_READ_CABC, (u8 *)&cabc_ctrl, 1);
263+ cabc_ctrl &= ~3;
264+ cabc_ctrl |= (1 << 8) | (mode & 3);
265+ acx565akm_write(md, MIPID_CMD_WRITE_CABC, (u8 *)&cabc_ctrl, 2);
266+}
267+
268+static int get_cabc_mode(struct acx565akm_device *md)
269+{
270+ u8 cabc_ctrl;
271+
272+ acx565akm_read(md, MIPID_CMD_READ_CABC, &cabc_ctrl, 1);
273+ return cabc_ctrl & 3;
274+}
275+
276+static int panel_detect(struct acx565akm_device *md)
277+{
278+ acx565akm_read(md, MIPID_CMD_READ_DISP_ID, md->display_id, 3);
279+ dev_dbg(&md->spi->dev, "MIPI display ID: %02x%02x%02x\n",
280+ md->display_id[0], md->display_id[1], md->display_id[2]);
281+
282+ switch (md->display_id[0]) {
283+ case 0x10:
284+ md->model = MIPID_VER_ACX565AKM;
285+ md->panel.name = "acx565akm";
286+ md->has_bc = 1;
287+ md->has_cabc = 1;
288+ break;
289+ case 0x29:
290+ md->model = MIPID_VER_L4F00311;
291+ md->panel.name = "l4f00311";
292+ break;
293+ case 0x45:
294+ md->model = MIPID_VER_LPH8923;
295+ md->panel.name = "lph8923";
296+ break;
297+ case 0x83:
298+ md->model = MIPID_VER_LS041Y3;
299+ md->panel.name = "ls041y3";
300+ break;
301+ default:
302+ md->panel.name = "unknown";
303+ dev_err(&md->spi->dev, "invalid display ID\n");
304+ return -ENODEV;
305+ }
306+
307+ md->revision = md->display_id[1];
308+
309+ pr_info("omapfb: %s rev %02x LCD detected\n",
310+ md->panel.name, md->revision);
311+
312+ return 0;
313+}
314+
315+static int acx565akm_panel_enable(struct omap_display *display)
316+{
317+ struct acx565akm_device *md =
318+ (struct acx565akm_device *)display->panel->priv;
319+
320+ dev_dbg(&md->spi->dev, "%s\n", __func__);
321+
322+ mutex_lock(&md->mutex);
323+
324+ if (display->hw_config.panel_enable)
325+ display->hw_config.panel_enable(display);
326+
327+ md->enabled = panel_enabled(md);
328+
329+ if (md->enabled) {
330+ dev_dbg(&md->spi->dev, "panel already enabled\n");
331+ mutex_unlock(&md->mutex);
332+ return 0;
333+ }
334+
335+ set_sleep_mode(md, 0);
336+ md->enabled = 1;
337+ set_display_state(md, 1);
338+
339+ mutex_unlock(&md->mutex);
340+
341+ return acx565akm_bl_update_status(md->bl_dev);
342+}
343+
344+static void acx565akm_panel_disable(struct omap_display *display)
345+{
346+ struct acx565akm_device *md =
347+ (struct acx565akm_device *)display->panel->priv;
348+
349+ dev_dbg(&md->spi->dev, "%s\n", __func__);
350+
351+ mutex_lock(&md->mutex);
352+
353+ if (!md->enabled) {
354+ mutex_unlock(&md->mutex);
355+ return;
356+ }
357+ set_display_state(md, 0);
358+ set_sleep_mode(md, 1);
359+ md->enabled = 0;
360+
361+ if (display->hw_config.panel_disable)
362+ display->hw_config.panel_disable(display);
363+
364+ mutex_unlock(&md->mutex);
365+}
366+
367+#if 0
368+static void acx565akm_set_mode(struct omap_display *display,
369+ int x_res, int y_res, int bpp)
370+{
371+ struct acx565akm_device *md =
372+ (struct acx565akm_device *)display->panel->priv;
373+ u16 par;
374+
375+ switch (bpp) {
376+ case 16:
377+ par = 0x150;
378+ break;
379+ case 18:
380+ par = 0x160;
381+ break;
382+ case 24:
383+ par = 0x170;
384+ break;
385+ }
386+
387+ acx565akm_write(md, 0x3a, (u8 *)&par, 2);
388+}
389+#endif
390+
391+static int acx565akm_panel_suspend(struct omap_display *display)
392+{
393+ acx565akm_panel_disable(display);
394+ return 0;
395+}
396+
397+static int acx565akm_panel_resume(struct omap_display *display)
398+{
399+ return acx565akm_panel_enable(display);
400+}
401+
402+static void acx565akm_set_brightness(struct acx565akm_device *md, int level)
403+{
404+ int bv;
405+
406+ bv = level | (1 << 8);
407+ acx565akm_write(md, MIPID_CMD_WRITE_DISP_BRIGHTNESS, (u8 *)&bv, 2);
408+
409+ if (level)
410+ enable_backlight_ctrl(md, 1);
411+ else
412+ enable_backlight_ctrl(md, 0);
413+}
414+
415+static int acx565akm_get_actual_brightness(struct acx565akm_device *md)
416+{
417+ u8 bv;
418+
419+ acx565akm_read(md, MIPID_CMD_READ_DISP_BRIGHTNESS, &bv, 1);
420+
421+ return bv;
422+}
423+
424+static int acx565akm_bl_update_status(struct backlight_device *dev)
425+{
426+ struct acx565akm_device *md = dev_get_drvdata(&dev->dev);
427+ struct omap_display *display = md->display;
428+ int r;
429+ int level;
430+
431+ dev_dbg(&md->spi->dev, "%s\n", __func__);
432+
433+ if (display->hw_config.set_backlight == NULL)
434+ return -ENODEV;
435+
436+ mutex_lock(&md->mutex);
437+
438+ if (dev->props.fb_blank == FB_BLANK_UNBLANK &&
439+ dev->props.power == FB_BLANK_UNBLANK)
440+ level = dev->props.brightness;
441+ else
442+ level = 0;
443+
444+ r = 0;
445+ if (md->has_bc)
446+ acx565akm_set_brightness(md, level);
447+ else
448+ if (display->hw_config.set_backlight != NULL)
449+ r = display->hw_config.set_backlight(display, level);
450+ else
451+ r = -ENODEV;
452+
453+ mutex_unlock(&md->mutex);
454+
455+ return r;
456+}
457+
458+static int acx565akm_bl_get_intensity(struct backlight_device *dev)
459+{
460+ struct acx565akm_device *md = dev_get_drvdata(&dev->dev);
461+ struct omap_display *display = md->display;
462+
463+ dev_dbg(&dev->dev, "%s\n", __func__);
464+
465+ if (md->has_bc && display->hw_config.set_backlight == NULL)
466+ return -ENODEV;
467+
468+ if (dev->props.fb_blank == FB_BLANK_UNBLANK &&
469+ dev->props.power == FB_BLANK_UNBLANK) {
470+ if (md->has_bc)
471+ return acx565akm_get_actual_brightness(md);
472+ else
473+ return dev->props.brightness;
474+ }
475+
476+ return 0;
477+}
478+
479+static struct backlight_ops acx565akm_bl_ops = {
480+ .get_brightness = acx565akm_bl_get_intensity,
481+ .update_status = acx565akm_bl_update_status,
482+};
483+
484+static const char *cabc_modes[] = {
485+ "off", /* used also always when CABC is not supported */
486+ "ui",
487+ "still-image",
488+ "moving-image",
489+};
490+
491+static ssize_t show_cabc_mode(struct device *dev,
492+ struct device_attribute *attr,
493+ char *buf)
494+{
495+ struct acx565akm_device *md = dev_get_drvdata(dev);
496+ const char *mode_str;
497+ int mode;
498+ int len;
499+
500+ if (!md->has_cabc)
501+ mode = 0;
502+ else
503+ mode = get_cabc_mode(md);
504+ mode_str = "unknown";
505+ if (mode >= 0 && mode < ARRAY_SIZE(cabc_modes))
506+ mode_str = cabc_modes[mode];
507+ len = snprintf(buf, PAGE_SIZE, "%s\n", mode_str);
508+
509+ return len < PAGE_SIZE - 1 ? len : PAGE_SIZE - 1;
510+}
511+
512+static ssize_t store_cabc_mode(struct device *dev,
513+ struct device_attribute *attr,
514+ const char *buf, size_t count)
515+{
516+ struct acx565akm_device *md = dev_get_drvdata(dev);
517+ int i;
518+
519+ for (i = 0; i < ARRAY_SIZE(cabc_modes); i++) {
520+ const char *mode_str = cabc_modes[i];
521+ int cmp_len = strlen(mode_str);
522+
523+ if (count > 0 && buf[count - 1] == '\n')
524+ count--;
525+ if (count != cmp_len)
526+ continue;
527+
528+ if (strncmp(buf, mode_str, cmp_len) == 0)
529+ break;
530+ }
531+
532+ if (i == ARRAY_SIZE(cabc_modes))
533+ return -EINVAL;
534+
535+ if (!md->has_cabc && i != 0)
536+ return -EINVAL;
537+
538+ mutex_lock(&md->mutex);
539+ set_cabc_mode(md, i);
540+ mutex_unlock(&md->mutex);
541+
542+ return count;
543+}
544+
545+static ssize_t show_cabc_available_modes(struct device *dev,
546+ struct device_attribute *attr,
547+ char *buf)
548+{
549+ struct acx565akm_device *md = dev_get_drvdata(dev);
550+ int len;
551+ int i;
552+
553+ if (!md->has_cabc)
554+ return snprintf(buf, PAGE_SIZE, "%s\n", cabc_modes[0]);
555+
556+ for (i = 0, len = 0;
557+ len < PAGE_SIZE && i < ARRAY_SIZE(cabc_modes); i++)
558+ len += snprintf(&buf[len], PAGE_SIZE - len, "%s%s%s",
559+ i ? " " : "", cabc_modes[i],
560+ i == ARRAY_SIZE(cabc_modes) - 1 ? "\n" : "");
561+
562+ return len < PAGE_SIZE ? len : PAGE_SIZE - 1;
563+}
564+
565+static DEVICE_ATTR(cabc_mode, S_IRUGO | S_IWUSR,
566+ show_cabc_mode, store_cabc_mode);
567+static DEVICE_ATTR(cabc_available_modes, S_IRUGO,
568+ show_cabc_available_modes, NULL);
569+
570+static struct attribute *bldev_attrs[] = {
571+ &dev_attr_cabc_mode.attr,
572+ &dev_attr_cabc_available_modes.attr,
573+ NULL,
574+};
575+
576+static struct attribute_group bldev_attr_group = {
577+ .attrs = bldev_attrs,
578+};
579+
580+static int acx565akm_panel_init(struct omap_display *display)
581+{
582+ struct omap_panel *panel = display->panel;
583+ struct acx565akm_panel_data *panel_data = display->hw_config.panel_data;
584+ struct acx565akm_device *md = (struct acx565akm_device *)panel->priv;
585+
586+ struct backlight_device *bldev;
587+ int brightness;
588+ int max_brightness;
589+ int r;
590+
591+ dev_dbg(&md->spi->dev, "%s\n", __func__);
592+
593+ if (!panel_data) {
594+ dev_err(&md->spi->dev, "no panel data\n");
595+ return -ENODEV;
596+ }
597+
598+ mutex_init(&md->mutex);
599+ md->display = display;
600+
601+ if (display->hw_config.panel_enable)
602+ display->hw_config.panel_enable(display);
603+
604+ md->enabled = panel_enabled(md);
605+
606+ r = panel_detect(md);
607+ if (r) {
608+ if (!md->enabled && display->hw_config.panel_disable)
609+ display->hw_config.panel_disable(display);
610+ mutex_unlock(&md->mutex);
611+ return r;
612+ }
613+
614+ if (!panel_data->bc_connected) {
615+ md->has_bc = 0;
616+ md->has_cabc = 0;
617+ }
618+
619+#if 0
620+ acx565akm_set_mode(display, panel->timings.x_res, panel->timings.y_res,
621+ panel->bpp);
622+#endif
623+
624+ if (!md->enabled)
625+ display->hw_config.panel_disable(display);
626+
627+ bldev = backlight_device_register("acx565akm", &md->spi->dev,
628+ md, &acx565akm_bl_ops);
629+ md->bl_dev = bldev;
630+
631+ if (md->has_cabc) {
632+ r = sysfs_create_group(&bldev->dev.kobj, &bldev_attr_group);
633+ if (r) {
634+ dev_err(&bldev->dev, "failed to create sysfs files\n");
635+ backlight_device_unregister(bldev);
636+ return r;
637+ }
638+ }
639+
640+ bldev->props.fb_blank = FB_BLANK_UNBLANK;
641+ bldev->props.power = FB_BLANK_UNBLANK;
642+
643+ if (md->has_bc)
644+ max_brightness = 255;
645+ else
646+ max_brightness = display->hw_config.max_backlight_level;
647+
648+ if (md->has_bc)
649+ brightness = acx565akm_get_actual_brightness(md);
650+ else {
651+ if (display->hw_config.get_backlight != NULL)
652+ brightness = display->hw_config.get_backlight(display);
653+ else
654+ brightness = 0;
655+ }
656+
657+ bldev->props.max_brightness = max_brightness;
658+ bldev->props.brightness = brightness;
659+ acx565akm_bl_update_status(bldev);
660+
661+ return 0;
662+}
663+
664+static struct omap_panel acx565akm_panel = {
665+ .name = "panel-acx565akm",
666+ .init = acx565akm_panel_init,
667+ .suspend = acx565akm_panel_suspend,
668+ .resume = acx565akm_panel_resume,
669+ .enable = acx565akm_panel_enable,
670+ .disable = acx565akm_panel_disable,
671+
672+ .timings = {
673+ .x_res = 800,
674+ .y_res = 480,
675+
676+ .pixel_clock = 24000,
677+
678+ .hsw = 4,
679+ .hfp = 16,
680+ .hbp = 12,
681+
682+ .vsw = 3,
683+ .vfp = 3,
684+ .vbp = 3,
685+ },
686+
687+ .config = OMAP_DSS_LCD_TFT,
688+
689+ .recommended_bpp = 16,
690+
691+ /*
692+ * supported modes: 12bpp(444), 16bpp(565), 18bpp(666), 24bpp(888)
693+ * resolutions.
694+ */
695+};
696+
697+static int acx565akm_spi_probe(struct spi_device *spi)
698+{
699+ struct acx565akm_device *md;
700+
701+ dev_dbg(&md->spi->dev, "%s\n", __func__);
702+
703+ md = kzalloc(sizeof(*md), GFP_KERNEL);
704+ if (md == NULL) {
705+ dev_err(&spi->dev, "out of memory\n");
706+ return -ENOMEM;
707+ }
708+
709+ spi->mode = SPI_MODE_3;
710+ md->spi = spi;
711+ dev_set_drvdata(&spi->dev, md);
712+ md->panel = acx565akm_panel;
713+ acx565akm_panel.priv = md;
714+
715+ omap_dss_register_panel(&acx565akm_panel);
716+
717+ return 0;
718+}
719+
720+static int acx565akm_spi_remove(struct spi_device *spi)
721+{
722+ struct acx565akm_device *md = dev_get_drvdata(&spi->dev);
723+
724+ dev_dbg(&md->spi->dev, "%s\n", __func__);
725+
726+ sysfs_remove_group(&md->bl_dev->dev.kobj, &bldev_attr_group);
727+ backlight_device_unregister(md->bl_dev);
728+ omap_dss_unregister_panel(&acx565akm_panel);
729+
730+ kfree(md);
731+
732+ return 0;
733+}
734+
735+static struct spi_driver acx565akm_spi_driver = {
736+ .driver = {
737+ .name = "acx565akm",
738+ .bus = &spi_bus_type,
739+ .owner = THIS_MODULE,
740+ },
741+ .probe = acx565akm_spi_probe,
742+ .remove = __devexit_p(acx565akm_spi_remove),
743+};
744+
745+static int __init acx565akm_init(void)
746+{
747+ return spi_register_driver(&acx565akm_spi_driver);
748+}
749+
750+static void __exit acx565akm_exit(void)
751+{
752+ spi_unregister_driver(&acx565akm_spi_driver);
753+}
754+
755+module_init(acx565akm_init);
756+module_exit(acx565akm_exit);
757+
758+MODULE_AUTHOR("Tomi Valkeinen <tomi.valkeinen@nokia.com>");
759+MODULE_DESCRIPTION("acx565akm LCD Driver");
760+MODULE_LICENSE("GPL");
761diff --git a/drivers/video/omap2/displays/panel-acx565akm.h b/drivers/video/omap2/displays/panel-acx565akm.h
762new file mode 100644
763index 0000000..6d3727b
764--- /dev/null
765+++ b/drivers/video/omap2/displays/panel-acx565akm.h
766@@ -0,0 +1,9 @@
767+#ifndef __DRIVERS_VIDEO_OMAP2_DISPLAYS_PANEL_ACX565AKM_H
768+#define __DRIVERS_VIDEO_OMAP2_DISPLAYS_PANEL_ACX565AKM_H
769+
770+struct acx565akm_panel_data {
771+ unsigned bc_connected:1;
772+};
773+
774+#endif
775+
776--
7771.5.6.5
778