PV_CONTROL_FIFO_LEVEL);
}
+static struct drm_encoder *vc4_get_connector_encoder(struct drm_connector *connector)
+{
+ struct drm_encoder *encoder;
+
+ if (drm_WARN_ON(connector->dev, hweight32(connector->possible_encoders) != 1))
+ return NULL;
+
+ drm_connector_for_each_possible_encoder(connector, encoder)
+ return encoder;
+
+ return NULL;
+}
+
/*
* Returns the encoder attached to the CRTC.
*
drm_connector_list_iter_begin(crtc->dev, &conn_iter);
drm_for_each_connector_iter(connector, &conn_iter) {
- if (connector->state->crtc == crtc) {
+ struct drm_encoder *encoder;
+ struct vc4_encoder *vc4_encoder;
+
+ encoder = vc4_get_connector_encoder(connector);
+ if (!encoder)
+ continue;
+
+ vc4_encoder = to_vc4_encoder(encoder);
+ if (vc4_encoder->crtc == crtc) {
drm_connector_list_iter_end(&conn_iter);
- return connector->encoder;
+ return encoder;
}
}
drm_connector_list_iter_end(&conn_iter);
return dev == data;
}
+static struct drm_crtc *vc4_drv_find_crtc(struct drm_device *drm,
+ struct drm_encoder *encoder)
+{
+ struct drm_crtc *crtc;
+
+ if (WARN_ON(hweight32(encoder->possible_crtcs) != 1))
+ return NULL;
+
+ drm_for_each_crtc(crtc, drm) {
+ if (!drm_encoder_crtc_ok(encoder, crtc))
+ continue;
+
+ return crtc;
+ }
+
+ return NULL;
+}
+
+static void vc4_drv_set_encoder_data(struct drm_device *drm)
+{
+ struct drm_encoder *encoder;
+
+ drm_for_each_encoder(encoder, drm) {
+ struct vc4_encoder *vc4_encoder;
+ struct drm_crtc *crtc;
+
+ crtc = vc4_drv_find_crtc(drm, encoder);
+ if (WARN_ON(!crtc))
+ return;
+
+ vc4_encoder = to_vc4_encoder(encoder);
+ vc4_encoder->crtc = crtc;
+ }
+}
+
static void vc4_match_add_drivers(struct device *dev,
struct component_match **match,
struct platform_driver *const *drivers,
ret = component_bind_all(dev, drm);
if (ret)
return ret;
+ vc4_drv_set_encoder_data(drm);
if (!vc4->firmware_kms) {
ret = vc4_plane_create_additional_planes(drm);
struct vc4_encoder {
struct drm_encoder base;
+
+ /*
+ * At boot time, we need to be able to retrieve the CRTC for a given
+ * connector in order to run the disable hooks below to avoid the stuck
+ * pixel issue. Unfortunately the drm_connector->encoder pointer is
+ * NULL at that time so we can't move up the chain, so we'll store it
+ * ourselves here.
+ */
+ struct drm_crtc *crtc;
+
enum vc4_encoder_type type;
u32 clock_select;