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