root/drivers/gpu/drm/panel/panel-tpo-td043mtea1.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. td043mtea1_write
  2. td043mtea1_write_gamma
  3. td043mtea1_write_mirror
  4. td043mtea1_power_on
  5. td043mtea1_power_off
  6. vmirror_show
  7. vmirror_store
  8. mode_show
  9. mode_store
  10. gamma_show
  11. gamma_store
  12. td043mtea1_unprepare
  13. td043mtea1_prepare
  14. td043mtea1_get_modes
  15. td043mtea1_suspend
  16. td043mtea1_resume
  17. td043mtea1_probe
  18. td043mtea1_remove

   1 // SPDX-License-Identifier: GPL-2.0+
   2 /*
   3  * Toppoly TD043MTEA1 Panel Driver
   4  *
   5  * Copyright (C) 2019 Texas Instruments Incorporated
   6  *
   7  * Based on the omapdrm-specific panel-tpo-td043mtea1 driver
   8  *
   9  * Author: Gražvydas Ignotas <notasas@gmail.com>
  10  */
  11 
  12 #include <linux/delay.h>
  13 #include <linux/module.h>
  14 #include <linux/regulator/consumer.h>
  15 #include <linux/spi/spi.h>
  16 
  17 #include <drm/drm_connector.h>
  18 #include <drm/drm_modes.h>
  19 #include <drm/drm_panel.h>
  20 
  21 #define TPO_R02_MODE(x)                 ((x) & 7)
  22 #define TPO_R02_MODE_800x480            7
  23 #define TPO_R02_NCLK_RISING             BIT(3)
  24 #define TPO_R02_HSYNC_HIGH              BIT(4)
  25 #define TPO_R02_VSYNC_HIGH              BIT(5)
  26 
  27 #define TPO_R03_NSTANDBY                BIT(0)
  28 #define TPO_R03_EN_CP_CLK               BIT(1)
  29 #define TPO_R03_EN_VGL_PUMP             BIT(2)
  30 #define TPO_R03_EN_PWM                  BIT(3)
  31 #define TPO_R03_DRIVING_CAP_100         BIT(4)
  32 #define TPO_R03_EN_PRE_CHARGE           BIT(6)
  33 #define TPO_R03_SOFTWARE_CTL            BIT(7)
  34 
  35 #define TPO_R04_NFLIP_H                 BIT(0)
  36 #define TPO_R04_NFLIP_V                 BIT(1)
  37 #define TPO_R04_CP_CLK_FREQ_1H          BIT(2)
  38 #define TPO_R04_VGL_FREQ_1H             BIT(4)
  39 
  40 #define TPO_R03_VAL_NORMAL \
  41         (TPO_R03_NSTANDBY | TPO_R03_EN_CP_CLK | TPO_R03_EN_VGL_PUMP | \
  42          TPO_R03_EN_PWM | TPO_R03_DRIVING_CAP_100 | TPO_R03_EN_PRE_CHARGE | \
  43          TPO_R03_SOFTWARE_CTL)
  44 
  45 #define TPO_R03_VAL_STANDBY \
  46         (TPO_R03_DRIVING_CAP_100 | TPO_R03_EN_PRE_CHARGE | \
  47          TPO_R03_SOFTWARE_CTL)
  48 
  49 static const u16 td043mtea1_def_gamma[12] = {
  50         105, 315, 381, 431, 490, 537, 579, 686, 780, 837, 880, 1023
  51 };
  52 
  53 struct td043mtea1_panel {
  54         struct drm_panel panel;
  55 
  56         struct spi_device *spi;
  57         struct regulator *vcc_reg;
  58         struct gpio_desc *reset_gpio;
  59 
  60         unsigned int mode;
  61         u16 gamma[12];
  62         bool vmirror;
  63         bool powered_on;
  64         bool spi_suspended;
  65         bool power_on_resume;
  66 };
  67 
  68 #define to_td043mtea1_device(p) container_of(p, struct td043mtea1_panel, panel)
  69 
  70 /* -----------------------------------------------------------------------------
  71  * Hardware Access
  72  */
  73 
  74 static int td043mtea1_write(struct td043mtea1_panel *lcd, u8 addr, u8 value)
  75 {
  76         struct spi_message msg;
  77         struct spi_transfer xfer;
  78         u16 data;
  79         int ret;
  80 
  81         spi_message_init(&msg);
  82 
  83         memset(&xfer, 0, sizeof(xfer));
  84 
  85         data = ((u16)addr << 10) | (1 << 8) | value;
  86         xfer.tx_buf = &data;
  87         xfer.bits_per_word = 16;
  88         xfer.len = 2;
  89         spi_message_add_tail(&xfer, &msg);
  90 
  91         ret = spi_sync(lcd->spi, &msg);
  92         if (ret < 0)
  93                 dev_warn(&lcd->spi->dev, "failed to write to LCD reg (%d)\n",
  94                          ret);
  95 
  96         return ret;
  97 }
  98 
  99 static void td043mtea1_write_gamma(struct td043mtea1_panel *lcd)
 100 {
 101         const u16 *gamma = lcd->gamma;
 102         unsigned int i;
 103         u8 val;
 104 
 105         /* gamma bits [9:8] */
 106         for (val = i = 0; i < 4; i++)
 107                 val |= (gamma[i] & 0x300) >> ((i + 1) * 2);
 108         td043mtea1_write(lcd, 0x11, val);
 109 
 110         for (val = i = 0; i < 4; i++)
 111                 val |= (gamma[i + 4] & 0x300) >> ((i + 1) * 2);
 112         td043mtea1_write(lcd, 0x12, val);
 113 
 114         for (val = i = 0; i < 4; i++)
 115                 val |= (gamma[i + 8] & 0x300) >> ((i + 1) * 2);
 116         td043mtea1_write(lcd, 0x13, val);
 117 
 118         /* gamma bits [7:0] */
 119         for (i = 0; i < 12; i++)
 120                 td043mtea1_write(lcd, 0x14 + i, gamma[i] & 0xff);
 121 }
 122 
 123 static int td043mtea1_write_mirror(struct td043mtea1_panel *lcd)
 124 {
 125         u8 reg4 = TPO_R04_NFLIP_H | TPO_R04_NFLIP_V |
 126                 TPO_R04_CP_CLK_FREQ_1H | TPO_R04_VGL_FREQ_1H;
 127         if (lcd->vmirror)
 128                 reg4 &= ~TPO_R04_NFLIP_V;
 129 
 130         return td043mtea1_write(lcd, 4, reg4);
 131 }
 132 
 133 static int td043mtea1_power_on(struct td043mtea1_panel *lcd)
 134 {
 135         int ret;
 136 
 137         if (lcd->powered_on)
 138                 return 0;
 139 
 140         ret = regulator_enable(lcd->vcc_reg);
 141         if (ret < 0)
 142                 return ret;
 143 
 144         /* Wait for the panel to stabilize. */
 145         msleep(160);
 146 
 147         gpiod_set_value(lcd->reset_gpio, 0);
 148 
 149         td043mtea1_write(lcd, 2, TPO_R02_MODE(lcd->mode) | TPO_R02_NCLK_RISING);
 150         td043mtea1_write(lcd, 3, TPO_R03_VAL_NORMAL);
 151         td043mtea1_write(lcd, 0x20, 0xf0);
 152         td043mtea1_write(lcd, 0x21, 0xf0);
 153         td043mtea1_write_mirror(lcd);
 154         td043mtea1_write_gamma(lcd);
 155 
 156         lcd->powered_on = true;
 157 
 158         return 0;
 159 }
 160 
 161 static void td043mtea1_power_off(struct td043mtea1_panel *lcd)
 162 {
 163         if (!lcd->powered_on)
 164                 return;
 165 
 166         td043mtea1_write(lcd, 3, TPO_R03_VAL_STANDBY | TPO_R03_EN_PWM);
 167 
 168         gpiod_set_value(lcd->reset_gpio, 1);
 169 
 170         /* wait for at least 2 vsyncs before cutting off power */
 171         msleep(50);
 172 
 173         td043mtea1_write(lcd, 3, TPO_R03_VAL_STANDBY);
 174 
 175         regulator_disable(lcd->vcc_reg);
 176 
 177         lcd->powered_on = false;
 178 }
 179 
 180 /* -----------------------------------------------------------------------------
 181  * sysfs
 182  */
 183 
 184 static ssize_t vmirror_show(struct device *dev, struct device_attribute *attr,
 185                             char *buf)
 186 {
 187         struct td043mtea1_panel *lcd = dev_get_drvdata(dev);
 188 
 189         return snprintf(buf, PAGE_SIZE, "%d\n", lcd->vmirror);
 190 }
 191 
 192 static ssize_t vmirror_store(struct device *dev, struct device_attribute *attr,
 193                              const char *buf, size_t count)
 194 {
 195         struct td043mtea1_panel *lcd = dev_get_drvdata(dev);
 196         int val;
 197         int ret;
 198 
 199         ret = kstrtoint(buf, 0, &val);
 200         if (ret < 0)
 201                 return ret;
 202 
 203         lcd->vmirror = !!val;
 204 
 205         ret = td043mtea1_write_mirror(lcd);
 206         if (ret < 0)
 207                 return ret;
 208 
 209         return count;
 210 }
 211 
 212 static ssize_t mode_show(struct device *dev, struct device_attribute *attr,
 213                          char *buf)
 214 {
 215         struct td043mtea1_panel *lcd = dev_get_drvdata(dev);
 216 
 217         return snprintf(buf, PAGE_SIZE, "%d\n", lcd->mode);
 218 }
 219 
 220 static ssize_t mode_store(struct device *dev, struct device_attribute *attr,
 221                           const char *buf, size_t count)
 222 {
 223         struct td043mtea1_panel *lcd = dev_get_drvdata(dev);
 224         long val;
 225         int ret;
 226 
 227         ret = kstrtol(buf, 0, &val);
 228         if (ret != 0 || val & ~7)
 229                 return -EINVAL;
 230 
 231         lcd->mode = val;
 232 
 233         val |= TPO_R02_NCLK_RISING;
 234         td043mtea1_write(lcd, 2, val);
 235 
 236         return count;
 237 }
 238 
 239 static ssize_t gamma_show(struct device *dev, struct device_attribute *attr,
 240                           char *buf)
 241 {
 242         struct td043mtea1_panel *lcd = dev_get_drvdata(dev);
 243         ssize_t len = 0;
 244         unsigned int i;
 245         int ret;
 246 
 247         for (i = 0; i < ARRAY_SIZE(lcd->gamma); i++) {
 248                 ret = snprintf(buf + len, PAGE_SIZE - len, "%u ",
 249                                lcd->gamma[i]);
 250                 if (ret < 0)
 251                         return ret;
 252                 len += ret;
 253         }
 254         buf[len - 1] = '\n';
 255 
 256         return len;
 257 }
 258 
 259 static ssize_t gamma_store(struct device *dev, struct device_attribute *attr,
 260                            const char *buf, size_t count)
 261 {
 262         struct td043mtea1_panel *lcd = dev_get_drvdata(dev);
 263         unsigned int g[12];
 264         unsigned int i;
 265         int ret;
 266 
 267         ret = sscanf(buf, "%u %u %u %u %u %u %u %u %u %u %u %u",
 268                      &g[0], &g[1], &g[2], &g[3], &g[4], &g[5],
 269                      &g[6], &g[7], &g[8], &g[9], &g[10], &g[11]);
 270         if (ret != 12)
 271                 return -EINVAL;
 272 
 273         for (i = 0; i < 12; i++)
 274                 lcd->gamma[i] = g[i];
 275 
 276         td043mtea1_write_gamma(lcd);
 277 
 278         return count;
 279 }
 280 
 281 static DEVICE_ATTR_RW(vmirror);
 282 static DEVICE_ATTR_RW(mode);
 283 static DEVICE_ATTR_RW(gamma);
 284 
 285 static struct attribute *td043mtea1_attrs[] = {
 286         &dev_attr_vmirror.attr,
 287         &dev_attr_mode.attr,
 288         &dev_attr_gamma.attr,
 289         NULL,
 290 };
 291 
 292 static const struct attribute_group td043mtea1_attr_group = {
 293         .attrs = td043mtea1_attrs,
 294 };
 295 
 296 /* -----------------------------------------------------------------------------
 297  * Panel Operations
 298  */
 299 
 300 static int td043mtea1_unprepare(struct drm_panel *panel)
 301 {
 302         struct td043mtea1_panel *lcd = to_td043mtea1_device(panel);
 303 
 304         if (!lcd->spi_suspended)
 305                 td043mtea1_power_off(lcd);
 306 
 307         return 0;
 308 }
 309 
 310 static int td043mtea1_prepare(struct drm_panel *panel)
 311 {
 312         struct td043mtea1_panel *lcd = to_td043mtea1_device(panel);
 313         int ret;
 314 
 315         /*
 316          * If we are resuming from system suspend, SPI might not be enabled
 317          * yet, so we'll program the LCD from SPI PM resume callback.
 318          */
 319         if (lcd->spi_suspended)
 320                 return 0;
 321 
 322         ret = td043mtea1_power_on(lcd);
 323         if (ret) {
 324                 dev_err(&lcd->spi->dev, "%s: power on failed (%d)\n",
 325                         __func__, ret);
 326                 return ret;
 327         }
 328 
 329         return 0;
 330 }
 331 
 332 static const struct drm_display_mode td043mtea1_mode = {
 333         .clock = 36000,
 334         .hdisplay = 800,
 335         .hsync_start = 800 + 68,
 336         .hsync_end = 800 + 68 + 1,
 337         .htotal = 800 + 68 + 1 + 214,
 338         .vdisplay = 480,
 339         .vsync_start = 480 + 39,
 340         .vsync_end = 480 + 39 + 1,
 341         .vtotal = 480 + 39 + 1 + 34,
 342         .vrefresh = 60,
 343         .type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED,
 344         .flags = DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC,
 345         .width_mm = 94,
 346         .height_mm = 56,
 347 };
 348 
 349 static int td043mtea1_get_modes(struct drm_panel *panel)
 350 {
 351         struct drm_connector *connector = panel->connector;
 352         struct drm_display_mode *mode;
 353 
 354         mode = drm_mode_duplicate(panel->drm, &td043mtea1_mode);
 355         if (!mode)
 356                 return -ENOMEM;
 357 
 358         drm_mode_set_name(mode);
 359         drm_mode_probed_add(connector, mode);
 360 
 361         connector->display_info.width_mm = td043mtea1_mode.width_mm;
 362         connector->display_info.height_mm = td043mtea1_mode.height_mm;
 363         /*
 364          * FIXME: According to the datasheet sync signals are sampled on the
 365          * rising edge of the clock, but the code running on the OMAP3 Pandora
 366          * indicates sampling on the falling edge. This should be tested on a
 367          * real device.
 368          */
 369         connector->display_info.bus_flags = DRM_BUS_FLAG_DE_HIGH
 370                                           | DRM_BUS_FLAG_SYNC_SAMPLE_NEGEDGE
 371                                           | DRM_BUS_FLAG_PIXDATA_SAMPLE_POSEDGE;
 372 
 373         return 1;
 374 }
 375 
 376 static const struct drm_panel_funcs td043mtea1_funcs = {
 377         .unprepare = td043mtea1_unprepare,
 378         .prepare = td043mtea1_prepare,
 379         .get_modes = td043mtea1_get_modes,
 380 };
 381 
 382 /* -----------------------------------------------------------------------------
 383  * Power Management, Probe and Remove
 384  */
 385 
 386 static int __maybe_unused td043mtea1_suspend(struct device *dev)
 387 {
 388         struct td043mtea1_panel *lcd = dev_get_drvdata(dev);
 389 
 390         if (lcd->powered_on) {
 391                 td043mtea1_power_off(lcd);
 392                 lcd->powered_on = true;
 393         }
 394 
 395         lcd->spi_suspended = true;
 396 
 397         return 0;
 398 }
 399 
 400 static int __maybe_unused td043mtea1_resume(struct device *dev)
 401 {
 402         struct td043mtea1_panel *lcd = dev_get_drvdata(dev);
 403         int ret;
 404 
 405         lcd->spi_suspended = false;
 406 
 407         if (lcd->powered_on) {
 408                 lcd->powered_on = false;
 409                 ret = td043mtea1_power_on(lcd);
 410                 if (ret)
 411                         return ret;
 412         }
 413 
 414         return 0;
 415 }
 416 
 417 static SIMPLE_DEV_PM_OPS(td043mtea1_pm_ops, td043mtea1_suspend,
 418                          td043mtea1_resume);
 419 
 420 static int td043mtea1_probe(struct spi_device *spi)
 421 {
 422         struct td043mtea1_panel *lcd;
 423         int ret;
 424 
 425         lcd = devm_kzalloc(&spi->dev, sizeof(*lcd), GFP_KERNEL);
 426         if (lcd == NULL)
 427                 return -ENOMEM;
 428 
 429         spi_set_drvdata(spi, lcd);
 430         lcd->spi = spi;
 431         lcd->mode = TPO_R02_MODE_800x480;
 432         memcpy(lcd->gamma, td043mtea1_def_gamma, sizeof(lcd->gamma));
 433 
 434         lcd->vcc_reg = devm_regulator_get(&spi->dev, "vcc");
 435         if (IS_ERR(lcd->vcc_reg)) {
 436                 dev_err(&spi->dev, "failed to get VCC regulator\n");
 437                 return PTR_ERR(lcd->vcc_reg);
 438         }
 439 
 440         lcd->reset_gpio = devm_gpiod_get(&spi->dev, "reset", GPIOD_OUT_HIGH);
 441         if (IS_ERR(lcd->reset_gpio)) {
 442                 dev_err(&spi->dev, "failed to get reset GPIO\n");
 443                 return PTR_ERR(lcd->reset_gpio);
 444         }
 445 
 446         spi->bits_per_word = 16;
 447         spi->mode = SPI_MODE_0;
 448 
 449         ret = spi_setup(spi);
 450         if (ret < 0) {
 451                 dev_err(&spi->dev, "failed to setup SPI: %d\n", ret);
 452                 return ret;
 453         }
 454 
 455         ret = sysfs_create_group(&spi->dev.kobj, &td043mtea1_attr_group);
 456         if (ret < 0) {
 457                 dev_err(&spi->dev, "failed to create sysfs files\n");
 458                 return ret;
 459         }
 460 
 461         drm_panel_init(&lcd->panel);
 462         lcd->panel.dev = &lcd->spi->dev;
 463         lcd->panel.funcs = &td043mtea1_funcs;
 464 
 465         ret = drm_panel_add(&lcd->panel);
 466         if (ret < 0) {
 467                 sysfs_remove_group(&spi->dev.kobj, &td043mtea1_attr_group);
 468                 return ret;
 469         }
 470 
 471         return 0;
 472 }
 473 
 474 static int td043mtea1_remove(struct spi_device *spi)
 475 {
 476         struct td043mtea1_panel *lcd = spi_get_drvdata(spi);
 477 
 478         drm_panel_remove(&lcd->panel);
 479         drm_panel_disable(&lcd->panel);
 480         drm_panel_unprepare(&lcd->panel);
 481 
 482         sysfs_remove_group(&spi->dev.kobj, &td043mtea1_attr_group);
 483 
 484         return 0;
 485 }
 486 
 487 static const struct of_device_id td043mtea1_of_match[] = {
 488         { .compatible = "tpo,td043mtea1", },
 489         { /* sentinel */ },
 490 };
 491 
 492 MODULE_DEVICE_TABLE(of, td043mtea1_of_match);
 493 
 494 static const struct spi_device_id td043mtea1_ids[] = {
 495         { "td043mtea1", 0 },
 496         { /* sentinel */ }
 497 };
 498 
 499 MODULE_DEVICE_TABLE(spi, td043mtea1_ids);
 500 
 501 static struct spi_driver td043mtea1_driver = {
 502         .probe          = td043mtea1_probe,
 503         .remove         = td043mtea1_remove,
 504         .id_table       = td043mtea1_ids,
 505         .driver         = {
 506                 .name   = "panel-tpo-td043mtea1",
 507                 .pm     = &td043mtea1_pm_ops,
 508                 .of_match_table = td043mtea1_of_match,
 509         },
 510 };
 511 
 512 module_spi_driver(td043mtea1_driver);
 513 
 514 MODULE_AUTHOR("Gražvydas Ignotas <notasas@gmail.com>");
 515 MODULE_DESCRIPTION("TPO TD043MTEA1 Panel Driver");
 516 MODULE_LICENSE("GPL");

/* [<][>][^][v][top][bottom][index][help] */