uboot/drivers/video/lg4573.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 * LCD: LG4573, TFT 4.3", 480x800, RGB24
   4 * LCD initialization via SPI
   5 *
   6 */
   7#include <common.h>
   8#include <backlight.h>
   9#include <command.h>
  10#include <display.h>
  11#include <dm.h>
  12#include <log.h>
  13#include <dm/read.h>
  14#include <dm/uclass-internal.h>
  15#include <errno.h>
  16#include <spi.h>
  17#include <asm/gpio.h>
  18#include <linux/delay.h>
  19
  20#define PWR_ON_DELAY_MSECS  120
  21
  22static int lb043wv_spi_write_u16(struct spi_slave *slave, u16 val)
  23{
  24        unsigned short buf16 = htons(val);
  25        int ret = 0;
  26
  27        ret = spi_xfer(slave, 16, &buf16, NULL,
  28                       SPI_XFER_BEGIN | SPI_XFER_END);
  29        if (ret)
  30                debug("%s: Failed to send: %d\n", __func__, ret);
  31
  32        return ret;
  33}
  34
  35static void lb043wv_spi_write_u16_array(struct spi_slave *slave, u16 *buff,
  36                                        int size)
  37{
  38        int i;
  39
  40        for (i = 0; i < size; i++)
  41                lb043wv_spi_write_u16(slave, buff[i]);
  42}
  43
  44static void lb043wv_display_mode_settings(struct spi_slave *slave)
  45{
  46        static u16 display_mode_settings[] = {
  47          0x703A,
  48          0x7270,
  49          0x70B1,
  50          0x7208,
  51          0x723B,
  52          0x720F,
  53          0x70B2,
  54          0x7200,
  55          0x72C8,
  56          0x70B3,
  57          0x7200,
  58          0x70B4,
  59          0x7200,
  60          0x70B5,
  61          0x7242,
  62          0x7210,
  63          0x7210,
  64          0x7200,
  65          0x7220,
  66          0x70B6,
  67          0x720B,
  68          0x720F,
  69          0x723C,
  70          0x7213,
  71          0x7213,
  72          0x72E8,
  73          0x70B7,
  74          0x7246,
  75          0x7206,
  76          0x720C,
  77          0x7200,
  78          0x7200,
  79        };
  80
  81        debug("transfer display mode settings\n");
  82        lb043wv_spi_write_u16_array(slave, display_mode_settings,
  83                                    ARRAY_SIZE(display_mode_settings));
  84}
  85
  86static void lb043wv_power_settings(struct spi_slave *slave)
  87{
  88        static u16 power_settings[] = {
  89          0x70C0,
  90          0x7201,
  91          0x7211,
  92          0x70C3,
  93          0x7207,
  94          0x7203,
  95          0x7204,
  96          0x7204,
  97          0x7204,
  98          0x70C4,
  99          0x7212,
 100          0x7224,
 101          0x7218,
 102          0x7218,
 103          0x7202,
 104          0x7249,
 105          0x70C5,
 106          0x726F,
 107          0x70C6,
 108          0x7241,
 109          0x7263,
 110        };
 111
 112        debug("transfer power settings\n");
 113        lb043wv_spi_write_u16_array(slave, power_settings,
 114                                    ARRAY_SIZE(power_settings));
 115}
 116
 117static void lb043wv_gamma_settings(struct spi_slave *slave)
 118{
 119        static u16 gamma_settings[] = {
 120          0x70D0,
 121          0x7203,
 122          0x7207,
 123          0x7273,
 124          0x7235,
 125          0x7200,
 126          0x7201,
 127          0x7220,
 128          0x7200,
 129          0x7203,
 130          0x70D1,
 131          0x7203,
 132          0x7207,
 133          0x7273,
 134          0x7235,
 135          0x7200,
 136          0x7201,
 137          0x7220,
 138          0x7200,
 139          0x7203,
 140          0x70D2,
 141          0x7203,
 142          0x7207,
 143          0x7273,
 144          0x7235,
 145          0x7200,
 146          0x7201,
 147          0x7220,
 148          0x7200,
 149          0x7203,
 150          0x70D3,
 151          0x7203,
 152          0x7207,
 153          0x7273,
 154          0x7235,
 155          0x7200,
 156          0x7201,
 157          0x7220,
 158          0x7200,
 159          0x7203,
 160          0x70D4,
 161          0x7203,
 162          0x7207,
 163          0x7273,
 164          0x7235,
 165          0x7200,
 166          0x7201,
 167          0x7220,
 168          0x7200,
 169          0x7203,
 170          0x70D5,
 171          0x7203,
 172          0x7207,
 173          0x7273,
 174          0x7235,
 175          0x7200,
 176          0x7201,
 177          0x7220,
 178          0x7200,
 179          0x7203,
 180        };
 181
 182        debug("transfer gamma settings\n");
 183        lb043wv_spi_write_u16_array(slave, gamma_settings,
 184                                    ARRAY_SIZE(gamma_settings));
 185}
 186
 187static void lb043wv_display_on(struct spi_slave *slave)
 188{
 189        static u16 sleep_out = 0x7011;
 190        static u16 display_on = 0x7029;
 191
 192        lb043wv_spi_write_u16(slave, sleep_out);
 193        mdelay(PWR_ON_DELAY_MSECS);
 194        lb043wv_spi_write_u16(slave, display_on);
 195}
 196
 197static int lg4573_spi_startup(struct spi_slave *slave)
 198{
 199        int ret;
 200
 201        ret = spi_claim_bus(slave);
 202        if (ret)
 203                return ret;
 204
 205        lb043wv_display_mode_settings(slave);
 206        lb043wv_power_settings(slave);
 207        lb043wv_gamma_settings(slave);
 208        lb043wv_display_on(slave);
 209
 210        spi_release_bus(slave);
 211        return 0;
 212}
 213
 214static int do_lgset(struct cmd_tbl *cmdtp, int flag, int argc,
 215                    char *const argv[])
 216{
 217        struct spi_slave *slave;
 218        struct udevice *dev;
 219        int ret;
 220
 221        ret = uclass_get_device_by_driver(UCLASS_DISPLAY,
 222                                          DM_DRIVER_GET(lg4573_lcd), &dev);
 223        if (ret) {
 224                printf("%s: Could not get lg4573 device\n", __func__);
 225                return ret;
 226        }
 227        slave = dev_get_parent_priv(dev);
 228        if (!slave) {
 229                printf("%s: No slave data\n", __func__);
 230                return -ENODEV;
 231        }
 232        lg4573_spi_startup(slave);
 233
 234        return 0;
 235}
 236
 237U_BOOT_CMD(
 238        lgset,  2,      1,      do_lgset,
 239        "set lgdisplay",
 240        ""
 241);
 242
 243static int lg4573_bind(struct udevice *dev)
 244{
 245        return 0;
 246}
 247
 248static int lg4573_probe(struct udevice *dev)
 249{
 250        return 0;
 251}
 252
 253static const struct udevice_id lg4573_ids[] = {
 254        { .compatible = "lg,lg4573" },
 255        { }
 256};
 257
 258struct lg4573_lcd_priv {
 259        struct display_timing timing;
 260        struct udevice *backlight;
 261        struct gpio_desc enable;
 262        int panel_bpp;
 263        u32 power_on_delay;
 264};
 265
 266static int lg4573_lcd_read_timing(struct udevice *dev,
 267                                  struct display_timing *timing)
 268{
 269        struct lg4573_lcd_priv *priv = dev_get_priv(dev);
 270
 271        memcpy(timing, &priv->timing, sizeof(struct display_timing));
 272
 273        return 0;
 274}
 275
 276static int lg4573_lcd_enable(struct udevice *dev, int bpp,
 277                             const struct display_timing *edid)
 278{
 279        struct spi_slave *slave = dev_get_parent_priv(dev);
 280        struct lg4573_lcd_priv *priv = dev_get_priv(dev);
 281        int ret = 0;
 282
 283        dm_gpio_set_value(&priv->enable, 1);
 284        ret = backlight_enable(priv->backlight);
 285
 286        mdelay(priv->power_on_delay);
 287        lg4573_spi_startup(slave);
 288
 289        return ret;
 290};
 291
 292static const struct dm_display_ops lg4573_lcd_ops = {
 293        .read_timing = lg4573_lcd_read_timing,
 294        .enable = lg4573_lcd_enable,
 295};
 296
 297static int lg4573_of_to_plat(struct udevice *dev)
 298{
 299        struct lg4573_lcd_priv *priv = dev_get_priv(dev);
 300        int ret;
 301
 302        ret = uclass_get_device_by_phandle(UCLASS_PANEL_BACKLIGHT, dev,
 303                                           "backlight", &priv->backlight);
 304        if (ret) {
 305                debug("%s: Cannot get backlight: ret=%d\n", __func__, ret);
 306                return log_ret(ret);
 307        }
 308        ret = gpio_request_by_name(dev, "enable-gpios", 0, &priv->enable,
 309                                   GPIOD_IS_OUT);
 310        if (ret) {
 311                debug("%s: Warning: cannot get enable GPIO: ret=%d\n",
 312                      __func__, ret);
 313                if (ret != -ENOENT)
 314                        return log_ret(ret);
 315        }
 316
 317        priv->power_on_delay = dev_read_u32_default(dev, "power-on-delay", 10);
 318
 319        return 0;
 320}
 321
 322U_BOOT_DRIVER(lg4573_lcd) = {
 323        .name   = "lg4573",
 324        .id     = UCLASS_DISPLAY,
 325        .ops    = &lg4573_lcd_ops,
 326        .of_to_plat     = lg4573_of_to_plat,
 327        .of_match = lg4573_ids,
 328        .bind   = lg4573_bind,
 329        .probe  = lg4573_probe,
 330        .priv_auto      = sizeof(struct lg4573_lcd_priv),
 331};
 332