Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * Sony ACX565AKM LCD Panel driver
0004  *
0005  * Copyright (C) 2010 Nokia Corporation
0006  *
0007  * Original Driver Author: Imre Deak <imre.deak@nokia.com>
0008  * Based on panel-generic.c by Tomi Valkeinen <tomi.valkeinen@nokia.com>
0009  * Adapted to new DSS2 framework: Roger Quadros <roger.quadros@nokia.com>
0010  */
0011 
0012 #include <linux/kernel.h>
0013 #include <linux/module.h>
0014 #include <linux/platform_device.h>
0015 #include <linux/delay.h>
0016 #include <linux/spi/spi.h>
0017 #include <linux/jiffies.h>
0018 #include <linux/sched.h>
0019 #include <linux/backlight.h>
0020 #include <linux/fb.h>
0021 #include <linux/gpio.h>
0022 #include <linux/of.h>
0023 #include <linux/of_gpio.h>
0024 
0025 #include <video/omapfb_dss.h>
0026 #include <video/omap-panel-data.h>
0027 
0028 #define MIPID_CMD_READ_DISP_ID      0x04
0029 #define MIPID_CMD_READ_RED      0x06
0030 #define MIPID_CMD_READ_GREEN        0x07
0031 #define MIPID_CMD_READ_BLUE     0x08
0032 #define MIPID_CMD_READ_DISP_STATUS  0x09
0033 #define MIPID_CMD_RDDSDR        0x0F
0034 #define MIPID_CMD_SLEEP_IN      0x10
0035 #define MIPID_CMD_SLEEP_OUT     0x11
0036 #define MIPID_CMD_DISP_OFF      0x28
0037 #define MIPID_CMD_DISP_ON       0x29
0038 #define MIPID_CMD_WRITE_DISP_BRIGHTNESS 0x51
0039 #define MIPID_CMD_READ_DISP_BRIGHTNESS  0x52
0040 #define MIPID_CMD_WRITE_CTRL_DISP   0x53
0041 
0042 #define CTRL_DISP_BRIGHTNESS_CTRL_ON    (1 << 5)
0043 #define CTRL_DISP_AMBIENT_LIGHT_CTRL_ON (1 << 4)
0044 #define CTRL_DISP_BACKLIGHT_ON      (1 << 2)
0045 #define CTRL_DISP_AUTO_BRIGHTNESS_ON    (1 << 1)
0046 
0047 #define MIPID_CMD_READ_CTRL_DISP    0x54
0048 #define MIPID_CMD_WRITE_CABC        0x55
0049 #define MIPID_CMD_READ_CABC     0x56
0050 
0051 #define MIPID_VER_LPH8923       3
0052 #define MIPID_VER_LS041Y3       4
0053 #define MIPID_VER_L4F00311      8
0054 #define MIPID_VER_ACX565AKM     9
0055 
0056 struct panel_drv_data {
0057     struct omap_dss_device  dssdev;
0058     struct omap_dss_device *in;
0059 
0060     int reset_gpio;
0061     int datapairs;
0062 
0063     struct omap_video_timings videomode;
0064 
0065     char        *name;
0066     int     enabled;
0067     int     model;
0068     int     revision;
0069     u8      display_id[3];
0070     unsigned    has_bc:1;
0071     unsigned    has_cabc:1;
0072     unsigned    cabc_mode;
0073     unsigned long   hw_guard_end;       /* next value of jiffies
0074                            when we can issue the
0075                            next sleep in/out command */
0076     unsigned long   hw_guard_wait;      /* max guard time in jiffies */
0077 
0078     struct spi_device   *spi;
0079     struct mutex        mutex;
0080 
0081     struct backlight_device *bl_dev;
0082 };
0083 
0084 static const struct omap_video_timings acx565akm_panel_timings = {
0085     .x_res      = 800,
0086     .y_res      = 480,
0087     .pixelclock = 24000000,
0088     .hfp        = 28,
0089     .hsw        = 4,
0090     .hbp        = 24,
0091     .vfp        = 3,
0092     .vsw        = 3,
0093     .vbp        = 4,
0094 
0095     .vsync_level    = OMAPDSS_SIG_ACTIVE_LOW,
0096     .hsync_level    = OMAPDSS_SIG_ACTIVE_LOW,
0097 
0098     .data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE,
0099     .de_level   = OMAPDSS_SIG_ACTIVE_HIGH,
0100     .sync_pclk_edge = OMAPDSS_DRIVE_SIG_FALLING_EDGE,
0101 };
0102 
0103 #define to_panel_data(p) container_of(p, struct panel_drv_data, dssdev)
0104 
0105 static void acx565akm_transfer(struct panel_drv_data *ddata, int cmd,
0106                   const u8 *wbuf, int wlen, u8 *rbuf, int rlen)
0107 {
0108     struct spi_message  m;
0109     struct spi_transfer *x, xfer[5];
0110     int         r;
0111 
0112     BUG_ON(ddata->spi == NULL);
0113 
0114     spi_message_init(&m);
0115 
0116     memset(xfer, 0, sizeof(xfer));
0117     x = &xfer[0];
0118 
0119     cmd &=  0xff;
0120     x->tx_buf = &cmd;
0121     x->bits_per_word = 9;
0122     x->len = 2;
0123 
0124     if (rlen > 1 && wlen == 0) {
0125         /*
0126          * Between the command and the response data there is a
0127          * dummy clock cycle. Add an extra bit after the command
0128          * word to account for this.
0129          */
0130         x->bits_per_word = 10;
0131         cmd <<= 1;
0132     }
0133     spi_message_add_tail(x, &m);
0134 
0135     if (wlen) {
0136         x++;
0137         x->tx_buf = wbuf;
0138         x->len = wlen;
0139         x->bits_per_word = 9;
0140         spi_message_add_tail(x, &m);
0141     }
0142 
0143     if (rlen) {
0144         x++;
0145         x->rx_buf   = rbuf;
0146         x->len      = rlen;
0147         spi_message_add_tail(x, &m);
0148     }
0149 
0150     r = spi_sync(ddata->spi, &m);
0151     if (r < 0)
0152         dev_dbg(&ddata->spi->dev, "spi_sync %d\n", r);
0153 }
0154 
0155 static inline void acx565akm_cmd(struct panel_drv_data *ddata, int cmd)
0156 {
0157     acx565akm_transfer(ddata, cmd, NULL, 0, NULL, 0);
0158 }
0159 
0160 static inline void acx565akm_write(struct panel_drv_data *ddata,
0161                    int reg, const u8 *buf, int len)
0162 {
0163     acx565akm_transfer(ddata, reg, buf, len, NULL, 0);
0164 }
0165 
0166 static inline void acx565akm_read(struct panel_drv_data *ddata,
0167                   int reg, u8 *buf, int len)
0168 {
0169     acx565akm_transfer(ddata, reg, NULL, 0, buf, len);
0170 }
0171 
0172 static void hw_guard_start(struct panel_drv_data *ddata, int guard_msec)
0173 {
0174     ddata->hw_guard_wait = msecs_to_jiffies(guard_msec);
0175     ddata->hw_guard_end = jiffies + ddata->hw_guard_wait;
0176 }
0177 
0178 static void hw_guard_wait(struct panel_drv_data *ddata)
0179 {
0180     unsigned long wait = ddata->hw_guard_end - jiffies;
0181 
0182     if ((long)wait > 0 && wait <= ddata->hw_guard_wait) {
0183         set_current_state(TASK_UNINTERRUPTIBLE);
0184         schedule_timeout(wait);
0185     }
0186 }
0187 
0188 static void set_sleep_mode(struct panel_drv_data *ddata, int on)
0189 {
0190     int cmd;
0191 
0192     if (on)
0193         cmd = MIPID_CMD_SLEEP_IN;
0194     else
0195         cmd = MIPID_CMD_SLEEP_OUT;
0196     /*
0197      * We have to keep 120msec between sleep in/out commands.
0198      * (8.2.15, 8.2.16).
0199      */
0200     hw_guard_wait(ddata);
0201     acx565akm_cmd(ddata, cmd);
0202     hw_guard_start(ddata, 120);
0203 }
0204 
0205 static void set_display_state(struct panel_drv_data *ddata, int enabled)
0206 {
0207     int cmd = enabled ? MIPID_CMD_DISP_ON : MIPID_CMD_DISP_OFF;
0208 
0209     acx565akm_cmd(ddata, cmd);
0210 }
0211 
0212 static int panel_enabled(struct panel_drv_data *ddata)
0213 {
0214     u32 disp_status;
0215     int enabled;
0216 
0217     acx565akm_read(ddata, MIPID_CMD_READ_DISP_STATUS,
0218             (u8 *)&disp_status, 4);
0219     disp_status = __be32_to_cpu(disp_status);
0220     enabled = (disp_status & (1 << 17)) && (disp_status & (1 << 10));
0221     dev_dbg(&ddata->spi->dev,
0222         "LCD panel %senabled by bootloader (status 0x%04x)\n",
0223         enabled ? "" : "not ", disp_status);
0224     return enabled;
0225 }
0226 
0227 static int panel_detect(struct panel_drv_data *ddata)
0228 {
0229     acx565akm_read(ddata, MIPID_CMD_READ_DISP_ID, ddata->display_id, 3);
0230     dev_dbg(&ddata->spi->dev, "MIPI display ID: %02x%02x%02x\n",
0231         ddata->display_id[0],
0232         ddata->display_id[1],
0233         ddata->display_id[2]);
0234 
0235     switch (ddata->display_id[0]) {
0236     case 0x10:
0237         ddata->model = MIPID_VER_ACX565AKM;
0238         ddata->name = "acx565akm";
0239         ddata->has_bc = 1;
0240         ddata->has_cabc = 1;
0241         break;
0242     case 0x29:
0243         ddata->model = MIPID_VER_L4F00311;
0244         ddata->name = "l4f00311";
0245         break;
0246     case 0x45:
0247         ddata->model = MIPID_VER_LPH8923;
0248         ddata->name = "lph8923";
0249         break;
0250     case 0x83:
0251         ddata->model = MIPID_VER_LS041Y3;
0252         ddata->name = "ls041y3";
0253         break;
0254     default:
0255         ddata->name = "unknown";
0256         dev_err(&ddata->spi->dev, "invalid display ID\n");
0257         return -ENODEV;
0258     }
0259 
0260     ddata->revision = ddata->display_id[1];
0261 
0262     dev_info(&ddata->spi->dev, "omapfb: %s rev %02x LCD detected\n",
0263             ddata->name, ddata->revision);
0264 
0265     return 0;
0266 }
0267 
0268 /*----------------------Backlight Control-------------------------*/
0269 
0270 static void enable_backlight_ctrl(struct panel_drv_data *ddata, int enable)
0271 {
0272     u16 ctrl;
0273 
0274     acx565akm_read(ddata, MIPID_CMD_READ_CTRL_DISP, (u8 *)&ctrl, 1);
0275     if (enable) {
0276         ctrl |= CTRL_DISP_BRIGHTNESS_CTRL_ON |
0277             CTRL_DISP_BACKLIGHT_ON;
0278     } else {
0279         ctrl &= ~(CTRL_DISP_BRIGHTNESS_CTRL_ON |
0280               CTRL_DISP_BACKLIGHT_ON);
0281     }
0282 
0283     ctrl |= 1 << 8;
0284     acx565akm_write(ddata, MIPID_CMD_WRITE_CTRL_DISP, (u8 *)&ctrl, 2);
0285 }
0286 
0287 static void set_cabc_mode(struct panel_drv_data *ddata, unsigned mode)
0288 {
0289     u16 cabc_ctrl;
0290 
0291     ddata->cabc_mode = mode;
0292     if (!ddata->enabled)
0293         return;
0294     cabc_ctrl = 0;
0295     acx565akm_read(ddata, MIPID_CMD_READ_CABC, (u8 *)&cabc_ctrl, 1);
0296     cabc_ctrl &= ~3;
0297     cabc_ctrl |= (1 << 8) | (mode & 3);
0298     acx565akm_write(ddata, MIPID_CMD_WRITE_CABC, (u8 *)&cabc_ctrl, 2);
0299 }
0300 
0301 static unsigned get_cabc_mode(struct panel_drv_data *ddata)
0302 {
0303     return ddata->cabc_mode;
0304 }
0305 
0306 static unsigned get_hw_cabc_mode(struct panel_drv_data *ddata)
0307 {
0308     u8 cabc_ctrl;
0309 
0310     acx565akm_read(ddata, MIPID_CMD_READ_CABC, &cabc_ctrl, 1);
0311     return cabc_ctrl & 3;
0312 }
0313 
0314 static void acx565akm_set_brightness(struct panel_drv_data *ddata, int level)
0315 {
0316     int bv;
0317 
0318     bv = level | (1 << 8);
0319     acx565akm_write(ddata, MIPID_CMD_WRITE_DISP_BRIGHTNESS, (u8 *)&bv, 2);
0320 
0321     if (level)
0322         enable_backlight_ctrl(ddata, 1);
0323     else
0324         enable_backlight_ctrl(ddata, 0);
0325 }
0326 
0327 static int acx565akm_get_actual_brightness(struct panel_drv_data *ddata)
0328 {
0329     u8 bv;
0330 
0331     acx565akm_read(ddata, MIPID_CMD_READ_DISP_BRIGHTNESS, &bv, 1);
0332 
0333     return bv;
0334 }
0335 
0336 
0337 static int acx565akm_bl_update_status(struct backlight_device *dev)
0338 {
0339     struct panel_drv_data *ddata = dev_get_drvdata(&dev->dev);
0340     int level;
0341 
0342     dev_dbg(&ddata->spi->dev, "%s\n", __func__);
0343 
0344     if (dev->props.fb_blank == FB_BLANK_UNBLANK &&
0345             dev->props.power == FB_BLANK_UNBLANK)
0346         level = dev->props.brightness;
0347     else
0348         level = 0;
0349 
0350     if (ddata->has_bc)
0351         acx565akm_set_brightness(ddata, level);
0352     else
0353         return -ENODEV;
0354 
0355     return 0;
0356 }
0357 
0358 static int acx565akm_bl_get_intensity(struct backlight_device *dev)
0359 {
0360     struct panel_drv_data *ddata = dev_get_drvdata(&dev->dev);
0361 
0362     dev_dbg(&dev->dev, "%s\n", __func__);
0363 
0364     if (!ddata->has_bc)
0365         return -ENODEV;
0366 
0367     if (dev->props.fb_blank == FB_BLANK_UNBLANK &&
0368             dev->props.power == FB_BLANK_UNBLANK) {
0369         if (ddata->has_bc)
0370             return acx565akm_get_actual_brightness(ddata);
0371         else
0372             return dev->props.brightness;
0373     }
0374 
0375     return 0;
0376 }
0377 
0378 static int acx565akm_bl_update_status_locked(struct backlight_device *dev)
0379 {
0380     struct panel_drv_data *ddata = dev_get_drvdata(&dev->dev);
0381     int r;
0382 
0383     mutex_lock(&ddata->mutex);
0384     r = acx565akm_bl_update_status(dev);
0385     mutex_unlock(&ddata->mutex);
0386 
0387     return r;
0388 }
0389 
0390 static int acx565akm_bl_get_intensity_locked(struct backlight_device *dev)
0391 {
0392     struct panel_drv_data *ddata = dev_get_drvdata(&dev->dev);
0393     int r;
0394 
0395     mutex_lock(&ddata->mutex);
0396     r = acx565akm_bl_get_intensity(dev);
0397     mutex_unlock(&ddata->mutex);
0398 
0399     return r;
0400 }
0401 
0402 static const struct backlight_ops acx565akm_bl_ops = {
0403     .get_brightness = acx565akm_bl_get_intensity_locked,
0404     .update_status  = acx565akm_bl_update_status_locked,
0405 };
0406 
0407 /*--------------------Auto Brightness control via Sysfs---------------------*/
0408 
0409 static const char * const cabc_modes[] = {
0410     "off",      /* always used when CABC is not supported */
0411     "ui",
0412     "still-image",
0413     "moving-image",
0414 };
0415 
0416 static ssize_t show_cabc_mode(struct device *dev,
0417         struct device_attribute *attr,
0418         char *buf)
0419 {
0420     struct panel_drv_data *ddata = dev_get_drvdata(dev);
0421     const char *mode_str;
0422     int mode;
0423     int len;
0424 
0425     if (!ddata->has_cabc)
0426         mode = 0;
0427     else
0428         mode = get_cabc_mode(ddata);
0429     mode_str = "unknown";
0430     if (mode >= 0 && mode < ARRAY_SIZE(cabc_modes))
0431         mode_str = cabc_modes[mode];
0432     len = snprintf(buf, PAGE_SIZE, "%s\n", mode_str);
0433 
0434     return len < PAGE_SIZE - 1 ? len : PAGE_SIZE - 1;
0435 }
0436 
0437 static ssize_t store_cabc_mode(struct device *dev,
0438         struct device_attribute *attr,
0439         const char *buf, size_t count)
0440 {
0441     struct panel_drv_data *ddata = dev_get_drvdata(dev);
0442     int i;
0443 
0444     for (i = 0; i < ARRAY_SIZE(cabc_modes); i++) {
0445         const char *mode_str = cabc_modes[i];
0446         int cmp_len = strlen(mode_str);
0447 
0448         if (count > 0 && buf[count - 1] == '\n')
0449             count--;
0450         if (count != cmp_len)
0451             continue;
0452 
0453         if (strncmp(buf, mode_str, cmp_len) == 0)
0454             break;
0455     }
0456 
0457     if (i == ARRAY_SIZE(cabc_modes))
0458         return -EINVAL;
0459 
0460     if (!ddata->has_cabc && i != 0)
0461         return -EINVAL;
0462 
0463     mutex_lock(&ddata->mutex);
0464     set_cabc_mode(ddata, i);
0465     mutex_unlock(&ddata->mutex);
0466 
0467     return count;
0468 }
0469 
0470 static ssize_t show_cabc_available_modes(struct device *dev,
0471         struct device_attribute *attr,
0472         char *buf)
0473 {
0474     struct panel_drv_data *ddata = dev_get_drvdata(dev);
0475     int len;
0476     int i;
0477 
0478     if (!ddata->has_cabc)
0479         return sysfs_emit(buf, "%s\n", cabc_modes[0]);
0480 
0481     for (i = 0, len = 0;
0482          len < PAGE_SIZE && i < ARRAY_SIZE(cabc_modes); i++)
0483         len += snprintf(&buf[len], PAGE_SIZE - len, "%s%s%s",
0484             i ? " " : "", cabc_modes[i],
0485             i == ARRAY_SIZE(cabc_modes) - 1 ? "\n" : "");
0486 
0487     return len < PAGE_SIZE ? len : PAGE_SIZE - 1;
0488 }
0489 
0490 static DEVICE_ATTR(cabc_mode, S_IRUGO | S_IWUSR,
0491         show_cabc_mode, store_cabc_mode);
0492 static DEVICE_ATTR(cabc_available_modes, S_IRUGO,
0493         show_cabc_available_modes, NULL);
0494 
0495 static struct attribute *bldev_attrs[] = {
0496     &dev_attr_cabc_mode.attr,
0497     &dev_attr_cabc_available_modes.attr,
0498     NULL,
0499 };
0500 
0501 static const struct attribute_group bldev_attr_group = {
0502     .attrs = bldev_attrs,
0503 };
0504 
0505 static int acx565akm_connect(struct omap_dss_device *dssdev)
0506 {
0507     struct panel_drv_data *ddata = to_panel_data(dssdev);
0508     struct omap_dss_device *in = ddata->in;
0509 
0510     if (omapdss_device_is_connected(dssdev))
0511         return 0;
0512 
0513     return in->ops.sdi->connect(in, dssdev);
0514 }
0515 
0516 static void acx565akm_disconnect(struct omap_dss_device *dssdev)
0517 {
0518     struct panel_drv_data *ddata = to_panel_data(dssdev);
0519     struct omap_dss_device *in = ddata->in;
0520 
0521     if (!omapdss_device_is_connected(dssdev))
0522         return;
0523 
0524     in->ops.sdi->disconnect(in, dssdev);
0525 }
0526 
0527 static int acx565akm_panel_power_on(struct omap_dss_device *dssdev)
0528 {
0529     struct panel_drv_data *ddata = to_panel_data(dssdev);
0530     struct omap_dss_device *in = ddata->in;
0531     int r;
0532 
0533     dev_dbg(&ddata->spi->dev, "%s\n", __func__);
0534 
0535     in->ops.sdi->set_timings(in, &ddata->videomode);
0536 
0537     if (ddata->datapairs > 0)
0538         in->ops.sdi->set_datapairs(in, ddata->datapairs);
0539 
0540     r = in->ops.sdi->enable(in);
0541     if (r) {
0542         pr_err("%s sdi enable failed\n", __func__);
0543         return r;
0544     }
0545 
0546     /*FIXME tweak me */
0547     msleep(50);
0548 
0549     if (gpio_is_valid(ddata->reset_gpio))
0550         gpio_set_value(ddata->reset_gpio, 1);
0551 
0552     if (ddata->enabled) {
0553         dev_dbg(&ddata->spi->dev, "panel already enabled\n");
0554         return 0;
0555     }
0556 
0557     /*
0558      * We have to meet all the following delay requirements:
0559      * 1. tRW: reset pulse width 10usec (7.12.1)
0560      * 2. tRT: reset cancel time 5msec (7.12.1)
0561      * 3. Providing PCLK,HS,VS signals for 2 frames = ~50msec worst
0562      *    case (7.6.2)
0563      * 4. 120msec before the sleep out command (7.12.1)
0564      */
0565     msleep(120);
0566 
0567     set_sleep_mode(ddata, 0);
0568     ddata->enabled = 1;
0569 
0570     /* 5msec between sleep out and the next command. (8.2.16) */
0571     usleep_range(5000, 10000);
0572     set_display_state(ddata, 1);
0573     set_cabc_mode(ddata, ddata->cabc_mode);
0574 
0575     return acx565akm_bl_update_status(ddata->bl_dev);
0576 }
0577 
0578 static void acx565akm_panel_power_off(struct omap_dss_device *dssdev)
0579 {
0580     struct panel_drv_data *ddata = to_panel_data(dssdev);
0581     struct omap_dss_device *in = ddata->in;
0582 
0583     dev_dbg(dssdev->dev, "%s\n", __func__);
0584 
0585     if (!ddata->enabled)
0586         return;
0587 
0588     set_display_state(ddata, 0);
0589     set_sleep_mode(ddata, 1);
0590     ddata->enabled = 0;
0591     /*
0592      * We have to provide PCLK,HS,VS signals for 2 frames (worst case
0593      * ~50msec) after sending the sleep in command and asserting the
0594      * reset signal. We probably could assert the reset w/o the delay
0595      * but we still delay to avoid possible artifacts. (7.6.1)
0596      */
0597     msleep(50);
0598 
0599     if (gpio_is_valid(ddata->reset_gpio))
0600         gpio_set_value(ddata->reset_gpio, 0);
0601 
0602     /* FIXME need to tweak this delay */
0603     msleep(100);
0604 
0605     in->ops.sdi->disable(in);
0606 }
0607 
0608 static int acx565akm_enable(struct omap_dss_device *dssdev)
0609 {
0610     struct panel_drv_data *ddata = to_panel_data(dssdev);
0611     int r;
0612 
0613     dev_dbg(dssdev->dev, "%s\n", __func__);
0614 
0615     if (!omapdss_device_is_connected(dssdev))
0616         return -ENODEV;
0617 
0618     if (omapdss_device_is_enabled(dssdev))
0619         return 0;
0620 
0621     mutex_lock(&ddata->mutex);
0622     r = acx565akm_panel_power_on(dssdev);
0623     mutex_unlock(&ddata->mutex);
0624     if (r)
0625         return r;
0626 
0627     dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
0628 
0629     return 0;
0630 }
0631 
0632 static void acx565akm_disable(struct omap_dss_device *dssdev)
0633 {
0634     struct panel_drv_data *ddata = to_panel_data(dssdev);
0635 
0636     dev_dbg(dssdev->dev, "%s\n", __func__);
0637 
0638     if (!omapdss_device_is_enabled(dssdev))
0639         return;
0640 
0641     mutex_lock(&ddata->mutex);
0642     acx565akm_panel_power_off(dssdev);
0643     mutex_unlock(&ddata->mutex);
0644 
0645     dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
0646 }
0647 
0648 static void acx565akm_set_timings(struct omap_dss_device *dssdev,
0649         struct omap_video_timings *timings)
0650 {
0651     struct panel_drv_data *ddata = to_panel_data(dssdev);
0652     struct omap_dss_device *in = ddata->in;
0653 
0654     ddata->videomode = *timings;
0655     dssdev->panel.timings = *timings;
0656 
0657     in->ops.sdi->set_timings(in, timings);
0658 }
0659 
0660 static void acx565akm_get_timings(struct omap_dss_device *dssdev,
0661         struct omap_video_timings *timings)
0662 {
0663     struct panel_drv_data *ddata = to_panel_data(dssdev);
0664 
0665     *timings = ddata->videomode;
0666 }
0667 
0668 static int acx565akm_check_timings(struct omap_dss_device *dssdev,
0669         struct omap_video_timings *timings)
0670 {
0671     struct panel_drv_data *ddata = to_panel_data(dssdev);
0672     struct omap_dss_device *in = ddata->in;
0673 
0674     return in->ops.sdi->check_timings(in, timings);
0675 }
0676 
0677 static struct omap_dss_driver acx565akm_ops = {
0678     .connect    = acx565akm_connect,
0679     .disconnect = acx565akm_disconnect,
0680 
0681     .enable     = acx565akm_enable,
0682     .disable    = acx565akm_disable,
0683 
0684     .set_timings    = acx565akm_set_timings,
0685     .get_timings    = acx565akm_get_timings,
0686     .check_timings  = acx565akm_check_timings,
0687 
0688     .get_resolution = omapdss_default_get_resolution,
0689 };
0690 
0691 static int acx565akm_probe_pdata(struct spi_device *spi)
0692 {
0693     const struct panel_acx565akm_platform_data *pdata;
0694     struct panel_drv_data *ddata = dev_get_drvdata(&spi->dev);
0695     struct omap_dss_device *dssdev, *in;
0696 
0697     pdata = dev_get_platdata(&spi->dev);
0698 
0699     ddata->reset_gpio = pdata->reset_gpio;
0700 
0701     in = omap_dss_find_output(pdata->source);
0702     if (in == NULL) {
0703         dev_err(&spi->dev, "failed to find video source '%s'\n",
0704                 pdata->source);
0705         return -EPROBE_DEFER;
0706     }
0707     ddata->in = in;
0708 
0709     ddata->datapairs = pdata->datapairs;
0710 
0711     dssdev = &ddata->dssdev;
0712     dssdev->name = pdata->name;
0713 
0714     return 0;
0715 }
0716 
0717 static int acx565akm_probe_of(struct spi_device *spi)
0718 {
0719     struct panel_drv_data *ddata = dev_get_drvdata(&spi->dev);
0720     struct device_node *np = spi->dev.of_node;
0721 
0722     ddata->reset_gpio = of_get_named_gpio(np, "reset-gpios", 0);
0723 
0724     ddata->in = omapdss_of_find_source_for_first_ep(np);
0725     if (IS_ERR(ddata->in)) {
0726         dev_err(&spi->dev, "failed to find video source\n");
0727         return PTR_ERR(ddata->in);
0728     }
0729 
0730     return 0;
0731 }
0732 
0733 static int acx565akm_probe(struct spi_device *spi)
0734 {
0735     struct panel_drv_data *ddata;
0736     struct omap_dss_device *dssdev;
0737     struct backlight_device *bldev;
0738     int max_brightness, brightness;
0739     struct backlight_properties props;
0740     int r;
0741 
0742     dev_dbg(&spi->dev, "%s\n", __func__);
0743 
0744     spi->mode = SPI_MODE_3;
0745 
0746     ddata = devm_kzalloc(&spi->dev, sizeof(*ddata), GFP_KERNEL);
0747     if (ddata == NULL)
0748         return -ENOMEM;
0749 
0750     dev_set_drvdata(&spi->dev, ddata);
0751 
0752     ddata->spi = spi;
0753 
0754     mutex_init(&ddata->mutex);
0755 
0756     if (dev_get_platdata(&spi->dev)) {
0757         r = acx565akm_probe_pdata(spi);
0758         if (r)
0759             return r;
0760     } else if (spi->dev.of_node) {
0761         r = acx565akm_probe_of(spi);
0762         if (r)
0763             return r;
0764     } else {
0765         dev_err(&spi->dev, "platform data missing!\n");
0766         return -ENODEV;
0767     }
0768 
0769     if (gpio_is_valid(ddata->reset_gpio)) {
0770         r = devm_gpio_request_one(&spi->dev, ddata->reset_gpio,
0771                 GPIOF_OUT_INIT_LOW, "lcd reset");
0772         if (r)
0773             goto err_gpio;
0774     }
0775 
0776     if (gpio_is_valid(ddata->reset_gpio))
0777         gpio_set_value(ddata->reset_gpio, 1);
0778 
0779     /*
0780      * After reset we have to wait 5 msec before the first
0781      * command can be sent.
0782      */
0783     usleep_range(5000, 10000);
0784 
0785     ddata->enabled = panel_enabled(ddata);
0786 
0787     r = panel_detect(ddata);
0788 
0789     if (!ddata->enabled && gpio_is_valid(ddata->reset_gpio))
0790         gpio_set_value(ddata->reset_gpio, 0);
0791 
0792     if (r) {
0793         dev_err(&spi->dev, "%s panel detect error\n", __func__);
0794         goto err_detect;
0795     }
0796 
0797     memset(&props, 0, sizeof(props));
0798     props.fb_blank = FB_BLANK_UNBLANK;
0799     props.power = FB_BLANK_UNBLANK;
0800     props.type = BACKLIGHT_RAW;
0801 
0802     bldev = backlight_device_register("acx565akm", &ddata->spi->dev,
0803             ddata, &acx565akm_bl_ops, &props);
0804     if (IS_ERR(bldev)) {
0805         r = PTR_ERR(bldev);
0806         goto err_reg_bl;
0807     }
0808     ddata->bl_dev = bldev;
0809     if (ddata->has_cabc) {
0810         r = sysfs_create_group(&bldev->dev.kobj, &bldev_attr_group);
0811         if (r) {
0812             dev_err(&bldev->dev,
0813                 "%s failed to create sysfs files\n", __func__);
0814             goto err_sysfs;
0815         }
0816         ddata->cabc_mode = get_hw_cabc_mode(ddata);
0817     }
0818 
0819     max_brightness = 255;
0820 
0821     if (ddata->has_bc)
0822         brightness = acx565akm_get_actual_brightness(ddata);
0823     else
0824         brightness = 0;
0825 
0826     bldev->props.max_brightness = max_brightness;
0827     bldev->props.brightness = brightness;
0828 
0829     acx565akm_bl_update_status(bldev);
0830 
0831 
0832     ddata->videomode = acx565akm_panel_timings;
0833 
0834     dssdev = &ddata->dssdev;
0835     dssdev->dev = &spi->dev;
0836     dssdev->driver = &acx565akm_ops;
0837     dssdev->type = OMAP_DISPLAY_TYPE_SDI;
0838     dssdev->owner = THIS_MODULE;
0839     dssdev->panel.timings = ddata->videomode;
0840 
0841     r = omapdss_register_display(dssdev);
0842     if (r) {
0843         dev_err(&spi->dev, "Failed to register panel\n");
0844         goto err_reg;
0845     }
0846 
0847     return 0;
0848 
0849 err_reg:
0850     sysfs_remove_group(&bldev->dev.kobj, &bldev_attr_group);
0851 err_sysfs:
0852     backlight_device_unregister(bldev);
0853 err_reg_bl:
0854 err_detect:
0855 err_gpio:
0856     omap_dss_put_device(ddata->in);
0857     return r;
0858 }
0859 
0860 static void acx565akm_remove(struct spi_device *spi)
0861 {
0862     struct panel_drv_data *ddata = dev_get_drvdata(&spi->dev);
0863     struct omap_dss_device *dssdev = &ddata->dssdev;
0864     struct omap_dss_device *in = ddata->in;
0865 
0866     dev_dbg(&ddata->spi->dev, "%s\n", __func__);
0867 
0868     sysfs_remove_group(&ddata->bl_dev->dev.kobj, &bldev_attr_group);
0869     backlight_device_unregister(ddata->bl_dev);
0870 
0871     omapdss_unregister_display(dssdev);
0872 
0873     acx565akm_disable(dssdev);
0874     acx565akm_disconnect(dssdev);
0875 
0876     omap_dss_put_device(in);
0877 }
0878 
0879 static const struct of_device_id acx565akm_of_match[] = {
0880     { .compatible = "omapdss,sony,acx565akm", },
0881     {},
0882 };
0883 MODULE_DEVICE_TABLE(of, acx565akm_of_match);
0884 
0885 static struct spi_driver acx565akm_driver = {
0886     .driver = {
0887         .name   = "acx565akm",
0888         .of_match_table = acx565akm_of_match,
0889         .suppress_bind_attrs = true,
0890     },
0891     .probe  = acx565akm_probe,
0892     .remove = acx565akm_remove,
0893 };
0894 
0895 module_spi_driver(acx565akm_driver);
0896 
0897 MODULE_AUTHOR("Nokia Corporation");
0898 MODULE_DESCRIPTION("acx565akm LCD Driver");
0899 MODULE_LICENSE("GPL");