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 struct drm_connector *connector) 305 { 306 struct drm_display_mode *mode; 307 struct jdi_panel *jdi = to_jdi_panel(panel); 308 struct device *dev = &jdi->dsi->dev; 309 310 mode = drm_mode_duplicate(connector->dev, &default_mode); 311 if (!mode) { 312 dev_err(dev, "failed to add mode %ux%ux@%u\n", 313 default_mode.hdisplay, default_mode.vdisplay, 314 default_mode.vrefresh); 315 return -ENOMEM; 316 } 317 318 drm_mode_set_name(mode); 319 320 drm_mode_probed_add(connector, mode); 321 322 connector->display_info.width_mm = 95; 323 connector->display_info.height_mm = 151; 324 325 return 1; 326 } 327 328 static int dsi_dcs_bl_get_brightness(struct backlight_device *bl) 329 { 330 struct mipi_dsi_device *dsi = bl_get_data(bl); 331 int ret; 332 u16 brightness = bl->props.brightness; 333 334 dsi->mode_flags &= ~MIPI_DSI_MODE_LPM; 335 336 ret = mipi_dsi_dcs_get_display_brightness(dsi, &brightness); 337 if (ret < 0) 338 return ret; 339 340 dsi->mode_flags |= MIPI_DSI_MODE_LPM; 341 342 return brightness & 0xff; 343 } 344 345 static int dsi_dcs_bl_update_status(struct backlight_device *bl) 346 { 347 struct mipi_dsi_device *dsi = bl_get_data(bl); 348 int ret; 349 350 dsi->mode_flags &= ~MIPI_DSI_MODE_LPM; 351 352 ret = mipi_dsi_dcs_set_display_brightness(dsi, bl->props.brightness); 353 if (ret < 0) 354 return ret; 355 356 dsi->mode_flags |= MIPI_DSI_MODE_LPM; 357 358 return 0; 359 } 360 361 static const struct backlight_ops dsi_bl_ops = { 362 .update_status = dsi_dcs_bl_update_status, 363 .get_brightness = dsi_dcs_bl_get_brightness, 364 }; 365 366 static struct backlight_device * 367 drm_panel_create_dsi_backlight(struct mipi_dsi_device *dsi) 368 { 369 struct device *dev = &dsi->dev; 370 struct backlight_properties props; 371 372 memset(&props, 0, sizeof(props)); 373 props.type = BACKLIGHT_RAW; 374 props.brightness = 255; 375 props.max_brightness = 255; 376 377 return devm_backlight_device_register(dev, dev_name(dev), dev, dsi, 378 &dsi_bl_ops, &props); 379 } 380 381 static const struct drm_panel_funcs jdi_panel_funcs = { 382 .disable = jdi_panel_disable, 383 .unprepare = jdi_panel_unprepare, 384 .prepare = jdi_panel_prepare, 385 .enable = jdi_panel_enable, 386 .get_modes = jdi_panel_get_modes, 387 }; 388 389 static const struct of_device_id jdi_of_match[] = { 390 { .compatible = "jdi,lt070me05000", }, 391 { } 392 }; 393 MODULE_DEVICE_TABLE(of, jdi_of_match); 394 395 static int jdi_panel_add(struct jdi_panel *jdi) 396 { 397 struct device *dev = &jdi->dsi->dev; 398 int ret; 399 unsigned int i; 400 401 jdi->mode = &default_mode; 402 403 for (i = 0; i < ARRAY_SIZE(jdi->supplies); i++) 404 jdi->supplies[i].supply = regulator_names[i]; 405 406 ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(jdi->supplies), 407 jdi->supplies); 408 if (ret < 0) { 409 dev_err(dev, "failed to init regulator, ret=%d\n", ret); 410 return ret; 411 } 412 413 jdi->enable_gpio = devm_gpiod_get(dev, "enable", GPIOD_OUT_LOW); 414 if (IS_ERR(jdi->enable_gpio)) { 415 ret = PTR_ERR(jdi->enable_gpio); 416 dev_err(dev, "cannot get enable-gpio %d\n", ret); 417 return ret; 418 } 419 420 jdi->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH); 421 if (IS_ERR(jdi->reset_gpio)) { 422 ret = PTR_ERR(jdi->reset_gpio); 423 dev_err(dev, "cannot get reset-gpios %d\n", ret); 424 return ret; 425 } 426 427 jdi->dcdc_en_gpio = devm_gpiod_get(dev, "dcdc-en", GPIOD_OUT_LOW); 428 if (IS_ERR(jdi->dcdc_en_gpio)) { 429 ret = PTR_ERR(jdi->dcdc_en_gpio); 430 dev_err(dev, "cannot get dcdc-en-gpio %d\n", ret); 431 return ret; 432 } 433 434 jdi->backlight = drm_panel_create_dsi_backlight(jdi->dsi); 435 if (IS_ERR(jdi->backlight)) { 436 ret = PTR_ERR(jdi->backlight); 437 dev_err(dev, "failed to register backlight %d\n", ret); 438 return ret; 439 } 440 441 drm_panel_init(&jdi->base, &jdi->dsi->dev, &jdi_panel_funcs, 442 DRM_MODE_CONNECTOR_DSI); 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"); 521