Implement the hardware state readout for the sii902x bridge now that all the infrastructure is in place.
Signed-off-by: Maxime Ripard <[email protected]> --- drivers/gpu/drm/bridge/sii902x.c | 72 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 71 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/bridge/sii902x.c b/drivers/gpu/drm/bridge/sii902x.c index 38d176d4eef2..90ed22b336ba 100644 --- a/drivers/gpu/drm/bridge/sii902x.c +++ b/drivers/gpu/drm/bridge/sii902x.c @@ -20,10 +20,12 @@ #include <linux/regmap.h> #include <linux/regulator/consumer.h> #include <linux/clk.h> #include <drm/drm_atomic_helper.h> +#include <drm/drm_atomic_sro.h> +#include <drm/drm_atomic_sro_helper.h> #include <drm/drm_bridge.h> #include <drm/drm_drv.h> #include <drm/drm_edid.h> #include <drm/drm_print.h> #include <drm/drm_probe_helper.h> @@ -535,17 +537,84 @@ sii902x_bridge_mode_valid(struct drm_bridge *bridge, return MODE_CLOCK_HIGH; return MODE_OK; } +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; + + if (regmap_test_bits(sii902x->regmap, SII902X_SYS_CTRL_DATA, SII902X_SYS_CTRL_PWR_DWN)) + return 0; + + encoder = bridge->encoder; + 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); + + 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; + + return 0; +} + static const struct drm_bridge_funcs sii902x_bridge_funcs = { .attach = sii902x_bridge_attach, .mode_set = sii902x_bridge_mode_set, .atomic_disable = sii902x_bridge_atomic_disable, .atomic_enable = sii902x_bridge_atomic_enable, .detect = sii902x_bridge_detect, .edid_read = sii902x_bridge_edid_read, + .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_reset = drm_atomic_helper_bridge_reset, .atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state, .atomic_destroy_state = drm_atomic_helper_bridge_destroy_state, .atomic_get_input_bus_fmts = sii902x_bridge_atomic_get_input_bus_fmts, .atomic_check = sii902x_bridge_atomic_check, @@ -1131,11 +1200,12 @@ static int sii902x_init(struct sii902x *sii902x) if (ret) goto err_unreg_audio; 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; if (sii902x->i2c->irq > 0) sii902x->bridge.ops |= DRM_BRIDGE_OP_HPD; -- 2.54.0
