Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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 <p.zabel@pengutronix.de>
Reviewed-by: Lucas Stach <l.stach@pengutronix.de>

+19 -12
+1 -1
drivers/gpu/drm/imx/ipuv3-plane.c
··· 181 181 ipu_idmac_wait_busy(ipu_plane->ipu_ch, 50); 182 182 183 183 if (ipu_plane->dp) 184 - ipu_dp_disable_channel(ipu_plane->dp); 184 + ipu_dp_disable_channel(ipu_plane->dp, true); 185 185 ipu_idmac_disable_channel(ipu_plane->ipu_ch); 186 186 ipu_dmfc_disable_channel(ipu_plane->dmfc); 187 187 if (ipu_plane->dp)
+5 -3
drivers/gpu/ipu-v3/ipu-common.c
··· 51 51 } 52 52 EXPORT_SYMBOL_GPL(ipu_get_num); 53 53 54 - void ipu_srm_dp_sync_update(struct ipu_soc *ipu) 54 + void ipu_srm_dp_update(struct ipu_soc *ipu, bool sync) 55 55 { 56 56 u32 val; 57 57 58 58 val = ipu_cm_read(ipu, IPU_SRM_PRI2); 59 - val |= 0x8; 59 + val &= ~DP_S_SRM_MODE_MASK; 60 + val |= sync ? DP_S_SRM_MODE_NEXT_FRAME : 61 + DP_S_SRM_MODE_NOW; 60 62 ipu_cm_write(ipu, val, IPU_SRM_PRI2); 61 63 } 62 - EXPORT_SYMBOL_GPL(ipu_srm_dp_sync_update); 64 + EXPORT_SYMBOL_GPL(ipu_srm_dp_update); 63 65 64 66 enum ipu_color_space ipu_drm_fourcc_to_colorspace(u32 drm_fourcc) 65 67 {
+6 -6
drivers/gpu/ipu-v3/ipu-dp.c
··· 112 112 writel(reg & ~DP_COM_CONF_GWAM, flow->base + DP_COM_CONF); 113 113 } 114 114 115 - ipu_srm_dp_sync_update(priv->ipu); 115 + ipu_srm_dp_update(priv->ipu, true); 116 116 117 117 mutex_unlock(&priv->mutex); 118 118 ··· 127 127 128 128 writel((x_pos << 16) | y_pos, flow->base + DP_FG_POS); 129 129 130 - ipu_srm_dp_sync_update(priv->ipu); 130 + ipu_srm_dp_update(priv->ipu, true); 131 131 132 132 return 0; 133 133 } ··· 207 207 flow->out_cs, DP_COM_CONF_CSC_DEF_FG); 208 208 } 209 209 210 - ipu_srm_dp_sync_update(priv->ipu); 210 + ipu_srm_dp_update(priv->ipu, true); 211 211 212 212 mutex_unlock(&priv->mutex); 213 213 ··· 247 247 reg |= DP_COM_CONF_FG_EN; 248 248 writel(reg, flow->base + DP_COM_CONF); 249 249 250 - ipu_srm_dp_sync_update(priv->ipu); 250 + ipu_srm_dp_update(priv->ipu, true); 251 251 252 252 mutex_unlock(&priv->mutex); 253 253 ··· 255 255 } 256 256 EXPORT_SYMBOL_GPL(ipu_dp_enable_channel); 257 257 258 - void ipu_dp_disable_channel(struct ipu_dp *dp) 258 + void ipu_dp_disable_channel(struct ipu_dp *dp, bool sync) 259 259 { 260 260 struct ipu_flow *flow = to_flow(dp); 261 261 struct ipu_dp_priv *priv = flow->priv; ··· 275 275 writel(reg, flow->base + DP_COM_CONF); 276 276 277 277 writel(0, flow->base + DP_FG_POS); 278 - ipu_srm_dp_sync_update(priv->ipu); 278 + ipu_srm_dp_update(priv->ipu, sync); 279 279 280 280 if (ipu_idmac_channel_busy(priv->ipu, IPUV3_CHANNEL_MEM_BG_SYNC)) 281 281 ipu_wait_interrupt(priv->ipu, IPU_IRQ_DP_SF_END, 50);
+6 -1
drivers/gpu/ipu-v3/ipu-prv.h
··· 75 75 #define IPU_INT_CTRL(n) IPU_CM_REG(0x003C + 4 * (n)) 76 76 #define IPU_INT_STAT(n) IPU_CM_REG(0x0200 + 4 * (n)) 77 77 78 + /* SRM_PRI2 */ 79 + #define DP_S_SRM_MODE_MASK (0x3 << 3) 80 + #define DP_S_SRM_MODE_NOW (0x3 << 3) 81 + #define DP_S_SRM_MODE_NEXT_FRAME (0x1 << 3) 82 + 78 83 /* FS_PROC_FLOW1 */ 79 84 #define FS_PRPENC_ROT_SRC_SEL_MASK (0xf << 0) 80 85 #define FS_PRPENC_ROT_SRC_SEL_ENC (0x7 << 0) ··· 220 215 writel(value, ipu->idmac_reg + offset); 221 216 } 222 217 223 - void ipu_srm_dp_sync_update(struct ipu_soc *ipu); 218 + void ipu_srm_dp_update(struct ipu_soc *ipu, bool sync); 224 219 225 220 int ipu_module_enable(struct ipu_soc *ipu, u32 mask); 226 221 int ipu_module_disable(struct ipu_soc *ipu, u32 mask);
+1 -1
include/video/imx-ipu-v3.h
··· 300 300 void ipu_dp_put(struct ipu_dp *); 301 301 int ipu_dp_enable(struct ipu_soc *ipu); 302 302 int ipu_dp_enable_channel(struct ipu_dp *dp); 303 - void ipu_dp_disable_channel(struct ipu_dp *dp); 303 + void ipu_dp_disable_channel(struct ipu_dp *dp, bool sync); 304 304 void ipu_dp_disable(struct ipu_soc *ipu); 305 305 int ipu_dp_setup_channel(struct ipu_dp *dp, 306 306 enum ipu_color_space in, enum ipu_color_space out);