Skip to content

Commit 29a25b9

Browse files
tmlindvinodkoul
authored andcommitted
dmaengine: ti: omap-dma: Block PM if SDMA is busy to fix audio
We now use cpu_pm for saving and restoring device context for deeper SoC idle states. But for omap3, we must also block idle if SDMA is busy. If we don't block idle when SDMA is busy, we eventually end up saving and restoring SDMA register state on PER domain idle while SDMA is active and that causes at least audio playback to fail. Fixes: 4c74ecf ("dmaengine: ti: omap-dma: Add device tree match data and use it for cpu_pm") Reported-by: Peter Ujfalusi <peter.ujfalusi@ti.com> Signed-off-by: Tony Lindgren <tony@atomide.com> Tested-by: Peter Ujfalusi <peter.ujfalusi@ti.com> Acked-by: Peter Ujfalusi <peter.ujfalusi@ti.com> Link: https://lore.kernel.org/r/20201109154013.11950-1-tony@atomide.com Signed-off-by: Vinod Koul <vkoul@kernel.org>
1 parent 96d5d88 commit 29a25b9

1 file changed

Lines changed: 24 additions & 13 deletions

File tree

drivers/dma/ti/omap-dma.c

Lines changed: 24 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1522,29 +1522,38 @@ static void omap_dma_free(struct omap_dmadev *od)
15221522
}
15231523
}
15241524

1525+
/* Currently used by omap2 & 3 to block deeper SoC idle states */
1526+
static bool omap_dma_busy(struct omap_dmadev *od)
1527+
{
1528+
struct omap_chan *c;
1529+
int lch = -1;
1530+
1531+
while (1) {
1532+
lch = find_next_bit(od->lch_bitmap, od->lch_count, lch + 1);
1533+
if (lch >= od->lch_count)
1534+
break;
1535+
c = od->lch_map[lch];
1536+
if (!c)
1537+
continue;
1538+
if (omap_dma_chan_read(c, CCR) & CCR_ENABLE)
1539+
return true;
1540+
}
1541+
1542+
return false;
1543+
}
1544+
15251545
/* Currently only used for omap2. For omap1, also a check for lcd_dma is needed */
15261546
static int omap_dma_busy_notifier(struct notifier_block *nb,
15271547
unsigned long cmd, void *v)
15281548
{
15291549
struct omap_dmadev *od;
1530-
struct omap_chan *c;
1531-
int lch = -1;
15321550

15331551
od = container_of(nb, struct omap_dmadev, nb);
15341552

15351553
switch (cmd) {
15361554
case CPU_CLUSTER_PM_ENTER:
1537-
while (1) {
1538-
lch = find_next_bit(od->lch_bitmap, od->lch_count,
1539-
lch + 1);
1540-
if (lch >= od->lch_count)
1541-
break;
1542-
c = od->lch_map[lch];
1543-
if (!c)
1544-
continue;
1545-
if (omap_dma_chan_read(c, CCR) & CCR_ENABLE)
1546-
return NOTIFY_BAD;
1547-
}
1555+
if (omap_dma_busy(od))
1556+
return NOTIFY_BAD;
15481557
break;
15491558
case CPU_CLUSTER_PM_ENTER_FAILED:
15501559
case CPU_CLUSTER_PM_EXIT:
@@ -1595,6 +1604,8 @@ static int omap_dma_context_notifier(struct notifier_block *nb,
15951604

15961605
switch (cmd) {
15971606
case CPU_CLUSTER_PM_ENTER:
1607+
if (omap_dma_busy(od))
1608+
return NOTIFY_BAD;
15981609
omap_dma_context_save(od);
15991610
break;
16001611
case CPU_CLUSTER_PM_ENTER_FAILED:

0 commit comments

Comments
 (0)