drm/bridge: cdns-dsi: Move DSI mode check to _atomic_check()
At present, the DSI mode configuration check happens during the _atomic_enable() phase, which is not really the best place for this. Moreover, if the mode is not valid, the driver gives a warning and continues the hardware configuration. Move the DSI mode configuration check to _atomic_check() instead, which can properly report back any invalid mode, before the _enable phase even begins. Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org> Reviewed-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com> Tested-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com> Signed-off-by: Aradhya Bhatia <a-bhatia1@ti.com> Signed-off-by: Aradhya Bhatia <aradhya.bhatia@linux.dev> Link: https://lore.kernel.org/r/20250329113925.68204-10-aradhya.bhatia@linux.dev Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>pull/1112/head
parent
bc36ee983f
commit
a53d987756
|
|
@ -425,6 +425,17 @@
|
||||||
#define DSI_NULL_FRAME_OVERHEAD 6
|
#define DSI_NULL_FRAME_OVERHEAD 6
|
||||||
#define DSI_EOT_PKT_SIZE 4
|
#define DSI_EOT_PKT_SIZE 4
|
||||||
|
|
||||||
|
struct cdns_dsi_bridge_state {
|
||||||
|
struct drm_bridge_state base;
|
||||||
|
struct cdns_dsi_cfg dsi_cfg;
|
||||||
|
};
|
||||||
|
|
||||||
|
static inline struct cdns_dsi_bridge_state *
|
||||||
|
to_cdns_dsi_bridge_state(struct drm_bridge_state *bridge_state)
|
||||||
|
{
|
||||||
|
return container_of(bridge_state, struct cdns_dsi_bridge_state, base);
|
||||||
|
}
|
||||||
|
|
||||||
static inline struct cdns_dsi *input_to_dsi(struct cdns_dsi_input *input)
|
static inline struct cdns_dsi *input_to_dsi(struct cdns_dsi_input *input)
|
||||||
{
|
{
|
||||||
return container_of(input, struct cdns_dsi, input);
|
return container_of(input, struct cdns_dsi, input);
|
||||||
|
|
@ -771,6 +782,8 @@ static void cdns_dsi_bridge_atomic_enable(struct drm_bridge *bridge,
|
||||||
struct cdns_dsi_output *output = &dsi->output;
|
struct cdns_dsi_output *output = &dsi->output;
|
||||||
struct drm_connector_state *conn_state;
|
struct drm_connector_state *conn_state;
|
||||||
struct drm_crtc_state *crtc_state;
|
struct drm_crtc_state *crtc_state;
|
||||||
|
struct cdns_dsi_bridge_state *dsi_state;
|
||||||
|
struct drm_bridge_state *new_bridge_state;
|
||||||
struct drm_display_mode *mode;
|
struct drm_display_mode *mode;
|
||||||
struct phy_configure_opts_mipi_dphy *phy_cfg = &output->phy_opts.mipi_dphy;
|
struct phy_configure_opts_mipi_dphy *phy_cfg = &output->phy_opts.mipi_dphy;
|
||||||
struct drm_connector *connector;
|
struct drm_connector *connector;
|
||||||
|
|
@ -782,6 +795,13 @@ static void cdns_dsi_bridge_atomic_enable(struct drm_bridge *bridge,
|
||||||
if (WARN_ON(pm_runtime_get_sync(dsi->base.dev) < 0))
|
if (WARN_ON(pm_runtime_get_sync(dsi->base.dev) < 0))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
new_bridge_state = drm_atomic_get_new_bridge_state(state, bridge);
|
||||||
|
if (WARN_ON(!new_bridge_state))
|
||||||
|
return;
|
||||||
|
|
||||||
|
dsi_state = to_cdns_dsi_bridge_state(new_bridge_state);
|
||||||
|
dsi_cfg = dsi_state->dsi_cfg;
|
||||||
|
|
||||||
if (dsi->platform_ops && dsi->platform_ops->enable)
|
if (dsi->platform_ops && dsi->platform_ops->enable)
|
||||||
dsi->platform_ops->enable(dsi);
|
dsi->platform_ops->enable(dsi);
|
||||||
|
|
||||||
|
|
@ -791,8 +811,6 @@ static void cdns_dsi_bridge_atomic_enable(struct drm_bridge *bridge,
|
||||||
mode = &crtc_state->adjusted_mode;
|
mode = &crtc_state->adjusted_mode;
|
||||||
nlanes = output->dev->lanes;
|
nlanes = output->dev->lanes;
|
||||||
|
|
||||||
WARN_ON_ONCE(cdns_dsi_check_conf(dsi, mode, &dsi_cfg, false));
|
|
||||||
|
|
||||||
cdns_dsi_hs_init(dsi);
|
cdns_dsi_hs_init(dsi);
|
||||||
cdns_dsi_init_link(dsi);
|
cdns_dsi_init_link(dsi);
|
||||||
|
|
||||||
|
|
@ -963,6 +981,70 @@ static u32 *cdns_dsi_bridge_get_input_bus_fmts(struct drm_bridge *bridge,
|
||||||
return input_fmts;
|
return input_fmts;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int cdns_dsi_bridge_atomic_check(struct drm_bridge *bridge,
|
||||||
|
struct drm_bridge_state *bridge_state,
|
||||||
|
struct drm_crtc_state *crtc_state,
|
||||||
|
struct drm_connector_state *conn_state)
|
||||||
|
{
|
||||||
|
struct cdns_dsi_input *input = bridge_to_cdns_dsi_input(bridge);
|
||||||
|
struct cdns_dsi *dsi = input_to_dsi(input);
|
||||||
|
struct cdns_dsi_bridge_state *dsi_state = to_cdns_dsi_bridge_state(bridge_state);
|
||||||
|
const struct drm_display_mode *mode = &crtc_state->mode;
|
||||||
|
struct cdns_dsi_cfg *dsi_cfg = &dsi_state->dsi_cfg;
|
||||||
|
|
||||||
|
return cdns_dsi_check_conf(dsi, mode, dsi_cfg, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct drm_bridge_state *
|
||||||
|
cdns_dsi_bridge_atomic_duplicate_state(struct drm_bridge *bridge)
|
||||||
|
{
|
||||||
|
struct cdns_dsi_bridge_state *dsi_state, *old_dsi_state;
|
||||||
|
struct drm_bridge_state *bridge_state;
|
||||||
|
|
||||||
|
if (WARN_ON(!bridge->base.state))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
bridge_state = drm_priv_to_bridge_state(bridge->base.state);
|
||||||
|
old_dsi_state = to_cdns_dsi_bridge_state(bridge_state);
|
||||||
|
|
||||||
|
dsi_state = kzalloc(sizeof(*dsi_state), GFP_KERNEL);
|
||||||
|
if (!dsi_state)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
__drm_atomic_helper_bridge_duplicate_state(bridge, &dsi_state->base);
|
||||||
|
|
||||||
|
memcpy(&dsi_state->dsi_cfg, &old_dsi_state->dsi_cfg,
|
||||||
|
sizeof(dsi_state->dsi_cfg));
|
||||||
|
|
||||||
|
return &dsi_state->base;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
cdns_dsi_bridge_atomic_destroy_state(struct drm_bridge *bridge,
|
||||||
|
struct drm_bridge_state *state)
|
||||||
|
{
|
||||||
|
struct cdns_dsi_bridge_state *dsi_state;
|
||||||
|
|
||||||
|
dsi_state = to_cdns_dsi_bridge_state(state);
|
||||||
|
|
||||||
|
kfree(dsi_state);
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct drm_bridge_state *
|
||||||
|
cdns_dsi_bridge_atomic_reset(struct drm_bridge *bridge)
|
||||||
|
{
|
||||||
|
struct cdns_dsi_bridge_state *dsi_state;
|
||||||
|
|
||||||
|
dsi_state = kzalloc(sizeof(*dsi_state), GFP_KERNEL);
|
||||||
|
if (!dsi_state)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
memset(dsi_state, 0, sizeof(*dsi_state));
|
||||||
|
dsi_state->base.bridge = bridge;
|
||||||
|
|
||||||
|
return &dsi_state->base;
|
||||||
|
}
|
||||||
|
|
||||||
static const struct drm_bridge_funcs cdns_dsi_bridge_funcs = {
|
static const struct drm_bridge_funcs cdns_dsi_bridge_funcs = {
|
||||||
.attach = cdns_dsi_bridge_attach,
|
.attach = cdns_dsi_bridge_attach,
|
||||||
.mode_valid = cdns_dsi_bridge_mode_valid,
|
.mode_valid = cdns_dsi_bridge_mode_valid,
|
||||||
|
|
@ -970,9 +1052,10 @@ static const struct drm_bridge_funcs cdns_dsi_bridge_funcs = {
|
||||||
.atomic_pre_enable = cdns_dsi_bridge_atomic_pre_enable,
|
.atomic_pre_enable = cdns_dsi_bridge_atomic_pre_enable,
|
||||||
.atomic_enable = cdns_dsi_bridge_atomic_enable,
|
.atomic_enable = cdns_dsi_bridge_atomic_enable,
|
||||||
.atomic_post_disable = cdns_dsi_bridge_atomic_post_disable,
|
.atomic_post_disable = cdns_dsi_bridge_atomic_post_disable,
|
||||||
.atomic_reset = drm_atomic_helper_bridge_reset,
|
.atomic_check = cdns_dsi_bridge_atomic_check,
|
||||||
.atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state,
|
.atomic_reset = cdns_dsi_bridge_atomic_reset,
|
||||||
.atomic_destroy_state = drm_atomic_helper_bridge_destroy_state,
|
.atomic_duplicate_state = cdns_dsi_bridge_atomic_duplicate_state,
|
||||||
|
.atomic_destroy_state = cdns_dsi_bridge_atomic_destroy_state,
|
||||||
.atomic_get_input_bus_fmts = cdns_dsi_bridge_get_input_bus_fmts,
|
.atomic_get_input_bus_fmts = cdns_dsi_bridge_get_input_bus_fmts,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue