catpt_dai_pcm_new() invoked during new PCM runtime creation configures SSP by sending IPC to DSP firmware. For that to succeed device needs to be up and running. While components default probing behavior - snd_soc_catpt causing machine board module to load just after it - needs no changes, machine board's module may be unloaded and re-loaded at a different time e.g.: when catpt is already asleep.
Wake device explicitly in catpt_dai_pcm_new() to ensure communication is established before sending any IPCs, enabling those advanced scenarios in the process.
Signed-off-by: Cezary Rojewski cezary.rojewski@intel.com ---
In short, this allows for following scenario (which user usually do not touch):
1. modprobe snd_soc_catpt // core driver 2. modprobe snd_soc_sst_broadwell // machine board driver 3. wait for snd_soc_catpt to suspend (~2s) 4. rmmod snd_soc_sst_broadwell 5. modprobe snd_soc_sst_broadwell
Without the 3. everything works just fine but let's be more flexible here. Right now, -110 (timeout) will occur as device will simply be asleep. To allow for this advanced scenario, pm_runtime manipulation is required. memcmp check is to prevent unnecessary operations from occurring.
sound/soc/intel/catpt/pcm.c | 10 ++++++++++ 1 file changed, 10 insertions(+)
diff --git a/sound/soc/intel/catpt/pcm.c b/sound/soc/intel/catpt/pcm.c index f78018c857b8..ba653ebea7d1 100644 --- a/sound/soc/intel/catpt/pcm.c +++ b/sound/soc/intel/catpt/pcm.c @@ -667,7 +667,17 @@ static int catpt_dai_pcm_new(struct snd_soc_pcm_runtime *rtm, break; }
+ /* see if this is a new configuration */ + if (!memcmp(&cdev->devfmt[devfmt.iface], &devfmt, sizeof(devfmt))) + return 0; + + pm_runtime_get_sync(cdev->dev); + ret = catpt_ipc_set_device_format(cdev, &devfmt); + + pm_runtime_mark_last_busy(cdev->dev); + pm_runtime_put_autosuspend(cdev->dev); + if (ret) return CATPT_IPC_ERROR(ret);