linux/drivers/gpu/drm/omapdrm/displays/panel-dsi-cm.c
<<
>>
Prefs
   1/*
   2 * Generic DSI Command Mode panel driver
   3 *
   4 * Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com/
   5 * Author: Tomi Valkeinen <tomi.valkeinen@ti.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 version 2 as published by
   9 * the Free Software Foundation.
  10 */
  11
  12/* #define DEBUG */
  13
  14#include <linux/backlight.h>
  15#include <linux/delay.h>
  16#include <linux/gpio/consumer.h>
  17#include <linux/interrupt.h>
  18#include <linux/jiffies.h>
  19#include <linux/module.h>
  20#include <linux/platform_device.h>
  21#include <linux/sched/signal.h>
  22#include <linux/slab.h>
  23#include <linux/workqueue.h>
  24#include <linux/of_device.h>
  25#include <linux/regulator/consumer.h>
  26
  27#include <video/mipi_display.h>
  28#include <video/of_display_timing.h>
  29
  30#include "../dss/omapdss.h"
  31
  32/* DSI Virtual channel. Hardcoded for now. */
  33#define TCH 0
  34
  35#define DCS_READ_NUM_ERRORS     0x05
  36#define DCS_BRIGHTNESS          0x51
  37#define DCS_CTRL_DISPLAY        0x53
  38#define DCS_GET_ID1             0xda
  39#define DCS_GET_ID2             0xdb
  40#define DCS_GET_ID3             0xdc
  41
  42struct panel_drv_data {
  43        struct omap_dss_device dssdev;
  44        struct omap_dss_device *in;
  45
  46        struct videomode vm;
  47
  48        struct platform_device *pdev;
  49
  50        struct mutex lock;
  51
  52        struct backlight_device *bldev;
  53        struct backlight_device *extbldev;
  54
  55        unsigned long   hw_guard_end;   /* next value of jiffies when we can
  56                                         * issue the next sleep in/out command
  57                                         */
  58        unsigned long   hw_guard_wait;  /* max guard time in jiffies */
  59
  60        /* panel HW configuration from DT or platform data */
  61        struct gpio_desc *reset_gpio;
  62        struct gpio_desc *ext_te_gpio;
  63
  64        struct regulator *vpnl;
  65        struct regulator *vddi;
  66
  67        bool use_dsi_backlight;
  68
  69        int width_mm;
  70        int height_mm;
  71
  72        struct omap_dsi_pin_config pin_config;
  73
  74        /* runtime variables */
  75        bool enabled;
  76
  77        bool te_enabled;
  78
  79        atomic_t do_update;
  80        int channel;
  81
  82        struct delayed_work te_timeout_work;
  83
  84        bool intro_printed;
  85
  86        struct workqueue_struct *workqueue;
  87
  88        bool ulps_enabled;
  89        unsigned int ulps_timeout;
  90        struct delayed_work ulps_work;
  91};
  92
  93#define to_panel_data(p) container_of(p, struct panel_drv_data, dssdev)
  94
  95static irqreturn_t dsicm_te_isr(int irq, void *data);
  96static void dsicm_te_timeout_work_callback(struct work_struct *work);
  97static int _dsicm_enable_te(struct panel_drv_data *ddata, bool enable);
  98
  99static int dsicm_panel_reset(struct panel_drv_data *ddata);
 100
 101static void dsicm_ulps_work(struct work_struct *work);
 102
 103static void dsicm_bl_power(struct panel_drv_data *ddata, bool enable)
 104{
 105        struct backlight_device *backlight;
 106
 107        if (ddata->bldev)
 108                backlight = ddata->bldev;
 109        else if (ddata->extbldev)
 110                backlight = ddata->extbldev;
 111        else
 112                return;
 113
 114        if (enable) {
 115                backlight->props.fb_blank = FB_BLANK_UNBLANK;
 116                backlight->props.state = ~(BL_CORE_FBBLANK | BL_CORE_SUSPENDED);
 117                backlight->props.power = FB_BLANK_UNBLANK;
 118        } else {
 119                backlight->props.fb_blank = FB_BLANK_NORMAL;
 120                backlight->props.power = FB_BLANK_POWERDOWN;
 121                backlight->props.state |= BL_CORE_FBBLANK | BL_CORE_SUSPENDED;
 122        }
 123
 124        backlight_update_status(backlight);
 125}
 126
 127static void hw_guard_start(struct panel_drv_data *ddata, int guard_msec)
 128{
 129        ddata->hw_guard_wait = msecs_to_jiffies(guard_msec);
 130        ddata->hw_guard_end = jiffies + ddata->hw_guard_wait;
 131}
 132
 133static void hw_guard_wait(struct panel_drv_data *ddata)
 134{
 135        unsigned long wait = ddata->hw_guard_end - jiffies;
 136
 137        if ((long)wait > 0 && wait <= ddata->hw_guard_wait) {
 138                set_current_state(TASK_UNINTERRUPTIBLE);
 139                schedule_timeout(wait);
 140        }
 141}
 142
 143static int dsicm_dcs_read_1(struct panel_drv_data *ddata, u8 dcs_cmd, u8 *data)
 144{
 145        struct omap_dss_device *in = ddata->in;
 146        int r;
 147        u8 buf[1];
 148
 149        r = in->ops.dsi->dcs_read(in, ddata->channel, dcs_cmd, buf, 1);
 150
 151        if (r < 0)
 152                return r;
 153
 154        *data = buf[0];
 155
 156        return 0;
 157}
 158
 159static int dsicm_dcs_write_0(struct panel_drv_data *ddata, u8 dcs_cmd)
 160{
 161        struct omap_dss_device *in = ddata->in;
 162        return in->ops.dsi->dcs_write(in, ddata->channel, &dcs_cmd, 1);
 163}
 164
 165static int dsicm_dcs_write_1(struct panel_drv_data *ddata, u8 dcs_cmd, u8 param)
 166{
 167        struct omap_dss_device *in = ddata->in;
 168        u8 buf[2] = { dcs_cmd, param };
 169
 170        return in->ops.dsi->dcs_write(in, ddata->channel, buf, 2);
 171}
 172
 173static int dsicm_sleep_in(struct panel_drv_data *ddata)
 174
 175{
 176        struct omap_dss_device *in = ddata->in;
 177        u8 cmd;
 178        int r;
 179
 180        hw_guard_wait(ddata);
 181
 182        cmd = MIPI_DCS_ENTER_SLEEP_MODE;
 183        r = in->ops.dsi->dcs_write_nosync(in, ddata->channel, &cmd, 1);
 184        if (r)
 185                return r;
 186
 187        hw_guard_start(ddata, 120);
 188
 189        usleep_range(5000, 10000);
 190
 191        return 0;
 192}
 193
 194static int dsicm_sleep_out(struct panel_drv_data *ddata)
 195{
 196        int r;
 197
 198        hw_guard_wait(ddata);
 199
 200        r = dsicm_dcs_write_0(ddata, MIPI_DCS_EXIT_SLEEP_MODE);
 201        if (r)
 202                return r;
 203
 204        hw_guard_start(ddata, 120);
 205
 206        usleep_range(5000, 10000);
 207
 208        return 0;
 209}
 210
 211static int dsicm_get_id(struct panel_drv_data *ddata, u8 *id1, u8 *id2, u8 *id3)
 212{
 213        int r;
 214
 215        r = dsicm_dcs_read_1(ddata, DCS_GET_ID1, id1);
 216        if (r)
 217                return r;
 218        r = dsicm_dcs_read_1(ddata, DCS_GET_ID2, id2);
 219        if (r)
 220                return r;
 221        r = dsicm_dcs_read_1(ddata, DCS_GET_ID3, id3);
 222        if (r)
 223                return r;
 224
 225        return 0;
 226}
 227
 228static int dsicm_set_update_window(struct panel_drv_data *ddata,
 229                u16 x, u16 y, u16 w, u16 h)
 230{
 231        struct omap_dss_device *in = ddata->in;
 232        int r;
 233        u16 x1 = x;
 234        u16 x2 = x + w - 1;
 235        u16 y1 = y;
 236        u16 y2 = y + h - 1;
 237
 238        u8 buf[5];
 239        buf[0] = MIPI_DCS_SET_COLUMN_ADDRESS;
 240        buf[1] = (x1 >> 8) & 0xff;
 241        buf[2] = (x1 >> 0) & 0xff;
 242        buf[3] = (x2 >> 8) & 0xff;
 243        buf[4] = (x2 >> 0) & 0xff;
 244
 245        r = in->ops.dsi->dcs_write_nosync(in, ddata->channel, buf, sizeof(buf));
 246        if (r)
 247                return r;
 248
 249        buf[0] = MIPI_DCS_SET_PAGE_ADDRESS;
 250        buf[1] = (y1 >> 8) & 0xff;
 251        buf[2] = (y1 >> 0) & 0xff;
 252        buf[3] = (y2 >> 8) & 0xff;
 253        buf[4] = (y2 >> 0) & 0xff;
 254
 255        r = in->ops.dsi->dcs_write_nosync(in, ddata->channel, buf, sizeof(buf));
 256        if (r)
 257                return r;
 258
 259        in->ops.dsi->bta_sync(in, ddata->channel);
 260
 261        return r;
 262}
 263
 264static void dsicm_queue_ulps_work(struct panel_drv_data *ddata)
 265{
 266        if (ddata->ulps_timeout > 0)
 267                queue_delayed_work(ddata->workqueue, &ddata->ulps_work,
 268                                msecs_to_jiffies(ddata->ulps_timeout));
 269}
 270
 271static void dsicm_cancel_ulps_work(struct panel_drv_data *ddata)
 272{
 273        cancel_delayed_work(&ddata->ulps_work);
 274}
 275
 276static int dsicm_enter_ulps(struct panel_drv_data *ddata)
 277{
 278        struct omap_dss_device *in = ddata->in;
 279        int r;
 280
 281        if (ddata->ulps_enabled)
 282                return 0;
 283
 284        dsicm_cancel_ulps_work(ddata);
 285
 286        r = _dsicm_enable_te(ddata, false);
 287        if (r)
 288                goto err;
 289
 290        if (ddata->ext_te_gpio)
 291                disable_irq(gpiod_to_irq(ddata->ext_te_gpio));
 292
 293        in->ops.dsi->disable(in, false, true);
 294
 295        ddata->ulps_enabled = true;
 296
 297        return 0;
 298
 299err:
 300        dev_err(&ddata->pdev->dev, "enter ULPS failed");
 301        dsicm_panel_reset(ddata);
 302
 303        ddata->ulps_enabled = false;
 304
 305        dsicm_queue_ulps_work(ddata);
 306
 307        return r;
 308}
 309
 310static int dsicm_exit_ulps(struct panel_drv_data *ddata)
 311{
 312        struct omap_dss_device *in = ddata->in;
 313        int r;
 314
 315        if (!ddata->ulps_enabled)
 316                return 0;
 317
 318        r = in->ops.dsi->enable(in);
 319        if (r) {
 320                dev_err(&ddata->pdev->dev, "failed to enable DSI\n");
 321                goto err1;
 322        }
 323
 324        in->ops.dsi->enable_hs(in, ddata->channel, true);
 325
 326        r = _dsicm_enable_te(ddata, true);
 327        if (r) {
 328                dev_err(&ddata->pdev->dev, "failed to re-enable TE");
 329                goto err2;
 330        }
 331
 332        if (ddata->ext_te_gpio)
 333                enable_irq(gpiod_to_irq(ddata->ext_te_gpio));
 334
 335        dsicm_queue_ulps_work(ddata);
 336
 337        ddata->ulps_enabled = false;
 338
 339        return 0;
 340
 341err2:
 342        dev_err(&ddata->pdev->dev, "failed to exit ULPS");
 343
 344        r = dsicm_panel_reset(ddata);
 345        if (!r) {
 346                if (ddata->ext_te_gpio)
 347                        enable_irq(gpiod_to_irq(ddata->ext_te_gpio));
 348                ddata->ulps_enabled = false;
 349        }
 350err1:
 351        dsicm_queue_ulps_work(ddata);
 352
 353        return r;
 354}
 355
 356static int dsicm_wake_up(struct panel_drv_data *ddata)
 357{
 358        if (ddata->ulps_enabled)
 359                return dsicm_exit_ulps(ddata);
 360
 361        dsicm_cancel_ulps_work(ddata);
 362        dsicm_queue_ulps_work(ddata);
 363        return 0;
 364}
 365
 366static int dsicm_bl_update_status(struct backlight_device *dev)
 367{
 368        struct panel_drv_data *ddata = dev_get_drvdata(&dev->dev);
 369        struct omap_dss_device *in = ddata->in;
 370        int r = 0;
 371        int level;
 372
 373        if (dev->props.fb_blank == FB_BLANK_UNBLANK &&
 374                        dev->props.power == FB_BLANK_UNBLANK)
 375                level = dev->props.brightness;
 376        else
 377                level = 0;
 378
 379        dev_dbg(&ddata->pdev->dev, "update brightness to %d\n", level);
 380
 381        mutex_lock(&ddata->lock);
 382
 383        if (ddata->enabled) {
 384                in->ops.dsi->bus_lock(in);
 385
 386                r = dsicm_wake_up(ddata);
 387                if (!r)
 388                        r = dsicm_dcs_write_1(ddata, DCS_BRIGHTNESS, level);
 389
 390                in->ops.dsi->bus_unlock(in);
 391        }
 392
 393        mutex_unlock(&ddata->lock);
 394
 395        return r;
 396}
 397
 398static int dsicm_bl_get_intensity(struct backlight_device *dev)
 399{
 400        if (dev->props.fb_blank == FB_BLANK_UNBLANK &&
 401                        dev->props.power == FB_BLANK_UNBLANK)
 402                return dev->props.brightness;
 403
 404        return 0;
 405}
 406
 407static const struct backlight_ops dsicm_bl_ops = {
 408        .get_brightness = dsicm_bl_get_intensity,
 409        .update_status  = dsicm_bl_update_status,
 410};
 411
 412static ssize_t dsicm_num_errors_show(struct device *dev,
 413                struct device_attribute *attr, char *buf)
 414{
 415        struct platform_device *pdev = to_platform_device(dev);
 416        struct panel_drv_data *ddata = platform_get_drvdata(pdev);
 417        struct omap_dss_device *in = ddata->in;
 418        u8 errors = 0;
 419        int r;
 420
 421        mutex_lock(&ddata->lock);
 422
 423        if (ddata->enabled) {
 424                in->ops.dsi->bus_lock(in);
 425
 426                r = dsicm_wake_up(ddata);
 427                if (!r)
 428                        r = dsicm_dcs_read_1(ddata, DCS_READ_NUM_ERRORS,
 429                                        &errors);
 430
 431                in->ops.dsi->bus_unlock(in);
 432        } else {
 433                r = -ENODEV;
 434        }
 435
 436        mutex_unlock(&ddata->lock);
 437
 438        if (r)
 439                return r;
 440
 441        return snprintf(buf, PAGE_SIZE, "%d\n", errors);
 442}
 443
 444static ssize_t dsicm_hw_revision_show(struct device *dev,
 445                struct device_attribute *attr, char *buf)
 446{
 447        struct platform_device *pdev = to_platform_device(dev);
 448        struct panel_drv_data *ddata = platform_get_drvdata(pdev);
 449        struct omap_dss_device *in = ddata->in;
 450        u8 id1, id2, id3;
 451        int r;
 452
 453        mutex_lock(&ddata->lock);
 454
 455        if (ddata->enabled) {
 456                in->ops.dsi->bus_lock(in);
 457
 458                r = dsicm_wake_up(ddata);
 459                if (!r)
 460                        r = dsicm_get_id(ddata, &id1, &id2, &id3);
 461
 462                in->ops.dsi->bus_unlock(in);
 463        } else {
 464                r = -ENODEV;
 465        }
 466
 467        mutex_unlock(&ddata->lock);
 468
 469        if (r)
 470                return r;
 471
 472        return snprintf(buf, PAGE_SIZE, "%02x.%02x.%02x\n", id1, id2, id3);
 473}
 474
 475static ssize_t dsicm_store_ulps(struct device *dev,
 476                struct device_attribute *attr,
 477                const char *buf, size_t count)
 478{
 479        struct platform_device *pdev = to_platform_device(dev);
 480        struct panel_drv_data *ddata = platform_get_drvdata(pdev);
 481        struct omap_dss_device *in = ddata->in;
 482        unsigned long t;
 483        int r;
 484
 485        r = kstrtoul(buf, 0, &t);
 486        if (r)
 487                return r;
 488
 489        mutex_lock(&ddata->lock);
 490
 491        if (ddata->enabled) {
 492                in->ops.dsi->bus_lock(in);
 493
 494                if (t)
 495                        r = dsicm_enter_ulps(ddata);
 496                else
 497                        r = dsicm_wake_up(ddata);
 498
 499                in->ops.dsi->bus_unlock(in);
 500        }
 501
 502        mutex_unlock(&ddata->lock);
 503
 504        if (r)
 505                return r;
 506
 507        return count;
 508}
 509
 510static ssize_t dsicm_show_ulps(struct device *dev,
 511                struct device_attribute *attr,
 512                char *buf)
 513{
 514        struct platform_device *pdev = to_platform_device(dev);
 515        struct panel_drv_data *ddata = platform_get_drvdata(pdev);
 516        unsigned int t;
 517
 518        mutex_lock(&ddata->lock);
 519        t = ddata->ulps_enabled;
 520        mutex_unlock(&ddata->lock);
 521
 522        return snprintf(buf, PAGE_SIZE, "%u\n", t);
 523}
 524
 525static ssize_t dsicm_store_ulps_timeout(struct device *dev,
 526                struct device_attribute *attr,
 527                const char *buf, size_t count)
 528{
 529        struct platform_device *pdev = to_platform_device(dev);
 530        struct panel_drv_data *ddata = platform_get_drvdata(pdev);
 531        struct omap_dss_device *in = ddata->in;
 532        unsigned long t;
 533        int r;
 534
 535        r = kstrtoul(buf, 0, &t);
 536        if (r)
 537                return r;
 538
 539        mutex_lock(&ddata->lock);
 540        ddata->ulps_timeout = t;
 541
 542        if (ddata->enabled) {
 543                /* dsicm_wake_up will restart the timer */
 544                in->ops.dsi->bus_lock(in);
 545                r = dsicm_wake_up(ddata);
 546                in->ops.dsi->bus_unlock(in);
 547        }
 548
 549        mutex_unlock(&ddata->lock);
 550
 551        if (r)
 552                return r;
 553
 554        return count;
 555}
 556
 557static ssize_t dsicm_show_ulps_timeout(struct device *dev,
 558                struct device_attribute *attr,
 559                char *buf)
 560{
 561        struct platform_device *pdev = to_platform_device(dev);
 562        struct panel_drv_data *ddata = platform_get_drvdata(pdev);
 563        unsigned int t;
 564
 565        mutex_lock(&ddata->lock);
 566        t = ddata->ulps_timeout;
 567        mutex_unlock(&ddata->lock);
 568
 569        return snprintf(buf, PAGE_SIZE, "%u\n", t);
 570}
 571
 572static DEVICE_ATTR(num_dsi_errors, S_IRUGO, dsicm_num_errors_show, NULL);
 573static DEVICE_ATTR(hw_revision, S_IRUGO, dsicm_hw_revision_show, NULL);
 574static DEVICE_ATTR(ulps, S_IRUGO | S_IWUSR,
 575                dsicm_show_ulps, dsicm_store_ulps);
 576static DEVICE_ATTR(ulps_timeout, S_IRUGO | S_IWUSR,
 577                dsicm_show_ulps_timeout, dsicm_store_ulps_timeout);
 578
 579static struct attribute *dsicm_attrs[] = {
 580        &dev_attr_num_dsi_errors.attr,
 581        &dev_attr_hw_revision.attr,
 582        &dev_attr_ulps.attr,
 583        &dev_attr_ulps_timeout.attr,
 584        NULL,
 585};
 586
 587static const struct attribute_group dsicm_attr_group = {
 588        .attrs = dsicm_attrs,
 589};
 590
 591static void dsicm_hw_reset(struct panel_drv_data *ddata)
 592{
 593        gpiod_set_value(ddata->reset_gpio, 1);
 594        udelay(10);
 595        /* reset the panel */
 596        gpiod_set_value(ddata->reset_gpio, 0);
 597        /* assert reset */
 598        udelay(10);
 599        gpiod_set_value(ddata->reset_gpio, 1);
 600        /* wait after releasing reset */
 601        usleep_range(5000, 10000);
 602}
 603
 604static int dsicm_power_on(struct panel_drv_data *ddata)
 605{
 606        struct omap_dss_device *in = ddata->in;
 607        u8 id1, id2, id3;
 608        int r;
 609        struct omap_dss_dsi_config dsi_config = {
 610                .mode = OMAP_DSS_DSI_CMD_MODE,
 611                .pixel_format = OMAP_DSS_DSI_FMT_RGB888,
 612                .vm = &ddata->vm,
 613                .hs_clk_min = 150000000,
 614                .hs_clk_max = 300000000,
 615                .lp_clk_min = 7000000,
 616                .lp_clk_max = 10000000,
 617        };
 618
 619        if (ddata->vpnl) {
 620                r = regulator_enable(ddata->vpnl);
 621                if (r) {
 622                        dev_err(&ddata->pdev->dev,
 623                                "failed to enable VPNL: %d\n", r);
 624                        return r;
 625                }
 626        }
 627
 628        if (ddata->vddi) {
 629                r = regulator_enable(ddata->vddi);
 630                if (r) {
 631                        dev_err(&ddata->pdev->dev,
 632                                "failed to enable VDDI: %d\n", r);
 633                        goto err_vpnl;
 634                }
 635        }
 636
 637        if (ddata->pin_config.num_pins > 0) {
 638                r = in->ops.dsi->configure_pins(in, &ddata->pin_config);
 639                if (r) {
 640                        dev_err(&ddata->pdev->dev,
 641                                "failed to configure DSI pins\n");
 642                        goto err_vddi;
 643                }
 644        }
 645
 646        r = in->ops.dsi->set_config(in, &dsi_config);
 647        if (r) {
 648                dev_err(&ddata->pdev->dev, "failed to configure DSI\n");
 649                goto err_vddi;
 650        }
 651
 652        r = in->ops.dsi->enable(in);
 653        if (r) {
 654                dev_err(&ddata->pdev->dev, "failed to enable DSI\n");
 655                goto err_vddi;
 656        }
 657
 658        dsicm_hw_reset(ddata);
 659
 660        in->ops.dsi->enable_hs(in, ddata->channel, false);
 661
 662        r = dsicm_sleep_out(ddata);
 663        if (r)
 664                goto err;
 665
 666        r = dsicm_get_id(ddata, &id1, &id2, &id3);
 667        if (r)
 668                goto err;
 669
 670        r = dsicm_dcs_write_1(ddata, DCS_BRIGHTNESS, 0xff);
 671        if (r)
 672                goto err;
 673
 674        r = dsicm_dcs_write_1(ddata, DCS_CTRL_DISPLAY,
 675                        (1<<2) | (1<<5));       /* BL | BCTRL */
 676        if (r)
 677                goto err;
 678
 679        r = dsicm_dcs_write_1(ddata, MIPI_DCS_SET_PIXEL_FORMAT,
 680                MIPI_DCS_PIXEL_FMT_24BIT);
 681        if (r)
 682                goto err;
 683
 684        r = dsicm_dcs_write_0(ddata, MIPI_DCS_SET_DISPLAY_ON);
 685        if (r)
 686                goto err;
 687
 688        r = _dsicm_enable_te(ddata, ddata->te_enabled);
 689        if (r)
 690                goto err;
 691
 692        r = in->ops.dsi->enable_video_output(in, ddata->channel);
 693        if (r)
 694                goto err;
 695
 696        ddata->enabled = 1;
 697
 698        if (!ddata->intro_printed) {
 699                dev_info(&ddata->pdev->dev, "panel revision %02x.%02x.%02x\n",
 700                        id1, id2, id3);
 701                ddata->intro_printed = true;
 702        }
 703
 704        in->ops.dsi->enable_hs(in, ddata->channel, true);
 705
 706        return 0;
 707err:
 708        dev_err(&ddata->pdev->dev, "error while enabling panel, issuing HW reset\n");
 709
 710        dsicm_hw_reset(ddata);
 711
 712        in->ops.dsi->disable(in, true, false);
 713err_vddi:
 714        if (ddata->vddi)
 715                regulator_disable(ddata->vddi);
 716err_vpnl:
 717        if (ddata->vpnl)
 718                regulator_disable(ddata->vpnl);
 719
 720        return r;
 721}
 722
 723static void dsicm_power_off(struct panel_drv_data *ddata)
 724{
 725        struct omap_dss_device *in = ddata->in;
 726        int r;
 727
 728        in->ops.dsi->disable_video_output(in, ddata->channel);
 729
 730        r = dsicm_dcs_write_0(ddata, MIPI_DCS_SET_DISPLAY_OFF);
 731        if (!r)
 732                r = dsicm_sleep_in(ddata);
 733
 734        if (r) {
 735                dev_err(&ddata->pdev->dev,
 736                                "error disabling panel, issuing HW reset\n");
 737                dsicm_hw_reset(ddata);
 738        }
 739
 740        in->ops.dsi->disable(in, true, false);
 741
 742        if (ddata->vddi)
 743                regulator_disable(ddata->vddi);
 744        if (ddata->vpnl)
 745                regulator_disable(ddata->vpnl);
 746
 747        ddata->enabled = 0;
 748}
 749
 750static int dsicm_panel_reset(struct panel_drv_data *ddata)
 751{
 752        dev_err(&ddata->pdev->dev, "performing LCD reset\n");
 753
 754        dsicm_power_off(ddata);
 755        dsicm_hw_reset(ddata);
 756        return dsicm_power_on(ddata);
 757}
 758
 759static int dsicm_connect(struct omap_dss_device *dssdev)
 760{
 761        struct panel_drv_data *ddata = to_panel_data(dssdev);
 762        struct device *dev = &ddata->pdev->dev;
 763        struct omap_dss_device *in;
 764        int r;
 765
 766        if (omapdss_device_is_connected(dssdev))
 767                return 0;
 768
 769        in = omapdss_of_find_source_for_first_ep(dssdev->dev->of_node);
 770        if (IS_ERR(in)) {
 771                dev_err(dssdev->dev, "failed to find video source\n");
 772                return PTR_ERR(in);
 773        }
 774
 775        r = in->ops.dsi->connect(in, dssdev);
 776        if (r) {
 777                dev_err(dev, "Failed to connect to video source\n");
 778                goto err_connect;
 779        }
 780
 781        r = in->ops.dsi->request_vc(in, &ddata->channel);
 782        if (r) {
 783                dev_err(dev, "failed to get virtual channel\n");
 784                goto err_req_vc;
 785        }
 786
 787        r = in->ops.dsi->set_vc_id(in, ddata->channel, TCH);
 788        if (r) {
 789                dev_err(dev, "failed to set VC_ID\n");
 790                goto err_vc_id;
 791        }
 792
 793        ddata->in = in;
 794        return 0;
 795
 796err_vc_id:
 797        in->ops.dsi->release_vc(in, ddata->channel);
 798err_req_vc:
 799        in->ops.dsi->disconnect(in, dssdev);
 800err_connect:
 801        omap_dss_put_device(in);
 802        return r;
 803}
 804
 805static void dsicm_disconnect(struct omap_dss_device *dssdev)
 806{
 807        struct panel_drv_data *ddata = to_panel_data(dssdev);
 808        struct omap_dss_device *in = ddata->in;
 809
 810        if (!omapdss_device_is_connected(dssdev))
 811                return;
 812
 813        in->ops.dsi->release_vc(in, ddata->channel);
 814        in->ops.dsi->disconnect(in, dssdev);
 815
 816        omap_dss_put_device(in);
 817        ddata->in = NULL;
 818}
 819
 820static int dsicm_enable(struct omap_dss_device *dssdev)
 821{
 822        struct panel_drv_data *ddata = to_panel_data(dssdev);
 823        struct omap_dss_device *in = ddata->in;
 824        int r;
 825
 826        dev_dbg(&ddata->pdev->dev, "enable\n");
 827
 828        mutex_lock(&ddata->lock);
 829
 830        if (!omapdss_device_is_connected(dssdev)) {
 831                r = -ENODEV;
 832                goto err;
 833        }
 834
 835        if (omapdss_device_is_enabled(dssdev)) {
 836                r = 0;
 837                goto err;
 838        }
 839
 840        in->ops.dsi->bus_lock(in);
 841
 842        r = dsicm_power_on(ddata);
 843
 844        in->ops.dsi->bus_unlock(in);
 845
 846        if (r)
 847                goto err;
 848
 849        dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
 850
 851        mutex_unlock(&ddata->lock);
 852
 853        dsicm_bl_power(ddata, true);
 854
 855        return 0;
 856err:
 857        dev_dbg(&ddata->pdev->dev, "enable failed\n");
 858        mutex_unlock(&ddata->lock);
 859        return r;
 860}
 861
 862static void dsicm_disable(struct omap_dss_device *dssdev)
 863{
 864        struct panel_drv_data *ddata = to_panel_data(dssdev);
 865        struct omap_dss_device *in = ddata->in;
 866        int r;
 867
 868        dev_dbg(&ddata->pdev->dev, "disable\n");
 869
 870        dsicm_bl_power(ddata, false);
 871
 872        mutex_lock(&ddata->lock);
 873
 874        dsicm_cancel_ulps_work(ddata);
 875
 876        in->ops.dsi->bus_lock(in);
 877
 878        if (omapdss_device_is_enabled(dssdev)) {
 879                r = dsicm_wake_up(ddata);
 880                if (!r)
 881                        dsicm_power_off(ddata);
 882        }
 883
 884        in->ops.dsi->bus_unlock(in);
 885
 886        dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
 887
 888        mutex_unlock(&ddata->lock);
 889}
 890
 891static void dsicm_framedone_cb(int err, void *data)
 892{
 893        struct panel_drv_data *ddata = data;
 894        struct omap_dss_device *in = ddata->in;
 895
 896        dev_dbg(&ddata->pdev->dev, "framedone, err %d\n", err);
 897        in->ops.dsi->bus_unlock(ddata->in);
 898}
 899
 900static irqreturn_t dsicm_te_isr(int irq, void *data)
 901{
 902        struct panel_drv_data *ddata = data;
 903        struct omap_dss_device *in = ddata->in;
 904        int old;
 905        int r;
 906
 907        old = atomic_cmpxchg(&ddata->do_update, 1, 0);
 908
 909        if (old) {
 910                cancel_delayed_work(&ddata->te_timeout_work);
 911
 912                r = in->ops.dsi->update(in, ddata->channel, dsicm_framedone_cb,
 913                                ddata);
 914                if (r)
 915                        goto err;
 916        }
 917
 918        return IRQ_HANDLED;
 919err:
 920        dev_err(&ddata->pdev->dev, "start update failed\n");
 921        in->ops.dsi->bus_unlock(in);
 922        return IRQ_HANDLED;
 923}
 924
 925static void dsicm_te_timeout_work_callback(struct work_struct *work)
 926{
 927        struct panel_drv_data *ddata = container_of(work, struct panel_drv_data,
 928                                        te_timeout_work.work);
 929        struct omap_dss_device *in = ddata->in;
 930
 931        dev_err(&ddata->pdev->dev, "TE not received for 250ms!\n");
 932
 933        atomic_set(&ddata->do_update, 0);
 934        in->ops.dsi->bus_unlock(in);
 935}
 936
 937static int dsicm_update(struct omap_dss_device *dssdev,
 938                                    u16 x, u16 y, u16 w, u16 h)
 939{
 940        struct panel_drv_data *ddata = to_panel_data(dssdev);
 941        struct omap_dss_device *in = ddata->in;
 942        int r;
 943
 944        dev_dbg(&ddata->pdev->dev, "update %d, %d, %d x %d\n", x, y, w, h);
 945
 946        mutex_lock(&ddata->lock);
 947        in->ops.dsi->bus_lock(in);
 948
 949        r = dsicm_wake_up(ddata);
 950        if (r)
 951                goto err;
 952
 953        if (!ddata->enabled) {
 954                r = 0;
 955                goto err;
 956        }
 957
 958        /* XXX no need to send this every frame, but dsi break if not done */
 959        r = dsicm_set_update_window(ddata, 0, 0,
 960                        dssdev->panel.vm.hactive,
 961                        dssdev->panel.vm.vactive);
 962        if (r)
 963                goto err;
 964
 965        if (ddata->te_enabled && ddata->ext_te_gpio) {
 966                schedule_delayed_work(&ddata->te_timeout_work,
 967                                msecs_to_jiffies(250));
 968                atomic_set(&ddata->do_update, 1);
 969        } else {
 970                r = in->ops.dsi->update(in, ddata->channel, dsicm_framedone_cb,
 971                                ddata);
 972                if (r)
 973                        goto err;
 974        }
 975
 976        /* note: no bus_unlock here. unlock is in framedone_cb */
 977        mutex_unlock(&ddata->lock);
 978        return 0;
 979err:
 980        in->ops.dsi->bus_unlock(in);
 981        mutex_unlock(&ddata->lock);
 982        return r;
 983}
 984
 985static int dsicm_sync(struct omap_dss_device *dssdev)
 986{
 987        struct panel_drv_data *ddata = to_panel_data(dssdev);
 988        struct omap_dss_device *in = ddata->in;
 989
 990        dev_dbg(&ddata->pdev->dev, "sync\n");
 991
 992        mutex_lock(&ddata->lock);
 993        in->ops.dsi->bus_lock(in);
 994        in->ops.dsi->bus_unlock(in);
 995        mutex_unlock(&ddata->lock);
 996
 997        dev_dbg(&ddata->pdev->dev, "sync done\n");
 998
 999        return 0;
1000}
1001
1002static int _dsicm_enable_te(struct panel_drv_data *ddata, bool enable)
1003{
1004        struct omap_dss_device *in = ddata->in;
1005        int r;
1006
1007        if (enable)
1008                r = dsicm_dcs_write_1(ddata, MIPI_DCS_SET_TEAR_ON, 0);
1009        else
1010                r = dsicm_dcs_write_0(ddata, MIPI_DCS_SET_TEAR_OFF);
1011
1012        if (!ddata->ext_te_gpio)
1013                in->ops.dsi->enable_te(in, enable);
1014
1015        /* possible panel bug */
1016        msleep(100);
1017
1018        return r;
1019}
1020
1021static int dsicm_enable_te(struct omap_dss_device *dssdev, bool enable)
1022{
1023        struct panel_drv_data *ddata = to_panel_data(dssdev);
1024        struct omap_dss_device *in = ddata->in;
1025        int r;
1026
1027        mutex_lock(&ddata->lock);
1028
1029        if (ddata->te_enabled == enable)
1030                goto end;
1031
1032        in->ops.dsi->bus_lock(in);
1033
1034        if (ddata->enabled) {
1035                r = dsicm_wake_up(ddata);
1036                if (r)
1037                        goto err;
1038
1039                r = _dsicm_enable_te(ddata, enable);
1040                if (r)
1041                        goto err;
1042        }
1043
1044        ddata->te_enabled = enable;
1045
1046        in->ops.dsi->bus_unlock(in);
1047end:
1048        mutex_unlock(&ddata->lock);
1049
1050        return 0;
1051err:
1052        in->ops.dsi->bus_unlock(in);
1053        mutex_unlock(&ddata->lock);
1054
1055        return r;
1056}
1057
1058static int dsicm_get_te(struct omap_dss_device *dssdev)
1059{
1060        struct panel_drv_data *ddata = to_panel_data(dssdev);
1061        int r;
1062
1063        mutex_lock(&ddata->lock);
1064        r = ddata->te_enabled;
1065        mutex_unlock(&ddata->lock);
1066
1067        return r;
1068}
1069
1070static int dsicm_memory_read(struct omap_dss_device *dssdev,
1071                void *buf, size_t size,
1072                u16 x, u16 y, u16 w, u16 h)
1073{
1074        struct panel_drv_data *ddata = to_panel_data(dssdev);
1075        struct omap_dss_device *in = ddata->in;
1076        int r;
1077        int first = 1;
1078        int plen;
1079        unsigned int buf_used = 0;
1080
1081        if (size < w * h * 3)
1082                return -ENOMEM;
1083
1084        mutex_lock(&ddata->lock);
1085
1086        if (!ddata->enabled) {
1087                r = -ENODEV;
1088                goto err1;
1089        }
1090
1091        size = min((u32)w * h * 3,
1092                   dssdev->panel.vm.hactive * dssdev->panel.vm.vactive * 3);
1093
1094        in->ops.dsi->bus_lock(in);
1095
1096        r = dsicm_wake_up(ddata);
1097        if (r)
1098                goto err2;
1099
1100        /* plen 1 or 2 goes into short packet. until checksum error is fixed,
1101         * use short packets. plen 32 works, but bigger packets seem to cause
1102         * an error. */
1103        if (size % 2)
1104                plen = 1;
1105        else
1106                plen = 2;
1107
1108        dsicm_set_update_window(ddata, x, y, w, h);
1109
1110        r = in->ops.dsi->set_max_rx_packet_size(in, ddata->channel, plen);
1111        if (r)
1112                goto err2;
1113
1114        while (buf_used < size) {
1115                u8 dcs_cmd = first ? 0x2e : 0x3e;
1116                first = 0;
1117
1118                r = in->ops.dsi->dcs_read(in, ddata->channel, dcs_cmd,
1119                                buf + buf_used, size - buf_used);
1120
1121                if (r < 0) {
1122                        dev_err(dssdev->dev, "read error\n");
1123                        goto err3;
1124                }
1125
1126                buf_used += r;
1127
1128                if (r < plen) {
1129                        dev_err(&ddata->pdev->dev, "short read\n");
1130                        break;
1131                }
1132
1133                if (signal_pending(current)) {
1134                        dev_err(&ddata->pdev->dev, "signal pending, "
1135                                        "aborting memory read\n");
1136                        r = -ERESTARTSYS;
1137                        goto err3;
1138                }
1139        }
1140
1141        r = buf_used;
1142
1143err3:
1144        in->ops.dsi->set_max_rx_packet_size(in, ddata->channel, 1);
1145err2:
1146        in->ops.dsi->bus_unlock(in);
1147err1:
1148        mutex_unlock(&ddata->lock);
1149        return r;
1150}
1151
1152static void dsicm_ulps_work(struct work_struct *work)
1153{
1154        struct panel_drv_data *ddata = container_of(work, struct panel_drv_data,
1155                        ulps_work.work);
1156        struct omap_dss_device *dssdev = &ddata->dssdev;
1157        struct omap_dss_device *in = ddata->in;
1158
1159        mutex_lock(&ddata->lock);
1160
1161        if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE || !ddata->enabled) {
1162                mutex_unlock(&ddata->lock);
1163                return;
1164        }
1165
1166        in->ops.dsi->bus_lock(in);
1167
1168        dsicm_enter_ulps(ddata);
1169
1170        in->ops.dsi->bus_unlock(in);
1171        mutex_unlock(&ddata->lock);
1172}
1173
1174static void dsicm_get_timings(struct omap_dss_device *dssdev,
1175                              struct videomode *vm)
1176{
1177        struct panel_drv_data *ddata = to_panel_data(dssdev);
1178
1179        *vm = ddata->vm;
1180}
1181
1182static int dsicm_check_timings(struct omap_dss_device *dssdev,
1183                               struct videomode *vm)
1184{
1185        struct panel_drv_data *ddata = to_panel_data(dssdev);
1186        int ret = 0;
1187
1188        if (vm->hactive != ddata->vm.hactive)
1189                ret = -EINVAL;
1190
1191        if (vm->vactive != ddata->vm.vactive)
1192                ret = -EINVAL;
1193
1194        if (ret) {
1195                dev_warn(dssdev->dev, "wrong resolution: %d x %d",
1196                         vm->hactive, vm->vactive);
1197                dev_warn(dssdev->dev, "panel resolution: %d x %d",
1198                         ddata->vm.hactive, ddata->vm.vactive);
1199        }
1200
1201        return ret;
1202}
1203
1204static void dsicm_get_size(struct omap_dss_device *dssdev,
1205                          unsigned int *width, unsigned int *height)
1206{
1207        struct panel_drv_data *ddata = to_panel_data(dssdev);
1208
1209        *width = ddata->width_mm;
1210        *height = ddata->height_mm;
1211}
1212
1213static struct omap_dss_driver dsicm_ops = {
1214        .connect        = dsicm_connect,
1215        .disconnect     = dsicm_disconnect,
1216
1217        .enable         = dsicm_enable,
1218        .disable        = dsicm_disable,
1219
1220        .update         = dsicm_update,
1221        .sync           = dsicm_sync,
1222
1223        .get_timings    = dsicm_get_timings,
1224        .check_timings  = dsicm_check_timings,
1225        .get_size       = dsicm_get_size,
1226
1227        .enable_te      = dsicm_enable_te,
1228        .get_te         = dsicm_get_te,
1229
1230        .memory_read    = dsicm_memory_read,
1231};
1232
1233static int dsicm_probe_of(struct platform_device *pdev)
1234{
1235        struct device_node *node = pdev->dev.of_node;
1236        struct device_node *backlight;
1237        struct panel_drv_data *ddata = platform_get_drvdata(pdev);
1238        struct display_timing timing;
1239        int err;
1240
1241        ddata->reset_gpio = devm_gpiod_get(&pdev->dev, "reset", GPIOD_OUT_LOW);
1242        if (IS_ERR(ddata->reset_gpio)) {
1243                err = PTR_ERR(ddata->reset_gpio);
1244                dev_err(&pdev->dev, "reset gpio request failed: %d", err);
1245                return err;
1246        }
1247
1248        ddata->ext_te_gpio = devm_gpiod_get_optional(&pdev->dev, "te",
1249                                                     GPIOD_IN);
1250        if (IS_ERR(ddata->ext_te_gpio)) {
1251                err = PTR_ERR(ddata->ext_te_gpio);
1252                dev_err(&pdev->dev, "TE gpio request failed: %d", err);
1253                return err;
1254        }
1255
1256        err = of_get_display_timing(node, "panel-timing", &timing);
1257        if (!err) {
1258                videomode_from_timing(&timing, &ddata->vm);
1259                if (!ddata->vm.pixelclock)
1260                        ddata->vm.pixelclock =
1261                                ddata->vm.hactive * ddata->vm.vactive * 60;
1262        } else {
1263                dev_warn(&pdev->dev,
1264                         "failed to get video timing, using defaults\n");
1265        }
1266
1267        ddata->width_mm = 0;
1268        of_property_read_u32(node, "width-mm", &ddata->width_mm);
1269
1270        ddata->height_mm = 0;
1271        of_property_read_u32(node, "height-mm", &ddata->height_mm);
1272
1273        ddata->vpnl = devm_regulator_get_optional(&pdev->dev, "vpnl");
1274        if (IS_ERR(ddata->vpnl)) {
1275                err = PTR_ERR(ddata->vpnl);
1276                if (err == -EPROBE_DEFER)
1277                        return err;
1278                ddata->vpnl = NULL;
1279        }
1280
1281        ddata->vddi = devm_regulator_get_optional(&pdev->dev, "vddi");
1282        if (IS_ERR(ddata->vddi)) {
1283                err = PTR_ERR(ddata->vddi);
1284                if (err == -EPROBE_DEFER)
1285                        return err;
1286                ddata->vddi = NULL;
1287        }
1288
1289        backlight = of_parse_phandle(node, "backlight", 0);
1290        if (backlight) {
1291                ddata->extbldev = of_find_backlight_by_node(backlight);
1292                of_node_put(backlight);
1293
1294                if (!ddata->extbldev)
1295                        return -EPROBE_DEFER;
1296        } else {
1297                /* assume native backlight support */
1298                ddata->use_dsi_backlight = true;
1299        }
1300
1301        /* TODO: ulps */
1302
1303        return 0;
1304}
1305
1306static int dsicm_probe(struct platform_device *pdev)
1307{
1308        struct panel_drv_data *ddata;
1309        struct backlight_device *bldev = NULL;
1310        struct device *dev = &pdev->dev;
1311        struct omap_dss_device *dssdev;
1312        int r;
1313
1314        dev_dbg(dev, "probe\n");
1315
1316        ddata = devm_kzalloc(dev, sizeof(*ddata), GFP_KERNEL);
1317        if (!ddata)
1318                return -ENOMEM;
1319
1320        platform_set_drvdata(pdev, ddata);
1321        ddata->pdev = pdev;
1322
1323        ddata->vm.hactive = 864;
1324        ddata->vm.vactive = 480;
1325        ddata->vm.pixelclock = 864 * 480 * 60;
1326
1327        r = dsicm_probe_of(pdev);
1328        if (r)
1329                return r;
1330
1331        dssdev = &ddata->dssdev;
1332        dssdev->dev = dev;
1333        dssdev->driver = &dsicm_ops;
1334        dssdev->panel.vm = ddata->vm;
1335        dssdev->type = OMAP_DISPLAY_TYPE_DSI;
1336        dssdev->owner = THIS_MODULE;
1337
1338        dssdev->panel.dsi_pix_fmt = OMAP_DSS_DSI_FMT_RGB888;
1339        dssdev->caps = OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE |
1340                OMAP_DSS_DISPLAY_CAP_TEAR_ELIM;
1341
1342        r = omapdss_register_display(dssdev);
1343        if (r) {
1344                dev_err(dev, "Failed to register panel\n");
1345                goto err_reg;
1346        }
1347
1348        mutex_init(&ddata->lock);
1349
1350        atomic_set(&ddata->do_update, 0);
1351
1352        if (ddata->ext_te_gpio) {
1353                r = devm_request_irq(dev, gpiod_to_irq(ddata->ext_te_gpio),
1354                                dsicm_te_isr,
1355                                IRQF_TRIGGER_RISING,
1356                                "taal vsync", ddata);
1357
1358                if (r) {
1359                        dev_err(dev, "IRQ request failed\n");
1360                        goto err_reg;
1361                }
1362
1363                INIT_DEFERRABLE_WORK(&ddata->te_timeout_work,
1364                                        dsicm_te_timeout_work_callback);
1365
1366                dev_dbg(dev, "Using GPIO TE\n");
1367        }
1368
1369        ddata->workqueue = create_singlethread_workqueue("dsicm_wq");
1370        if (!ddata->workqueue) {
1371                r = -ENOMEM;
1372                goto err_reg;
1373        }
1374        INIT_DELAYED_WORK(&ddata->ulps_work, dsicm_ulps_work);
1375
1376        dsicm_hw_reset(ddata);
1377
1378        if (ddata->use_dsi_backlight) {
1379                struct backlight_properties props = { 0 };
1380                props.max_brightness = 255;
1381                props.type = BACKLIGHT_RAW;
1382
1383                bldev = devm_backlight_device_register(dev, dev_name(dev),
1384                        dev, ddata, &dsicm_bl_ops, &props);
1385                if (IS_ERR(bldev)) {
1386                        r = PTR_ERR(bldev);
1387                        goto err_bl;
1388                }
1389
1390                ddata->bldev = bldev;
1391        }
1392
1393        r = sysfs_create_group(&dev->kobj, &dsicm_attr_group);
1394        if (r) {
1395                dev_err(dev, "failed to create sysfs files\n");
1396                goto err_bl;
1397        }
1398
1399        return 0;
1400
1401err_bl:
1402        destroy_workqueue(ddata->workqueue);
1403err_reg:
1404        if (ddata->extbldev)
1405                put_device(&ddata->extbldev->dev);
1406
1407        return r;
1408}
1409
1410static int __exit dsicm_remove(struct platform_device *pdev)
1411{
1412        struct panel_drv_data *ddata = platform_get_drvdata(pdev);
1413        struct omap_dss_device *dssdev = &ddata->dssdev;
1414
1415        dev_dbg(&pdev->dev, "remove\n");
1416
1417        omapdss_unregister_display(dssdev);
1418
1419        dsicm_disable(dssdev);
1420        dsicm_disconnect(dssdev);
1421
1422        sysfs_remove_group(&pdev->dev.kobj, &dsicm_attr_group);
1423
1424        if (ddata->extbldev)
1425                put_device(&ddata->extbldev->dev);
1426
1427        dsicm_cancel_ulps_work(ddata);
1428        destroy_workqueue(ddata->workqueue);
1429
1430        /* reset, to be sure that the panel is in a valid state */
1431        dsicm_hw_reset(ddata);
1432
1433        return 0;
1434}
1435
1436static const struct of_device_id dsicm_of_match[] = {
1437        { .compatible = "omapdss,panel-dsi-cm", },
1438        {},
1439};
1440
1441MODULE_DEVICE_TABLE(of, dsicm_of_match);
1442
1443static struct platform_driver dsicm_driver = {
1444        .probe = dsicm_probe,
1445        .remove = __exit_p(dsicm_remove),
1446        .driver = {
1447                .name = "panel-dsi-cm",
1448                .of_match_table = dsicm_of_match,
1449                .suppress_bind_attrs = true,
1450        },
1451};
1452
1453module_platform_driver(dsicm_driver);
1454
1455MODULE_AUTHOR("Tomi Valkeinen <tomi.valkeinen@ti.com>");
1456MODULE_DESCRIPTION("Generic DSI Command Mode Panel Driver");
1457MODULE_LICENSE("GPL");
1458