]> asedeno.scripts.mit.edu Git - linux.git/blob - drivers/gpu/drm/omapdrm/displays/panel-sony-acx565akm.c
drm/omap: Merge omap_dss_device type and output_type fields
[linux.git] / drivers / gpu / drm / omapdrm / displays / panel-sony-acx565akm.c
1 /*
2  * Sony ACX565AKM LCD Panel driver
3  *
4  * Copyright (C) 2010 Nokia Corporation
5  *
6  * Original Driver Author: Imre Deak <imre.deak@nokia.com>
7  * Based on panel-generic.c by Tomi Valkeinen <tomi.valkeinen@ti.com>
8  * Adapted to new DSS2 framework: Roger Quadros <roger.quadros@nokia.com>
9  *
10  * This program is free software; you can redistribute it and/or modify it
11  * under the terms of the GNU General Public License version 2 as published by
12  * the Free Software Foundation.
13  *
14  * This program is distributed in the hope that it will be useful, but WITHOUT
15  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
17  * more details.
18  *
19  * You should have received a copy of the GNU General Public License along with
20  * this program.  If not, see <http://www.gnu.org/licenses/>.
21  */
22
23 #include <linux/backlight.h>
24 #include <linux/delay.h>
25 #include <linux/gpio/consumer.h>
26 #include <linux/jiffies.h>
27 #include <linux/kernel.h>
28 #include <linux/module.h>
29 #include <linux/platform_device.h>
30 #include <linux/sched.h>
31 #include <linux/spi/spi.h>
32
33 #include "../dss/omapdss.h"
34
35 #define MIPID_CMD_READ_DISP_ID          0x04
36 #define MIPID_CMD_READ_RED              0x06
37 #define MIPID_CMD_READ_GREEN            0x07
38 #define MIPID_CMD_READ_BLUE             0x08
39 #define MIPID_CMD_READ_DISP_STATUS      0x09
40 #define MIPID_CMD_RDDSDR                0x0F
41 #define MIPID_CMD_SLEEP_IN              0x10
42 #define MIPID_CMD_SLEEP_OUT             0x11
43 #define MIPID_CMD_DISP_OFF              0x28
44 #define MIPID_CMD_DISP_ON               0x29
45 #define MIPID_CMD_WRITE_DISP_BRIGHTNESS 0x51
46 #define MIPID_CMD_READ_DISP_BRIGHTNESS  0x52
47 #define MIPID_CMD_WRITE_CTRL_DISP       0x53
48
49 #define CTRL_DISP_BRIGHTNESS_CTRL_ON    (1 << 5)
50 #define CTRL_DISP_AMBIENT_LIGHT_CTRL_ON (1 << 4)
51 #define CTRL_DISP_BACKLIGHT_ON          (1 << 2)
52 #define CTRL_DISP_AUTO_BRIGHTNESS_ON    (1 << 1)
53
54 #define MIPID_CMD_READ_CTRL_DISP        0x54
55 #define MIPID_CMD_WRITE_CABC            0x55
56 #define MIPID_CMD_READ_CABC             0x56
57
58 #define MIPID_VER_LPH8923               3
59 #define MIPID_VER_LS041Y3               4
60 #define MIPID_VER_L4F00311              8
61 #define MIPID_VER_ACX565AKM             9
62
63 struct panel_drv_data {
64         struct omap_dss_device  dssdev;
65
66         struct gpio_desc *reset_gpio;
67
68         struct videomode vm;
69
70         char            *name;
71         int             enabled;
72         int             model;
73         int             revision;
74         u8              display_id[3];
75         unsigned        has_bc:1;
76         unsigned        has_cabc:1;
77         unsigned        cabc_mode;
78         unsigned long   hw_guard_end;           /* next value of jiffies
79                                                    when we can issue the
80                                                    next sleep in/out command */
81         unsigned long   hw_guard_wait;          /* max guard time in jiffies */
82
83         struct spi_device       *spi;
84         struct mutex            mutex;
85
86         struct backlight_device *bl_dev;
87 };
88
89 static const struct videomode acx565akm_panel_vm = {
90         .hactive        = 800,
91         .vactive        = 480,
92         .pixelclock     = 24000000,
93         .hfront_porch   = 28,
94         .hsync_len      = 4,
95         .hback_porch    = 24,
96         .vfront_porch   = 3,
97         .vsync_len      = 3,
98         .vback_porch    = 4,
99
100         .flags          = DISPLAY_FLAGS_HSYNC_LOW | DISPLAY_FLAGS_VSYNC_LOW,
101 };
102
103 #define to_panel_data(p) container_of(p, struct panel_drv_data, dssdev)
104
105 static void acx565akm_transfer(struct panel_drv_data *ddata, int cmd,
106                               const u8 *wbuf, int wlen, u8 *rbuf, int rlen)
107 {
108         struct spi_message      m;
109         struct spi_transfer     *x, xfer[5];
110         int                     r;
111
112         BUG_ON(ddata->spi == NULL);
113
114         spi_message_init(&m);
115
116         memset(xfer, 0, sizeof(xfer));
117         x = &xfer[0];
118
119         cmd &=  0xff;
120         x->tx_buf = &cmd;
121         x->bits_per_word = 9;
122         x->len = 2;
123
124         if (rlen > 1 && wlen == 0) {
125                 /*
126                  * Between the command and the response data there is a
127                  * dummy clock cycle. Add an extra bit after the command
128                  * word to account for this.
129                  */
130                 x->bits_per_word = 10;
131                 cmd <<= 1;
132         }
133         spi_message_add_tail(x, &m);
134
135         if (wlen) {
136                 x++;
137                 x->tx_buf = wbuf;
138                 x->len = wlen;
139                 x->bits_per_word = 9;
140                 spi_message_add_tail(x, &m);
141         }
142
143         if (rlen) {
144                 x++;
145                 x->rx_buf       = rbuf;
146                 x->len          = rlen;
147                 spi_message_add_tail(x, &m);
148         }
149
150         r = spi_sync(ddata->spi, &m);
151         if (r < 0)
152                 dev_dbg(&ddata->spi->dev, "spi_sync %d\n", r);
153 }
154
155 static inline void acx565akm_cmd(struct panel_drv_data *ddata, int cmd)
156 {
157         acx565akm_transfer(ddata, cmd, NULL, 0, NULL, 0);
158 }
159
160 static inline void acx565akm_write(struct panel_drv_data *ddata,
161                                int reg, const u8 *buf, int len)
162 {
163         acx565akm_transfer(ddata, reg, buf, len, NULL, 0);
164 }
165
166 static inline void acx565akm_read(struct panel_drv_data *ddata,
167                               int reg, u8 *buf, int len)
168 {
169         acx565akm_transfer(ddata, reg, NULL, 0, buf, len);
170 }
171
172 static void hw_guard_start(struct panel_drv_data *ddata, int guard_msec)
173 {
174         ddata->hw_guard_wait = msecs_to_jiffies(guard_msec);
175         ddata->hw_guard_end = jiffies + ddata->hw_guard_wait;
176 }
177
178 static void hw_guard_wait(struct panel_drv_data *ddata)
179 {
180         unsigned long wait = ddata->hw_guard_end - jiffies;
181
182         if ((long)wait > 0 && wait <= ddata->hw_guard_wait) {
183                 set_current_state(TASK_UNINTERRUPTIBLE);
184                 schedule_timeout(wait);
185         }
186 }
187
188 static void set_sleep_mode(struct panel_drv_data *ddata, int on)
189 {
190         int cmd;
191
192         if (on)
193                 cmd = MIPID_CMD_SLEEP_IN;
194         else
195                 cmd = MIPID_CMD_SLEEP_OUT;
196         /*
197          * We have to keep 120msec between sleep in/out commands.
198          * (8.2.15, 8.2.16).
199          */
200         hw_guard_wait(ddata);
201         acx565akm_cmd(ddata, cmd);
202         hw_guard_start(ddata, 120);
203 }
204
205 static void set_display_state(struct panel_drv_data *ddata, int enabled)
206 {
207         int cmd = enabled ? MIPID_CMD_DISP_ON : MIPID_CMD_DISP_OFF;
208
209         acx565akm_cmd(ddata, cmd);
210 }
211
212 static int panel_enabled(struct panel_drv_data *ddata)
213 {
214         __be32 v;
215         u32 disp_status;
216         int enabled;
217
218         acx565akm_read(ddata, MIPID_CMD_READ_DISP_STATUS, (u8 *)&v, 4);
219         disp_status = __be32_to_cpu(v);
220         enabled = (disp_status & (1 << 17)) && (disp_status & (1 << 10));
221         dev_dbg(&ddata->spi->dev,
222                 "LCD panel %senabled by bootloader (status 0x%04x)\n",
223                 enabled ? "" : "not ", disp_status);
224         return enabled;
225 }
226
227 static int panel_detect(struct panel_drv_data *ddata)
228 {
229         acx565akm_read(ddata, MIPID_CMD_READ_DISP_ID, ddata->display_id, 3);
230         dev_dbg(&ddata->spi->dev, "MIPI display ID: %02x%02x%02x\n",
231                 ddata->display_id[0],
232                 ddata->display_id[1],
233                 ddata->display_id[2]);
234
235         switch (ddata->display_id[0]) {
236         case 0x10:
237                 ddata->model = MIPID_VER_ACX565AKM;
238                 ddata->name = "acx565akm";
239                 ddata->has_bc = 1;
240                 ddata->has_cabc = 1;
241                 break;
242         case 0x29:
243                 ddata->model = MIPID_VER_L4F00311;
244                 ddata->name = "l4f00311";
245                 break;
246         case 0x45:
247                 ddata->model = MIPID_VER_LPH8923;
248                 ddata->name = "lph8923";
249                 break;
250         case 0x83:
251                 ddata->model = MIPID_VER_LS041Y3;
252                 ddata->name = "ls041y3";
253                 break;
254         default:
255                 ddata->name = "unknown";
256                 dev_err(&ddata->spi->dev, "invalid display ID\n");
257                 return -ENODEV;
258         }
259
260         ddata->revision = ddata->display_id[1];
261
262         dev_info(&ddata->spi->dev, "omapfb: %s rev %02x LCD detected\n",
263                         ddata->name, ddata->revision);
264
265         return 0;
266 }
267
268 /*----------------------Backlight Control-------------------------*/
269
270 static void enable_backlight_ctrl(struct panel_drv_data *ddata, int enable)
271 {
272         u16 ctrl;
273
274         acx565akm_read(ddata, MIPID_CMD_READ_CTRL_DISP, (u8 *)&ctrl, 1);
275         if (enable) {
276                 ctrl |= CTRL_DISP_BRIGHTNESS_CTRL_ON |
277                         CTRL_DISP_BACKLIGHT_ON;
278         } else {
279                 ctrl &= ~(CTRL_DISP_BRIGHTNESS_CTRL_ON |
280                           CTRL_DISP_BACKLIGHT_ON);
281         }
282
283         ctrl |= 1 << 8;
284         acx565akm_write(ddata, MIPID_CMD_WRITE_CTRL_DISP, (u8 *)&ctrl, 2);
285 }
286
287 static void set_cabc_mode(struct panel_drv_data *ddata, unsigned int mode)
288 {
289         u16 cabc_ctrl;
290
291         ddata->cabc_mode = mode;
292         if (!ddata->enabled)
293                 return;
294         cabc_ctrl = 0;
295         acx565akm_read(ddata, MIPID_CMD_READ_CABC, (u8 *)&cabc_ctrl, 1);
296         cabc_ctrl &= ~3;
297         cabc_ctrl |= (1 << 8) | (mode & 3);
298         acx565akm_write(ddata, MIPID_CMD_WRITE_CABC, (u8 *)&cabc_ctrl, 2);
299 }
300
301 static unsigned int get_cabc_mode(struct panel_drv_data *ddata)
302 {
303         return ddata->cabc_mode;
304 }
305
306 static unsigned int get_hw_cabc_mode(struct panel_drv_data *ddata)
307 {
308         u8 cabc_ctrl;
309
310         acx565akm_read(ddata, MIPID_CMD_READ_CABC, &cabc_ctrl, 1);
311         return cabc_ctrl & 3;
312 }
313
314 static void acx565akm_set_brightness(struct panel_drv_data *ddata, int level)
315 {
316         int bv;
317
318         bv = level | (1 << 8);
319         acx565akm_write(ddata, MIPID_CMD_WRITE_DISP_BRIGHTNESS, (u8 *)&bv, 2);
320
321         if (level)
322                 enable_backlight_ctrl(ddata, 1);
323         else
324                 enable_backlight_ctrl(ddata, 0);
325 }
326
327 static int acx565akm_get_actual_brightness(struct panel_drv_data *ddata)
328 {
329         u8 bv;
330
331         acx565akm_read(ddata, MIPID_CMD_READ_DISP_BRIGHTNESS, &bv, 1);
332
333         return bv;
334 }
335
336
337 static int acx565akm_bl_update_status(struct backlight_device *dev)
338 {
339         struct panel_drv_data *ddata = dev_get_drvdata(&dev->dev);
340         int level;
341
342         dev_dbg(&ddata->spi->dev, "%s\n", __func__);
343
344         if (dev->props.fb_blank == FB_BLANK_UNBLANK &&
345                         dev->props.power == FB_BLANK_UNBLANK)
346                 level = dev->props.brightness;
347         else
348                 level = 0;
349
350         if (ddata->has_bc)
351                 acx565akm_set_brightness(ddata, level);
352         else
353                 return -ENODEV;
354
355         return 0;
356 }
357
358 static int acx565akm_bl_get_intensity(struct backlight_device *dev)
359 {
360         struct panel_drv_data *ddata = dev_get_drvdata(&dev->dev);
361
362         dev_dbg(&dev->dev, "%s\n", __func__);
363
364         if (!ddata->has_bc)
365                 return -ENODEV;
366
367         if (dev->props.fb_blank == FB_BLANK_UNBLANK &&
368                         dev->props.power == FB_BLANK_UNBLANK) {
369                 if (ddata->has_bc)
370                         return acx565akm_get_actual_brightness(ddata);
371                 else
372                         return dev->props.brightness;
373         }
374
375         return 0;
376 }
377
378 static int acx565akm_bl_update_status_locked(struct backlight_device *dev)
379 {
380         struct panel_drv_data *ddata = dev_get_drvdata(&dev->dev);
381         int r;
382
383         mutex_lock(&ddata->mutex);
384         r = acx565akm_bl_update_status(dev);
385         mutex_unlock(&ddata->mutex);
386
387         return r;
388 }
389
390 static int acx565akm_bl_get_intensity_locked(struct backlight_device *dev)
391 {
392         struct panel_drv_data *ddata = dev_get_drvdata(&dev->dev);
393         int r;
394
395         mutex_lock(&ddata->mutex);
396         r = acx565akm_bl_get_intensity(dev);
397         mutex_unlock(&ddata->mutex);
398
399         return r;
400 }
401
402 static const struct backlight_ops acx565akm_bl_ops = {
403         .get_brightness = acx565akm_bl_get_intensity_locked,
404         .update_status  = acx565akm_bl_update_status_locked,
405 };
406
407 /*--------------------Auto Brightness control via Sysfs---------------------*/
408
409 static const char * const cabc_modes[] = {
410         "off",          /* always used when CABC is not supported */
411         "ui",
412         "still-image",
413         "moving-image",
414 };
415
416 static ssize_t show_cabc_mode(struct device *dev,
417                 struct device_attribute *attr,
418                 char *buf)
419 {
420         struct panel_drv_data *ddata = dev_get_drvdata(dev);
421         const char *mode_str;
422         int mode;
423         int len;
424
425         if (!ddata->has_cabc)
426                 mode = 0;
427         else
428                 mode = get_cabc_mode(ddata);
429         mode_str = "unknown";
430         if (mode >= 0 && mode < ARRAY_SIZE(cabc_modes))
431                 mode_str = cabc_modes[mode];
432         len = snprintf(buf, PAGE_SIZE, "%s\n", mode_str);
433
434         return len < PAGE_SIZE - 1 ? len : PAGE_SIZE - 1;
435 }
436
437 static ssize_t store_cabc_mode(struct device *dev,
438                 struct device_attribute *attr,
439                 const char *buf, size_t count)
440 {
441         struct panel_drv_data *ddata = dev_get_drvdata(dev);
442         int i;
443
444         for (i = 0; i < ARRAY_SIZE(cabc_modes); i++) {
445                 const char *mode_str = cabc_modes[i];
446                 int cmp_len = strlen(mode_str);
447
448                 if (count > 0 && buf[count - 1] == '\n')
449                         count--;
450                 if (count != cmp_len)
451                         continue;
452
453                 if (strncmp(buf, mode_str, cmp_len) == 0)
454                         break;
455         }
456
457         if (i == ARRAY_SIZE(cabc_modes))
458                 return -EINVAL;
459
460         if (!ddata->has_cabc && i != 0)
461                 return -EINVAL;
462
463         mutex_lock(&ddata->mutex);
464         set_cabc_mode(ddata, i);
465         mutex_unlock(&ddata->mutex);
466
467         return count;
468 }
469
470 static ssize_t show_cabc_available_modes(struct device *dev,
471                 struct device_attribute *attr,
472                 char *buf)
473 {
474         struct panel_drv_data *ddata = dev_get_drvdata(dev);
475         int len;
476         int i;
477
478         if (!ddata->has_cabc)
479                 return snprintf(buf, PAGE_SIZE, "%s\n", cabc_modes[0]);
480
481         for (i = 0, len = 0;
482              len < PAGE_SIZE && i < ARRAY_SIZE(cabc_modes); i++)
483                 len += snprintf(&buf[len], PAGE_SIZE - len, "%s%s%s",
484                         i ? " " : "", cabc_modes[i],
485                         i == ARRAY_SIZE(cabc_modes) - 1 ? "\n" : "");
486
487         return len < PAGE_SIZE ? len : PAGE_SIZE - 1;
488 }
489
490 static DEVICE_ATTR(cabc_mode, S_IRUGO | S_IWUSR,
491                 show_cabc_mode, store_cabc_mode);
492 static DEVICE_ATTR(cabc_available_modes, S_IRUGO,
493                 show_cabc_available_modes, NULL);
494
495 static struct attribute *bldev_attrs[] = {
496         &dev_attr_cabc_mode.attr,
497         &dev_attr_cabc_available_modes.attr,
498         NULL,
499 };
500
501 static const struct attribute_group bldev_attr_group = {
502         .attrs = bldev_attrs,
503 };
504
505 static int acx565akm_connect(struct omap_dss_device *src,
506                              struct omap_dss_device *dst)
507 {
508         return 0;
509 }
510
511 static void acx565akm_disconnect(struct omap_dss_device *src,
512                                  struct omap_dss_device *dst)
513 {
514 }
515
516 static int acx565akm_panel_power_on(struct omap_dss_device *dssdev)
517 {
518         struct panel_drv_data *ddata = to_panel_data(dssdev);
519
520         dev_dbg(&ddata->spi->dev, "%s\n", __func__);
521
522         /*FIXME tweak me */
523         msleep(50);
524
525         if (ddata->reset_gpio)
526                 gpiod_set_value(ddata->reset_gpio, 1);
527
528         if (ddata->enabled) {
529                 dev_dbg(&ddata->spi->dev, "panel already enabled\n");
530                 return 0;
531         }
532
533         /*
534          * We have to meet all the following delay requirements:
535          * 1. tRW: reset pulse width 10usec (7.12.1)
536          * 2. tRT: reset cancel time 5msec (7.12.1)
537          * 3. Providing PCLK,HS,VS signals for 2 frames = ~50msec worst
538          *    case (7.6.2)
539          * 4. 120msec before the sleep out command (7.12.1)
540          */
541         msleep(120);
542
543         set_sleep_mode(ddata, 0);
544         ddata->enabled = 1;
545
546         /* 5msec between sleep out and the next command. (8.2.16) */
547         usleep_range(5000, 10000);
548         set_display_state(ddata, 1);
549         set_cabc_mode(ddata, ddata->cabc_mode);
550
551         return acx565akm_bl_update_status(ddata->bl_dev);
552 }
553
554 static void acx565akm_panel_power_off(struct omap_dss_device *dssdev)
555 {
556         struct panel_drv_data *ddata = to_panel_data(dssdev);
557
558         dev_dbg(dssdev->dev, "%s\n", __func__);
559
560         if (!ddata->enabled)
561                 return;
562
563         set_display_state(ddata, 0);
564         set_sleep_mode(ddata, 1);
565         ddata->enabled = 0;
566         /*
567          * We have to provide PCLK,HS,VS signals for 2 frames (worst case
568          * ~50msec) after sending the sleep in command and asserting the
569          * reset signal. We probably could assert the reset w/o the delay
570          * but we still delay to avoid possible artifacts. (7.6.1)
571          */
572         msleep(50);
573
574         if (ddata->reset_gpio)
575                 gpiod_set_value(ddata->reset_gpio, 0);
576
577         /* FIXME need to tweak this delay */
578         msleep(100);
579 }
580
581 static void acx565akm_enable(struct omap_dss_device *dssdev)
582 {
583         struct panel_drv_data *ddata = to_panel_data(dssdev);
584
585         mutex_lock(&ddata->mutex);
586         acx565akm_panel_power_on(dssdev);
587         mutex_unlock(&ddata->mutex);
588 }
589
590 static void acx565akm_disable(struct omap_dss_device *dssdev)
591 {
592         struct panel_drv_data *ddata = to_panel_data(dssdev);
593
594         mutex_lock(&ddata->mutex);
595         acx565akm_panel_power_off(dssdev);
596         mutex_unlock(&ddata->mutex);
597 }
598
599 static int acx565akm_get_modes(struct omap_dss_device *dssdev,
600                                struct drm_connector *connector)
601 {
602         struct panel_drv_data *ddata = to_panel_data(dssdev);
603
604         return omapdss_display_get_modes(connector, &ddata->vm);
605 }
606
607 static const struct omap_dss_device_ops acx565akm_ops = {
608         .connect        = acx565akm_connect,
609         .disconnect     = acx565akm_disconnect,
610
611         .enable         = acx565akm_enable,
612         .disable        = acx565akm_disable,
613
614         .get_modes      = acx565akm_get_modes,
615 };
616
617 static int acx565akm_probe(struct spi_device *spi)
618 {
619         struct panel_drv_data *ddata;
620         struct omap_dss_device *dssdev;
621         struct backlight_device *bldev;
622         int max_brightness, brightness;
623         struct backlight_properties props;
624         struct gpio_desc *gpio;
625         int r;
626
627         dev_dbg(&spi->dev, "%s\n", __func__);
628
629         spi->mode = SPI_MODE_3;
630
631         ddata = devm_kzalloc(&spi->dev, sizeof(*ddata), GFP_KERNEL);
632         if (ddata == NULL)
633                 return -ENOMEM;
634
635         dev_set_drvdata(&spi->dev, ddata);
636
637         ddata->spi = spi;
638
639         mutex_init(&ddata->mutex);
640
641         gpio = devm_gpiod_get_optional(&spi->dev, "reset", GPIOD_OUT_LOW);
642         if (IS_ERR(gpio)) {
643                 dev_err(&spi->dev, "failed to parse reset gpio\n");
644                 return PTR_ERR(gpio);
645         }
646
647         ddata->reset_gpio = gpio;
648
649         if (ddata->reset_gpio)
650                 gpiod_set_value(ddata->reset_gpio, 1);
651
652         /*
653          * After reset we have to wait 5 msec before the first
654          * command can be sent.
655          */
656         usleep_range(5000, 10000);
657
658         ddata->enabled = panel_enabled(ddata);
659
660         r = panel_detect(ddata);
661
662         if (!ddata->enabled && ddata->reset_gpio)
663                 gpiod_set_value(ddata->reset_gpio, 0);
664
665         if (r) {
666                 dev_err(&spi->dev, "%s panel detect error\n", __func__);
667                 return r;
668         }
669
670         memset(&props, 0, sizeof(props));
671         props.fb_blank = FB_BLANK_UNBLANK;
672         props.power = FB_BLANK_UNBLANK;
673         props.type = BACKLIGHT_RAW;
674
675         bldev = backlight_device_register("acx565akm", &ddata->spi->dev,
676                         ddata, &acx565akm_bl_ops, &props);
677         if (IS_ERR(bldev))
678                 return PTR_ERR(bldev);
679         ddata->bl_dev = bldev;
680         if (ddata->has_cabc) {
681                 r = sysfs_create_group(&bldev->dev.kobj, &bldev_attr_group);
682                 if (r) {
683                         dev_err(&bldev->dev,
684                                 "%s failed to create sysfs files\n", __func__);
685                         goto err_backlight_unregister;
686                 }
687                 ddata->cabc_mode = get_hw_cabc_mode(ddata);
688         }
689
690         max_brightness = 255;
691
692         if (ddata->has_bc)
693                 brightness = acx565akm_get_actual_brightness(ddata);
694         else
695                 brightness = 0;
696
697         bldev->props.max_brightness = max_brightness;
698         bldev->props.brightness = brightness;
699
700         acx565akm_bl_update_status(bldev);
701
702
703         ddata->vm = acx565akm_panel_vm;
704
705         dssdev = &ddata->dssdev;
706         dssdev->dev = &spi->dev;
707         dssdev->ops = &acx565akm_ops;
708         dssdev->type = OMAP_DISPLAY_TYPE_SDI;
709         dssdev->display = true;
710         dssdev->owner = THIS_MODULE;
711         dssdev->of_ports = BIT(0);
712         dssdev->ops_flags = OMAP_DSS_DEVICE_OP_MODES;
713         dssdev->bus_flags = DRM_BUS_FLAG_DE_HIGH | DRM_BUS_FLAG_SYNC_NEGEDGE
714                           | DRM_BUS_FLAG_PIXDATA_POSEDGE;
715
716         omapdss_display_init(dssdev);
717         omapdss_device_register(dssdev);
718
719         return 0;
720
721 err_backlight_unregister:
722         backlight_device_unregister(bldev);
723         return r;
724 }
725
726 static int acx565akm_remove(struct spi_device *spi)
727 {
728         struct panel_drv_data *ddata = dev_get_drvdata(&spi->dev);
729         struct omap_dss_device *dssdev = &ddata->dssdev;
730
731         dev_dbg(&ddata->spi->dev, "%s\n", __func__);
732
733         sysfs_remove_group(&ddata->bl_dev->dev.kobj, &bldev_attr_group);
734         backlight_device_unregister(ddata->bl_dev);
735
736         omapdss_device_unregister(dssdev);
737
738         if (omapdss_device_is_enabled(dssdev))
739                 acx565akm_disable(dssdev);
740
741         return 0;
742 }
743
744 static const struct of_device_id acx565akm_of_match[] = {
745         { .compatible = "omapdss,sony,acx565akm", },
746         {},
747 };
748 MODULE_DEVICE_TABLE(of, acx565akm_of_match);
749
750 static struct spi_driver acx565akm_driver = {
751         .driver = {
752                 .name   = "acx565akm",
753                 .of_match_table = acx565akm_of_match,
754                 .suppress_bind_attrs = true,
755         },
756         .probe  = acx565akm_probe,
757         .remove = acx565akm_remove,
758 };
759
760 module_spi_driver(acx565akm_driver);
761
762 MODULE_ALIAS("spi:sony,acx565akm");
763 MODULE_AUTHOR("Nokia Corporation");
764 MODULE_DESCRIPTION("acx565akm LCD Driver");
765 MODULE_LICENSE("GPL");