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