[Letux-kernel] OMAP5+TWL6040: CONFIG_CPU_IDLE=y breaks (non AESS) audio

H. Nikolaus Schaller hns at goldelico.com
Mon Nov 12 20:40:01 CET 2018


Hi Tony,

> Am 06.11.2018 um 16:47 schrieb Tony Lindgren <tony at atomide.com>:
> 
> * H. Nikolaus Schaller <hns at goldelico.com> [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);
 



More information about the Letux-kernel mailing list