diff options
| author | Eric Anholt <eric@anholt.net> | 2018-06-21 19:17:59 -0400 |
|---|---|---|
| committer | Eric Anholt <eric@anholt.net> | 2018-06-29 16:42:09 -0400 |
| commit | 491657a915601febfb9d0c253d843124438ae35d (patch) | |
| tree | 5b5fcaf8d6721fdf5aad2f32a956e86200d42289 /drivers/gpu/drm/vc4 | |
| parent | 14d9deeb273c2bf4ec256589adabd8df65395d36 (diff) | |
drm/vc4: Make DSI call into the bridge after the DSI link is enabled.
This allows panels or bridges that need to send DSI commands during
pre_enable() to successfully send them. We delay DISP0 (aka the
actual display) enabling until after pre_enable so that pixels aren't
streaming before then.
v2: Just clear out the encoder->bridge value to disable the midlayer
calls (idea by Andrzej Hajda).
Signed-off-by: Eric Anholt <eric@anholt.net>
Cc: Andrzej Hajda <a.hajda@samsung.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20180621231759.29604-1-eric@anholt.net
Reviewed-by: Andrzej Hajda <a.hajda@samsung.com>
Diffstat (limited to 'drivers/gpu/drm/vc4')
| -rw-r--r-- | drivers/gpu/drm/vc4/vc4_dsi.c | 42 |
1 files changed, 27 insertions, 15 deletions
diff --git a/drivers/gpu/drm/vc4/vc4_dsi.c b/drivers/gpu/drm/vc4/vc4_dsi.c index 8aa897835118..9c8e89372d1c 100644 --- a/drivers/gpu/drm/vc4/vc4_dsi.c +++ b/drivers/gpu/drm/vc4/vc4_dsi.c | |||
| @@ -814,7 +814,9 @@ static void vc4_dsi_encoder_disable(struct drm_encoder *encoder) | |||
| 814 | struct vc4_dsi *dsi = vc4_encoder->dsi; | 814 | struct vc4_dsi *dsi = vc4_encoder->dsi; |
| 815 | struct device *dev = &dsi->pdev->dev; | 815 | struct device *dev = &dsi->pdev->dev; |
| 816 | 816 | ||
| 817 | drm_bridge_disable(dsi->bridge); | ||
| 817 | vc4_dsi_ulps(dsi, true); | 818 | vc4_dsi_ulps(dsi, true); |
| 819 | drm_bridge_post_disable(dsi->bridge); | ||
| 818 | 820 | ||
| 819 | clk_disable_unprepare(dsi->pll_phy_clock); | 821 | clk_disable_unprepare(dsi->pll_phy_clock); |
| 820 | clk_disable_unprepare(dsi->escape_clock); | 822 | clk_disable_unprepare(dsi->escape_clock); |
| @@ -1089,21 +1091,6 @@ static void vc4_dsi_encoder_enable(struct drm_encoder *encoder) | |||
| 1089 | /* Display reset sequence timeout */ | 1091 | /* Display reset sequence timeout */ |
| 1090 | DSI_PORT_WRITE(PR_TO_CNT, 100000); | 1092 | DSI_PORT_WRITE(PR_TO_CNT, 100000); |
| 1091 | 1093 | ||
| 1092 | if (dsi->mode_flags & MIPI_DSI_MODE_VIDEO) { | ||
| 1093 | DSI_PORT_WRITE(DISP0_CTRL, | ||
| 1094 | VC4_SET_FIELD(dsi->divider, | ||
| 1095 | DSI_DISP0_PIX_CLK_DIV) | | ||
| 1096 | VC4_SET_FIELD(dsi->format, DSI_DISP0_PFORMAT) | | ||
| 1097 | VC4_SET_FIELD(DSI_DISP0_LP_STOP_PERFRAME, | ||
| 1098 | DSI_DISP0_LP_STOP_CTRL) | | ||
| 1099 | DSI_DISP0_ST_END | | ||
| 1100 | DSI_DISP0_ENABLE); | ||
| 1101 | } else { | ||
| 1102 | DSI_PORT_WRITE(DISP0_CTRL, | ||
| 1103 | DSI_DISP0_COMMAND_MODE | | ||
| 1104 | DSI_DISP0_ENABLE); | ||
| 1105 | } | ||
| 1106 | |||
| 1107 | /* Set up DISP1 for transferring long command payloads through | 1094 | /* Set up DISP1 for transferring long command payloads through |
| 1108 | * the pixfifo. | 1095 | * the pixfifo. |
| 1109 | */ | 1096 | */ |
| @@ -1128,6 +1115,25 @@ static void vc4_dsi_encoder_enable(struct drm_encoder *encoder) | |||
| 1128 | 1115 | ||
| 1129 | vc4_dsi_ulps(dsi, false); | 1116 | vc4_dsi_ulps(dsi, false); |
| 1130 | 1117 | ||
| 1118 | drm_bridge_pre_enable(dsi->bridge); | ||
| 1119 | |||
| 1120 | if (dsi->mode_flags & MIPI_DSI_MODE_VIDEO) { | ||
| 1121 | DSI_PORT_WRITE(DISP0_CTRL, | ||
| 1122 | VC4_SET_FIELD(dsi->divider, | ||
| 1123 | DSI_DISP0_PIX_CLK_DIV) | | ||
| 1124 | VC4_SET_FIELD(dsi->format, DSI_DISP0_PFORMAT) | | ||
| 1125 | VC4_SET_FIELD(DSI_DISP0_LP_STOP_PERFRAME, | ||
| 1126 | DSI_DISP0_LP_STOP_CTRL) | | ||
| 1127 | DSI_DISP0_ST_END | | ||
| 1128 | DSI_DISP0_ENABLE); | ||
| 1129 | } else { | ||
| 1130 | DSI_PORT_WRITE(DISP0_CTRL, | ||
| 1131 | DSI_DISP0_COMMAND_MODE | | ||
| 1132 | DSI_DISP0_ENABLE); | ||
| 1133 | } | ||
| 1134 | |||
| 1135 | drm_bridge_enable(dsi->bridge); | ||
| 1136 | |||
| 1131 | if (debug_dump_regs) { | 1137 | if (debug_dump_regs) { |
| 1132 | DRM_INFO("DSI regs after:\n"); | 1138 | DRM_INFO("DSI regs after:\n"); |
| 1133 | vc4_dsi_dump_regs(dsi); | 1139 | vc4_dsi_dump_regs(dsi); |
| @@ -1639,6 +1645,12 @@ static int vc4_dsi_bind(struct device *dev, struct device *master, void *data) | |||
| 1639 | dev_err(dev, "bridge attach failed: %d\n", ret); | 1645 | dev_err(dev, "bridge attach failed: %d\n", ret); |
| 1640 | return ret; | 1646 | return ret; |
| 1641 | } | 1647 | } |
| 1648 | /* Disable the atomic helper calls into the bridge. We | ||
| 1649 | * manually call the bridge pre_enable / enable / etc. calls | ||
| 1650 | * from our driver, since we need to sequence them within the | ||
| 1651 | * encoder's enable/disable paths. | ||
| 1652 | */ | ||
| 1653 | dsi->encoder->bridge = NULL; | ||
| 1642 | 1654 | ||
| 1643 | pm_runtime_enable(dev); | 1655 | pm_runtime_enable(dev); |
| 1644 | 1656 | ||
