Hi Martin, On Thu, Mar 20, 2014 at 12:17 PM, Martin Fuzzey <mfuzzey@xxxxxxxxxxx> wrote: > Currently i.MX53 boards with the imx-drm display driver active > fail an intensive suspend to ram / resume test. > > After around 5 - 50 cycles it is no longer possible to resume > the board. > > The culprit is the imx-drm driver which does not stop DMA > before suspending. Removing the driver "fixes" the problem. > > This patch provides a minimal suspend / resume implementation > enabling the intensive test to work (500 cycles ok). > > I am only sending this as RFC for the moment since I don't > really know the hardware or driver code well enough to be > sure this is the "right" way of doing it. Does this patch still cause the visual artifacts you mentioned earlier? Regards, Fabio Estevam > > Signed-off-by: Martin Fuzzey <mfuzzey@xxxxxxxxxxx> > --- > drivers/staging/imx-drm/ipu-v3/ipu-common.c | 47 +++++++++++++++++++++++++++ > drivers/staging/imx-drm/ipu-v3/ipu-prv.h | 1 + > 2 files changed, 48 insertions(+) > > diff --git a/drivers/staging/imx-drm/ipu-v3/ipu-common.c b/drivers/staging/imx-drm/ipu-v3/ipu-common.c > index 97ca692..484a90a 100644 > --- a/drivers/staging/imx-drm/ipu-v3/ipu-common.c > +++ b/drivers/staging/imx-drm/ipu-v3/ipu-common.c > @@ -692,6 +692,8 @@ int ipu_idmac_enable_channel(struct ipuv3_channel *channel) > val |= idma_mask(channel->num); > ipu_idmac_write(ipu, val, IDMAC_CHA_EN(channel->num)); > > + channel->enabled = true; > + > spin_unlock_irqrestore(&ipu->lock, flags); > > return 0; > @@ -750,6 +752,8 @@ int ipu_idmac_disable_channel(struct ipuv3_channel *channel) > val &= ~idma_mask(channel->num); > ipu_cm_write(ipu, val, IPU_CHA_DB_MODE_SEL(channel->num)); > > + channel->enabled = false; > + > spin_unlock_irqrestore(&ipu->lock, flags); > > return 0; > @@ -1245,10 +1249,53 @@ static int ipu_remove(struct platform_device *pdev) > return 0; > } > > +#ifdef CONFIG_PM_SLEEP > + > +static int ipu_suspend(struct device *dev) > +{ > + struct ipu_soc *ipu = dev_get_drvdata(dev); > + struct ipuv3_channel *channel; > + int i; > + > + channel = ipu->channel; > + for (i = 0; i < ARRAY_SIZE(ipu->channel); i++, channel++) { > + channel->suspended = false; > + if (channel->enabled) { > + if (ipu_idmac_wait_busy(channel, 50)) > + dev_warn(dev, > + "%s: Timeout channel %d idle\n", > + __func__, i); > + ipu_idmac_disable_channel(channel); > + channel->suspended = true; > + } > + } > + return 0; > +} > + > +static int ipu_resume(struct device *dev) > +{ > + struct ipu_soc *ipu = dev_get_drvdata(dev); > + struct ipuv3_channel *channel; > + int i; > + > + channel = ipu->channel; > + for (i = 0; i < ARRAY_SIZE(ipu->channel); i++, channel++) { > + if (channel->suspended) { > + ipu_idmac_enable_channel(channel); > + channel->suspended = false; > + } > + } > + return 0; > +} > +#endif > + > +static SIMPLE_DEV_PM_OPS(ipu_pm_ops, ipu_suspend, ipu_resume); > + > static struct platform_driver imx_ipu_driver = { > .driver = { > .name = "imx-ipuv3", > .of_match_table = imx_ipu_dt_ids, > + .pm = &ipu_pm_ops, > }, > .probe = ipu_probe, > .remove = ipu_remove, > diff --git a/drivers/staging/imx-drm/ipu-v3/ipu-prv.h b/drivers/staging/imx-drm/ipu-v3/ipu-prv.h > index 4df0050..233749a 100644 > --- a/drivers/staging/imx-drm/ipu-v3/ipu-prv.h > +++ b/drivers/staging/imx-drm/ipu-v3/ipu-prv.h > @@ -144,6 +144,7 @@ struct ipuv3_channel { > > bool enabled; > bool busy; > + bool suspended; > > struct ipu_soc *ipu; > }; > > > _______________________________________________ > linux-arm-kernel mailing list > linux-arm-kernel@xxxxxxxxxxxxxxxxxxx > http://lists.infradead.org/mailman/listinfo/linux-arm-kernel _______________________________________________ devel mailing list devel@xxxxxxxxxxxxxxxxxxxxxx http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel