Merge branch 'parisc-3.16-5' of git://git.kernel.org/pub/scm/linux/kernel/git/deller...
[firefly-linux-kernel-4.4.55.git] / drivers / gpu / ipu-v3 / ipu-dmfc.c
index e1493ab36ca277a6849b975a1c900998043ac2fd..042c3958e2a099224b25cafd194e076b7150f67c 100644 (file)
 #define DMFC_GENERAL1          0x0014
 #define DMFC_GENERAL2          0x0018
 #define DMFC_IC_CTRL           0x001c
-#define DMFC_STAT              0x0020
+#define DMFC_WR_CHAN_ALT       0x0020
+#define DMFC_WR_CHAN_DEF_ALT   0x0024
+#define DMFC_DP_CHAN_ALT       0x0028
+#define DMFC_DP_CHAN_DEF_ALT   0x002c
+#define DMFC_GENERAL1_ALT      0x0030
+#define DMFC_STAT              0x0034
 
 #define DMFC_WR_CHAN_1_28              0
 #define DMFC_WR_CHAN_2_41              8
@@ -133,6 +138,20 @@ int ipu_dmfc_enable_channel(struct dmfc_channel *dmfc)
 }
 EXPORT_SYMBOL_GPL(ipu_dmfc_enable_channel);
 
+static void ipu_dmfc_wait_fifos(struct ipu_dmfc_priv *priv)
+{
+       unsigned long timeout = jiffies + msecs_to_jiffies(1000);
+
+       while ((readl(priv->base + DMFC_STAT) & 0x02fff000) != 0x02fff000) {
+               if (time_after(jiffies, timeout)) {
+                       dev_warn(priv->dev,
+                                "Timeout waiting for DMFC FIFOs to clear\n");
+                       break;
+               }
+               cpu_relax();
+       }
+}
+
 void ipu_dmfc_disable_channel(struct dmfc_channel *dmfc)
 {
        struct ipu_dmfc_priv *priv = dmfc->priv;
@@ -141,8 +160,10 @@ void ipu_dmfc_disable_channel(struct dmfc_channel *dmfc)
 
        priv->use_count--;
 
-       if (!priv->use_count)
+       if (!priv->use_count) {
+               ipu_dmfc_wait_fifos(priv);
                ipu_module_disable(priv->ipu, IPU_CONF_DMFC_EN);
+       }
 
        if (priv->use_count < 0)
                priv->use_count = 0;