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