Hi Tony, > Am 06.11.2018 um 16:47 schrieb Tony Lindgren <tony@xxxxxxxxxxx>: > > * H. Nikolaus Schaller <hns@xxxxxxxxxxxxx> [181029 18:12]: >> So we face this situation: >> * CONFIG_CPU_IDLE=y reduces idle current of OMAP3 by 10mA (important for power saving! also for Pyra) >> * CONFIG_CPU_IDLE=y breaks audio on OMAP5 + twl6040 (but not on Pandaboard ES OMAP4 + twl6040) >> >> What fix is needed to make mainline (does not include AESS) OMAP5+TWL6040 work >> in combination with CONFIG_CPU_IDLE=y? > > The audio components do not block deeper idle states in the > hardware. So the driver needs to use PM QoS to prevent glitches, > see for example what was done in commit 9834ffd1ecc3 ("ASoC: > omap-mcbsp: Add PM QoS support for McBSP to prevent glitches"). > > I guess you need to do it for mcpdm in this case? I have sketched some hack for first experiments (only compile-tested but not for function). Is this the correct direction? BR, Nikolaus diff --git a/sound/soc/omap/omap-mcpdm.c b/sound/soc/omap/omap-mcpdm.c index 4c1be36c2207..fb479b76f112 100644 --- a/sound/soc/omap/omap-mcpdm.c +++ b/sound/soc/omap/omap-mcpdm.c @@ -70,6 +70,9 @@ struct omap_mcpdm { int pm_active_count; struct snd_dmaengine_dai_dma_data dma_data[2]; + + struct pm_qos_request pm_qos_req; + }; /* @@ -289,6 +292,8 @@ static void omap_mcpdm_dai_shutdown(struct snd_pcm_substream *substream, } } + /* FIXME: remove/update pm_qos */ + mutex_unlock(&mcpdm->mutex); } @@ -359,6 +364,8 @@ static int omap_mcpdm_dai_hw_params(struct snd_pcm_substream *substream, mcpdm->config[stream].link_mask = link_mask; + /* FIXME: handle latency calculations */ + return 0; } @@ -367,6 +374,10 @@ static int omap_mcpdm_prepare(struct snd_pcm_substream *substream, { struct omap_mcpdm *mcpdm = snd_soc_dai_get_drvdata(dai); + #define latency 10 /* in usec https://www.kernel.org/doc/Documentation/power/pm_qos_interface.txt */ + + struct pm_qos_request *pm_qos_req = &mcpdm->pm_qos_req; + if (!omap_mcpdm_active(mcpdm)) { omap_mcpdm_start(mcpdm); omap_mcpdm_reg_dump(mcpdm); @@ -377,6 +388,12 @@ static int omap_mcpdm_prepare(struct snd_pcm_substream *substream, omap_mcpdm_reg_dump(mcpdm); } + /* FIXME: use different latencies for channels */ + if (pm_qos_request_active(pm_qos_req)) + pm_qos_update_request(pm_qos_req, latency); + else + pm_qos_add_request(pm_qos_req, PM_QOS_CPU_DMA_LATENCY, latency); + return 0; } @@ -424,6 +441,9 @@ static int omap_mcpdm_remove(struct snd_soc_dai *dai) { struct omap_mcpdm *mcpdm = snd_soc_dai_get_drvdata(dai); + if (pm_qos_request_active(&mcpdm->pm_qos_req)) + pm_qos_remove_request(&mcpdm->pm_qos_req); + free_irq(mcpdm->irq, (void *)mcpdm); pm_runtime_disable(mcpdm->dev);