Skip to content

Commit 3cf3d39

Browse files
mripardpelwell
authored andcommitted
drm/vc4: Rework the encoder retrieval code
Due to a FIFO that cannot be flushed between the pixelvalve and the HDMI controllers on BCM2711, we need to carefully disable both at boot time if they were left enabled by the firmware. However, at the time we're running that code, the struct drm_connector encoder pointer isn't set yet, and thus we cannot retrieve the encoder associated to our CRTC. We can however make use of the fact that we have a less flexible setup than what DRM allows where we have a 1:1 relationship between our CRTCs and encoders (and connectors), and thus store the crtc associated to our encoder at boot time. We cannot do that at the time the encoders are probed though, since the CRTCs won't be probed yet and thus we don't know at that time which CRTC index we're going to get, so let's do this in two passes: we can first bind all the components and then once they all are bound, we can iterate over all the encoders to find their associated CRTC and set the pointer. This is similar to what we're doing to set the possible_crtcs field. Fixes: 875a4d5 ("drm/vc4: drv: Disable the CRTC at boot time") Signed-off-by: Maxime Ripard <[email protected]>
1 parent 4fb83a7 commit 3cf3d39

File tree

3 files changed

+69
-2
lines changed

3 files changed

+69
-2
lines changed

drivers/gpu/drm/vc4/vc4_crtc.c

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -272,6 +272,19 @@ static u32 vc4_crtc_get_fifo_full_level_bits(struct vc4_crtc *vc4_crtc,
272272
PV_CONTROL_FIFO_LEVEL);
273273
}
274274

275+
static struct drm_encoder *vc4_get_connector_encoder(struct drm_connector *connector)
276+
{
277+
struct drm_encoder *encoder;
278+
279+
if (drm_WARN_ON(connector->dev, hweight32(connector->possible_encoders) != 1))
280+
return NULL;
281+
282+
drm_connector_for_each_possible_encoder(connector, encoder)
283+
return encoder;
284+
285+
return NULL;
286+
}
287+
275288
/*
276289
* Returns the encoder attached to the CRTC.
277290
*
@@ -286,9 +299,17 @@ static struct drm_encoder *vc4_get_crtc_encoder(struct drm_crtc *crtc)
286299

287300
drm_connector_list_iter_begin(crtc->dev, &conn_iter);
288301
drm_for_each_connector_iter(connector, &conn_iter) {
289-
if (connector->state->crtc == crtc) {
302+
struct drm_encoder *encoder;
303+
struct vc4_encoder *vc4_encoder;
304+
305+
encoder = vc4_get_connector_encoder(connector);
306+
if (!encoder)
307+
continue;
308+
309+
vc4_encoder = to_vc4_encoder(encoder);
310+
if (vc4_encoder->crtc == crtc) {
290311
drm_connector_list_iter_end(&conn_iter);
291-
return connector->encoder;
312+
return encoder;
292313
}
293314
}
294315
drm_connector_list_iter_end(&conn_iter);

drivers/gpu/drm/vc4/vc4_drv.c

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -226,6 +226,41 @@ static int compare_dev(struct device *dev, void *data)
226226
return dev == data;
227227
}
228228

229+
static struct drm_crtc *vc4_drv_find_crtc(struct drm_device *drm,
230+
struct drm_encoder *encoder)
231+
{
232+
struct drm_crtc *crtc;
233+
234+
if (WARN_ON(hweight32(encoder->possible_crtcs) != 1))
235+
return NULL;
236+
237+
drm_for_each_crtc(crtc, drm) {
238+
if (!drm_encoder_crtc_ok(encoder, crtc))
239+
continue;
240+
241+
return crtc;
242+
}
243+
244+
return NULL;
245+
}
246+
247+
static void vc4_drv_set_encoder_data(struct drm_device *drm)
248+
{
249+
struct drm_encoder *encoder;
250+
251+
drm_for_each_encoder(encoder, drm) {
252+
struct vc4_encoder *vc4_encoder;
253+
struct drm_crtc *crtc;
254+
255+
crtc = vc4_drv_find_crtc(drm, encoder);
256+
if (WARN_ON(!crtc))
257+
return;
258+
259+
vc4_encoder = to_vc4_encoder(encoder);
260+
vc4_encoder->crtc = crtc;
261+
}
262+
}
263+
229264
static void vc4_match_add_drivers(struct device *dev,
230265
struct component_match **match,
231266
struct platform_driver *const *drivers,
@@ -308,6 +343,7 @@ static int vc4_drm_bind(struct device *dev)
308343
ret = component_bind_all(dev, drm);
309344
if (ret)
310345
return ret;
346+
vc4_drv_set_encoder_data(drm);
311347

312348
if (!vc4->firmware_kms) {
313349
ret = vc4_plane_create_additional_planes(drm);

drivers/gpu/drm/vc4/vc4_drv.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -445,6 +445,16 @@ enum vc4_encoder_type {
445445

446446
struct vc4_encoder {
447447
struct drm_encoder base;
448+
449+
/*
450+
* At boot time, we need to be able to retrieve the CRTC for a given
451+
* connector in order to run the disable hooks below to avoid the stuck
452+
* pixel issue. Unfortunately the drm_connector->encoder pointer is
453+
* NULL at that time so we can't move up the chain, so we'll store it
454+
* ourselves here.
455+
*/
456+
struct drm_crtc *crtc;
457+
448458
enum vc4_encoder_type type;
449459
u32 clock_select;
450460

0 commit comments

Comments
 (0)