Message ID | 0984a62c9f18d2f4d6e6ee7a874f729db7099439.1479832733.git.jsarha@ti.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
2016-11-22 17:54 GMT+01:00 Jyri Sarha <jsarha@ti.com>: > We should wait for the last frame to complete before shutting things > down also on LCDC rev 1. > > Signed-off-by: Jyri Sarha <jsarha@ti.com> > --- > drivers/gpu/drm/tilcdc/tilcdc_crtc.c | 34 +++++++++++++++++----------------- > drivers/gpu/drm/tilcdc/tilcdc_regs.h | 1 + > 2 files changed, 18 insertions(+), 17 deletions(-) > > diff --git a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c > index 1a1ff8d..f251546 100644 > --- a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c > +++ b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c > @@ -183,7 +183,7 @@ static void tilcdc_crtc_enable_irqs(struct drm_device *dev) > > if (priv->rev == 1) { > tilcdc_set(dev, LCDC_RASTER_CTRL_REG, > - LCDC_V1_SYNC_LOST_ENA | > + LCDC_V1_SYNC_LOST_ENA | LCDC_V1_FRAME_DONE_ENA | > LCDC_V1_UNDERFLOW_INT_ENA); > tilcdc_set(dev, LCDC_DMA_CTRL_REG, > LCDC_V1_END_OF_FRAME_INT_ENA); > @@ -201,7 +201,8 @@ static void tilcdc_crtc_disable_irqs(struct drm_device *dev) > > /* disable irqs that we might have enabled: */ > if (priv->rev == 1) { > - tilcdc_clear(dev, LCDC_RASTER_CTRL_REG, LCDC_V1_SYNC_LOST_ENA | > + tilcdc_clear(dev, LCDC_RASTER_CTRL_REG, > + LCDC_V1_SYNC_LOST_ENA | LCDC_V1_FRAME_DONE_ENA | > LCDC_V1_UNDERFLOW_INT_ENA | LCDC_V1_PL_INT_ENA); > tilcdc_clear(dev, LCDC_DMA_CTRL_REG, > LCDC_V1_END_OF_FRAME_INT_ENA); > @@ -261,6 +262,7 @@ static void tilcdc_crtc_off(struct drm_crtc *crtc, bool shutdown) > struct tilcdc_crtc *tilcdc_crtc = to_tilcdc_crtc(crtc); > struct drm_device *dev = crtc->dev; > struct tilcdc_drm_private *priv = dev->dev_private; > + int ret; > > mutex_lock(&tilcdc_crtc->enable_lock); > if (shutdown) > @@ -273,17 +275,15 @@ static void tilcdc_crtc_off(struct drm_crtc *crtc, bool shutdown) > tilcdc_clear(dev, LCDC_RASTER_CTRL_REG, LCDC_RASTER_ENABLE); > > /* > - * if necessary wait for framedone irq which will still come > - * before putting things to sleep.. > + * Wait for framedone irq which will still come before putting > + * things to sleep.. > */ > - if (priv->rev == 2) { > - int ret = wait_event_timeout(tilcdc_crtc->frame_done_wq, > - tilcdc_crtc->frame_done, > - msecs_to_jiffies(500)); > - if (ret == 0) > - dev_err(dev->dev, "%s: timeout waiting for framedone\n", > - __func__); > - } > + ret = wait_event_timeout(tilcdc_crtc->frame_done_wq, > + tilcdc_crtc->frame_done, > + msecs_to_jiffies(500)); > + if (ret == 0) > + dev_err(dev->dev, "%s: timeout waiting for framedone\n", > + __func__); > > drm_crtc_vblank_off(crtc); > > @@ -938,13 +938,13 @@ irqreturn_t tilcdc_crtc_irq(struct drm_crtc *crtc) > } > } > > + if (stat & LCDC_FRAME_DONE) { > + tilcdc_crtc->frame_done = true; > + wake_up(&tilcdc_crtc->frame_done_wq); > + } This seems to be a general quirk with interrupts on rev1, but if we don't disable the FRAME_DONE interrupt here, then - similarly to SYNC_LOST - we get stuck with an interrupt flood. > + > /* For revision 2 only */ > if (priv->rev == 2) { > - if (stat & LCDC_FRAME_DONE) { > - tilcdc_crtc->frame_done = true; > - wake_up(&tilcdc_crtc->frame_done_wq); > - } > - > /* Indicate to LCDC that the interrupt service routine has > * completed, see 13.3.6.1.6 in AM335x TRM. > */ > diff --git a/drivers/gpu/drm/tilcdc/tilcdc_regs.h b/drivers/gpu/drm/tilcdc/tilcdc_regs.h > index 56dbfbd..4e6975a 100644 > --- a/drivers/gpu/drm/tilcdc/tilcdc_regs.h > +++ b/drivers/gpu/drm/tilcdc/tilcdc_regs.h > @@ -67,6 +67,7 @@ > #define LCDC_V1_PL_INT_ENA BIT(4) > #define LCDC_V2_PL_INT_ENA BIT(6) > #define LCDC_V1_SYNC_LOST_ENA BIT(5) > +#define LCDC_V1_FRAME_DONE_ENA BIT(3) I'd call it LCDC_V1_FRAME_DONE_INT_ENA for consistency. Thanks, Bartosz Golaszewski > #define LCDC_MONOCHROME_MODE BIT(1) > #define LCDC_RASTER_ENABLE BIT(0) > #define LCDC_TFT_ALT_ENABLE BIT(23) > -- > 1.9.1 >
diff --git a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c index 1a1ff8d..f251546 100644 --- a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c +++ b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c @@ -183,7 +183,7 @@ static void tilcdc_crtc_enable_irqs(struct drm_device *dev) if (priv->rev == 1) { tilcdc_set(dev, LCDC_RASTER_CTRL_REG, - LCDC_V1_SYNC_LOST_ENA | + LCDC_V1_SYNC_LOST_ENA | LCDC_V1_FRAME_DONE_ENA | LCDC_V1_UNDERFLOW_INT_ENA); tilcdc_set(dev, LCDC_DMA_CTRL_REG, LCDC_V1_END_OF_FRAME_INT_ENA); @@ -201,7 +201,8 @@ static void tilcdc_crtc_disable_irqs(struct drm_device *dev) /* disable irqs that we might have enabled: */ if (priv->rev == 1) { - tilcdc_clear(dev, LCDC_RASTER_CTRL_REG, LCDC_V1_SYNC_LOST_ENA | + tilcdc_clear(dev, LCDC_RASTER_CTRL_REG, + LCDC_V1_SYNC_LOST_ENA | LCDC_V1_FRAME_DONE_ENA | LCDC_V1_UNDERFLOW_INT_ENA | LCDC_V1_PL_INT_ENA); tilcdc_clear(dev, LCDC_DMA_CTRL_REG, LCDC_V1_END_OF_FRAME_INT_ENA); @@ -261,6 +262,7 @@ static void tilcdc_crtc_off(struct drm_crtc *crtc, bool shutdown) struct tilcdc_crtc *tilcdc_crtc = to_tilcdc_crtc(crtc); struct drm_device *dev = crtc->dev; struct tilcdc_drm_private *priv = dev->dev_private; + int ret; mutex_lock(&tilcdc_crtc->enable_lock); if (shutdown) @@ -273,17 +275,15 @@ static void tilcdc_crtc_off(struct drm_crtc *crtc, bool shutdown) tilcdc_clear(dev, LCDC_RASTER_CTRL_REG, LCDC_RASTER_ENABLE); /* - * if necessary wait for framedone irq which will still come - * before putting things to sleep.. + * Wait for framedone irq which will still come before putting + * things to sleep.. */ - if (priv->rev == 2) { - int ret = wait_event_timeout(tilcdc_crtc->frame_done_wq, - tilcdc_crtc->frame_done, - msecs_to_jiffies(500)); - if (ret == 0) - dev_err(dev->dev, "%s: timeout waiting for framedone\n", - __func__); - } + ret = wait_event_timeout(tilcdc_crtc->frame_done_wq, + tilcdc_crtc->frame_done, + msecs_to_jiffies(500)); + if (ret == 0) + dev_err(dev->dev, "%s: timeout waiting for framedone\n", + __func__); drm_crtc_vblank_off(crtc); @@ -938,13 +938,13 @@ irqreturn_t tilcdc_crtc_irq(struct drm_crtc *crtc) } } + if (stat & LCDC_FRAME_DONE) { + tilcdc_crtc->frame_done = true; + wake_up(&tilcdc_crtc->frame_done_wq); + } + /* For revision 2 only */ if (priv->rev == 2) { - if (stat & LCDC_FRAME_DONE) { - tilcdc_crtc->frame_done = true; - wake_up(&tilcdc_crtc->frame_done_wq); - } - /* Indicate to LCDC that the interrupt service routine has * completed, see 13.3.6.1.6 in AM335x TRM. */ diff --git a/drivers/gpu/drm/tilcdc/tilcdc_regs.h b/drivers/gpu/drm/tilcdc/tilcdc_regs.h index 56dbfbd..4e6975a 100644 --- a/drivers/gpu/drm/tilcdc/tilcdc_regs.h +++ b/drivers/gpu/drm/tilcdc/tilcdc_regs.h @@ -67,6 +67,7 @@ #define LCDC_V1_PL_INT_ENA BIT(4) #define LCDC_V2_PL_INT_ENA BIT(6) #define LCDC_V1_SYNC_LOST_ENA BIT(5) +#define LCDC_V1_FRAME_DONE_ENA BIT(3) #define LCDC_MONOCHROME_MODE BIT(1) #define LCDC_RASTER_ENABLE BIT(0) #define LCDC_TFT_ALT_ENABLE BIT(23)
We should wait for the last frame to complete before shutting things down also on LCDC rev 1. Signed-off-by: Jyri Sarha <jsarha@ti.com> --- drivers/gpu/drm/tilcdc/tilcdc_crtc.c | 34 +++++++++++++++++----------------- drivers/gpu/drm/tilcdc/tilcdc_regs.h | 1 + 2 files changed, 18 insertions(+), 17 deletions(-)