MLK-18848-1: drm: imx: dcss: do not turn off DTG LINE0/1 interrupts
authorLaurentiu Palcu <laurentiu.palcu@nxp.com>
Fri, 31 Aug 2018 14:00:01 +0000 (17:00 +0300)
committerLeonard Crestez <leonard.crestez@nxp.com>
Wed, 17 Apr 2019 23:51:34 +0000 (02:51 +0300)
DTG registers are double bufferred. Hence, enabling LINE0/1 interrupts
in DTG in frame 0 will actually activate them in frame 1. Hence, the
LINE0/1 interrupts (vblank and ctxld kick) will be missed in frame 0.

This patch will permanently activate the LINE0/1 interrupts in DTG and
only mask/unmask them at irq_steer controller level (disable_irq/enable_irq).

While at it, do the same change for DPR completion interrupts. Since, these are
only used for tracing purposes, the change is not supposed to affect
driver functionality in any way.

Signed-off-by: Laurentiu Palcu <laurentiu.palcu@nxp.com>
drivers/gpu/imx/dcss/dcss-dpr.c
drivers/gpu/imx/dcss/dcss-dtg.c

index c0da802..bfff87b 100644 (file)
@@ -220,6 +220,10 @@ static int dcss_dpr_irq_config(struct dcss_soc *dcss, int ch_num)
                return ret;
        }
 
+       disable_irq(ch->irq);
+
+       dcss_writel(0xfe, ch->base_reg + DCSS_DPR_IRQ_MASK);
+
        return 0;
 }
 
@@ -731,9 +735,21 @@ void dcss_dpr_irq_enable(struct dcss_soc *dcss, bool en)
 {
        struct dcss_dpr_priv *dpr = dcss->dpr_priv;
 
-       dcss_writel(en ? 0xfe : 0xff, dpr->ch[0].base_reg + DCSS_DPR_IRQ_MASK);
-       dcss_writel(en ? 0xfe : 0xff, dpr->ch[1].base_reg + DCSS_DPR_IRQ_MASK);
-       dcss_writel(en ? 0xfe : 0xff, dpr->ch[2].base_reg + DCSS_DPR_IRQ_MASK);
+       if (!en) {
+               disable_irq(dpr->ch[0].irq);
+               disable_irq(dpr->ch[1].irq);
+               disable_irq(dpr->ch[2].irq);
+
+               return;
+       }
+
+       dcss_clr(1, dpr->ch[0].base_reg + DCSS_DPR_IRQ_NONMASK_STATUS);
+       dcss_clr(1, dpr->ch[1].base_reg + DCSS_DPR_IRQ_NONMASK_STATUS);
+       dcss_clr(1, dpr->ch[2].base_reg + DCSS_DPR_IRQ_NONMASK_STATUS);
+
+       enable_irq(dpr->ch[0].irq);
+       enable_irq(dpr->ch[1].irq);
+       enable_irq(dpr->ch[2].irq);
 }
 
 void dcss_dpr_set_rotation(struct dcss_soc *dcss, int ch_num, u32 rotation)
index 1bd686d..c1b64d8 100644 (file)
@@ -140,6 +140,7 @@ struct dcss_dtg_priv {
        u32 use_global;
 
        int ctxld_kick_irq;
+       bool ctxld_kick_irq_en;
 
        /*
         * This will be passed on by DRM CRTC so that we can signal when DTG has
@@ -209,6 +210,12 @@ static int dcss_dtg_irq_config(struct dcss_dtg_priv *dtg)
                return ret;
        }
 
+       disable_irq(dtg->ctxld_kick_irq);
+
+       dtg->ctxld_kick_irq_en = false;
+
+       dcss_update(LINE1_IRQ, LINE1_IRQ, dtg->base_reg + DCSS_DTG_INT_MASK);
+
        return 0;
 }
 
@@ -470,20 +477,37 @@ EXPORT_SYMBOL(dcss_dtg_ch_enable);
 
 void dcss_dtg_vblank_irq_enable(struct dcss_soc *dcss, bool en)
 {
-       void __iomem *reg;
        struct dcss_dtg_priv *dtg = dcss->dtg_priv;
-       u32 val = en ? (LINE0_IRQ | LINE1_IRQ) : 0;
+       u32 status;
+
+       dcss_update(LINE0_IRQ, LINE0_IRQ, dtg->base_reg + DCSS_DTG_INT_MASK);
+
+       dcss_dpr_irq_enable(dcss, en);
 
        /* need to keep the CTXLD kick interrupt ON if DTRC is used */
        if (!en && (dcss_dtrc_is_running(dcss, 1) ||
                    dcss_dtrc_is_running(dcss, 2)))
-               val |= LINE1_IRQ;
+               return;
 
-       reg = dtg->base_reg + DCSS_DTG_INT_MASK;
+       if (en) {
+               status = dcss_readl(dtg->base_reg + DCSS_DTG_INT_STATUS);
 
-       dcss_update(val, LINE0_IRQ | LINE1_IRQ, reg);
+               if (!dtg->ctxld_kick_irq_en) {
+                       dcss_writel(status & (LINE0_IRQ | LINE1_IRQ),
+                                   dtg->base_reg + DCSS_DTG_INT_CONTROL);
+                       enable_irq(dtg->ctxld_kick_irq);
+                       dtg->ctxld_kick_irq_en = true;
+                       return;
+               }
 
-       dcss_dpr_irq_enable(dcss, en);
+               dcss_writel(status & LINE0_IRQ,
+                           dtg->base_reg + DCSS_DTG_INT_CONTROL);
+
+               return;
+       }
+
+       disable_irq(dtg->ctxld_kick_irq);
+       dtg->ctxld_kick_irq_en = false;
 }
 
 void dcss_dtg_vblank_irq_clear(struct dcss_soc *dcss)