[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