Commit 5a184d95 authored by Maxime Ripard's avatar Maxime Ripard

drm/vc4: crtc: Fix vc4_get_crtc_encoder logic

The vc4_get_crtc_encoder function currently only works when the
connector->state->crtc pointer is set, which is only true when the
connector is currently enabled.

However, we use it as part of the disable path as well, and our lookup
will fail in that case, resulting in it returning a null pointer we
can't act on.

We can access the connector that used to be connected to that crtc
though using the old connector state in the disable path.

Since we want to support both the enable and disable path, we can
support it by passing the state accessor variant as a function pointer,
together with the atomic state.

Fixes: 792c3132 ("drm/vc4: encoder: Add finer-grained encoder callbacks")
Signed-off-by: default avatarMaxime Ripard <maxime@cerno.tech>
Reviewed-by: default avatarDave Stevenson <dave.stevenson@raspberrypi.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20210507150515.257424-5-maxime@cerno.tech
parent c6883985
...@@ -279,14 +279,22 @@ static u32 vc4_crtc_get_fifo_full_level_bits(struct vc4_crtc *vc4_crtc, ...@@ -279,14 +279,22 @@ static u32 vc4_crtc_get_fifo_full_level_bits(struct vc4_crtc *vc4_crtc,
* allows drivers to push pixels to more than one encoder from the * allows drivers to push pixels to more than one encoder from the
* same CRTC. * same CRTC.
*/ */
static struct drm_encoder *vc4_get_crtc_encoder(struct drm_crtc *crtc) static struct drm_encoder *vc4_get_crtc_encoder(struct drm_crtc *crtc,
struct drm_atomic_state *state,
struct drm_connector_state *(*get_state)(struct drm_atomic_state *state,
struct drm_connector *connector))
{ {
struct drm_connector *connector; struct drm_connector *connector;
struct drm_connector_list_iter conn_iter; struct drm_connector_list_iter conn_iter;
drm_connector_list_iter_begin(crtc->dev, &conn_iter); drm_connector_list_iter_begin(crtc->dev, &conn_iter);
drm_for_each_connector_iter(connector, &conn_iter) { drm_for_each_connector_iter(connector, &conn_iter) {
if (connector->state->crtc == crtc) { struct drm_connector_state *conn_state = get_state(state, connector);
if (!conn_state)
continue;
if (conn_state->crtc == crtc) {
drm_connector_list_iter_end(&conn_iter); drm_connector_list_iter_end(&conn_iter);
return connector->encoder; return connector->encoder;
} }
...@@ -309,7 +317,8 @@ static void vc4_crtc_config_pv(struct drm_crtc *crtc, struct drm_atomic_state *s ...@@ -309,7 +317,8 @@ static void vc4_crtc_config_pv(struct drm_crtc *crtc, struct drm_atomic_state *s
{ {
struct drm_device *dev = crtc->dev; struct drm_device *dev = crtc->dev;
struct vc4_dev *vc4 = to_vc4_dev(dev); struct vc4_dev *vc4 = to_vc4_dev(dev);
struct drm_encoder *encoder = vc4_get_crtc_encoder(crtc); struct drm_encoder *encoder = vc4_get_crtc_encoder(crtc, state,
drm_atomic_get_new_connector_state);
struct vc4_encoder *vc4_encoder = to_vc4_encoder(encoder); struct vc4_encoder *vc4_encoder = to_vc4_encoder(encoder);
struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc); struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
const struct vc4_pv_data *pv_data = vc4_crtc_to_vc4_pv_data(vc4_crtc); const struct vc4_pv_data *pv_data = vc4_crtc_to_vc4_pv_data(vc4_crtc);
...@@ -424,7 +433,8 @@ static int vc4_crtc_disable(struct drm_crtc *crtc, ...@@ -424,7 +433,8 @@ static int vc4_crtc_disable(struct drm_crtc *crtc,
struct drm_atomic_state *state, struct drm_atomic_state *state,
unsigned int channel) unsigned int channel)
{ {
struct drm_encoder *encoder = vc4_get_crtc_encoder(crtc); struct drm_encoder *encoder = vc4_get_crtc_encoder(crtc, state,
drm_atomic_get_old_connector_state);
struct vc4_encoder *vc4_encoder = to_vc4_encoder(encoder); struct vc4_encoder *vc4_encoder = to_vc4_encoder(encoder);
struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc); struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
struct drm_device *dev = crtc->dev; struct drm_device *dev = crtc->dev;
...@@ -524,7 +534,8 @@ static void vc4_crtc_atomic_enable(struct drm_crtc *crtc, ...@@ -524,7 +534,8 @@ static void vc4_crtc_atomic_enable(struct drm_crtc *crtc,
{ {
struct drm_device *dev = crtc->dev; struct drm_device *dev = crtc->dev;
struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc); struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
struct drm_encoder *encoder = vc4_get_crtc_encoder(crtc); struct drm_encoder *encoder = vc4_get_crtc_encoder(crtc, state,
drm_atomic_get_new_connector_state);
struct vc4_encoder *vc4_encoder = to_vc4_encoder(encoder); struct vc4_encoder *vc4_encoder = to_vc4_encoder(encoder);
require_hvs_enabled(dev); require_hvs_enabled(dev);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment