diff options
Diffstat (limited to 'drivers/gpu/drm/tinydrm/mipi-dbi.c')
-rw-r--r-- | drivers/gpu/drm/tinydrm/mipi-dbi.c | 101 |
1 files changed, 86 insertions, 15 deletions
diff --git a/drivers/gpu/drm/tinydrm/mipi-dbi.c b/drivers/gpu/drm/tinydrm/mipi-dbi.c index aa6b6ce56891..75dd65c57e74 100644 --- a/drivers/gpu/drm/tinydrm/mipi-dbi.c +++ b/drivers/gpu/drm/tinydrm/mipi-dbi.c | |||
@@ -271,21 +271,16 @@ static const struct drm_framebuffer_funcs mipi_dbi_fb_funcs = { | |||
271 | }; | 271 | }; |
272 | 272 | ||
273 | /** | 273 | /** |
274 | * mipi_dbi_pipe_enable - MIPI DBI pipe enable helper | 274 | * mipi_dbi_enable_flush - MIPI DBI enable helper |
275 | * @pipe: Display pipe | 275 | * @mipi: MIPI DBI structure |
276 | * @crtc_state: CRTC state | ||
277 | * | 276 | * |
278 | * This function enables backlight. Drivers can use this as their | 277 | * This function sets &mipi_dbi->enabled, flushes the whole framebuffer and |
278 | * enables the backlight. Drivers can use this in their | ||
279 | * &drm_simple_display_pipe_funcs->enable callback. | 279 | * &drm_simple_display_pipe_funcs->enable callback. |
280 | */ | 280 | */ |
281 | void mipi_dbi_pipe_enable(struct drm_simple_display_pipe *pipe, | 281 | void mipi_dbi_enable_flush(struct mipi_dbi *mipi) |
282 | struct drm_crtc_state *crtc_state) | ||
283 | { | 282 | { |
284 | struct tinydrm_device *tdev = pipe_to_tinydrm(pipe); | 283 | struct drm_framebuffer *fb = mipi->tinydrm.pipe.plane.fb; |
285 | struct mipi_dbi *mipi = mipi_dbi_from_tinydrm(tdev); | ||
286 | struct drm_framebuffer *fb = pipe->plane.fb; | ||
287 | |||
288 | DRM_DEBUG_KMS("\n"); | ||
289 | 284 | ||
290 | mipi->enabled = true; | 285 | mipi->enabled = true; |
291 | if (fb) | 286 | if (fb) |
@@ -293,7 +288,7 @@ void mipi_dbi_pipe_enable(struct drm_simple_display_pipe *pipe, | |||
293 | 288 | ||
294 | tinydrm_enable_backlight(mipi->backlight); | 289 | tinydrm_enable_backlight(mipi->backlight); |
295 | } | 290 | } |
296 | EXPORT_SYMBOL(mipi_dbi_pipe_enable); | 291 | EXPORT_SYMBOL(mipi_dbi_enable_flush); |
297 | 292 | ||
298 | static void mipi_dbi_blank(struct mipi_dbi *mipi) | 293 | static void mipi_dbi_blank(struct mipi_dbi *mipi) |
299 | { | 294 | { |
@@ -316,8 +311,8 @@ static void mipi_dbi_blank(struct mipi_dbi *mipi) | |||
316 | * mipi_dbi_pipe_disable - MIPI DBI pipe disable helper | 311 | * mipi_dbi_pipe_disable - MIPI DBI pipe disable helper |
317 | * @pipe: Display pipe | 312 | * @pipe: Display pipe |
318 | * | 313 | * |
319 | * This function disables backlight if present or if not the | 314 | * This function disables backlight if present, if not the display memory is |
320 | * display memory is blanked. Drivers can use this as their | 315 | * blanked. The regulator is disabled if in use. Drivers can use this as their |
321 | * &drm_simple_display_pipe_funcs->disable callback. | 316 | * &drm_simple_display_pipe_funcs->disable callback. |
322 | */ | 317 | */ |
323 | void mipi_dbi_pipe_disable(struct drm_simple_display_pipe *pipe) | 318 | void mipi_dbi_pipe_disable(struct drm_simple_display_pipe *pipe) |
@@ -333,6 +328,9 @@ void mipi_dbi_pipe_disable(struct drm_simple_display_pipe *pipe) | |||
333 | tinydrm_disable_backlight(mipi->backlight); | 328 | tinydrm_disable_backlight(mipi->backlight); |
334 | else | 329 | else |
335 | mipi_dbi_blank(mipi); | 330 | mipi_dbi_blank(mipi); |
331 | |||
332 | if (mipi->regulator) | ||
333 | regulator_disable(mipi->regulator); | ||
336 | } | 334 | } |
337 | EXPORT_SYMBOL(mipi_dbi_pipe_disable); | 335 | EXPORT_SYMBOL(mipi_dbi_pipe_disable); |
338 | 336 | ||
@@ -416,7 +414,7 @@ void mipi_dbi_hw_reset(struct mipi_dbi *mipi) | |||
416 | return; | 414 | return; |
417 | 415 | ||
418 | gpiod_set_value_cansleep(mipi->reset, 0); | 416 | gpiod_set_value_cansleep(mipi->reset, 0); |
419 | msleep(20); | 417 | usleep_range(20, 1000); |
420 | gpiod_set_value_cansleep(mipi->reset, 1); | 418 | gpiod_set_value_cansleep(mipi->reset, 1); |
421 | msleep(120); | 419 | msleep(120); |
422 | } | 420 | } |
@@ -443,6 +441,7 @@ bool mipi_dbi_display_is_on(struct mipi_dbi *mipi) | |||
443 | 441 | ||
444 | val &= ~DCS_POWER_MODE_RESERVED_MASK; | 442 | val &= ~DCS_POWER_MODE_RESERVED_MASK; |
445 | 443 | ||
444 | /* The poweron/reset value is 08h DCS_POWER_MODE_DISPLAY_NORMAL_MODE */ | ||
446 | if (val != (DCS_POWER_MODE_DISPLAY | | 445 | if (val != (DCS_POWER_MODE_DISPLAY | |
447 | DCS_POWER_MODE_DISPLAY_NORMAL_MODE | DCS_POWER_MODE_SLEEP_MODE)) | 446 | DCS_POWER_MODE_DISPLAY_NORMAL_MODE | DCS_POWER_MODE_SLEEP_MODE)) |
448 | return false; | 447 | return false; |
@@ -453,6 +452,78 @@ bool mipi_dbi_display_is_on(struct mipi_dbi *mipi) | |||
453 | } | 452 | } |
454 | EXPORT_SYMBOL(mipi_dbi_display_is_on); | 453 | EXPORT_SYMBOL(mipi_dbi_display_is_on); |
455 | 454 | ||
455 | static int mipi_dbi_poweron_reset_conditional(struct mipi_dbi *mipi, bool cond) | ||
456 | { | ||
457 | struct device *dev = mipi->tinydrm.drm->dev; | ||
458 | int ret; | ||
459 | |||
460 | if (mipi->regulator) { | ||
461 | ret = regulator_enable(mipi->regulator); | ||
462 | if (ret) { | ||
463 | DRM_DEV_ERROR(dev, "Failed to enable regulator (%d)\n", ret); | ||
464 | return ret; | ||
465 | } | ||
466 | } | ||
467 | |||
468 | if (cond && mipi_dbi_display_is_on(mipi)) | ||
469 | return 1; | ||
470 | |||
471 | mipi_dbi_hw_reset(mipi); | ||
472 | ret = mipi_dbi_command(mipi, MIPI_DCS_SOFT_RESET); | ||
473 | if (ret) { | ||
474 | DRM_DEV_ERROR(dev, "Failed to send reset command (%d)\n", ret); | ||
475 | if (mipi->regulator) | ||
476 | regulator_disable(mipi->regulator); | ||
477 | return ret; | ||
478 | } | ||
479 | |||
480 | /* | ||
481 | * If we did a hw reset, we know the controller is in Sleep mode and | ||
482 | * per MIPI DSC spec should wait 5ms after soft reset. If we didn't, | ||
483 | * we assume worst case and wait 120ms. | ||
484 | */ | ||
485 | if (mipi->reset) | ||
486 | usleep_range(5000, 20000); | ||
487 | else | ||
488 | msleep(120); | ||
489 | |||
490 | return 0; | ||
491 | } | ||
492 | |||
493 | /** | ||
494 | * mipi_dbi_poweron_reset - MIPI DBI poweron and reset | ||
495 | * @mipi: MIPI DBI structure | ||
496 | * | ||
497 | * This function enables the regulator if used and does a hardware and software | ||
498 | * reset. | ||
499 | * | ||
500 | * Returns: | ||
501 | * Zero on success, or a negative error code. | ||
502 | */ | ||
503 | int mipi_dbi_poweron_reset(struct mipi_dbi *mipi) | ||
504 | { | ||
505 | return mipi_dbi_poweron_reset_conditional(mipi, false); | ||
506 | } | ||
507 | EXPORT_SYMBOL(mipi_dbi_poweron_reset); | ||
508 | |||
509 | /** | ||
510 | * mipi_dbi_poweron_conditional_reset - MIPI DBI poweron and conditional reset | ||
511 | * @mipi: MIPI DBI structure | ||
512 | * | ||
513 | * This function enables the regulator if used and if the display is off, it | ||
514 | * does a hardware and software reset. If mipi_dbi_display_is_on() determines | ||
515 | * that the display is on, no reset is performed. | ||
516 | * | ||
517 | * Returns: | ||
518 | * Zero if the controller was reset, 1 if the display was already on, or a | ||
519 | * negative error code. | ||
520 | */ | ||
521 | int mipi_dbi_poweron_conditional_reset(struct mipi_dbi *mipi) | ||
522 | { | ||
523 | return mipi_dbi_poweron_reset_conditional(mipi, true); | ||
524 | } | ||
525 | EXPORT_SYMBOL(mipi_dbi_poweron_conditional_reset); | ||
526 | |||
456 | #if IS_ENABLED(CONFIG_SPI) | 527 | #if IS_ENABLED(CONFIG_SPI) |
457 | 528 | ||
458 | /** | 529 | /** |