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 backlight_disable(jdi->backlight); 196 197 jdi->enabled = false; 198 199 return 0; 200 } 201 202 static int jdi_panel_unprepare(struct drm_panel *panel) 203 { 204 struct jdi_panel *jdi = to_jdi_panel(panel); 205 struct device *dev = &jdi->dsi->dev; 206 int ret; 207 208 if (!jdi->prepared) 209 return 0; 210 211 jdi_panel_off(jdi); 212 213 ret = regulator_bulk_disable(ARRAY_SIZE(jdi->supplies), jdi->supplies); 214 if (ret < 0) 215 dev_err(dev, "regulator disable failed, %d\n", ret); 216 217 gpiod_set_value(jdi->enable_gpio, 0); 218 219 gpiod_set_value(jdi->reset_gpio, 1); 220 221 gpiod_set_value(jdi->dcdc_en_gpio, 0); 222 223 jdi->prepared = false; 224 225 return 0; 226 } 227 228 static int jdi_panel_prepare(struct drm_panel *panel) 229 { 230 struct jdi_panel *jdi = to_jdi_panel(panel); 231 struct device *dev = &jdi->dsi->dev; 232 int ret; 233 234 if (jdi->prepared) 235 return 0; 236 237 ret = regulator_bulk_enable(ARRAY_SIZE(jdi->supplies), jdi->supplies); 238 if (ret < 0) { 239 dev_err(dev, "regulator enable failed, %d\n", ret); 240 return ret; 241 } 242 243 msleep(20); 244 245 gpiod_set_value(jdi->dcdc_en_gpio, 1); 246 usleep_range(10, 20); 247 248 gpiod_set_value(jdi->reset_gpio, 0); 249 usleep_range(10, 20); 250 251 gpiod_set_value(jdi->enable_gpio, 1); 252 usleep_range(10, 20); 253 254 ret = jdi_panel_init(jdi); 255 if (ret < 0) { 256 dev_err(dev, "failed to init panel: %d\n", ret); 257 goto poweroff; 258 } 259 260 ret = jdi_panel_on(jdi); 261 if (ret < 0) { 262 dev_err(dev, "failed to set panel on: %d\n", ret); 263 goto poweroff; 264 } 265 266 jdi->prepared = true; 267 268 return 0; 269 270 poweroff: 271 ret = regulator_bulk_disable(ARRAY_SIZE(jdi->supplies), jdi->supplies); 272 if (ret < 0) 273 dev_err(dev, "regulator disable failed, %d\n", ret); 274 275 gpiod_set_value(jdi->enable_gpio, 0); 276 277 gpiod_set_value(jdi->reset_gpio, 1); 278 279 gpiod_set_value(jdi->dcdc_en_gpio, 0); 280 281 return ret; 282 } 283 284 static int jdi_panel_enable(struct drm_panel *panel) 285 { 286 struct jdi_panel *jdi = to_jdi_panel(panel); 287 288 if (jdi->enabled) 289 return 0; 290 291 backlight_enable(jdi->backlight); 292 293 jdi->enabled = true; 294 295 return 0; 296 } 297 298 static const struct drm_display_mode default_mode = { 299 .clock = 155493, 300 .hdisplay = 1200, 301 .hsync_start = 1200 + 48, 302 .hsync_end = 1200 + 48 + 32, 303 .htotal = 1200 + 48 + 32 + 60, 304 .vdisplay = 1920, 305 .vsync_start = 1920 + 3, 306 .vsync_end = 1920 + 3 + 5, 307 .vtotal = 1920 + 3 + 5 + 6, 308 .vrefresh = 60, 309 .flags = 0, 310 }; 311 312 static int jdi_panel_get_modes(struct drm_panel *panel) 313 { 314 struct drm_display_mode *mode; 315 struct jdi_panel *jdi = to_jdi_panel(panel); 316 struct device *dev = &jdi->dsi->dev; 317 318 mode = drm_mode_duplicate(panel->drm, &default_mode); 319 if (!mode) { 320 dev_err(dev, "failed to add mode %ux%ux@%u\n", 321 default_mode.hdisplay, default_mode.vdisplay, 322 default_mode.vrefresh); 323 return -ENOMEM; 324 } 325 326 drm_mode_set_name(mode); 327 328 drm_mode_probed_add(panel->connector, mode); 329 330 panel->connector->display_info.width_mm = 95; 331 panel->connector->display_info.height_mm = 151; 332 333 return 1; 334 } 335 336 static int dsi_dcs_bl_get_brightness(struct backlight_device *bl) 337 { 338 struct mipi_dsi_device *dsi = bl_get_data(bl); 339 int ret; 340 u16 brightness = bl->props.brightness; 341 342 dsi->mode_flags &= ~MIPI_DSI_MODE_LPM; 343 344 ret = mipi_dsi_dcs_get_display_brightness(dsi, &brightness); 345 if (ret < 0) 346 return ret; 347 348 dsi->mode_flags |= MIPI_DSI_MODE_LPM; 349 350 return brightness & 0xff; 351 } 352 353 static int dsi_dcs_bl_update_status(struct backlight_device *bl) 354 { 355 struct mipi_dsi_device *dsi = bl_get_data(bl); 356 int ret; 357 358 dsi->mode_flags &= ~MIPI_DSI_MODE_LPM; 359 360 ret = mipi_dsi_dcs_set_display_brightness(dsi, bl->props.brightness); 361 if (ret < 0) 362 return ret; 363 364 dsi->mode_flags |= MIPI_DSI_MODE_LPM; 365 366 return 0; 367 } 368 369 static const struct backlight_ops dsi_bl_ops = { 370 .update_status = dsi_dcs_bl_update_status, 371 .get_brightness = dsi_dcs_bl_get_brightness, 372 }; 373 374 static struct backlight_device * 375 drm_panel_create_dsi_backlight(struct mipi_dsi_device *dsi) 376 { 377 struct device *dev = &dsi->dev; 378 struct backlight_properties props; 379 380 memset(&props, 0, sizeof(props)); 381 props.type = BACKLIGHT_RAW; 382 props.brightness = 255; 383 props.max_brightness = 255; 384 385 return devm_backlight_device_register(dev, dev_name(dev), dev, dsi, 386 &dsi_bl_ops, &props); 387 } 388 389 static const struct drm_panel_funcs jdi_panel_funcs = { 390 .disable = jdi_panel_disable, 391 .unprepare = jdi_panel_unprepare, 392 .prepare = jdi_panel_prepare, 393 .enable = jdi_panel_enable, 394 .get_modes = jdi_panel_get_modes, 395 }; 396 397 static const struct of_device_id jdi_of_match[] = { 398 { .compatible = "jdi,lt070me05000", }, 399 { } 400 }; 401 MODULE_DEVICE_TABLE(of, jdi_of_match); 402 403 static int jdi_panel_add(struct jdi_panel *jdi) 404 { 405 struct device *dev = &jdi->dsi->dev; 406 int ret; 407 unsigned int i; 408 409 jdi->mode = &default_mode; 410 411 for (i = 0; i < ARRAY_SIZE(jdi->supplies); i++) 412 jdi->supplies[i].supply = regulator_names[i]; 413 414 ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(jdi->supplies), 415 jdi->supplies); 416 if (ret < 0) { 417 dev_err(dev, "failed to init regulator, ret=%d\n", ret); 418 return ret; 419 } 420 421 jdi->enable_gpio = devm_gpiod_get(dev, "enable", GPIOD_OUT_LOW); 422 if (IS_ERR(jdi->enable_gpio)) { 423 ret = PTR_ERR(jdi->enable_gpio); 424 dev_err(dev, "cannot get enable-gpio %d\n", ret); 425 return ret; 426 } 427 428 jdi->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH); 429 if (IS_ERR(jdi->reset_gpio)) { 430 ret = PTR_ERR(jdi->reset_gpio); 431 dev_err(dev, "cannot get reset-gpios %d\n", ret); 432 return ret; 433 } 434 435 jdi->dcdc_en_gpio = devm_gpiod_get(dev, "dcdc-en", GPIOD_OUT_LOW); 436 if (IS_ERR(jdi->dcdc_en_gpio)) { 437 ret = PTR_ERR(jdi->dcdc_en_gpio); 438 dev_err(dev, "cannot get dcdc-en-gpio %d\n", ret); 439 return ret; 440 } 441 442 jdi->backlight = drm_panel_create_dsi_backlight(jdi->dsi); 443 if (IS_ERR(jdi->backlight)) { 444 ret = PTR_ERR(jdi->backlight); 445 dev_err(dev, "failed to register backlight %d\n", ret); 446 return ret; 447 } 448 449 drm_panel_init(&jdi->base); 450 jdi->base.funcs = &jdi_panel_funcs; 451 jdi->base.dev = &jdi->dsi->dev; 452 453 ret = drm_panel_add(&jdi->base); 454 455 return ret; 456 } 457 458 static void jdi_panel_del(struct jdi_panel *jdi) 459 { 460 if (jdi->base.dev) 461 drm_panel_remove(&jdi->base); 462 } 463 464 static int jdi_panel_probe(struct mipi_dsi_device *dsi) 465 { 466 struct jdi_panel *jdi; 467 int ret; 468 469 dsi->lanes = 4; 470 dsi->format = MIPI_DSI_FMT_RGB888; 471 dsi->mode_flags = MIPI_DSI_MODE_VIDEO_HSE | MIPI_DSI_MODE_VIDEO | 472 MIPI_DSI_CLOCK_NON_CONTINUOUS; 473 474 jdi = devm_kzalloc(&dsi->dev, sizeof(*jdi), GFP_KERNEL); 475 if (!jdi) 476 return -ENOMEM; 477 478 mipi_dsi_set_drvdata(dsi, jdi); 479 480 jdi->dsi = dsi; 481 482 ret = jdi_panel_add(jdi); 483 if (ret < 0) 484 return ret; 485 486 return mipi_dsi_attach(dsi); 487 } 488 489 static int jdi_panel_remove(struct mipi_dsi_device *dsi) 490 { 491 struct jdi_panel *jdi = mipi_dsi_get_drvdata(dsi); 492 int ret; 493 494 ret = jdi_panel_disable(&jdi->base); 495 if (ret < 0) 496 dev_err(&dsi->dev, "failed to disable panel: %d\n", ret); 497 498 ret = mipi_dsi_detach(dsi); 499 if (ret < 0) 500 dev_err(&dsi->dev, "failed to detach from DSI host: %d\n", 501 ret); 502 503 jdi_panel_del(jdi); 504 505 return 0; 506 } 507 508 static void jdi_panel_shutdown(struct mipi_dsi_device *dsi) 509 { 510 struct jdi_panel *jdi = mipi_dsi_get_drvdata(dsi); 511 512 jdi_panel_disable(&jdi->base); 513 } 514 515 static struct mipi_dsi_driver jdi_panel_driver = { 516 .driver = { 517 .name = "panel-jdi-lt070me05000", 518 .of_match_table = jdi_of_match, 519 }, 520 .probe = jdi_panel_probe, 521 .remove = jdi_panel_remove, 522 .shutdown = jdi_panel_shutdown, 523 }; 524 module_mipi_dsi_driver(jdi_panel_driver); 525 526 MODULE_AUTHOR("Sumit Semwal <sumit.semwal@linaro.org>"); 527 MODULE_AUTHOR("Vinay Simha BN <simhavcs@gmail.com>"); 528 MODULE_DESCRIPTION("JDI LT070ME05000 WUXGA"); 529 MODULE_LICENSE("GPL v2"); 530