950-0715-drm-vc4-Convert-vc4_dsi-to-using-a-bridge-instead-of.patch 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264
  1. From 3e6793632310f9991b75c3095a9795b6a8d1d859 Mon Sep 17 00:00:00 2001
  2. From: Dave Stevenson <[email protected]>
  3. Date: Wed, 15 Dec 2021 17:57:45 +0000
  4. Subject: [PATCH] drm/vc4: Convert vc4_dsi to using a bridge instead of
  5. encoder.
  6. Remove the encoder functions, and create a bridge attached to
  7. this dumb encoder which implements the same functionality.
  8. As a bridge has state which an encoder doesn't, we need to
  9. add the state management functions as well.
  10. As there is no bridge atomic_mode_set, move the initialisation
  11. code that was in mode_set into _pre_enable.
  12. The code to actually enable and disable sending video are split
  13. from the general control into _enable and _disable.
  14. Signed-off-by: Dave Stevenson <[email protected]>
  15. ---
  16. drivers/gpu/drm/vc4/vc4_dsi.c | 124 ++++++++++++++++++++++++----------
  17. 1 file changed, 90 insertions(+), 34 deletions(-)
  18. --- a/drivers/gpu/drm/vc4/vc4_dsi.c
  19. +++ b/drivers/gpu/drm/vc4/vc4_dsi.c
  20. @@ -554,6 +554,7 @@ struct vc4_dsi {
  21. struct mipi_dsi_host dsi_host;
  22. struct drm_encoder *encoder;
  23. struct drm_bridge *out_bridge;
  24. + struct drm_bridge bridge;
  25. void __iomem *regs;
  26. @@ -655,6 +656,12 @@ to_vc4_dsi_encoder(struct drm_encoder *e
  27. return container_of(encoder, struct vc4_dsi_encoder, base.base);
  28. }
  29. +static inline struct vc4_dsi *
  30. +bridge_to_vc4_dsi(struct drm_bridge *bridge)
  31. +{
  32. + return container_of(bridge, struct vc4_dsi, bridge);
  33. +}
  34. +
  35. static const struct debugfs_reg32 dsi0_regs[] = {
  36. VC4_REG32(DSI0_CTRL),
  37. VC4_REG32(DSI0_STAT),
  38. @@ -792,11 +799,21 @@ dsi_esc_timing(u32 ns)
  39. return DIV_ROUND_UP(ns, ESC_TIME_NS);
  40. }
  41. -static void vc4_dsi_encoder_disable(struct drm_encoder *encoder,
  42. - struct drm_atomic_state *state)
  43. +static void vc4_dsi_bridge_disable(struct drm_bridge *bridge,
  44. + struct drm_bridge_state *state)
  45. +{
  46. + struct vc4_dsi *dsi = bridge_to_vc4_dsi(bridge);
  47. + u32 disp0_ctrl;
  48. +
  49. + disp0_ctrl = DSI_PORT_READ(DISP0_CTRL);
  50. + disp0_ctrl &= ~DSI_DISP0_ENABLE;
  51. + DSI_PORT_WRITE(DISP0_CTRL, disp0_ctrl);
  52. +}
  53. +
  54. +static void vc4_dsi_bridge_post_disable(struct drm_bridge *bridge,
  55. + struct drm_bridge_state *state)
  56. {
  57. - struct vc4_dsi_encoder *vc4_encoder = to_vc4_dsi_encoder(encoder);
  58. - struct vc4_dsi *dsi = vc4_encoder->dsi;
  59. + struct vc4_dsi *dsi = bridge_to_vc4_dsi(bridge);
  60. struct device *dev = &dsi->pdev->dev;
  61. vc4_dsi_ulps(dsi, true);
  62. @@ -821,12 +838,11 @@ static void vc4_dsi_encoder_disable(stru
  63. * higher-than-expected clock rate to the panel, but that's what the
  64. * firmware does too.
  65. */
  66. -static bool vc4_dsi_encoder_mode_fixup(struct drm_encoder *encoder,
  67. - const struct drm_display_mode *mode,
  68. - struct drm_display_mode *adjusted_mode)
  69. +static bool vc4_dsi_bridge_mode_fixup(struct drm_bridge *bridge,
  70. + const struct drm_display_mode *mode,
  71. + struct drm_display_mode *adjusted_mode)
  72. {
  73. - struct vc4_dsi_encoder *vc4_encoder = to_vc4_dsi_encoder(encoder);
  74. - struct vc4_dsi *dsi = vc4_encoder->dsi;
  75. + struct vc4_dsi *dsi = bridge_to_vc4_dsi(bridge);
  76. struct clk *phy_parent = clk_get_parent(dsi->pll_phy_clock);
  77. unsigned long parent_rate = clk_get_rate(phy_parent);
  78. unsigned long pixel_clock_hz = mode->clock * 1000;
  79. @@ -858,16 +874,18 @@ static bool vc4_dsi_encoder_mode_fixup(s
  80. return true;
  81. }
  82. -static void vc4_dsi_encoder_mode_set(struct drm_encoder *encoder,
  83. - struct drm_crtc_state *crtc_state,
  84. - struct drm_connector_state *conn_state)
  85. +static void vc4_dsi_bridge_pre_enable(struct drm_bridge *bridge,
  86. + struct drm_bridge_state *old_state)
  87. {
  88. - struct vc4_dsi_encoder *vc4_encoder = to_vc4_dsi_encoder(encoder);
  89. - struct vc4_dsi *dsi = vc4_encoder->dsi;
  90. + struct drm_atomic_state *state = old_state->base.state;
  91. + struct vc4_dsi *dsi = bridge_to_vc4_dsi(bridge);
  92. + const struct drm_crtc_state *crtc_state;
  93. struct device *dev = &dsi->pdev->dev;
  94. const struct drm_display_mode *mode;
  95. + struct drm_connector *connector;
  96. bool debug_dump_regs = false;
  97. unsigned long hs_clock;
  98. + struct drm_crtc *crtc;
  99. u32 ui_ns;
  100. /* Minimum LP state duration in escape clock cycles. */
  101. u32 lpx = dsi_esc_timing(60);
  102. @@ -888,6 +906,14 @@ static void vc4_dsi_encoder_mode_set(str
  103. drm_print_regset32(&p, &dsi->regset);
  104. }
  105. + /*
  106. + * Retrieve the CRTC adjusted mode. This requires a little dance to go
  107. + * from the bridge to the encoder, to the connector and to the CRTC.
  108. + */
  109. + connector = drm_atomic_get_new_connector_for_encoder(state,
  110. + bridge->encoder);
  111. + crtc = drm_atomic_get_new_connector_state(state, connector)->crtc;
  112. + crtc_state = drm_atomic_get_new_crtc_state(state, crtc);
  113. mode = &crtc_state->adjusted_mode;
  114. pixel_clock_hz = mode->clock * 1000;
  115. @@ -1102,14 +1128,6 @@ static void vc4_dsi_encoder_mode_set(str
  116. ~DSI_PORT_BIT(PHY_AFEC0_RESET));
  117. vc4_dsi_ulps(dsi, false);
  118. -}
  119. -
  120. -static void vc4_dsi_encoder_enable(struct drm_encoder *encoder,
  121. - struct drm_atomic_state *state)
  122. -{
  123. - struct vc4_dsi_encoder *vc4_encoder = to_vc4_dsi_encoder(encoder);
  124. - struct vc4_dsi *dsi = vc4_encoder->dsi;
  125. - bool debug_dump_regs = false;
  126. if (dsi->mode_flags & MIPI_DSI_MODE_VIDEO) {
  127. DSI_PORT_WRITE(DISP0_CTRL,
  128. @@ -1118,13 +1136,23 @@ static void vc4_dsi_encoder_enable(struc
  129. VC4_SET_FIELD(dsi->format, DSI_DISP0_PFORMAT) |
  130. VC4_SET_FIELD(DSI_DISP0_LP_STOP_PERFRAME,
  131. DSI_DISP0_LP_STOP_CTRL) |
  132. - DSI_DISP0_ST_END |
  133. - DSI_DISP0_ENABLE);
  134. + DSI_DISP0_ST_END);
  135. } else {
  136. DSI_PORT_WRITE(DISP0_CTRL,
  137. - DSI_DISP0_COMMAND_MODE |
  138. - DSI_DISP0_ENABLE);
  139. + DSI_DISP0_COMMAND_MODE);
  140. }
  141. +}
  142. +
  143. +static void vc4_dsi_bridge_enable(struct drm_bridge *bridge,
  144. + struct drm_bridge_state *old_state)
  145. +{
  146. + struct vc4_dsi *dsi = bridge_to_vc4_dsi(bridge);
  147. + bool debug_dump_regs = false;
  148. + u32 disp0_ctrl;
  149. +
  150. + disp0_ctrl = DSI_PORT_READ(DISP0_CTRL);
  151. + disp0_ctrl |= DSI_DISP0_ENABLE;
  152. + DSI_PORT_WRITE(DISP0_CTRL, disp0_ctrl);
  153. if (debug_dump_regs) {
  154. struct drm_printer p = drm_info_printer(&dsi->pdev->dev);
  155. @@ -1133,6 +1161,16 @@ static void vc4_dsi_encoder_enable(struc
  156. }
  157. }
  158. +static int vc4_dsi_bridge_attach(struct drm_bridge *bridge,
  159. + enum drm_bridge_attach_flags flags)
  160. +{
  161. + struct vc4_dsi *dsi = bridge_to_vc4_dsi(bridge);
  162. +
  163. + /* Attach the panel or bridge to the dsi bridge */
  164. + return drm_bridge_attach(bridge->encoder, dsi->out_bridge,
  165. + &dsi->bridge, flags);
  166. +}
  167. +
  168. static ssize_t vc4_dsi_host_transfer(struct mipi_dsi_host *host,
  169. const struct mipi_dsi_msg *msg)
  170. {
  171. @@ -1309,6 +1347,7 @@ static int vc4_dsi_host_attach(struct mi
  172. struct mipi_dsi_device *device)
  173. {
  174. struct vc4_dsi *dsi = host_to_dsi(host);
  175. + int ret;
  176. dsi->lanes = device->lanes;
  177. dsi->channel = device->channel;
  178. @@ -1343,7 +1382,15 @@ static int vc4_dsi_host_attach(struct mi
  179. return 0;
  180. }
  181. - return component_add(&dsi->pdev->dev, &vc4_dsi_ops);
  182. + drm_bridge_add(&dsi->bridge);
  183. +
  184. + ret = component_add(&dsi->pdev->dev, &vc4_dsi_ops);
  185. + if (ret) {
  186. + drm_bridge_remove(&dsi->bridge);
  187. + return ret;
  188. + }
  189. +
  190. + return 0;
  191. }
  192. static int vc4_dsi_host_detach(struct mipi_dsi_host *host,
  193. @@ -1352,6 +1399,7 @@ static int vc4_dsi_host_detach(struct mi
  194. struct vc4_dsi *dsi = host_to_dsi(host);
  195. component_del(&dsi->pdev->dev, &vc4_dsi_ops);
  196. + drm_bridge_remove(&dsi->bridge);
  197. return 0;
  198. }
  199. @@ -1361,11 +1409,16 @@ static const struct mipi_dsi_host_ops vc
  200. .transfer = vc4_dsi_host_transfer,
  201. };
  202. -static const struct drm_encoder_helper_funcs vc4_dsi_encoder_helper_funcs = {
  203. - .atomic_disable = vc4_dsi_encoder_disable,
  204. - .atomic_enable = vc4_dsi_encoder_enable,
  205. - .mode_fixup = vc4_dsi_encoder_mode_fixup,
  206. - .atomic_mode_set = vc4_dsi_encoder_mode_set,
  207. +static const struct drm_bridge_funcs vc4_dsi_bridge_funcs = {
  208. + .atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state,
  209. + .atomic_destroy_state = drm_atomic_helper_bridge_destroy_state,
  210. + .atomic_reset = drm_atomic_helper_bridge_reset,
  211. + .atomic_pre_enable = vc4_dsi_bridge_pre_enable,
  212. + .atomic_enable = vc4_dsi_bridge_enable,
  213. + .atomic_disable = vc4_dsi_bridge_disable,
  214. + .atomic_post_disable = vc4_dsi_bridge_post_disable,
  215. + .attach = vc4_dsi_bridge_attach,
  216. + .mode_fixup = vc4_dsi_bridge_mode_fixup,
  217. };
  218. static const struct vc4_dsi_variant bcm2711_dsi1_variant = {
  219. @@ -1692,9 +1745,8 @@ static int vc4_dsi_bind(struct device *d
  220. return ret;
  221. drm_simple_encoder_init(drm, dsi->encoder, DRM_MODE_ENCODER_DSI);
  222. - drm_encoder_helper_add(dsi->encoder, &vc4_dsi_encoder_helper_funcs);
  223. - ret = drm_bridge_attach(dsi->encoder, dsi->out_bridge, NULL, 0);
  224. + ret = drm_bridge_attach(dsi->encoder, &dsi->bridge, NULL, 0);
  225. if (ret)
  226. return ret;
  227. @@ -1730,6 +1782,10 @@ static int vc4_dsi_dev_probe(struct plat
  228. return -ENOMEM;
  229. dev_set_drvdata(dev, dsi);
  230. + dsi->bridge.funcs = &vc4_dsi_bridge_funcs;
  231. + dsi->bridge.of_node = dev->of_node;
  232. + dsi->bridge.type = DRM_MODE_CONNECTOR_DSI;
  233. +
  234. dsi->pdev = pdev;
  235. dsi->dsi_host.ops = &vc4_dsi_host_ops;
  236. dsi->dsi_host.dev = dev;