aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/tegra
diff options
context:
space:
mode:
authorThierry Reding <treding@nvidia.com>2014-11-13 08:44:27 -0500
committerThierry Reding <treding@nvidia.com>2014-11-13 10:12:20 -0500
commit563eff1f989917779d8db4c5208e12adcbfcf655 (patch)
treebce4ba10b92f7973edaef0ce4944ae78f65e6413 /drivers/gpu/drm/tegra
parentd2d0a9d21285ace23b7e99c89a52ee9b5ceef792 (diff)
drm/tegra: dsi: Refactor in preparation for command mode
For command mode panels, the DSI controller needs to be enabled and configured so that panel drivers can send commands prior to the video stream being enabled. Move code from the monolithic output enable/disable functions into smaller, reusable units to allow more fine-grained control over the controller state. Signed-off-by: Thierry Reding <treding@nvidia.com>
Diffstat (limited to 'drivers/gpu/drm/tegra')
-rw-r--r--drivers/gpu/drm/tegra/dsi.c100
1 files changed, 81 insertions, 19 deletions
diff --git a/drivers/gpu/drm/tegra/dsi.c b/drivers/gpu/drm/tegra/dsi.c
index 5dae8053e8c9..b91d9e4016bc 100644
--- a/drivers/gpu/drm/tegra/dsi.c
+++ b/drivers/gpu/drm/tegra/dsi.c
@@ -426,20 +426,24 @@ static int tegra_dsi_get_format(enum mipi_dsi_pixel_format format,
426 return 0; 426 return 0;
427} 427}
428 428
429static int tegra_output_dsi_enable(struct tegra_output *output) 429static void tegra_dsi_enable(struct tegra_dsi *dsi)
430{
431 u32 value;
432
433 value = tegra_dsi_readl(dsi, DSI_POWER_CONTROL);
434 value |= DSI_POWER_CONTROL_ENABLE;
435 tegra_dsi_writel(dsi, value, DSI_POWER_CONTROL);
436}
437
438static int tegra_dsi_configure(struct tegra_dsi *dsi, unsigned int pipe,
439 const struct drm_display_mode *mode)
430{ 440{
431 struct tegra_dc *dc = to_tegra_dc(output->encoder.crtc);
432 struct drm_display_mode *mode = &dc->base.mode;
433 unsigned int hact, hsw, hbp, hfp, i, mul, div; 441 unsigned int hact, hsw, hbp, hfp, i, mul, div;
434 struct tegra_dsi *dsi = to_dsi(output);
435 enum tegra_dsi_format format; 442 enum tegra_dsi_format format;
436 unsigned long value;
437 const u32 *pkt_seq; 443 const u32 *pkt_seq;
444 u32 value;
438 int err; 445 int err;
439 446
440 if (dsi->enabled)
441 return 0;
442
443 if (dsi->flags & MIPI_DSI_MODE_VIDEO_SYNC_PULSE) { 447 if (dsi->flags & MIPI_DSI_MODE_VIDEO_SYNC_PULSE) {
444 DRM_DEBUG_KMS("Non-burst video mode with sync pulses\n"); 448 DRM_DEBUG_KMS("Non-burst video mode with sync pulses\n");
445 pkt_seq = pkt_seq_video_non_burst_sync_pulses; 449 pkt_seq = pkt_seq_video_non_burst_sync_pulses;
@@ -458,18 +462,19 @@ static int tegra_output_dsi_enable(struct tegra_output *output)
458 462
459 value = DSI_CONTROL_CHANNEL(0) | DSI_CONTROL_FORMAT(format) | 463 value = DSI_CONTROL_CHANNEL(0) | DSI_CONTROL_FORMAT(format) |
460 DSI_CONTROL_LANES(dsi->lanes - 1) | 464 DSI_CONTROL_LANES(dsi->lanes - 1) |
461 DSI_CONTROL_SOURCE(dc->pipe); 465 DSI_CONTROL_SOURCE(pipe);
462 tegra_dsi_writel(dsi, value, DSI_CONTROL); 466 tegra_dsi_writel(dsi, value, DSI_CONTROL);
463 467
464 tegra_dsi_writel(dsi, dsi->video_fifo_depth, DSI_MAX_THRESHOLD); 468 tegra_dsi_writel(dsi, dsi->video_fifo_depth, DSI_MAX_THRESHOLD);
465 469
466 value = DSI_HOST_CONTROL_HS | DSI_HOST_CONTROL_CS | 470 value = DSI_HOST_CONTROL_HS;
467 DSI_HOST_CONTROL_ECC;
468 tegra_dsi_writel(dsi, value, DSI_HOST_CONTROL); 471 tegra_dsi_writel(dsi, value, DSI_HOST_CONTROL);
469 472
470 value = tegra_dsi_readl(dsi, DSI_CONTROL); 473 value = tegra_dsi_readl(dsi, DSI_CONTROL);
474
471 if (dsi->flags & MIPI_DSI_CLOCK_NON_CONTINUOUS) 475 if (dsi->flags & MIPI_DSI_CLOCK_NON_CONTINUOUS)
472 value |= DSI_CONTROL_HS_CLK_CTRL; 476 value |= DSI_CONTROL_HS_CLK_CTRL;
477
473 value &= ~DSI_CONTROL_TX_TRIG(3); 478 value &= ~DSI_CONTROL_TX_TRIG(3);
474 value &= ~DSI_CONTROL_DCS_ENABLE; 479 value &= ~DSI_CONTROL_DCS_ENABLE;
475 value |= DSI_CONTROL_VIDEO_ENABLE; 480 value |= DSI_CONTROL_VIDEO_ENABLE;
@@ -503,9 +508,27 @@ static int tegra_output_dsi_enable(struct tegra_output *output)
503 tegra_dsi_writel(dsi, hfp, DSI_PKT_LEN_4_5); 508 tegra_dsi_writel(dsi, hfp, DSI_PKT_LEN_4_5);
504 tegra_dsi_writel(dsi, 0x0f0f << 16, DSI_PKT_LEN_6_7); 509 tegra_dsi_writel(dsi, 0x0f0f << 16, DSI_PKT_LEN_6_7);
505 510
506 /* set SOL delay */ 511 /* set SOL delay (for non-burst mode only) */
507 tegra_dsi_writel(dsi, 8 * mul / div, DSI_SOL_DELAY); 512 tegra_dsi_writel(dsi, 8 * mul / div, DSI_SOL_DELAY);
508 513
514 return 0;
515}
516
517static int tegra_output_dsi_enable(struct tegra_output *output)
518{
519 struct tegra_dc *dc = to_tegra_dc(output->encoder.crtc);
520 const struct drm_display_mode *mode = &dc->base.mode;
521 struct tegra_dsi *dsi = to_dsi(output);
522 u32 value;
523 int err;
524
525 if (dsi->enabled)
526 return 0;
527
528 err = tegra_dsi_configure(dsi, dc->pipe, mode);
529 if (err < 0)
530 return err;
531
509 /* enable display controller */ 532 /* enable display controller */
510 value = tegra_dc_readl(dc, DC_DISP_DISP_WIN_OPTIONS); 533 value = tegra_dc_readl(dc, DC_DISP_DISP_WIN_OPTIONS);
511 value |= DSI_ENABLE; 534 value |= DSI_ENABLE;
@@ -525,28 +548,61 @@ static int tegra_output_dsi_enable(struct tegra_output *output)
525 tegra_dc_writel(dc, GENERAL_ACT_REQ, DC_CMD_STATE_CONTROL); 548 tegra_dc_writel(dc, GENERAL_ACT_REQ, DC_CMD_STATE_CONTROL);
526 549
527 /* enable DSI controller */ 550 /* enable DSI controller */
528 value = tegra_dsi_readl(dsi, DSI_POWER_CONTROL); 551 tegra_dsi_enable(dsi);
529 value |= DSI_POWER_CONTROL_ENABLE;
530 tegra_dsi_writel(dsi, value, DSI_POWER_CONTROL);
531 552
532 dsi->enabled = true; 553 dsi->enabled = true;
533 554
534 return 0; 555 return 0;
535} 556}
536 557
558static int tegra_dsi_wait_idle(struct tegra_dsi *dsi, unsigned long timeout)
559{
560 u32 value;
561
562 timeout = jiffies + msecs_to_jiffies(timeout);
563
564 while (time_before(jiffies, timeout)) {
565 value = tegra_dsi_readl(dsi, DSI_STATUS);
566 if (value & DSI_STATUS_IDLE)
567 return 0;
568
569 usleep_range(1000, 2000);
570 }
571
572 return -ETIMEDOUT;
573}
574
575static void tegra_dsi_video_disable(struct tegra_dsi *dsi)
576{
577 u32 value;
578
579 value = tegra_dsi_readl(dsi, DSI_CONTROL);
580 value &= ~DSI_CONTROL_VIDEO_ENABLE;
581 tegra_dsi_writel(dsi, value, DSI_CONTROL);
582}
583
584static void tegra_dsi_disable(struct tegra_dsi *dsi)
585{
586 u32 value;
587
588 value = tegra_dsi_readl(dsi, DSI_POWER_CONTROL);
589 value &= ~DSI_POWER_CONTROL_ENABLE;
590 tegra_dsi_writel(dsi, value, DSI_POWER_CONTROL);
591
592 usleep_range(5000, 10000);
593}
594
537static int tegra_output_dsi_disable(struct tegra_output *output) 595static int tegra_output_dsi_disable(struct tegra_output *output)
538{ 596{
539 struct tegra_dc *dc = to_tegra_dc(output->encoder.crtc); 597 struct tegra_dc *dc = to_tegra_dc(output->encoder.crtc);
540 struct tegra_dsi *dsi = to_dsi(output); 598 struct tegra_dsi *dsi = to_dsi(output);
541 unsigned long value; 599 unsigned long value;
600 int err;
542 601
543 if (!dsi->enabled) 602 if (!dsi->enabled)
544 return 0; 603 return 0;
545 604
546 /* disable DSI controller */ 605 tegra_dsi_video_disable(dsi);
547 value = tegra_dsi_readl(dsi, DSI_POWER_CONTROL);
548 value &= ~DSI_POWER_CONTROL_ENABLE;
549 tegra_dsi_writel(dsi, value, DSI_POWER_CONTROL);
550 606
551 /* 607 /*
552 * The following accesses registers of the display controller, so make 608 * The following accesses registers of the display controller, so make
@@ -570,6 +626,12 @@ static int tegra_output_dsi_disable(struct tegra_output *output)
570 tegra_dc_writel(dc, GENERAL_ACT_REQ, DC_CMD_STATE_CONTROL); 626 tegra_dc_writel(dc, GENERAL_ACT_REQ, DC_CMD_STATE_CONTROL);
571 } 627 }
572 628
629 err = tegra_dsi_wait_idle(dsi, 100);
630 if (err < 0)
631 dev_dbg(dsi->dev, "failed to idle DSI: %d\n", err);
632
633 tegra_dsi_disable(dsi);
634
573 dsi->enabled = false; 635 dsi->enabled = false;
574 636
575 return 0; 637 return 0;