root/drivers/gpu/drm/panel/panel-jdi-lt070me05000.c

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

DEFINITIONS

This source file includes following definitions.
  1. to_jdi_panel
  2. jdi_panel_init
  3. jdi_panel_on
  4. jdi_panel_off
  5. jdi_panel_disable
  6. jdi_panel_unprepare
  7. jdi_panel_prepare
  8. jdi_panel_enable
  9. jdi_panel_get_modes
  10. dsi_dcs_bl_get_brightness
  11. dsi_dcs_bl_update_status
  12. drm_panel_create_dsi_backlight
  13. jdi_panel_add
  14. jdi_panel_del
  15. jdi_panel_probe
  16. jdi_panel_remove
  17. jdi_panel_shutdown

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  * Copyright (C) 2016 InforceComputing
   4  * Author: Vinay Simha BN <simhavcs@gmail.com>
   5  *
   6  * Copyright (C) 2016 Linaro Ltd
   7  * Author: Sumit Semwal <sumit.semwal@linaro.org>
   8  *
   9  * From internet archives, the panel for Nexus 7 2nd Gen, 2013 model is a
  10  * JDI model LT070ME05000, and its data sheet is at:
  11  * http://panelone.net/en/7-0-inch/JDI_LT070ME05000_7.0_inch-datasheet
  12  */
  13 
  14 #include <linux/backlight.h>
  15 #include <linux/delay.h>
  16 #include <linux/gpio/consumer.h>
  17 #include <linux/module.h>
  18 #include <linux/of.h>
  19 #include <linux/regulator/consumer.h>
  20 
  21 #include <video/mipi_display.h>
  22 
  23 #include <drm/drm_crtc.h>
  24 #include <drm/drm_mipi_dsi.h>
  25 #include <drm/drm_modes.h>
  26 #include <drm/drm_panel.h>
  27 
  28 static const char * const regulator_names[] = {
  29         "vddp",
  30         "iovcc"
  31 };
  32 
  33 struct jdi_panel {
  34         struct drm_panel base;
  35         struct mipi_dsi_device *dsi;
  36 
  37         struct regulator_bulk_data supplies[ARRAY_SIZE(regulator_names)];
  38 
  39         struct gpio_desc *enable_gpio;
  40         struct gpio_desc *reset_gpio;
  41         struct gpio_desc *dcdc_en_gpio;
  42         struct backlight_device *backlight;
  43 
  44         bool prepared;
  45         bool enabled;
  46 
  47         const struct drm_display_mode *mode;
  48 };
  49 
  50 static inline struct jdi_panel *to_jdi_panel(struct drm_panel *panel)
  51 {
  52         return container_of(panel, struct jdi_panel, base);
  53 }
  54 
  55 static int jdi_panel_init(struct jdi_panel *jdi)
  56 {
  57         struct mipi_dsi_device *dsi = jdi->dsi;
  58         struct device *dev = &jdi->dsi->dev;
  59         int ret;
  60 
  61         dsi->mode_flags |= MIPI_DSI_MODE_LPM;
  62 
  63         ret = mipi_dsi_dcs_soft_reset(dsi);
  64         if (ret < 0)
  65                 return ret;
  66 
  67         usleep_range(10000, 20000);
  68 
  69         ret = mipi_dsi_dcs_set_pixel_format(dsi, MIPI_DCS_PIXEL_FMT_24BIT << 4);
  70         if (ret < 0) {
  71                 dev_err(dev, "failed to set pixel format: %d\n", ret);
  72                 return ret;
  73         }
  74 
  75         ret = mipi_dsi_dcs_set_column_address(dsi, 0, jdi->mode->hdisplay - 1);
  76         if (ret < 0) {
  77                 dev_err(dev, "failed to set column address: %d\n", ret);
  78                 return ret;
  79         }
  80 
  81         ret = mipi_dsi_dcs_set_page_address(dsi, 0, jdi->mode->vdisplay - 1);
  82         if (ret < 0) {
  83                 dev_err(dev, "failed to set page address: %d\n", ret);
  84                 return ret;
  85         }
  86 
  87         /*
  88          * BIT(5) BCTRL = 1 Backlight Control Block On, Brightness registers
  89          *                  are active
  90          * BIT(3) BL = 1    Backlight Control On
  91          * BIT(2) DD = 0    Display Dimming is Off
  92          */
  93         ret = mipi_dsi_dcs_write(dsi, MIPI_DCS_WRITE_CONTROL_DISPLAY,
  94                                  (u8[]){ 0x24 }, 1);
  95         if (ret < 0) {
  96                 dev_err(dev, "failed to write control display: %d\n", ret);
  97                 return ret;
  98         }
  99 
 100         /* CABC off */
 101         ret = mipi_dsi_dcs_write(dsi, MIPI_DCS_WRITE_POWER_SAVE,
 102                                  (u8[]){ 0x00 }, 1);
 103         if (ret < 0) {
 104                 dev_err(dev, "failed to set cabc off: %d\n", ret);
 105                 return ret;
 106         }
 107 
 108         ret = mipi_dsi_dcs_exit_sleep_mode(dsi);
 109         if (ret < 0) {
 110                 dev_err(dev, "failed to set exit sleep mode: %d\n", ret);
 111                 return ret;
 112         }
 113 
 114         msleep(120);
 115 
 116         ret = mipi_dsi_generic_write(dsi, (u8[]){0xB0, 0x00}, 2);
 117         if (ret < 0) {
 118                 dev_err(dev, "failed to set mcap: %d\n", ret);
 119                 return ret;
 120         }
 121 
 122         mdelay(10);
 123 
 124         /* Interface setting, video mode */
 125         ret = mipi_dsi_generic_write(dsi, (u8[])
 126                                      {0xB3, 0x26, 0x08, 0x00, 0x20, 0x00}, 6);
 127         if (ret < 0) {
 128                 dev_err(dev, "failed to set display interface setting: %d\n"
 129                         , ret);
 130                 return ret;
 131         }
 132 
 133         mdelay(20);
 134 
 135         ret = mipi_dsi_generic_write(dsi, (u8[]){0xB0, 0x03}, 2);
 136         if (ret < 0) {
 137                 dev_err(dev, "failed to set default values for mcap: %d\n"
 138                         , ret);
 139                 return ret;
 140         }
 141 
 142         return 0;
 143 }
 144 
 145 static int jdi_panel_on(struct jdi_panel *jdi)
 146 {
 147         struct mipi_dsi_device *dsi = jdi->dsi;
 148         struct device *dev = &jdi->dsi->dev;
 149         int ret;
 150 
 151         dsi->mode_flags |= MIPI_DSI_MODE_LPM;
 152 
 153         ret = mipi_dsi_dcs_set_display_on(dsi);
 154         if (ret < 0)
 155                 dev_err(dev, "failed to set display on: %d\n", ret);
 156 
 157         return ret;
 158 }
 159 
 160 static void jdi_panel_off(struct jdi_panel *jdi)
 161 {
 162         struct mipi_dsi_device *dsi = jdi->dsi;
 163         struct device *dev = &jdi->dsi->dev;
 164         int ret;
 165 
 166         dsi->mode_flags &= ~MIPI_DSI_MODE_LPM;
 167 
 168         ret = mipi_dsi_dcs_set_display_off(dsi);
 169         if (ret < 0)
 170                 dev_err(dev, "failed to set display off: %d\n", ret);
 171 
 172         ret = mipi_dsi_dcs_enter_sleep_mode(dsi);
 173         if (ret < 0)
 174                 dev_err(dev, "failed to enter sleep mode: %d\n", ret);
 175 
 176         msleep(100);
 177 }
 178 
 179 static int jdi_panel_disable(struct drm_panel *panel)
 180 {
 181         struct jdi_panel *jdi = to_jdi_panel(panel);
 182 
 183         if (!jdi->enabled)
 184                 return 0;
 185 
 186         backlight_disable(jdi->backlight);
 187 
 188         jdi->enabled = false;
 189 
 190         return 0;
 191 }
 192 
 193 static int jdi_panel_unprepare(struct drm_panel *panel)
 194 {
 195         struct jdi_panel *jdi = to_jdi_panel(panel);
 196         struct device *dev = &jdi->dsi->dev;
 197         int ret;
 198 
 199         if (!jdi->prepared)
 200                 return 0;
 201 
 202         jdi_panel_off(jdi);
 203 
 204         ret = regulator_bulk_disable(ARRAY_SIZE(jdi->supplies), jdi->supplies);
 205         if (ret < 0)
 206                 dev_err(dev, "regulator disable failed, %d\n", ret);
 207 
 208         gpiod_set_value(jdi->enable_gpio, 0);
 209 
 210         gpiod_set_value(jdi->reset_gpio, 1);
 211 
 212         gpiod_set_value(jdi->dcdc_en_gpio, 0);
 213 
 214         jdi->prepared = false;
 215 
 216         return 0;
 217 }
 218 
 219 static int jdi_panel_prepare(struct drm_panel *panel)
 220 {
 221         struct jdi_panel *jdi = to_jdi_panel(panel);
 222         struct device *dev = &jdi->dsi->dev;
 223         int ret;
 224 
 225         if (jdi->prepared)
 226                 return 0;
 227 
 228         ret = regulator_bulk_enable(ARRAY_SIZE(jdi->supplies), jdi->supplies);
 229         if (ret < 0) {
 230                 dev_err(dev, "regulator enable failed, %d\n", ret);
 231                 return ret;
 232         }
 233 
 234         msleep(20);
 235 
 236         gpiod_set_value(jdi->dcdc_en_gpio, 1);
 237         usleep_range(10, 20);
 238 
 239         gpiod_set_value(jdi->reset_gpio, 0);
 240         usleep_range(10, 20);
 241 
 242         gpiod_set_value(jdi->enable_gpio, 1);
 243         usleep_range(10, 20);
 244 
 245         ret = jdi_panel_init(jdi);
 246         if (ret < 0) {
 247                 dev_err(dev, "failed to init panel: %d\n", ret);
 248                 goto poweroff;
 249         }
 250 
 251         ret = jdi_panel_on(jdi);
 252         if (ret < 0) {
 253                 dev_err(dev, "failed to set panel on: %d\n", ret);
 254                 goto poweroff;
 255         }
 256 
 257         jdi->prepared = true;
 258 
 259         return 0;
 260 
 261 poweroff:
 262         ret = regulator_bulk_disable(ARRAY_SIZE(jdi->supplies), jdi->supplies);
 263         if (ret < 0)
 264                 dev_err(dev, "regulator disable failed, %d\n", ret);
 265 
 266         gpiod_set_value(jdi->enable_gpio, 0);
 267 
 268         gpiod_set_value(jdi->reset_gpio, 1);
 269 
 270         gpiod_set_value(jdi->dcdc_en_gpio, 0);
 271 
 272         return ret;
 273 }
 274 
 275 static int jdi_panel_enable(struct drm_panel *panel)
 276 {
 277         struct jdi_panel *jdi = to_jdi_panel(panel);
 278 
 279         if (jdi->enabled)
 280                 return 0;
 281 
 282         backlight_enable(jdi->backlight);
 283 
 284         jdi->enabled = true;
 285 
 286         return 0;
 287 }
 288 
 289 static const struct drm_display_mode default_mode = {
 290                 .clock = 155493,
 291                 .hdisplay = 1200,
 292                 .hsync_start = 1200 + 48,
 293                 .hsync_end = 1200 + 48 + 32,
 294                 .htotal = 1200 + 48 + 32 + 60,
 295                 .vdisplay = 1920,
 296                 .vsync_start = 1920 + 3,
 297                 .vsync_end = 1920 + 3 + 5,
 298                 .vtotal = 1920 + 3 + 5 + 6,
 299                 .vrefresh = 60,
 300                 .flags = 0,
 301 };
 302 
 303 static int jdi_panel_get_modes(struct drm_panel *panel)
 304 {
 305         struct drm_display_mode *mode;
 306         struct jdi_panel *jdi = to_jdi_panel(panel);
 307         struct device *dev = &jdi->dsi->dev;
 308 
 309         mode = drm_mode_duplicate(panel->drm, &default_mode);
 310         if (!mode) {
 311                 dev_err(dev, "failed to add mode %ux%ux@%u\n",
 312                         default_mode.hdisplay, default_mode.vdisplay,
 313                         default_mode.vrefresh);
 314                 return -ENOMEM;
 315         }
 316 
 317         drm_mode_set_name(mode);
 318 
 319         drm_mode_probed_add(panel->connector, mode);
 320 
 321         panel->connector->display_info.width_mm = 95;
 322         panel->connector->display_info.height_mm = 151;
 323 
 324         return 1;
 325 }
 326 
 327 static int dsi_dcs_bl_get_brightness(struct backlight_device *bl)
 328 {
 329         struct mipi_dsi_device *dsi = bl_get_data(bl);
 330         int ret;
 331         u16 brightness = bl->props.brightness;
 332 
 333         dsi->mode_flags &= ~MIPI_DSI_MODE_LPM;
 334 
 335         ret = mipi_dsi_dcs_get_display_brightness(dsi, &brightness);
 336         if (ret < 0)
 337                 return ret;
 338 
 339         dsi->mode_flags |= MIPI_DSI_MODE_LPM;
 340 
 341         return brightness & 0xff;
 342 }
 343 
 344 static int dsi_dcs_bl_update_status(struct backlight_device *bl)
 345 {
 346         struct mipi_dsi_device *dsi = bl_get_data(bl);
 347         int ret;
 348 
 349         dsi->mode_flags &= ~MIPI_DSI_MODE_LPM;
 350 
 351         ret = mipi_dsi_dcs_set_display_brightness(dsi, bl->props.brightness);
 352         if (ret < 0)
 353                 return ret;
 354 
 355         dsi->mode_flags |= MIPI_DSI_MODE_LPM;
 356 
 357         return 0;
 358 }
 359 
 360 static const struct backlight_ops dsi_bl_ops = {
 361         .update_status = dsi_dcs_bl_update_status,
 362         .get_brightness = dsi_dcs_bl_get_brightness,
 363 };
 364 
 365 static struct backlight_device *
 366 drm_panel_create_dsi_backlight(struct mipi_dsi_device *dsi)
 367 {
 368         struct device *dev = &dsi->dev;
 369         struct backlight_properties props;
 370 
 371         memset(&props, 0, sizeof(props));
 372         props.type = BACKLIGHT_RAW;
 373         props.brightness = 255;
 374         props.max_brightness = 255;
 375 
 376         return devm_backlight_device_register(dev, dev_name(dev), dev, dsi,
 377                                               &dsi_bl_ops, &props);
 378 }
 379 
 380 static const struct drm_panel_funcs jdi_panel_funcs = {
 381         .disable = jdi_panel_disable,
 382         .unprepare = jdi_panel_unprepare,
 383         .prepare = jdi_panel_prepare,
 384         .enable = jdi_panel_enable,
 385         .get_modes = jdi_panel_get_modes,
 386 };
 387 
 388 static const struct of_device_id jdi_of_match[] = {
 389         { .compatible = "jdi,lt070me05000", },
 390         { }
 391 };
 392 MODULE_DEVICE_TABLE(of, jdi_of_match);
 393 
 394 static int jdi_panel_add(struct jdi_panel *jdi)
 395 {
 396         struct device *dev = &jdi->dsi->dev;
 397         int ret;
 398         unsigned int i;
 399 
 400         jdi->mode = &default_mode;
 401 
 402         for (i = 0; i < ARRAY_SIZE(jdi->supplies); i++)
 403                 jdi->supplies[i].supply = regulator_names[i];
 404 
 405         ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(jdi->supplies),
 406                                       jdi->supplies);
 407         if (ret < 0) {
 408                 dev_err(dev, "failed to init regulator, ret=%d\n", ret);
 409                 return ret;
 410         }
 411 
 412         jdi->enable_gpio = devm_gpiod_get(dev, "enable", GPIOD_OUT_LOW);
 413         if (IS_ERR(jdi->enable_gpio)) {
 414                 ret = PTR_ERR(jdi->enable_gpio);
 415                 dev_err(dev, "cannot get enable-gpio %d\n", ret);
 416                 return ret;
 417         }
 418 
 419         jdi->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH);
 420         if (IS_ERR(jdi->reset_gpio)) {
 421                 ret = PTR_ERR(jdi->reset_gpio);
 422                 dev_err(dev, "cannot get reset-gpios %d\n", ret);
 423                 return ret;
 424         }
 425 
 426         jdi->dcdc_en_gpio = devm_gpiod_get(dev, "dcdc-en", GPIOD_OUT_LOW);
 427         if (IS_ERR(jdi->dcdc_en_gpio)) {
 428                 ret = PTR_ERR(jdi->dcdc_en_gpio);
 429                 dev_err(dev, "cannot get dcdc-en-gpio %d\n", ret);
 430                 return ret;
 431         }
 432 
 433         jdi->backlight = drm_panel_create_dsi_backlight(jdi->dsi);
 434         if (IS_ERR(jdi->backlight)) {
 435                 ret = PTR_ERR(jdi->backlight);
 436                 dev_err(dev, "failed to register backlight %d\n", ret);
 437                 return ret;
 438         }
 439 
 440         drm_panel_init(&jdi->base);
 441         jdi->base.funcs = &jdi_panel_funcs;
 442         jdi->base.dev = &jdi->dsi->dev;
 443 
 444         ret = drm_panel_add(&jdi->base);
 445 
 446         return ret;
 447 }
 448 
 449 static void jdi_panel_del(struct jdi_panel *jdi)
 450 {
 451         if (jdi->base.dev)
 452                 drm_panel_remove(&jdi->base);
 453 }
 454 
 455 static int jdi_panel_probe(struct mipi_dsi_device *dsi)
 456 {
 457         struct jdi_panel *jdi;
 458         int ret;
 459 
 460         dsi->lanes = 4;
 461         dsi->format = MIPI_DSI_FMT_RGB888;
 462         dsi->mode_flags =  MIPI_DSI_MODE_VIDEO_HSE | MIPI_DSI_MODE_VIDEO |
 463                            MIPI_DSI_CLOCK_NON_CONTINUOUS;
 464 
 465         jdi = devm_kzalloc(&dsi->dev, sizeof(*jdi), GFP_KERNEL);
 466         if (!jdi)
 467                 return -ENOMEM;
 468 
 469         mipi_dsi_set_drvdata(dsi, jdi);
 470 
 471         jdi->dsi = dsi;
 472 
 473         ret = jdi_panel_add(jdi);
 474         if (ret < 0)
 475                 return ret;
 476 
 477         return mipi_dsi_attach(dsi);
 478 }
 479 
 480 static int jdi_panel_remove(struct mipi_dsi_device *dsi)
 481 {
 482         struct jdi_panel *jdi = mipi_dsi_get_drvdata(dsi);
 483         int ret;
 484 
 485         ret = jdi_panel_disable(&jdi->base);
 486         if (ret < 0)
 487                 dev_err(&dsi->dev, "failed to disable panel: %d\n", ret);
 488 
 489         ret = mipi_dsi_detach(dsi);
 490         if (ret < 0)
 491                 dev_err(&dsi->dev, "failed to detach from DSI host: %d\n",
 492                         ret);
 493 
 494         jdi_panel_del(jdi);
 495 
 496         return 0;
 497 }
 498 
 499 static void jdi_panel_shutdown(struct mipi_dsi_device *dsi)
 500 {
 501         struct jdi_panel *jdi = mipi_dsi_get_drvdata(dsi);
 502 
 503         jdi_panel_disable(&jdi->base);
 504 }
 505 
 506 static struct mipi_dsi_driver jdi_panel_driver = {
 507         .driver = {
 508                 .name = "panel-jdi-lt070me05000",
 509                 .of_match_table = jdi_of_match,
 510         },
 511         .probe = jdi_panel_probe,
 512         .remove = jdi_panel_remove,
 513         .shutdown = jdi_panel_shutdown,
 514 };
 515 module_mipi_dsi_driver(jdi_panel_driver);
 516 
 517 MODULE_AUTHOR("Sumit Semwal <sumit.semwal@linaro.org>");
 518 MODULE_AUTHOR("Vinay Simha BN <simhavcs@gmail.com>");
 519 MODULE_DESCRIPTION("JDI LT070ME05000 WUXGA");
 520 MODULE_LICENSE("GPL v2");

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