From f9bb7acb9b19a40dbd9d1b89380335dc8e23925f Mon Sep 17 00:00:00 2001 From: Philipp Zabel Date: Fri, 24 Feb 2017 18:23:55 +0100 Subject: [PATCH] gpu: ipu-v3: add unsynchronised DP channel disabling When disabling the foreground DP channel during a modeset, the DC is already disabled without waiting for end of frame. There is no reason to wait for a frame boundary before updating the DP registers in that case. Add support to apply updates immediately. No functional changes, yet. Signed-off-by: Philipp Zabel Reviewed-by: Lucas Stach --- drivers/gpu/drm/imx/ipuv3-plane.c | 2 +- drivers/gpu/ipu-v3/ipu-common.c | 8 +++++--- drivers/gpu/ipu-v3/ipu-dp.c | 12 ++++++------ drivers/gpu/ipu-v3/ipu-prv.h | 7 ++++++- include/video/imx-ipu-v3.h | 2 +- 5 files changed, 19 insertions(+), 12 deletions(-) diff --git a/drivers/gpu/drm/imx/ipuv3-plane.c b/drivers/gpu/drm/imx/ipuv3-plane.c index 24819c9..55991d4 100644 --- a/drivers/gpu/drm/imx/ipuv3-plane.c +++ b/drivers/gpu/drm/imx/ipuv3-plane.c @@ -181,7 +181,7 @@ static int ipu_disable_plane(struct drm_plane *plane) ipu_idmac_wait_busy(ipu_plane->ipu_ch, 50); if (ipu_plane->dp) - ipu_dp_disable_channel(ipu_plane->dp); + ipu_dp_disable_channel(ipu_plane->dp, true); ipu_idmac_disable_channel(ipu_plane->ipu_ch); ipu_dmfc_disable_channel(ipu_plane->dmfc); if (ipu_plane->dp) diff --git a/drivers/gpu/ipu-v3/ipu-common.c b/drivers/gpu/ipu-v3/ipu-common.c index 8368e6f..8a32ed2 100644 --- a/drivers/gpu/ipu-v3/ipu-common.c +++ b/drivers/gpu/ipu-v3/ipu-common.c @@ -51,15 +51,17 @@ int ipu_get_num(struct ipu_soc *ipu) } EXPORT_SYMBOL_GPL(ipu_get_num); -void ipu_srm_dp_sync_update(struct ipu_soc *ipu) +void ipu_srm_dp_update(struct ipu_soc *ipu, bool sync) { u32 val; val = ipu_cm_read(ipu, IPU_SRM_PRI2); - val |= 0x8; + val &= ~DP_S_SRM_MODE_MASK; + val |= sync ? DP_S_SRM_MODE_NEXT_FRAME : + DP_S_SRM_MODE_NOW; ipu_cm_write(ipu, val, IPU_SRM_PRI2); } -EXPORT_SYMBOL_GPL(ipu_srm_dp_sync_update); +EXPORT_SYMBOL_GPL(ipu_srm_dp_update); enum ipu_color_space ipu_drm_fourcc_to_colorspace(u32 drm_fourcc) { diff --git a/drivers/gpu/ipu-v3/ipu-dp.c b/drivers/gpu/ipu-v3/ipu-dp.c index 98686ed..0e09c98 100644 --- a/drivers/gpu/ipu-v3/ipu-dp.c +++ b/drivers/gpu/ipu-v3/ipu-dp.c @@ -112,7 +112,7 @@ int ipu_dp_set_global_alpha(struct ipu_dp *dp, bool enable, writel(reg & ~DP_COM_CONF_GWAM, flow->base + DP_COM_CONF); } - ipu_srm_dp_sync_update(priv->ipu); + ipu_srm_dp_update(priv->ipu, true); mutex_unlock(&priv->mutex); @@ -127,7 +127,7 @@ int ipu_dp_set_window_pos(struct ipu_dp *dp, u16 x_pos, u16 y_pos) writel((x_pos << 16) | y_pos, flow->base + DP_FG_POS); - ipu_srm_dp_sync_update(priv->ipu); + ipu_srm_dp_update(priv->ipu, true); return 0; } @@ -207,7 +207,7 @@ int ipu_dp_setup_channel(struct ipu_dp *dp, flow->out_cs, DP_COM_CONF_CSC_DEF_FG); } - ipu_srm_dp_sync_update(priv->ipu); + ipu_srm_dp_update(priv->ipu, true); mutex_unlock(&priv->mutex); @@ -247,7 +247,7 @@ int ipu_dp_enable_channel(struct ipu_dp *dp) reg |= DP_COM_CONF_FG_EN; writel(reg, flow->base + DP_COM_CONF); - ipu_srm_dp_sync_update(priv->ipu); + ipu_srm_dp_update(priv->ipu, true); mutex_unlock(&priv->mutex); @@ -255,7 +255,7 @@ int ipu_dp_enable_channel(struct ipu_dp *dp) } EXPORT_SYMBOL_GPL(ipu_dp_enable_channel); -void ipu_dp_disable_channel(struct ipu_dp *dp) +void ipu_dp_disable_channel(struct ipu_dp *dp, bool sync) { struct ipu_flow *flow = to_flow(dp); struct ipu_dp_priv *priv = flow->priv; @@ -275,7 +275,7 @@ void ipu_dp_disable_channel(struct ipu_dp *dp) writel(reg, flow->base + DP_COM_CONF); writel(0, flow->base + DP_FG_POS); - ipu_srm_dp_sync_update(priv->ipu); + ipu_srm_dp_update(priv->ipu, sync); if (ipu_idmac_channel_busy(priv->ipu, IPUV3_CHANNEL_MEM_BG_SYNC)) ipu_wait_interrupt(priv->ipu, IPU_IRQ_DP_SF_END, 50); diff --git a/drivers/gpu/ipu-v3/ipu-prv.h b/drivers/gpu/ipu-v3/ipu-prv.h index 22e47b6..2855957 100644 --- a/drivers/gpu/ipu-v3/ipu-prv.h +++ b/drivers/gpu/ipu-v3/ipu-prv.h @@ -75,6 +75,11 @@ struct ipu_soc; #define IPU_INT_CTRL(n) IPU_CM_REG(0x003C + 4 * (n)) #define IPU_INT_STAT(n) IPU_CM_REG(0x0200 + 4 * (n)) +/* SRM_PRI2 */ +#define DP_S_SRM_MODE_MASK (0x3 << 3) +#define DP_S_SRM_MODE_NOW (0x3 << 3) +#define DP_S_SRM_MODE_NEXT_FRAME (0x1 << 3) + /* FS_PROC_FLOW1 */ #define FS_PRPENC_ROT_SRC_SEL_MASK (0xf << 0) #define FS_PRPENC_ROT_SRC_SEL_ENC (0x7 << 0) @@ -215,7 +220,7 @@ static inline void ipu_idmac_write(struct ipu_soc *ipu, u32 value, writel(value, ipu->idmac_reg + offset); } -void ipu_srm_dp_sync_update(struct ipu_soc *ipu); +void ipu_srm_dp_update(struct ipu_soc *ipu, bool sync); int ipu_module_enable(struct ipu_soc *ipu, u32 mask); int ipu_module_disable(struct ipu_soc *ipu, u32 mask); diff --git a/include/video/imx-ipu-v3.h b/include/video/imx-ipu-v3.h index 53cd07c..899d2b0 100644 --- a/include/video/imx-ipu-v3.h +++ b/include/video/imx-ipu-v3.h @@ -300,7 +300,7 @@ struct ipu_dp *ipu_dp_get(struct ipu_soc *ipu, unsigned int flow); void ipu_dp_put(struct ipu_dp *); int ipu_dp_enable(struct ipu_soc *ipu); int ipu_dp_enable_channel(struct ipu_dp *dp); -void ipu_dp_disable_channel(struct ipu_dp *dp); +void ipu_dp_disable_channel(struct ipu_dp *dp, bool sync); void ipu_dp_disable(struct ipu_soc *ipu); int ipu_dp_setup_channel(struct ipu_dp *dp, enum ipu_color_space in, enum ipu_color_space out); -- 2.7.4