Implement the hardware state readout for the sii902x bridge now that all the infrastructure is in place.
Reviewed-by: Maarten Lankhorst <[email protected]> Signed-off-by: Maxime Ripard <[email protected]> --- drivers/gpu/drm/bridge/sii902x.c | 91 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 90 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/bridge/sii902x.c b/drivers/gpu/drm/bridge/sii902x.c index e067c0636e7f..ab5ffcf6882f 100644 --- a/drivers/gpu/drm/bridge/sii902x.c +++ b/drivers/gpu/drm/bridge/sii902x.c @@ -23,4 +23,6 @@ #include <drm/drm_atomic_helper.h> +#include <drm/drm_atomic_state_readout.h> +#include <drm/drm_atomic_state_readout_helper.h> #include <drm/drm_bridge.h> #include <drm/drm_drv.h> @@ -538,4 +540,87 @@ sii902x_bridge_mode_valid(struct drm_bridge *bridge, } +static int +sii902x_bridge_connector_readout(struct drm_bridge *bridge, + struct drm_atomic_sro_state *state, + struct drm_connector_state *conn_state) +{ + struct sii902x *sii902x = bridge_to_sii902x(bridge); + struct drm_connector *connector = conn_state->connector; + struct drm_crtc_state *crtc_state; + struct drm_encoder *encoder; + struct drm_crtc *crtc; + int ret; + + ret = regmap_test_bits(sii902x->regmap, SII902X_SYS_CTRL_DATA, SII902X_SYS_CTRL_PWR_DWN); + /* I2C error */ + if (ret < 0) + return ret; + /* Device is powered down, nothing to read out */ + if (ret) + return 0; + + encoder = bridge->encoder; + if (!encoder->funcs || !encoder->funcs->atomic_sro_get_current_crtc) + return -ENODEV; + + crtc = encoder->funcs->atomic_sro_get_current_crtc(encoder); + if (!crtc) + return -ENODEV; + + crtc_state = drm_atomic_sro_get_crtc_state(state, crtc); + if (!crtc_state) + return -ENODEV; + + crtc_state->encoder_mask |= drm_encoder_mask(encoder); + crtc_state->connector_mask |= drm_connector_mask(connector); + + /* + * drm_atomic_set_crtc_for_connector() takes a connector reference + * when setting the crtc pointer, which is later released by + * __drm_atomic_helper_connector_destroy_state(). SRO readout + * bypasses that path, so take the reference explicitly. + */ + drm_connector_get(connector); + conn_state->crtc = crtc; + conn_state->best_encoder = encoder; + + return 0; +} + +static int sii902x_bridge_readout_state(struct drm_bridge *bridge, + struct drm_atomic_sro_state *state, + struct drm_bridge_state *bridge_state, + struct drm_crtc_state *crtc_state, + struct drm_connector_state *conn_state) +{ + struct sii902x *sii902x = bridge_to_sii902x(bridge); + u32 input_format; + + if (regmap_test_bits(sii902x->regmap, SII902X_SYS_CTRL_DATA, SII902X_SYS_CTRL_PWR_DWN)) + return 0; + + switch (sii902x->bus_width) { + case 16: + input_format = MEDIA_BUS_FMT_RGB565_1X16; + break; + case 18: + input_format = MEDIA_BUS_FMT_RGB666_1X18; + break; + case 24: + input_format = MEDIA_BUS_FMT_RGB888_1X24; + break; + default: + return -EINVAL; + } + + bridge_state->input_bus_cfg.format = input_format; + bridge_state->input_bus_cfg.flags = bridge->timings->input_bus_flags; + + /* The sii902x is a passthrough transmitter, output format equals input. */ + bridge_state->output_bus_cfg.format = input_format; + + return 0; +} + static const struct drm_bridge_funcs sii902x_bridge_funcs = { .attach = sii902x_bridge_attach, @@ -548,4 +633,7 @@ static const struct drm_bridge_funcs sii902x_bridge_funcs = { .atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state, .atomic_destroy_state = drm_atomic_helper_bridge_destroy_state, + .atomic_sro_compare_state = drm_atomic_helper_bridge_compare_state, + .atomic_sro_readout_state = sii902x_bridge_readout_state, + .atomic_sro_connector_readout = sii902x_bridge_connector_readout, .atomic_get_input_bus_fmts = sii902x_bridge_atomic_get_input_bus_fmts, .atomic_check = sii902x_bridge_atomic_check, @@ -1134,5 +1222,6 @@ static int sii902x_init(struct sii902x *sii902x) sii902x->bridge.of_node = dev->of_node; sii902x->bridge.timings = &default_sii902x_timings; - sii902x->bridge.ops = DRM_BRIDGE_OP_DETECT | DRM_BRIDGE_OP_EDID; + sii902x->bridge.ops = DRM_BRIDGE_OP_DETECT | DRM_BRIDGE_OP_EDID | + DRM_BRIDGE_OP_CONNECTOR_HW_READOUT; sii902x->bridge.type = DRM_MODE_CONNECTOR_HDMIA; -- 2.55.0
