Many (or even all?) K3 SoCs have DSS VP_CONTROL.DPIENABLE bit described in their documentation. This bit controls whether the DPI block is enabled, and is set to 1 by default (i.e. DPI is enabled at HW reset).
However, in almost all SoCs the setting does not actually do anything, and at the moment the bit is not managed by the driver. The exception is AM62L, which does have DPIENABLE connected, and disabling the DPI block when it is not in use provides power savings. Let's add a new feature flag for this, 'has_vp_control_dpienable', and implement the support. Disable DPIENABLE for all videoports at resume time, so that it is 0 by default. Specifically enable and disable it in dispc_vp_enable() and dispc_vp_disable() for DPI output. Tested-by: Swamil Jain <[email protected]> Signed-off-by: Tomi Valkeinen <[email protected]> --- drivers/gpu/drm/tidss/tidss_dispc.c | 23 +++++++++++++++++++++-- drivers/gpu/drm/tidss/tidss_dispc.h | 2 ++ drivers/gpu/drm/tidss/tidss_dispc_regs.h | 1 + 3 files changed, 24 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/tidss/tidss_dispc.c b/drivers/gpu/drm/tidss/tidss_dispc.c index 92cba069ed6c..82e0b3184cc4 100644 --- a/drivers/gpu/drm/tidss/tidss_dispc.c +++ b/drivers/gpu/drm/tidss/tidss_dispc.c @@ -442,6 +442,8 @@ const struct dispc_features dispc_am62l_feats = { }, .vid_order = {0}, + + .has_vp_control_dpienable = true, }; static const u16 *dispc_common_regmap; @@ -1214,6 +1216,11 @@ void dispc_vp_prepare(struct dispc_device *dispc, u32 hw_videoport, void dispc_vp_enable(struct dispc_device *dispc, u32 hw_videoport) { + if (dispc->feat->has_vp_control_dpienable && + dispc->vp_data[hw_videoport].dpi_output) + VP_REG_FLD_MOD(dispc, hw_videoport, DISPC_VP_CONTROL, 1, + DISPC_VP_CONTROL_DPIENABLE_MASK); + VP_REG_FLD_MOD(dispc, hw_videoport, DISPC_VP_CONTROL, 1, DISPC_VP_CONTROL_ENABLE_MASK); } @@ -1222,6 +1229,11 @@ void dispc_vp_disable(struct dispc_device *dispc, u32 hw_videoport) { VP_REG_FLD_MOD(dispc, hw_videoport, DISPC_VP_CONTROL, 0, DISPC_VP_CONTROL_ENABLE_MASK); + + if (dispc->feat->has_vp_control_dpienable && + dispc->vp_data[hw_videoport].dpi_output) + VP_REG_FLD_MOD(dispc, hw_videoport, DISPC_VP_CONTROL, 0, + DISPC_VP_CONTROL_DPIENABLE_MASK); } void dispc_vp_unprepare(struct dispc_device *dispc, u32 hw_videoport) @@ -2445,10 +2457,17 @@ static void dispc_vp_init(struct dispc_device *dispc) dev_dbg(dispc->dev, "%s()\n", __func__); - /* Enable the gamma Shadow bit-field for all VPs*/ - for (i = 0; i < dispc->feat->num_vps; i++) + for (i = 0; i < dispc->feat->num_vps; i++) { + /* Enable the gamma Shadow bit-field for all VPs*/ VP_REG_FLD_MOD(dispc, i, DISPC_VP_CONFIG, 1, DISPC_VP_CONFIG_GAMMAENABLE_MASK); + + if (dispc->feat->has_vp_control_dpienable) { + /* Disable DPIENABLE for all VPs */ + VP_REG_FLD_MOD(dispc, i, DISPC_VP_CONTROL, 0, + DISPC_VP_CONTROL_DPIENABLE_MASK); + } + } } static void dispc_initial_config(struct dispc_device *dispc) diff --git a/drivers/gpu/drm/tidss/tidss_dispc.h b/drivers/gpu/drm/tidss/tidss_dispc.h index 6f53d554259c..0fbfb86adfbf 100644 --- a/drivers/gpu/drm/tidss/tidss_dispc.h +++ b/drivers/gpu/drm/tidss/tidss_dispc.h @@ -92,6 +92,8 @@ struct dispc_features { u32 num_vids; struct dispc_vid_info vid_info[TIDSS_MAX_PLANES]; u32 vid_order[TIDSS_MAX_PLANES]; + /* The DSS has VP_CONTROL.DPIENABLE bit */ + bool has_vp_control_dpienable; }; extern const struct dispc_features dispc_k2g_feats; diff --git a/drivers/gpu/drm/tidss/tidss_dispc_regs.h b/drivers/gpu/drm/tidss/tidss_dispc_regs.h index 4cdde24d8372..4246c72efdd5 100644 --- a/drivers/gpu/drm/tidss/tidss_dispc_regs.h +++ b/drivers/gpu/drm/tidss/tidss_dispc_regs.h @@ -230,6 +230,7 @@ enum dispc_common_regs { #define DISPC_VP_CONTROL 0x4 #define DISPC_VP_CONTROL_DATALINES_MASK GENMASK(10, 8) +#define DISPC_VP_CONTROL_DPIENABLE_MASK GENMASK(6, 6) #define DISPC_VP_CONTROL_GOBIT_MASK GENMASK(5, 5) #define DISPC_VP_CONTROL_ENABLE_MASK GENMASK(0, 0) -- 2.43.0
