480a600e632bbc854826e7232d6912dc17f39379
[openwrt/staging/ansuel.git] /
1 From c0611a36761fb6abf5a806bbfe417db1f4464a56 Mon Sep 17 00:00:00 2001
2 From: Dave Stevenson <dave.stevenson@raspberrypi.com>
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
7 Remove the encoder functions, and create a bridge attached to
8 this dumb encoder which implements the same functionality.
9
10 As a bridge has state which an encoder doesn't, we need to
11 add the state management functions as well.
12
13 As there is no bridge atomic_mode_set, move the initialisation
14 code that was in mode_set into _pre_enable.
15 The code to actually enable and disable sending video are split
16 from the general control into _enable and _disable.
17
18 Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
19 ---
20 drivers/gpu/drm/vc4/vc4_dsi.c | 122 +++++++++++++++++++++++++---------
21 1 file changed, 90 insertions(+), 32 deletions(-)
22
23 --- a/drivers/gpu/drm/vc4/vc4_dsi.c
24 +++ b/drivers/gpu/drm/vc4/vc4_dsi.c
25 @@ -557,6 +557,7 @@ struct vc4_dsi {
26 struct platform_device *pdev;
27
28 struct drm_bridge *out_bridge;
29 + struct drm_bridge bridge;
30
31 void __iomem *regs;
32
33 @@ -608,6 +609,12 @@ to_vc4_dsi(struct drm_encoder *encoder)
34 return container_of(encoder, struct vc4_dsi, encoder.base);
35 }
36
37 +static inline struct vc4_dsi *
38 +bridge_to_vc4_dsi(struct drm_bridge *bridge)
39 +{
40 + return container_of(bridge, struct vc4_dsi, bridge);
41 +}
42 +
43 static inline void
44 dsi_dma_workaround_write(struct vc4_dsi *dsi, u32 offset, u32 val)
45 {
46 @@ -789,10 +796,21 @@ dsi_esc_timing(u32 ns)
47 return DIV_ROUND_UP(ns, ESC_TIME_NS);
48 }
49
50 -static void vc4_dsi_encoder_disable(struct drm_encoder *encoder,
51 - struct drm_atomic_state *state)
52 +static void vc4_dsi_bridge_disable(struct drm_bridge *bridge,
53 + struct drm_bridge_state *state)
54 {
55 - struct vc4_dsi *dsi = to_vc4_dsi(encoder);
56 + struct vc4_dsi *dsi = bridge_to_vc4_dsi(bridge);
57 + u32 disp0_ctrl;
58 +
59 + disp0_ctrl = DSI_PORT_READ(DISP0_CTRL);
60 + disp0_ctrl &= ~DSI_DISP0_ENABLE;
61 + DSI_PORT_WRITE(DISP0_CTRL, disp0_ctrl);
62 +}
63 +
64 +static void vc4_dsi_bridge_post_disable(struct drm_bridge *bridge,
65 + struct drm_bridge_state *state)
66 +{
67 + struct vc4_dsi *dsi = bridge_to_vc4_dsi(bridge);
68 struct device *dev = &dsi->pdev->dev;
69
70 vc4_dsi_ulps(dsi, true);
71 @@ -817,11 +835,11 @@ static void vc4_dsi_encoder_disable(stru
72 * higher-than-expected clock rate to the panel, but that's what the
73 * firmware does too.
74 */
75 -static bool vc4_dsi_encoder_mode_fixup(struct drm_encoder *encoder,
76 - const struct drm_display_mode *mode,
77 - struct drm_display_mode *adjusted_mode)
78 +static bool vc4_dsi_bridge_mode_fixup(struct drm_bridge *bridge,
79 + const struct drm_display_mode *mode,
80 + struct drm_display_mode *adjusted_mode)
81 {
82 - struct vc4_dsi *dsi = to_vc4_dsi(encoder);
83 + struct vc4_dsi *dsi = bridge_to_vc4_dsi(bridge);
84 struct clk *phy_parent = clk_get_parent(dsi->pll_phy_clock);
85 unsigned long parent_rate = clk_get_rate(phy_parent);
86 unsigned long pixel_clock_hz = mode->clock * 1000;
87 @@ -853,15 +871,18 @@ static bool vc4_dsi_encoder_mode_fixup(s
88 return true;
89 }
90
91 -static void vc4_dsi_encoder_mode_set(struct drm_encoder *encoder,
92 - struct drm_crtc_state *crtc_state,
93 - struct drm_connector_state *conn_state)
94 +static void vc4_dsi_bridge_pre_enable(struct drm_bridge *bridge,
95 + struct drm_bridge_state *old_state)
96 {
97 - struct vc4_dsi *dsi = to_vc4_dsi(encoder);
98 + struct drm_atomic_state *state = old_state->base.state;
99 + struct vc4_dsi *dsi = bridge_to_vc4_dsi(bridge);
100 + const struct drm_crtc_state *crtc_state;
101 struct device *dev = &dsi->pdev->dev;
102 const struct drm_display_mode *mode;
103 + struct drm_connector *connector;
104 bool debug_dump_regs = false;
105 unsigned long hs_clock;
106 + struct drm_crtc *crtc;
107 u32 ui_ns;
108 /* Minimum LP state duration in escape clock cycles. */
109 u32 lpx = dsi_esc_timing(60);
110 @@ -882,6 +903,14 @@ static void vc4_dsi_encoder_mode_set(str
111 drm_print_regset32(&p, &dsi->regset);
112 }
113
114 + /*
115 + * Retrieve the CRTC adjusted mode. This requires a little dance to go
116 + * from the bridge to the encoder, to the connector and to the CRTC.
117 + */
118 + connector = drm_atomic_get_new_connector_for_encoder(state,
119 + bridge->encoder);
120 + crtc = drm_atomic_get_new_connector_state(state, connector)->crtc;
121 + crtc_state = drm_atomic_get_new_crtc_state(state, crtc);
122 mode = &crtc_state->adjusted_mode;
123
124 pixel_clock_hz = mode->clock * 1000;
125 @@ -1096,14 +1125,6 @@ static void vc4_dsi_encoder_mode_set(str
126 ~DSI_PORT_BIT(PHY_AFEC0_RESET));
127
128 vc4_dsi_ulps(dsi, false);
129 -}
130 -
131 -static void vc4_dsi_encoder_enable(struct drm_encoder *encoder,
132 - struct drm_atomic_state *state)
133 -{
134 - struct vc4_dsi_encoder *vc4_encoder = to_vc4_dsi_encoder(encoder);
135 - struct vc4_dsi *dsi = vc4_encoder->dsi;
136 - bool debug_dump_regs = false;
137
138 if (dsi->mode_flags & MIPI_DSI_MODE_VIDEO) {
139 DSI_PORT_WRITE(DISP0_CTRL,
140 @@ -1112,13 +1133,23 @@ static void vc4_dsi_encoder_enable(struc
141 VC4_SET_FIELD(dsi->format, DSI_DISP0_PFORMAT) |
142 VC4_SET_FIELD(DSI_DISP0_LP_STOP_PERFRAME,
143 DSI_DISP0_LP_STOP_CTRL) |
144 - DSI_DISP0_ST_END |
145 - DSI_DISP0_ENABLE);
146 + DSI_DISP0_ST_END);
147 } else {
148 DSI_PORT_WRITE(DISP0_CTRL,
149 - DSI_DISP0_COMMAND_MODE |
150 - DSI_DISP0_ENABLE);
151 + DSI_DISP0_COMMAND_MODE);
152 }
153 +}
154 +
155 +static void vc4_dsi_bridge_enable(struct drm_bridge *bridge,
156 + struct drm_bridge_state *old_state)
157 +{
158 + struct vc4_dsi *dsi = bridge_to_vc4_dsi(bridge);
159 + bool debug_dump_regs = false;
160 + u32 disp0_ctrl;
161 +
162 + disp0_ctrl = DSI_PORT_READ(DISP0_CTRL);
163 + disp0_ctrl |= DSI_DISP0_ENABLE;
164 + DSI_PORT_WRITE(DISP0_CTRL, disp0_ctrl);
165
166 if (debug_dump_regs) {
167 struct drm_printer p = drm_info_printer(&dsi->pdev->dev);
168 @@ -1127,6 +1158,16 @@ static void vc4_dsi_encoder_enable(struc
169 }
170 }
171
172 +static int vc4_dsi_bridge_attach(struct drm_bridge *bridge,
173 + enum drm_bridge_attach_flags flags)
174 +{
175 + struct vc4_dsi *dsi = bridge_to_vc4_dsi(bridge);
176 +
177 + /* Attach the panel or bridge to the dsi bridge */
178 + return drm_bridge_attach(bridge->encoder, dsi->out_bridge,
179 + &dsi->bridge, flags);
180 +}
181 +
182 static ssize_t vc4_dsi_host_transfer(struct mipi_dsi_host *host,
183 const struct mipi_dsi_msg *msg)
184 {
185 @@ -1303,6 +1344,7 @@ static int vc4_dsi_host_attach(struct mi
186 struct mipi_dsi_device *device)
187 {
188 struct vc4_dsi *dsi = host_to_dsi(host);
189 + int ret;
190
191 dsi->lanes = device->lanes;
192 dsi->channel = device->channel;
193 @@ -1337,7 +1379,15 @@ static int vc4_dsi_host_attach(struct mi
194 return 0;
195 }
196
197 - return component_add(&dsi->pdev->dev, &vc4_dsi_ops);
198 + drm_bridge_add(&dsi->bridge);
199 +
200 + ret = component_add(&dsi->pdev->dev, &vc4_dsi_ops);
201 + if (ret) {
202 + drm_bridge_remove(&dsi->bridge);
203 + return ret;
204 + }
205 +
206 + return 0;
207 }
208
209 static int vc4_dsi_host_detach(struct mipi_dsi_host *host,
210 @@ -1346,6 +1396,7 @@ static int vc4_dsi_host_detach(struct mi
211 struct vc4_dsi *dsi = host_to_dsi(host);
212
213 component_del(&dsi->pdev->dev, &vc4_dsi_ops);
214 + drm_bridge_remove(&dsi->bridge);
215 return 0;
216 }
217
218 @@ -1355,11 +1406,16 @@ static const struct mipi_dsi_host_ops vc
219 .transfer = vc4_dsi_host_transfer,
220 };
221
222 -static const struct drm_encoder_helper_funcs vc4_dsi_encoder_helper_funcs = {
223 - .atomic_disable = vc4_dsi_encoder_disable,
224 - .atomic_enable = vc4_dsi_encoder_enable,
225 - .mode_fixup = vc4_dsi_encoder_mode_fixup,
226 - .atomic_mode_set = vc4_dsi_encoder_mode_set,
227 +static const struct drm_bridge_funcs vc4_dsi_bridge_funcs = {
228 + .atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state,
229 + .atomic_destroy_state = drm_atomic_helper_bridge_destroy_state,
230 + .atomic_reset = drm_atomic_helper_bridge_reset,
231 + .atomic_pre_enable = vc4_dsi_bridge_pre_enable,
232 + .atomic_enable = vc4_dsi_bridge_enable,
233 + .atomic_disable = vc4_dsi_bridge_disable,
234 + .atomic_post_disable = vc4_dsi_bridge_post_disable,
235 + .attach = vc4_dsi_bridge_attach,
236 + .mode_fixup = vc4_dsi_bridge_mode_fixup,
237 };
238
239 static int vc4_dsi_late_register(struct drm_encoder *encoder)
240 @@ -1734,13 +1790,11 @@ static int vc4_dsi_bind(struct device *d
241 if (ret)
242 return ret;
243
244 - drm_encoder_helper_add(encoder, &vc4_dsi_encoder_helper_funcs);
245 -
246 ret = devm_pm_runtime_enable(dev);
247 if (ret)
248 return ret;
249
250 - ret = drm_bridge_attach(encoder, dsi->out_bridge, NULL, 0);
251 + ret = drm_bridge_attach(encoder, &dsi->bridge, NULL, 0);
252 if (ret)
253 return ret;
254
255 @@ -1762,7 +1816,11 @@ static int vc4_dsi_dev_probe(struct plat
256 dev_set_drvdata(dev, dsi);
257
258 kref_init(&dsi->kref);
259 +
260 dsi->pdev = pdev;
261 + dsi->bridge.funcs = &vc4_dsi_bridge_funcs;
262 + dsi->bridge.of_node = dev->of_node;
263 + dsi->bridge.type = DRM_MODE_CONNECTOR_DSI;
264 dsi->dsi_host.ops = &vc4_dsi_host_ops;
265 dsi->dsi_host.dev = dev;
266 mipi_dsi_host_register(&dsi->dsi_host);