linux/drivers/gpu/drm/omapdrm/displays/panel-tpo-td043mtea1.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-or-later
   2/*
   3 * TPO TD043MTEA1 Panel driver
   4 *
   5 * Author: Gražvydas Ignotas <notasas@gmail.com>
   6 * Converted to new DSS device model: Tomi Valkeinen <tomi.valkeinen@ti.com>
   7 */
   8
   9#include <linux/delay.h>
  10#include <linux/err.h>
  11#include <linux/gpio/consumer.h>
  12#include <linux/module.h>
  13#include <linux/regulator/consumer.h>
  14#include <linux/slab.h>
  15#include <linux/spi/spi.h>
  16
  17#include "../dss/omapdss.h"
  18
  19#define TPO_R02_MODE(x)         ((x) & 7)
  20#define TPO_R02_MODE_800x480    7
  21#define TPO_R02_NCLK_RISING     BIT(3)
  22#define TPO_R02_HSYNC_HIGH      BIT(4)
  23#define TPO_R02_VSYNC_HIGH      BIT(5)
  24
  25#define TPO_R03_NSTANDBY        BIT(0)
  26#define TPO_R03_EN_CP_CLK       BIT(1)
  27#define TPO_R03_EN_VGL_PUMP     BIT(2)
  28#define TPO_R03_EN_PWM          BIT(3)
  29#define TPO_R03_DRIVING_CAP_100 BIT(4)
  30#define TPO_R03_EN_PRE_CHARGE   BIT(6)
  31#define TPO_R03_SOFTWARE_CTL    BIT(7)
  32
  33#define TPO_R04_NFLIP_H         BIT(0)
  34#define TPO_R04_NFLIP_V         BIT(1)
  35#define TPO_R04_CP_CLK_FREQ_1H  BIT(2)
  36#define TPO_R04_VGL_FREQ_1H     BIT(4)
  37
  38#define TPO_R03_VAL_NORMAL (TPO_R03_NSTANDBY | TPO_R03_EN_CP_CLK | \
  39                        TPO_R03_EN_VGL_PUMP |  TPO_R03_EN_PWM | \
  40                        TPO_R03_DRIVING_CAP_100 | TPO_R03_EN_PRE_CHARGE | \
  41                        TPO_R03_SOFTWARE_CTL)
  42
  43#define TPO_R03_VAL_STANDBY (TPO_R03_DRIVING_CAP_100 | \
  44                        TPO_R03_EN_PRE_CHARGE | TPO_R03_SOFTWARE_CTL)
  45
  46static const u16 tpo_td043_def_gamma[12] = {
  47        105, 315, 381, 431, 490, 537, 579, 686, 780, 837, 880, 1023
  48};
  49
  50struct panel_drv_data {
  51        struct omap_dss_device  dssdev;
  52
  53        struct videomode vm;
  54
  55        struct spi_device *spi;
  56        struct regulator *vcc_reg;
  57        struct gpio_desc *reset_gpio;
  58        u16 gamma[12];
  59        u32 mode;
  60        u32 vmirror:1;
  61        u32 powered_on:1;
  62        u32 spi_suspended:1;
  63        u32 power_on_resume:1;
  64};
  65
  66static const struct videomode tpo_td043_vm = {
  67        .hactive        = 800,
  68        .vactive        = 480,
  69
  70        .pixelclock     = 36000000,
  71
  72        .hsync_len      = 1,
  73        .hfront_porch   = 68,
  74        .hback_porch    = 214,
  75
  76        .vsync_len      = 1,
  77        .vfront_porch   = 39,
  78        .vback_porch    = 34,
  79
  80        .flags          = DISPLAY_FLAGS_HSYNC_LOW | DISPLAY_FLAGS_VSYNC_LOW,
  81};
  82
  83#define to_panel_data(p) container_of(p, struct panel_drv_data, dssdev)
  84
  85static int tpo_td043_write(struct spi_device *spi, u8 addr, u8 data)
  86{
  87        struct spi_message      m;
  88        struct spi_transfer     xfer;
  89        u16                     w;
  90        int                     r;
  91
  92        spi_message_init(&m);
  93
  94        memset(&xfer, 0, sizeof(xfer));
  95
  96        w = ((u16)addr << 10) | (1 << 8) | data;
  97        xfer.tx_buf = &w;
  98        xfer.bits_per_word = 16;
  99        xfer.len = 2;
 100        spi_message_add_tail(&xfer, &m);
 101
 102        r = spi_sync(spi, &m);
 103        if (r < 0)
 104                dev_warn(&spi->dev, "failed to write to LCD reg (%d)\n", r);
 105        return r;
 106}
 107
 108static void tpo_td043_write_gamma(struct spi_device *spi, u16 gamma[12])
 109{
 110        u8 i, val;
 111
 112        /* gamma bits [9:8] */
 113        for (val = i = 0; i < 4; i++)
 114                val |= (gamma[i] & 0x300) >> ((i + 1) * 2);
 115        tpo_td043_write(spi, 0x11, val);
 116
 117        for (val = i = 0; i < 4; i++)
 118                val |= (gamma[i+4] & 0x300) >> ((i + 1) * 2);
 119        tpo_td043_write(spi, 0x12, val);
 120
 121        for (val = i = 0; i < 4; i++)
 122                val |= (gamma[i+8] & 0x300) >> ((i + 1) * 2);
 123        tpo_td043_write(spi, 0x13, val);
 124
 125        /* gamma bits [7:0] */
 126        for (val = i = 0; i < 12; i++)
 127                tpo_td043_write(spi, 0x14 + i, gamma[i] & 0xff);
 128}
 129
 130static int tpo_td043_write_mirror(struct spi_device *spi, bool h, bool v)
 131{
 132        u8 reg4 = TPO_R04_NFLIP_H | TPO_R04_NFLIP_V |
 133                TPO_R04_CP_CLK_FREQ_1H | TPO_R04_VGL_FREQ_1H;
 134        if (h)
 135                reg4 &= ~TPO_R04_NFLIP_H;
 136        if (v)
 137                reg4 &= ~TPO_R04_NFLIP_V;
 138
 139        return tpo_td043_write(spi, 4, reg4);
 140}
 141
 142static ssize_t tpo_td043_vmirror_show(struct device *dev,
 143        struct device_attribute *attr, char *buf)
 144{
 145        struct panel_drv_data *ddata = dev_get_drvdata(dev);
 146
 147        return snprintf(buf, PAGE_SIZE, "%d\n", ddata->vmirror);
 148}
 149
 150static ssize_t tpo_td043_vmirror_store(struct device *dev,
 151        struct device_attribute *attr, const char *buf, size_t count)
 152{
 153        struct panel_drv_data *ddata = dev_get_drvdata(dev);
 154        int val;
 155        int ret;
 156
 157        ret = kstrtoint(buf, 0, &val);
 158        if (ret < 0)
 159                return ret;
 160
 161        val = !!val;
 162
 163        ret = tpo_td043_write_mirror(ddata->spi, false, val);
 164        if (ret < 0)
 165                return ret;
 166
 167        ddata->vmirror = val;
 168
 169        return count;
 170}
 171
 172static ssize_t tpo_td043_mode_show(struct device *dev,
 173        struct device_attribute *attr, char *buf)
 174{
 175        struct panel_drv_data *ddata = dev_get_drvdata(dev);
 176
 177        return snprintf(buf, PAGE_SIZE, "%d\n", ddata->mode);
 178}
 179
 180static ssize_t tpo_td043_mode_store(struct device *dev,
 181        struct device_attribute *attr, const char *buf, size_t count)
 182{
 183        struct panel_drv_data *ddata = dev_get_drvdata(dev);
 184        long val;
 185        int ret;
 186
 187        ret = kstrtol(buf, 0, &val);
 188        if (ret != 0 || val & ~7)
 189                return -EINVAL;
 190
 191        ddata->mode = val;
 192
 193        val |= TPO_R02_NCLK_RISING;
 194        tpo_td043_write(ddata->spi, 2, val);
 195
 196        return count;
 197}
 198
 199static ssize_t tpo_td043_gamma_show(struct device *dev,
 200        struct device_attribute *attr, char *buf)
 201{
 202        struct panel_drv_data *ddata = dev_get_drvdata(dev);
 203        ssize_t len = 0;
 204        int ret;
 205        int i;
 206
 207        for (i = 0; i < ARRAY_SIZE(ddata->gamma); i++) {
 208                ret = snprintf(buf + len, PAGE_SIZE - len, "%u ",
 209                                ddata->gamma[i]);
 210                if (ret < 0)
 211                        return ret;
 212                len += ret;
 213        }
 214        buf[len - 1] = '\n';
 215
 216        return len;
 217}
 218
 219static ssize_t tpo_td043_gamma_store(struct device *dev,
 220        struct device_attribute *attr, const char *buf, size_t count)
 221{
 222        struct panel_drv_data *ddata = dev_get_drvdata(dev);
 223        unsigned int g[12];
 224        int ret;
 225        int i;
 226
 227        ret = sscanf(buf, "%u %u %u %u %u %u %u %u %u %u %u %u",
 228                        &g[0], &g[1], &g[2], &g[3], &g[4], &g[5],
 229                        &g[6], &g[7], &g[8], &g[9], &g[10], &g[11]);
 230
 231        if (ret != 12)
 232                return -EINVAL;
 233
 234        for (i = 0; i < 12; i++)
 235                ddata->gamma[i] = g[i];
 236
 237        tpo_td043_write_gamma(ddata->spi, ddata->gamma);
 238
 239        return count;
 240}
 241
 242static DEVICE_ATTR(vmirror, S_IRUGO | S_IWUSR,
 243                tpo_td043_vmirror_show, tpo_td043_vmirror_store);
 244static DEVICE_ATTR(mode, S_IRUGO | S_IWUSR,
 245                tpo_td043_mode_show, tpo_td043_mode_store);
 246static DEVICE_ATTR(gamma, S_IRUGO | S_IWUSR,
 247                tpo_td043_gamma_show, tpo_td043_gamma_store);
 248
 249static struct attribute *tpo_td043_attrs[] = {
 250        &dev_attr_vmirror.attr,
 251        &dev_attr_mode.attr,
 252        &dev_attr_gamma.attr,
 253        NULL,
 254};
 255
 256static const struct attribute_group tpo_td043_attr_group = {
 257        .attrs = tpo_td043_attrs,
 258};
 259
 260static int tpo_td043_power_on(struct panel_drv_data *ddata)
 261{
 262        int r;
 263
 264        if (ddata->powered_on)
 265                return 0;
 266
 267        r = regulator_enable(ddata->vcc_reg);
 268        if (r != 0)
 269                return r;
 270
 271        /* wait for panel to stabilize */
 272        msleep(160);
 273
 274        gpiod_set_value(ddata->reset_gpio, 0);
 275
 276        tpo_td043_write(ddata->spi, 2,
 277                        TPO_R02_MODE(ddata->mode) | TPO_R02_NCLK_RISING);
 278        tpo_td043_write(ddata->spi, 3, TPO_R03_VAL_NORMAL);
 279        tpo_td043_write(ddata->spi, 0x20, 0xf0);
 280        tpo_td043_write(ddata->spi, 0x21, 0xf0);
 281        tpo_td043_write_mirror(ddata->spi, false, ddata->vmirror);
 282        tpo_td043_write_gamma(ddata->spi, ddata->gamma);
 283
 284        ddata->powered_on = 1;
 285        return 0;
 286}
 287
 288static void tpo_td043_power_off(struct panel_drv_data *ddata)
 289{
 290        if (!ddata->powered_on)
 291                return;
 292
 293        tpo_td043_write(ddata->spi, 3,
 294                        TPO_R03_VAL_STANDBY | TPO_R03_EN_PWM);
 295
 296        gpiod_set_value(ddata->reset_gpio, 1);
 297
 298        /* wait for at least 2 vsyncs before cutting off power */
 299        msleep(50);
 300
 301        tpo_td043_write(ddata->spi, 3, TPO_R03_VAL_STANDBY);
 302
 303        regulator_disable(ddata->vcc_reg);
 304
 305        ddata->powered_on = 0;
 306}
 307
 308static int tpo_td043_connect(struct omap_dss_device *src,
 309                             struct omap_dss_device *dst)
 310{
 311        return 0;
 312}
 313
 314static void tpo_td043_disconnect(struct omap_dss_device *src,
 315                                 struct omap_dss_device *dst)
 316{
 317}
 318
 319static void tpo_td043_enable(struct omap_dss_device *dssdev)
 320{
 321        struct panel_drv_data *ddata = to_panel_data(dssdev);
 322        int r;
 323
 324        /*
 325         * If we are resuming from system suspend, SPI clocks might not be
 326         * enabled yet, so we'll program the LCD from SPI PM resume callback.
 327         */
 328        if (!ddata->spi_suspended) {
 329                r = tpo_td043_power_on(ddata);
 330                if (r) {
 331                        dev_err(&ddata->spi->dev, "%s: power on failed (%d)\n",
 332                                __func__, r);
 333                        return;
 334                }
 335        }
 336}
 337
 338static void tpo_td043_disable(struct omap_dss_device *dssdev)
 339{
 340        struct panel_drv_data *ddata = to_panel_data(dssdev);
 341
 342        if (!ddata->spi_suspended)
 343                tpo_td043_power_off(ddata);
 344}
 345
 346static int tpo_td043_get_modes(struct omap_dss_device *dssdev,
 347                               struct drm_connector *connector)
 348{
 349        struct panel_drv_data *ddata = to_panel_data(dssdev);
 350
 351        return omapdss_display_get_modes(connector, &ddata->vm);
 352}
 353
 354static const struct omap_dss_device_ops tpo_td043_ops = {
 355        .connect        = tpo_td043_connect,
 356        .disconnect     = tpo_td043_disconnect,
 357
 358        .enable         = tpo_td043_enable,
 359        .disable        = tpo_td043_disable,
 360
 361        .get_modes      = tpo_td043_get_modes,
 362};
 363
 364static int tpo_td043_probe(struct spi_device *spi)
 365{
 366        struct panel_drv_data *ddata;
 367        struct omap_dss_device *dssdev;
 368        struct gpio_desc *gpio;
 369        int r;
 370
 371        dev_dbg(&spi->dev, "%s\n", __func__);
 372
 373        spi->bits_per_word = 16;
 374        spi->mode = SPI_MODE_0;
 375
 376        r = spi_setup(spi);
 377        if (r < 0) {
 378                dev_err(&spi->dev, "spi_setup failed: %d\n", r);
 379                return r;
 380        }
 381
 382        ddata = devm_kzalloc(&spi->dev, sizeof(*ddata), GFP_KERNEL);
 383        if (ddata == NULL)
 384                return -ENOMEM;
 385
 386        dev_set_drvdata(&spi->dev, ddata);
 387
 388        ddata->spi = spi;
 389
 390        ddata->mode = TPO_R02_MODE_800x480;
 391        memcpy(ddata->gamma, tpo_td043_def_gamma, sizeof(ddata->gamma));
 392
 393        ddata->vcc_reg = devm_regulator_get(&spi->dev, "vcc");
 394        if (IS_ERR(ddata->vcc_reg)) {
 395                dev_err(&spi->dev, "failed to get LCD VCC regulator\n");
 396                return PTR_ERR(ddata->vcc_reg);
 397        }
 398
 399        gpio = devm_gpiod_get(&spi->dev, "reset", GPIOD_OUT_HIGH);
 400        if (IS_ERR(gpio)) {
 401                dev_err(&spi->dev, "failed to get reset gpio\n");
 402                return PTR_ERR(gpio);
 403        }
 404
 405        ddata->reset_gpio = gpio;
 406
 407        r = sysfs_create_group(&spi->dev.kobj, &tpo_td043_attr_group);
 408        if (r) {
 409                dev_err(&spi->dev, "failed to create sysfs files\n");
 410                return r;
 411        }
 412
 413        ddata->vm = tpo_td043_vm;
 414
 415        dssdev = &ddata->dssdev;
 416        dssdev->dev = &spi->dev;
 417        dssdev->ops = &tpo_td043_ops;
 418        dssdev->type = OMAP_DISPLAY_TYPE_DPI;
 419        dssdev->display = true;
 420        dssdev->owner = THIS_MODULE;
 421        dssdev->of_ports = BIT(0);
 422        dssdev->ops_flags = OMAP_DSS_DEVICE_OP_MODES;
 423
 424        /*
 425         * Note: According to the panel documentation:
 426         * SYNC needs to be driven on the FALLING edge
 427         */
 428        dssdev->bus_flags = DRM_BUS_FLAG_DE_HIGH
 429                          | DRM_BUS_FLAG_SYNC_DRIVE_POSEDGE
 430                          | DRM_BUS_FLAG_PIXDATA_DRIVE_NEGEDGE;
 431
 432        omapdss_display_init(dssdev);
 433        omapdss_device_register(dssdev);
 434
 435        return 0;
 436}
 437
 438static int tpo_td043_remove(struct spi_device *spi)
 439{
 440        struct panel_drv_data *ddata = dev_get_drvdata(&spi->dev);
 441        struct omap_dss_device *dssdev = &ddata->dssdev;
 442
 443        dev_dbg(&ddata->spi->dev, "%s\n", __func__);
 444
 445        omapdss_device_unregister(dssdev);
 446
 447        if (omapdss_device_is_enabled(dssdev))
 448                tpo_td043_disable(dssdev);
 449
 450        sysfs_remove_group(&spi->dev.kobj, &tpo_td043_attr_group);
 451
 452        return 0;
 453}
 454
 455#ifdef CONFIG_PM_SLEEP
 456static int tpo_td043_spi_suspend(struct device *dev)
 457{
 458        struct panel_drv_data *ddata = dev_get_drvdata(dev);
 459
 460        dev_dbg(dev, "tpo_td043_spi_suspend, tpo %p\n", ddata);
 461
 462        ddata->power_on_resume = ddata->powered_on;
 463        tpo_td043_power_off(ddata);
 464        ddata->spi_suspended = 1;
 465
 466        return 0;
 467}
 468
 469static int tpo_td043_spi_resume(struct device *dev)
 470{
 471        struct panel_drv_data *ddata = dev_get_drvdata(dev);
 472        int ret;
 473
 474        dev_dbg(dev, "tpo_td043_spi_resume\n");
 475
 476        if (ddata->power_on_resume) {
 477                ret = tpo_td043_power_on(ddata);
 478                if (ret)
 479                        return ret;
 480        }
 481        ddata->spi_suspended = 0;
 482
 483        return 0;
 484}
 485#endif
 486
 487static SIMPLE_DEV_PM_OPS(tpo_td043_spi_pm,
 488        tpo_td043_spi_suspend, tpo_td043_spi_resume);
 489
 490static const struct of_device_id tpo_td043_of_match[] = {
 491        { .compatible = "omapdss,tpo,td043mtea1", },
 492        {},
 493};
 494
 495MODULE_DEVICE_TABLE(of, tpo_td043_of_match);
 496
 497static struct spi_driver tpo_td043_spi_driver = {
 498        .driver = {
 499                .name   = "panel-tpo-td043mtea1",
 500                .pm     = &tpo_td043_spi_pm,
 501                .of_match_table = tpo_td043_of_match,
 502                .suppress_bind_attrs = true,
 503        },
 504        .probe  = tpo_td043_probe,
 505        .remove = tpo_td043_remove,
 506};
 507
 508module_spi_driver(tpo_td043_spi_driver);
 509
 510MODULE_ALIAS("spi:tpo,td043mtea1");
 511MODULE_AUTHOR("Gražvydas Ignotas <notasas@gmail.com>");
 512MODULE_DESCRIPTION("TPO TD043MTEA1 LCD Driver");
 513MODULE_LICENSE("GPL");
 514