linux/drivers/video/fbdev/omap/lcd_mipid.c
<<
>>
Prefs
   1/*
   2 * LCD driver for MIPI DBI-C / DCS compatible LCDs
   3 *
   4 * Copyright (C) 2006 Nokia Corporation
   5 * Author: Imre Deak <imre.deak@nokia.com>
   6 *
   7 * This program is free software; you can redistribute it and/or modify it
   8 * under the terms of the GNU General Public License as published by the
   9 * Free Software Foundation; either version 2 of the License, or (at your
  10 * option) any later version.
  11 *
  12 * This program is distributed in the hope that it will be useful, but
  13 * WITHOUT ANY WARRANTY; without even the implied warranty of
  14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  15 * General Public License for more details.
  16 *
  17 * You should have received a copy of the GNU General Public License along
  18 * with this program; if not, write to the Free Software Foundation, Inc.,
  19 * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  20 */
  21#include <linux/device.h>
  22#include <linux/delay.h>
  23#include <linux/slab.h>
  24#include <linux/workqueue.h>
  25#include <linux/spi/spi.h>
  26#include <linux/module.h>
  27
  28#include <linux/platform_data/lcd-mipid.h>
  29
  30#include "omapfb.h"
  31
  32#define MIPID_MODULE_NAME               "lcd_mipid"
  33
  34#define MIPID_CMD_READ_DISP_ID          0x04
  35#define MIPID_CMD_READ_RED              0x06
  36#define MIPID_CMD_READ_GREEN            0x07
  37#define MIPID_CMD_READ_BLUE             0x08
  38#define MIPID_CMD_READ_DISP_STATUS      0x09
  39#define MIPID_CMD_RDDSDR                0x0F
  40#define MIPID_CMD_SLEEP_IN              0x10
  41#define MIPID_CMD_SLEEP_OUT             0x11
  42#define MIPID_CMD_DISP_OFF              0x28
  43#define MIPID_CMD_DISP_ON               0x29
  44
  45#define MIPID_ESD_CHECK_PERIOD          msecs_to_jiffies(5000)
  46
  47#define to_mipid_device(p)              container_of(p, struct mipid_device, \
  48                                                panel)
  49struct mipid_device {
  50        int             enabled;
  51        int             revision;
  52        unsigned int    saved_bklight_level;
  53        unsigned long   hw_guard_end;           /* next value of jiffies
  54                                                   when we can issue the
  55                                                   next sleep in/out command */
  56        unsigned long   hw_guard_wait;          /* max guard time in jiffies */
  57
  58        struct omapfb_device    *fbdev;
  59        struct spi_device       *spi;
  60        struct mutex            mutex;
  61        struct lcd_panel        panel;
  62
  63        struct workqueue_struct *esd_wq;
  64        struct delayed_work     esd_work;
  65        void                    (*esd_check)(struct mipid_device *m);
  66};
  67
  68static void mipid_transfer(struct mipid_device *md, int cmd, const u8 *wbuf,
  69                           int wlen, u8 *rbuf, int rlen)
  70{
  71        struct spi_message      m;
  72        struct spi_transfer     *x, xfer[4];
  73        u16                     w;
  74        int                     r;
  75
  76        BUG_ON(md->spi == NULL);
  77
  78        spi_message_init(&m);
  79
  80        memset(xfer, 0, sizeof(xfer));
  81        x = &xfer[0];
  82
  83        cmd &=  0xff;
  84        x->tx_buf               = &cmd;
  85        x->bits_per_word        = 9;
  86        x->len                  = 2;
  87        spi_message_add_tail(x, &m);
  88
  89        if (wlen) {
  90                x++;
  91                x->tx_buf               = wbuf;
  92                x->len                  = wlen;
  93                x->bits_per_word        = 9;
  94                spi_message_add_tail(x, &m);
  95        }
  96
  97        if (rlen) {
  98                x++;
  99                x->rx_buf       = &w;
 100                x->len          = 1;
 101                spi_message_add_tail(x, &m);
 102
 103                if (rlen > 1) {
 104                        /* Arrange for the extra clock before the first
 105                         * data bit.
 106                         */
 107                        x->bits_per_word = 9;
 108                        x->len           = 2;
 109
 110                        x++;
 111                        x->rx_buf        = &rbuf[1];
 112                        x->len           = rlen - 1;
 113                        spi_message_add_tail(x, &m);
 114                }
 115        }
 116
 117        r = spi_sync(md->spi, &m);
 118        if (r < 0)
 119                dev_dbg(&md->spi->dev, "spi_sync %d\n", r);
 120
 121        if (rlen)
 122                rbuf[0] = w & 0xff;
 123}
 124
 125static inline void mipid_cmd(struct mipid_device *md, int cmd)
 126{
 127        mipid_transfer(md, cmd, NULL, 0, NULL, 0);
 128}
 129
 130static inline void mipid_write(struct mipid_device *md,
 131                               int reg, const u8 *buf, int len)
 132{
 133        mipid_transfer(md, reg, buf, len, NULL, 0);
 134}
 135
 136static inline void mipid_read(struct mipid_device *md,
 137                              int reg, u8 *buf, int len)
 138{
 139        mipid_transfer(md, reg, NULL, 0, buf, len);
 140}
 141
 142static void set_data_lines(struct mipid_device *md, int data_lines)
 143{
 144        u16 par;
 145
 146        switch (data_lines) {
 147        case 16:
 148                par = 0x150;
 149                break;
 150        case 18:
 151                par = 0x160;
 152                break;
 153        case 24:
 154                par = 0x170;
 155                break;
 156        }
 157        mipid_write(md, 0x3a, (u8 *)&par, 2);
 158}
 159
 160static void send_init_string(struct mipid_device *md)
 161{
 162        u16 initpar[] = { 0x0102, 0x0100, 0x0100 };
 163
 164        mipid_write(md, 0xc2, (u8 *)initpar, sizeof(initpar));
 165        set_data_lines(md, md->panel.data_lines);
 166}
 167
 168static void hw_guard_start(struct mipid_device *md, int guard_msec)
 169{
 170        md->hw_guard_wait = msecs_to_jiffies(guard_msec);
 171        md->hw_guard_end = jiffies + md->hw_guard_wait;
 172}
 173
 174static void hw_guard_wait(struct mipid_device *md)
 175{
 176        unsigned long wait = md->hw_guard_end - jiffies;
 177
 178        if ((long)wait > 0 && wait <= md->hw_guard_wait) {
 179                set_current_state(TASK_UNINTERRUPTIBLE);
 180                schedule_timeout(wait);
 181        }
 182}
 183
 184static void set_sleep_mode(struct mipid_device *md, int on)
 185{
 186        int cmd, sleep_time = 50;
 187
 188        if (on)
 189                cmd = MIPID_CMD_SLEEP_IN;
 190        else
 191                cmd = MIPID_CMD_SLEEP_OUT;
 192        hw_guard_wait(md);
 193        mipid_cmd(md, cmd);
 194        hw_guard_start(md, 120);
 195        /*
 196         * When we enable the panel, it seems we _have_ to sleep
 197         * 120 ms before sending the init string. When disabling the
 198         * panel we'll sleep for the duration of 2 frames, so that the
 199         * controller can still provide the PCLK,HS,VS signals.
 200         */
 201        if (!on)
 202                sleep_time = 120;
 203        msleep(sleep_time);
 204}
 205
 206static void set_display_state(struct mipid_device *md, int enabled)
 207{
 208        int cmd = enabled ? MIPID_CMD_DISP_ON : MIPID_CMD_DISP_OFF;
 209
 210        mipid_cmd(md, cmd);
 211}
 212
 213static int mipid_set_bklight_level(struct lcd_panel *panel, unsigned int level)
 214{
 215        struct mipid_device *md = to_mipid_device(panel);
 216        struct mipid_platform_data *pd = md->spi->dev.platform_data;
 217
 218        if (pd->get_bklight_max == NULL || pd->set_bklight_level == NULL)
 219                return -ENODEV;
 220        if (level > pd->get_bklight_max(pd))
 221                return -EINVAL;
 222        if (!md->enabled) {
 223                md->saved_bklight_level = level;
 224                return 0;
 225        }
 226        pd->set_bklight_level(pd, level);
 227
 228        return 0;
 229}
 230
 231static unsigned int mipid_get_bklight_level(struct lcd_panel *panel)
 232{
 233        struct mipid_device *md = to_mipid_device(panel);
 234        struct mipid_platform_data *pd = md->spi->dev.platform_data;
 235
 236        if (pd->get_bklight_level == NULL)
 237                return -ENODEV;
 238        return pd->get_bklight_level(pd);
 239}
 240
 241static unsigned int mipid_get_bklight_max(struct lcd_panel *panel)
 242{
 243        struct mipid_device *md = to_mipid_device(panel);
 244        struct mipid_platform_data *pd = md->spi->dev.platform_data;
 245
 246        if (pd->get_bklight_max == NULL)
 247                return -ENODEV;
 248
 249        return pd->get_bklight_max(pd);
 250}
 251
 252static unsigned long mipid_get_caps(struct lcd_panel *panel)
 253{
 254        return OMAPFB_CAPS_SET_BACKLIGHT;
 255}
 256
 257static u16 read_first_pixel(struct mipid_device *md)
 258{
 259        u16 pixel;
 260        u8 red, green, blue;
 261
 262        mutex_lock(&md->mutex);
 263        mipid_read(md, MIPID_CMD_READ_RED, &red, 1);
 264        mipid_read(md, MIPID_CMD_READ_GREEN, &green, 1);
 265        mipid_read(md, MIPID_CMD_READ_BLUE, &blue, 1);
 266        mutex_unlock(&md->mutex);
 267
 268        switch (md->panel.data_lines) {
 269        case 16:
 270                pixel = ((red >> 1) << 11) | (green << 5) | (blue >> 1);
 271                break;
 272        case 24:
 273                /* 24 bit -> 16 bit */
 274                pixel = ((red >> 3) << 11) | ((green >> 2) << 5) |
 275                        (blue >> 3);
 276                break;
 277        default:
 278                pixel = 0;
 279                BUG();
 280        }
 281
 282        return pixel;
 283}
 284
 285static int mipid_run_test(struct lcd_panel *panel, int test_num)
 286{
 287        struct mipid_device *md = to_mipid_device(panel);
 288        static const u16 test_values[4] = {
 289                0x0000, 0xffff, 0xaaaa, 0x5555,
 290        };
 291        int i;
 292
 293        if (test_num != MIPID_TEST_RGB_LINES)
 294                return MIPID_TEST_INVALID;
 295
 296        for (i = 0; i < ARRAY_SIZE(test_values); i++) {
 297                int delay;
 298                unsigned long tmo;
 299
 300                omapfb_write_first_pixel(md->fbdev, test_values[i]);
 301                tmo = jiffies + msecs_to_jiffies(100);
 302                delay = 25;
 303                while (1) {
 304                        u16 pixel;
 305
 306                        msleep(delay);
 307                        pixel = read_first_pixel(md);
 308                        if (pixel == test_values[i])
 309                                break;
 310                        if (time_after(jiffies, tmo)) {
 311                                dev_err(&md->spi->dev,
 312                                        "MIPI LCD RGB I/F test failed: "
 313                                        "expecting %04x, got %04x\n",
 314                                        test_values[i], pixel);
 315                                return MIPID_TEST_FAILED;
 316                        }
 317                        delay = 10;
 318                }
 319        }
 320
 321        return 0;
 322}
 323
 324static void ls041y3_esd_recover(struct mipid_device *md)
 325{
 326        dev_err(&md->spi->dev, "performing LCD ESD recovery\n");
 327        set_sleep_mode(md, 1);
 328        set_sleep_mode(md, 0);
 329}
 330
 331static void ls041y3_esd_check_mode1(struct mipid_device *md)
 332{
 333        u8 state1, state2;
 334
 335        mipid_read(md, MIPID_CMD_RDDSDR, &state1, 1);
 336        set_sleep_mode(md, 0);
 337        mipid_read(md, MIPID_CMD_RDDSDR, &state2, 1);
 338        dev_dbg(&md->spi->dev, "ESD mode 1 state1 %02x state2 %02x\n",
 339                state1, state2);
 340        /* Each sleep out command will trigger a self diagnostic and flip
 341        * Bit6 if the test passes.
 342        */
 343        if (!((state1 ^ state2) & (1 << 6)))
 344                ls041y3_esd_recover(md);
 345}
 346
 347static void ls041y3_esd_check_mode2(struct mipid_device *md)
 348{
 349        int i;
 350        u8 rbuf[2];
 351        static const struct {
 352                int     cmd;
 353                int     wlen;
 354                u16     wbuf[3];
 355        } *rd, rd_ctrl[7] = {
 356                { 0xb0, 4, { 0x0101, 0x01fe, } },
 357                { 0xb1, 4, { 0x01de, 0x0121, } },
 358                { 0xc2, 4, { 0x0100, 0x0100, } },
 359                { 0xbd, 2, { 0x0100, } },
 360                { 0xc2, 4, { 0x01fc, 0x0103, } },
 361                { 0xb4, 0, },
 362                { 0x00, 0, },
 363        };
 364
 365        rd = rd_ctrl;
 366        for (i = 0; i < 3; i++, rd++)
 367                mipid_write(md, rd->cmd, (u8 *)rd->wbuf, rd->wlen);
 368
 369        udelay(10);
 370        mipid_read(md, rd->cmd, rbuf, 2);
 371        rd++;
 372
 373        for (i = 0; i < 3; i++, rd++) {
 374                udelay(10);
 375                mipid_write(md, rd->cmd, (u8 *)rd->wbuf, rd->wlen);
 376        }
 377
 378        dev_dbg(&md->spi->dev, "ESD mode 2 state %02x\n", rbuf[1]);
 379        if (rbuf[1] == 0x00)
 380                ls041y3_esd_recover(md);
 381}
 382
 383static void ls041y3_esd_check(struct mipid_device *md)
 384{
 385        ls041y3_esd_check_mode1(md);
 386        if (md->revision >= 0x88)
 387                ls041y3_esd_check_mode2(md);
 388}
 389
 390static void mipid_esd_start_check(struct mipid_device *md)
 391{
 392        if (md->esd_check != NULL)
 393                queue_delayed_work(md->esd_wq, &md->esd_work,
 394                                   MIPID_ESD_CHECK_PERIOD);
 395}
 396
 397static void mipid_esd_stop_check(struct mipid_device *md)
 398{
 399        if (md->esd_check != NULL)
 400                cancel_delayed_work_sync(&md->esd_work);
 401}
 402
 403static void mipid_esd_work(struct work_struct *work)
 404{
 405        struct mipid_device *md = container_of(work, struct mipid_device,
 406                                               esd_work.work);
 407
 408        mutex_lock(&md->mutex);
 409        md->esd_check(md);
 410        mutex_unlock(&md->mutex);
 411        mipid_esd_start_check(md);
 412}
 413
 414static int mipid_enable(struct lcd_panel *panel)
 415{
 416        struct mipid_device *md = to_mipid_device(panel);
 417
 418        mutex_lock(&md->mutex);
 419
 420        if (md->enabled) {
 421                mutex_unlock(&md->mutex);
 422                return 0;
 423        }
 424        set_sleep_mode(md, 0);
 425        md->enabled = 1;
 426        send_init_string(md);
 427        set_display_state(md, 1);
 428        mipid_set_bklight_level(panel, md->saved_bklight_level);
 429        mipid_esd_start_check(md);
 430
 431        mutex_unlock(&md->mutex);
 432        return 0;
 433}
 434
 435static void mipid_disable(struct lcd_panel *panel)
 436{
 437        struct mipid_device *md = to_mipid_device(panel);
 438
 439        /*
 440         * A final ESD work might be called before returning,
 441         * so do this without holding the lock.
 442         */
 443        mipid_esd_stop_check(md);
 444        mutex_lock(&md->mutex);
 445
 446        if (!md->enabled) {
 447                mutex_unlock(&md->mutex);
 448                return;
 449        }
 450        md->saved_bklight_level = mipid_get_bklight_level(panel);
 451        mipid_set_bklight_level(panel, 0);
 452        set_display_state(md, 0);
 453        set_sleep_mode(md, 1);
 454        md->enabled = 0;
 455
 456        mutex_unlock(&md->mutex);
 457}
 458
 459static int panel_enabled(struct mipid_device *md)
 460{
 461        u32 disp_status;
 462        int enabled;
 463
 464        mipid_read(md, MIPID_CMD_READ_DISP_STATUS, (u8 *)&disp_status, 4);
 465        disp_status = __be32_to_cpu(disp_status);
 466        enabled = (disp_status & (1 << 17)) && (disp_status & (1 << 10));
 467        dev_dbg(&md->spi->dev,
 468                "LCD panel %senabled by bootloader (status 0x%04x)\n",
 469                enabled ? "" : "not ", disp_status);
 470        return enabled;
 471}
 472
 473static int mipid_init(struct lcd_panel *panel,
 474                            struct omapfb_device *fbdev)
 475{
 476        struct mipid_device *md = to_mipid_device(panel);
 477
 478        md->fbdev = fbdev;
 479        md->esd_wq = create_singlethread_workqueue("mipid_esd");
 480        if (md->esd_wq == NULL) {
 481                dev_err(&md->spi->dev, "can't create ESD workqueue\n");
 482                return -ENOMEM;
 483        }
 484        INIT_DELAYED_WORK(&md->esd_work, mipid_esd_work);
 485        mutex_init(&md->mutex);
 486
 487        md->enabled = panel_enabled(md);
 488
 489        if (md->enabled)
 490                mipid_esd_start_check(md);
 491        else
 492                md->saved_bklight_level = mipid_get_bklight_level(panel);
 493
 494        return 0;
 495}
 496
 497static void mipid_cleanup(struct lcd_panel *panel)
 498{
 499        struct mipid_device *md = to_mipid_device(panel);
 500
 501        if (md->enabled)
 502                mipid_esd_stop_check(md);
 503        destroy_workqueue(md->esd_wq);
 504}
 505
 506static struct lcd_panel mipid_panel = {
 507        .config         = OMAP_LCDC_PANEL_TFT,
 508
 509        .bpp            = 16,
 510        .x_res          = 800,
 511        .y_res          = 480,
 512        .pixel_clock    = 21940,
 513        .hsw            = 50,
 514        .hfp            = 20,
 515        .hbp            = 15,
 516        .vsw            = 2,
 517        .vfp            = 1,
 518        .vbp            = 3,
 519
 520        .init                   = mipid_init,
 521        .cleanup                = mipid_cleanup,
 522        .enable                 = mipid_enable,
 523        .disable                = mipid_disable,
 524        .get_caps               = mipid_get_caps,
 525        .set_bklight_level      = mipid_set_bklight_level,
 526        .get_bklight_level      = mipid_get_bklight_level,
 527        .get_bklight_max        = mipid_get_bklight_max,
 528        .run_test               = mipid_run_test,
 529};
 530
 531static int mipid_detect(struct mipid_device *md)
 532{
 533        struct mipid_platform_data *pdata;
 534        u8 display_id[3];
 535
 536        pdata = md->spi->dev.platform_data;
 537        if (pdata == NULL) {
 538                dev_err(&md->spi->dev, "missing platform data\n");
 539                return -ENOENT;
 540        }
 541
 542        mipid_read(md, MIPID_CMD_READ_DISP_ID, display_id, 3);
 543        dev_dbg(&md->spi->dev, "MIPI display ID: %02x%02x%02x\n",
 544                display_id[0], display_id[1], display_id[2]);
 545
 546        switch (display_id[0]) {
 547        case 0x45:
 548                md->panel.name = "lph8923";
 549                break;
 550        case 0x83:
 551                md->panel.name = "ls041y3";
 552                md->esd_check = ls041y3_esd_check;
 553                break;
 554        default:
 555                md->panel.name = "unknown";
 556                dev_err(&md->spi->dev, "invalid display ID\n");
 557                return -ENODEV;
 558        }
 559
 560        md->revision = display_id[1];
 561        md->panel.data_lines = pdata->data_lines;
 562        pr_info("omapfb: %s rev %02x LCD detected, %d data lines\n",
 563                        md->panel.name, md->revision, md->panel.data_lines);
 564
 565        return 0;
 566}
 567
 568static int mipid_spi_probe(struct spi_device *spi)
 569{
 570        struct mipid_device *md;
 571        int r;
 572
 573        md = kzalloc(sizeof(*md), GFP_KERNEL);
 574        if (md == NULL) {
 575                dev_err(&spi->dev, "out of memory\n");
 576                return -ENOMEM;
 577        }
 578
 579        spi->mode = SPI_MODE_0;
 580        md->spi = spi;
 581        dev_set_drvdata(&spi->dev, md);
 582        md->panel = mipid_panel;
 583
 584        r = mipid_detect(md);
 585        if (r < 0)
 586                return r;
 587
 588        omapfb_register_panel(&md->panel);
 589
 590        return 0;
 591}
 592
 593static int mipid_spi_remove(struct spi_device *spi)
 594{
 595        struct mipid_device *md = dev_get_drvdata(&spi->dev);
 596
 597        mipid_disable(&md->panel);
 598        kfree(md);
 599
 600        return 0;
 601}
 602
 603static struct spi_driver mipid_spi_driver = {
 604        .driver = {
 605                .name   = MIPID_MODULE_NAME,
 606                .owner  = THIS_MODULE,
 607        },
 608        .probe  = mipid_spi_probe,
 609        .remove = mipid_spi_remove,
 610};
 611
 612module_spi_driver(mipid_spi_driver);
 613
 614MODULE_DESCRIPTION("MIPI display driver");
 615MODULE_LICENSE("GPL");
 616