imx-drm: ipu-dp: split disabling the DP foreground channel from disabling the DP...
authorPhilipp Zabel <p.zabel@pengutronix.de>
Mon, 14 Apr 2014 21:53:20 +0000 (23:53 +0200)
committerRussell King <rmk+kernel@arm.linux.org.uk>
Sat, 26 Apr 2014 10:24:17 +0000 (11:24 +0100)
The former has to be done before disabling the DMFC, the latter has to be
done afterwards. Otherwise the DMFC FIFOs never get cleared properly.

Signed-off-by: Philipp Zabel <p.zabel@pengutronix.de>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
drivers/staging/imx-drm/ipu-v3/imx-ipu-v3.h
drivers/staging/imx-drm/ipu-v3/ipu-dp.c
drivers/staging/imx-drm/ipuv3-plane.c

index 2966e425990e436471d763035817121f5bb35585..8678ad18a3eff2d44a7ce0b6af989a72046bfefd 100644 (file)
@@ -153,8 +153,10 @@ void ipu_dmfc_put(struct dmfc_channel *dmfc);
 
 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(struct ipu_soc *ipu);
 int ipu_dp_setup_channel(struct ipu_dp *dp,
                enum ipu_color_space in, enum ipu_color_space out);
 int ipu_dp_set_window_pos(struct ipu_dp *, u16 x_pos, u16 y_pos);
index 58f87c8d7c07ad611a09d0c0bae62df482adb121..6980fa125517a89329a4e416ecd28dc04a2634da 100644 (file)
@@ -215,10 +215,9 @@ int ipu_dp_setup_channel(struct ipu_dp *dp,
 }
 EXPORT_SYMBOL_GPL(ipu_dp_setup_channel);
 
-int ipu_dp_enable_channel(struct ipu_dp *dp)
+int ipu_dp_enable(struct ipu_soc *ipu)
 {
-       struct ipu_flow *flow = to_flow(dp);
-       struct ipu_dp_priv *priv = flow->priv;
+       struct ipu_dp_priv *priv = ipu->dp_priv;
 
        mutex_lock(&priv->mutex);
 
@@ -227,15 +226,28 @@ int ipu_dp_enable_channel(struct ipu_dp *dp)
 
        priv->use_count++;
 
-       if (dp->foreground) {
-               u32 reg;
+       mutex_unlock(&priv->mutex);
 
-               reg = readl(flow->base + DP_COM_CONF);
-               reg |= DP_COM_CONF_FG_EN;
-               writel(reg, flow->base + DP_COM_CONF);
+       return 0;
+}
+EXPORT_SYMBOL_GPL(ipu_dp_enable);
 
-               ipu_srm_dp_sync_update(priv->ipu);
-       }
+int ipu_dp_enable_channel(struct ipu_dp *dp)
+{
+       struct ipu_flow *flow = to_flow(dp);
+       struct ipu_dp_priv *priv = flow->priv;
+       u32 reg;
+
+       if (!dp->foreground)
+               return 0;
+
+       mutex_lock(&priv->mutex);
+
+       reg = readl(flow->base + DP_COM_CONF);
+       reg |= DP_COM_CONF_FG_EN;
+       writel(reg, flow->base + DP_COM_CONF);
+
+       ipu_srm_dp_sync_update(priv->ipu);
 
        mutex_unlock(&priv->mutex);
 
@@ -247,25 +259,35 @@ void ipu_dp_disable_channel(struct ipu_dp *dp)
 {
        struct ipu_flow *flow = to_flow(dp);
        struct ipu_dp_priv *priv = flow->priv;
+       u32 reg, csc;
+
+       if (!dp->foreground)
+               return;
 
        mutex_lock(&priv->mutex);
 
-       priv->use_count--;
+       reg = readl(flow->base + DP_COM_CONF);
+       csc = reg & DP_COM_CONF_CSC_DEF_MASK;
+       if (csc == DP_COM_CONF_CSC_DEF_FG)
+               reg &= ~DP_COM_CONF_CSC_DEF_MASK;
 
-       if (dp->foreground) {
-               u32 reg, csc;
+       reg &= ~DP_COM_CONF_FG_EN;
+       writel(reg, flow->base + DP_COM_CONF);
 
-               reg = readl(flow->base + DP_COM_CONF);
-               csc = reg & DP_COM_CONF_CSC_DEF_MASK;
-               if (csc == DP_COM_CONF_CSC_DEF_FG)
-                       reg &= ~DP_COM_CONF_CSC_DEF_MASK;
+       writel(0, flow->base + DP_FG_POS);
+       ipu_srm_dp_sync_update(priv->ipu);
 
-               reg &= ~DP_COM_CONF_FG_EN;
-               writel(reg, flow->base + DP_COM_CONF);
+       mutex_unlock(&priv->mutex);
+}
+EXPORT_SYMBOL_GPL(ipu_dp_disable_channel);
 
-               writel(0, flow->base + DP_FG_POS);
-               ipu_srm_dp_sync_update(priv->ipu);
-       }
+void ipu_dp_disable(struct ipu_soc *ipu)
+{
+       struct ipu_dp_priv *priv = ipu->dp_priv;
+
+       mutex_lock(&priv->mutex);
+
+       priv->use_count--;
 
        if (!priv->use_count)
                ipu_module_disable(priv->ipu, IPU_CONF_DP_EN);
@@ -275,7 +297,7 @@ void ipu_dp_disable_channel(struct ipu_dp *dp)
 
        mutex_unlock(&priv->mutex);
 }
-EXPORT_SYMBOL_GPL(ipu_dp_disable_channel);
+EXPORT_SYMBOL_GPL(ipu_dp_disable);
 
 struct ipu_dp *ipu_dp_get(struct ipu_soc *ipu, unsigned int flow)
 {
index 27a8d735dae0273e81c226e00b8eee5d482244f3..5697e59ddf1dc01b1da0aaf9f0f161b4bf71cfdc 100644 (file)
@@ -239,6 +239,8 @@ err_out:
 
 void ipu_plane_enable(struct ipu_plane *ipu_plane)
 {
+       if (ipu_plane->dp)
+               ipu_dp_enable(ipu_plane->ipu);
        ipu_dmfc_enable_channel(ipu_plane->dmfc);
        ipu_idmac_enable_channel(ipu_plane->ipu_ch);
        if (ipu_plane->dp)
@@ -257,6 +259,8 @@ void ipu_plane_disable(struct ipu_plane *ipu_plane)
                ipu_dp_disable_channel(ipu_plane->dp);
        ipu_idmac_disable_channel(ipu_plane->ipu_ch);
        ipu_dmfc_disable_channel(ipu_plane->dmfc);
+       if (ipu_plane->dp)
+               ipu_dp_disable(ipu_plane->ipu);
 }
 
 static void ipu_plane_dpms(struct ipu_plane *ipu_plane, int mode)