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

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

DEFINITIONS

This source file includes following definitions.
  1. to_tpg110
  2. tpg110_readwrite_reg
  3. tpg110_read_reg
  4. tpg110_write_reg
  5. tpg110_startup
  6. tpg110_disable
  7. tpg110_enable
  8. tpg110_get_modes
  9. tpg110_probe
  10. tpg110_remove

   1 // SPDX-License-Identifier: GPL-2.0
   2 /*
   3  * Panel driver for the TPO TPG110 400CH LTPS TFT LCD Single Chip
   4  * Digital Driver.
   5  *
   6  * This chip drives a TFT LCD, so it does not know what kind of
   7  * display is actually connected to it, so the width and height of that
   8  * display needs to be supplied from the machine configuration.
   9  *
  10  * Author:
  11  * Linus Walleij <linus.walleij@linaro.org>
  12  */
  13 #include <drm/drm_modes.h>
  14 #include <drm/drm_panel.h>
  15 #include <drm/drm_print.h>
  16 
  17 #include <linux/backlight.h>
  18 #include <linux/bitops.h>
  19 #include <linux/delay.h>
  20 #include <linux/gpio/consumer.h>
  21 #include <linux/init.h>
  22 #include <linux/kernel.h>
  23 #include <linux/module.h>
  24 #include <linux/platform_device.h>
  25 #include <linux/spi/spi.h>
  26 
  27 #define TPG110_TEST                     0x00
  28 #define TPG110_CHIPID                   0x01
  29 #define TPG110_CTRL1                    0x02
  30 #define TPG110_RES_MASK                 GENMASK(2, 0)
  31 #define TPG110_RES_800X480              0x07
  32 #define TPG110_RES_640X480              0x06
  33 #define TPG110_RES_480X272              0x05
  34 #define TPG110_RES_480X640              0x04
  35 #define TPG110_RES_480X272_D            0x01 /* Dual scan: outputs 800x480 */
  36 #define TPG110_RES_400X240_D            0x00 /* Dual scan: outputs 800x480 */
  37 #define TPG110_CTRL2                    0x03
  38 #define TPG110_CTRL2_PM                 BIT(0)
  39 #define TPG110_CTRL2_RES_PM_CTRL        BIT(7)
  40 
  41 /**
  42  * struct tpg110_panel_mode - lookup struct for the supported modes
  43  */
  44 struct tpg110_panel_mode {
  45         /**
  46          * @name: the name of this panel
  47          */
  48         const char *name;
  49         /**
  50          * @magic: the magic value from the detection register
  51          */
  52         u32 magic;
  53         /**
  54          * @mode: the DRM display mode for this panel
  55          */
  56         struct drm_display_mode mode;
  57         /**
  58          * @bus_flags: the DRM bus flags for this panel e.g. inverted clock
  59          */
  60         u32 bus_flags;
  61 };
  62 
  63 /**
  64  * struct tpg110 - state container for the TPG110 panel
  65  */
  66 struct tpg110 {
  67         /**
  68          * @dev: the container device
  69          */
  70         struct device *dev;
  71         /**
  72          * @spi: the corresponding SPI device
  73          */
  74         struct spi_device *spi;
  75         /**
  76          * @panel: the DRM panel instance for this device
  77          */
  78         struct drm_panel panel;
  79         /**
  80          * @backlight: backlight for this panel
  81          */
  82         struct backlight_device *backlight;
  83         /**
  84          * @panel_type: the panel mode as detected
  85          */
  86         const struct tpg110_panel_mode *panel_mode;
  87         /**
  88          * @width: the width of this panel in mm
  89          */
  90         u32 width;
  91         /**
  92          * @height: the height of this panel in mm
  93          */
  94         u32 height;
  95         /**
  96          * @grestb: reset GPIO line
  97          */
  98         struct gpio_desc *grestb;
  99 };
 100 
 101 /*
 102  * TPG110 modes, these are the simple modes, the dualscan modes that
 103  * take 400x240 or 480x272 in and display as 800x480 are not listed.
 104  */
 105 static const struct tpg110_panel_mode tpg110_modes[] = {
 106         {
 107                 .name = "800x480 RGB",
 108                 .magic = TPG110_RES_800X480,
 109                 .mode = {
 110                         .clock = 33200,
 111                         .hdisplay = 800,
 112                         .hsync_start = 800 + 40,
 113                         .hsync_end = 800 + 40 + 1,
 114                         .htotal = 800 + 40 + 1 + 216,
 115                         .vdisplay = 480,
 116                         .vsync_start = 480 + 10,
 117                         .vsync_end = 480 + 10 + 1,
 118                         .vtotal = 480 + 10 + 1 + 35,
 119                         .vrefresh = 60,
 120                 },
 121                 .bus_flags = DRM_BUS_FLAG_PIXDATA_DRIVE_POSEDGE,
 122         },
 123         {
 124                 .name = "640x480 RGB",
 125                 .magic = TPG110_RES_640X480,
 126                 .mode = {
 127                         .clock = 25200,
 128                         .hdisplay = 640,
 129                         .hsync_start = 640 + 24,
 130                         .hsync_end = 640 + 24 + 1,
 131                         .htotal = 640 + 24 + 1 + 136,
 132                         .vdisplay = 480,
 133                         .vsync_start = 480 + 18,
 134                         .vsync_end = 480 + 18 + 1,
 135                         .vtotal = 480 + 18 + 1 + 27,
 136                         .vrefresh = 60,
 137                 },
 138                 .bus_flags = DRM_BUS_FLAG_PIXDATA_DRIVE_POSEDGE,
 139         },
 140         {
 141                 .name = "480x272 RGB",
 142                 .magic = TPG110_RES_480X272,
 143                 .mode = {
 144                         .clock = 9000,
 145                         .hdisplay = 480,
 146                         .hsync_start = 480 + 2,
 147                         .hsync_end = 480 + 2 + 1,
 148                         .htotal = 480 + 2 + 1 + 43,
 149                         .vdisplay = 272,
 150                         .vsync_start = 272 + 2,
 151                         .vsync_end = 272 + 2 + 1,
 152                         .vtotal = 272 + 2 + 1 + 12,
 153                         .vrefresh = 60,
 154                 },
 155                 .bus_flags = DRM_BUS_FLAG_PIXDATA_DRIVE_POSEDGE,
 156         },
 157         {
 158                 .name = "480x640 RGB",
 159                 .magic = TPG110_RES_480X640,
 160                 .mode = {
 161                         .clock = 20500,
 162                         .hdisplay = 480,
 163                         .hsync_start = 480 + 2,
 164                         .hsync_end = 480 + 2 + 1,
 165                         .htotal = 480 + 2 + 1 + 43,
 166                         .vdisplay = 640,
 167                         .vsync_start = 640 + 4,
 168                         .vsync_end = 640 + 4 + 1,
 169                         .vtotal = 640 + 4 + 1 + 8,
 170                         .vrefresh = 60,
 171                 },
 172                 .bus_flags = DRM_BUS_FLAG_PIXDATA_DRIVE_POSEDGE,
 173         },
 174         {
 175                 .name = "400x240 RGB",
 176                 .magic = TPG110_RES_400X240_D,
 177                 .mode = {
 178                         .clock = 8300,
 179                         .hdisplay = 400,
 180                         .hsync_start = 400 + 20,
 181                         .hsync_end = 400 + 20 + 1,
 182                         .htotal = 400 + 20 + 1 + 108,
 183                         .vdisplay = 240,
 184                         .vsync_start = 240 + 2,
 185                         .vsync_end = 240 + 2 + 1,
 186                         .vtotal = 240 + 2 + 1 + 20,
 187                         .vrefresh = 60,
 188                 },
 189                 .bus_flags = DRM_BUS_FLAG_PIXDATA_DRIVE_POSEDGE,
 190         },
 191 };
 192 
 193 static inline struct tpg110 *
 194 to_tpg110(struct drm_panel *panel)
 195 {
 196         return container_of(panel, struct tpg110, panel);
 197 }
 198 
 199 static u8 tpg110_readwrite_reg(struct tpg110 *tpg, bool write,
 200                                u8 address, u8 outval)
 201 {
 202         struct spi_message m;
 203         struct spi_transfer t[2];
 204         u8 buf[2];
 205         int ret;
 206 
 207         spi_message_init(&m);
 208         memset(t, 0, sizeof(t));
 209 
 210         if (write) {
 211                 /*
 212                  * Clear address bit 0, 1 when writing, just to be sure
 213                  * The actual bit indicating a write here is bit 1, bit
 214                  * 0 is just surplus to pad it up to 8 bits.
 215                  */
 216                 buf[0] = address << 2;
 217                 buf[0] &= ~0x03;
 218                 buf[1] = outval;
 219 
 220                 t[0].bits_per_word = 8;
 221                 t[0].tx_buf = &buf[0];
 222                 t[0].len = 1;
 223 
 224                 t[1].tx_buf = &buf[1];
 225                 t[1].len = 1;
 226                 t[1].bits_per_word = 8;
 227         } else {
 228                 /* Set address bit 0 to 1 to read */
 229                 buf[0] = address << 1;
 230                 buf[0] |= 0x01;
 231 
 232                 /*
 233                  * The last bit/clock is Hi-Z turnaround cycle, so we need
 234                  * to send only 7 bits here. The 8th bit is the high impedance
 235                  * turn-around cycle.
 236                  */
 237                 t[0].bits_per_word = 7;
 238                 t[0].tx_buf = &buf[0];
 239                 t[0].len = 1;
 240 
 241                 t[1].rx_buf = &buf[1];
 242                 t[1].len = 1;
 243                 t[1].bits_per_word = 8;
 244         }
 245 
 246         spi_message_add_tail(&t[0], &m);
 247         spi_message_add_tail(&t[1], &m);
 248         ret = spi_sync(tpg->spi, &m);
 249         if (ret) {
 250                 DRM_DEV_ERROR(tpg->dev, "SPI message error %d\n", ret);
 251                 return ret;
 252         }
 253         if (write)
 254                 return 0;
 255         /* Read */
 256         return buf[1];
 257 }
 258 
 259 static u8 tpg110_read_reg(struct tpg110 *tpg, u8 address)
 260 {
 261         return tpg110_readwrite_reg(tpg, false, address, 0);
 262 }
 263 
 264 static void tpg110_write_reg(struct tpg110 *tpg, u8 address, u8 outval)
 265 {
 266         tpg110_readwrite_reg(tpg, true, address, outval);
 267 }
 268 
 269 static int tpg110_startup(struct tpg110 *tpg)
 270 {
 271         u8 val;
 272         int i;
 273 
 274         /* De-assert the reset signal */
 275         gpiod_set_value_cansleep(tpg->grestb, 0);
 276         usleep_range(1000, 2000);
 277         DRM_DEV_DEBUG(tpg->dev, "de-asserted GRESTB\n");
 278 
 279         /* Test display communication */
 280         tpg110_write_reg(tpg, TPG110_TEST, 0x55);
 281         val = tpg110_read_reg(tpg, TPG110_TEST);
 282         if (val != 0x55) {
 283                 DRM_DEV_ERROR(tpg->dev, "failed communication test\n");
 284                 return -ENODEV;
 285         }
 286 
 287         val = tpg110_read_reg(tpg, TPG110_CHIPID);
 288         DRM_DEV_INFO(tpg->dev, "TPG110 chip ID: %d version: %d\n",
 289                  val >> 4, val & 0x0f);
 290 
 291         /* Show display resolution */
 292         val = tpg110_read_reg(tpg, TPG110_CTRL1);
 293         val &= TPG110_RES_MASK;
 294         switch (val) {
 295         case TPG110_RES_400X240_D:
 296                 DRM_DEV_INFO(tpg->dev,
 297                          "IN 400x240 RGB -> OUT 800x480 RGB (dual scan)\n");
 298                 break;
 299         case TPG110_RES_480X272_D:
 300                 DRM_DEV_INFO(tpg->dev,
 301                          "IN 480x272 RGB -> OUT 800x480 RGB (dual scan)\n");
 302                 break;
 303         case TPG110_RES_480X640:
 304                 DRM_DEV_INFO(tpg->dev, "480x640 RGB\n");
 305                 break;
 306         case TPG110_RES_480X272:
 307                 DRM_DEV_INFO(tpg->dev, "480x272 RGB\n");
 308                 break;
 309         case TPG110_RES_640X480:
 310                 DRM_DEV_INFO(tpg->dev, "640x480 RGB\n");
 311                 break;
 312         case TPG110_RES_800X480:
 313                 DRM_DEV_INFO(tpg->dev, "800x480 RGB\n");
 314                 break;
 315         default:
 316                 DRM_DEV_ERROR(tpg->dev, "ILLEGAL RESOLUTION 0x%02x\n", val);
 317                 break;
 318         }
 319 
 320         /* From the producer side, this is the same resolution */
 321         if (val == TPG110_RES_480X272_D)
 322                 val = TPG110_RES_480X272;
 323 
 324         for (i = 0; i < ARRAY_SIZE(tpg110_modes); i++) {
 325                 const struct tpg110_panel_mode *pm;
 326 
 327                 pm = &tpg110_modes[i];
 328                 if (pm->magic == val) {
 329                         tpg->panel_mode = pm;
 330                         break;
 331                 }
 332         }
 333         if (i == ARRAY_SIZE(tpg110_modes)) {
 334                 DRM_DEV_ERROR(tpg->dev, "unsupported mode (%02x) detected\n",
 335                         val);
 336                 return -ENODEV;
 337         }
 338 
 339         val = tpg110_read_reg(tpg, TPG110_CTRL2);
 340         DRM_DEV_INFO(tpg->dev, "resolution and standby is controlled by %s\n",
 341                  (val & TPG110_CTRL2_RES_PM_CTRL) ? "software" : "hardware");
 342         /* Take control over resolution and standby */
 343         val |= TPG110_CTRL2_RES_PM_CTRL;
 344         tpg110_write_reg(tpg, TPG110_CTRL2, val);
 345 
 346         return 0;
 347 }
 348 
 349 static int tpg110_disable(struct drm_panel *panel)
 350 {
 351         struct tpg110 *tpg = to_tpg110(panel);
 352         u8 val;
 353 
 354         /* Put chip into standby */
 355         val = tpg110_read_reg(tpg, TPG110_CTRL2_PM);
 356         val &= ~TPG110_CTRL2_PM;
 357         tpg110_write_reg(tpg, TPG110_CTRL2_PM, val);
 358 
 359         backlight_disable(tpg->backlight);
 360 
 361         return 0;
 362 }
 363 
 364 static int tpg110_enable(struct drm_panel *panel)
 365 {
 366         struct tpg110 *tpg = to_tpg110(panel);
 367         u8 val;
 368 
 369         backlight_enable(tpg->backlight);
 370 
 371         /* Take chip out of standby */
 372         val = tpg110_read_reg(tpg, TPG110_CTRL2_PM);
 373         val |= TPG110_CTRL2_PM;
 374         tpg110_write_reg(tpg, TPG110_CTRL2_PM, val);
 375 
 376         return 0;
 377 }
 378 
 379 /**
 380  * tpg110_get_modes() - return the appropriate mode
 381  * @panel: the panel to get the mode for
 382  *
 383  * This currently does not present a forest of modes, instead it
 384  * presents the mode that is configured for the system under use,
 385  * and which is detected by reading the registers of the display.
 386  */
 387 static int tpg110_get_modes(struct drm_panel *panel)
 388 {
 389         struct drm_connector *connector = panel->connector;
 390         struct tpg110 *tpg = to_tpg110(panel);
 391         struct drm_display_mode *mode;
 392 
 393         connector->display_info.width_mm = tpg->width;
 394         connector->display_info.height_mm = tpg->height;
 395         connector->display_info.bus_flags = tpg->panel_mode->bus_flags;
 396 
 397         mode = drm_mode_duplicate(panel->drm, &tpg->panel_mode->mode);
 398         drm_mode_set_name(mode);
 399         mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
 400 
 401         mode->width_mm = tpg->width;
 402         mode->height_mm = tpg->height;
 403 
 404         drm_mode_probed_add(connector, mode);
 405 
 406         return 1;
 407 }
 408 
 409 static const struct drm_panel_funcs tpg110_drm_funcs = {
 410         .disable = tpg110_disable,
 411         .enable = tpg110_enable,
 412         .get_modes = tpg110_get_modes,
 413 };
 414 
 415 static int tpg110_probe(struct spi_device *spi)
 416 {
 417         struct device *dev = &spi->dev;
 418         struct device_node *np = dev->of_node;
 419         struct tpg110 *tpg;
 420         int ret;
 421 
 422         tpg = devm_kzalloc(dev, sizeof(*tpg), GFP_KERNEL);
 423         if (!tpg)
 424                 return -ENOMEM;
 425         tpg->dev = dev;
 426 
 427         /* We get the physical display dimensions from the DT */
 428         ret = of_property_read_u32(np, "width-mm", &tpg->width);
 429         if (ret)
 430                 DRM_DEV_ERROR(dev, "no panel width specified\n");
 431         ret = of_property_read_u32(np, "height-mm", &tpg->height);
 432         if (ret)
 433                 DRM_DEV_ERROR(dev, "no panel height specified\n");
 434 
 435         /* Look for some optional backlight */
 436         tpg->backlight = devm_of_find_backlight(dev);
 437         if (IS_ERR(tpg->backlight))
 438                 return PTR_ERR(tpg->backlight);
 439 
 440         /* This asserts the GRESTB signal, putting the display into reset */
 441         tpg->grestb = devm_gpiod_get(dev, "grestb", GPIOD_OUT_HIGH);
 442         if (IS_ERR(tpg->grestb)) {
 443                 DRM_DEV_ERROR(dev, "no GRESTB GPIO\n");
 444                 return -ENODEV;
 445         }
 446 
 447         spi->bits_per_word = 8;
 448         spi->mode |= SPI_3WIRE_HIZ;
 449         ret = spi_setup(spi);
 450         if (ret < 0) {
 451                 DRM_DEV_ERROR(dev, "spi setup failed.\n");
 452                 return ret;
 453         }
 454         tpg->spi = spi;
 455 
 456         ret = tpg110_startup(tpg);
 457         if (ret)
 458                 return ret;
 459 
 460         drm_panel_init(&tpg->panel);
 461         tpg->panel.dev = dev;
 462         tpg->panel.funcs = &tpg110_drm_funcs;
 463         spi_set_drvdata(spi, tpg);
 464 
 465         return drm_panel_add(&tpg->panel);
 466 }
 467 
 468 static int tpg110_remove(struct spi_device *spi)
 469 {
 470         struct tpg110 *tpg = spi_get_drvdata(spi);
 471 
 472         drm_panel_remove(&tpg->panel);
 473         return 0;
 474 }
 475 
 476 static const struct of_device_id tpg110_match[] = {
 477         { .compatible = "tpo,tpg110", },
 478         {},
 479 };
 480 MODULE_DEVICE_TABLE(of, tpg110_match);
 481 
 482 static struct spi_driver tpg110_driver = {
 483         .probe          = tpg110_probe,
 484         .remove         = tpg110_remove,
 485         .driver         = {
 486                 .name   = "tpo-tpg110-panel",
 487                 .of_match_table = tpg110_match,
 488         },
 489 };
 490 module_spi_driver(tpg110_driver);
 491 
 492 MODULE_AUTHOR("Linus Walleij <linus.walleij@linaro.org>");
 493 MODULE_DESCRIPTION("TPO TPG110 panel driver");
 494 MODULE_LICENSE("GPL v2");

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