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