Hi Lars
I think moving forward we should get rid of the whole CPU/CODEC/platform concept. This is an outdated view of how the hardware looks like. When ASoC was initially introduce all hardware basically had a CPU side DAI, a CODEC side DAI and a DMA. The DMA was connected to the CPU DAI and the CPU DAI was connected to the CODEC DAI and that was it. The CPU side was also really simple, no signal processing, no signal routing, just the raw audio data directly transferred via DMA (or PIO sometimes) to the CPU DAI controller. And all digital audio was assumed to be in a single digital domain running at them same clock rate.
This no longer reflects todays typical systems. Sometimes you have more than those three components (e.g. additional amplifier IC, BT chip ...), sometimes you less (just a DAC or ADC directly connected to a DMA in the SoC). You often have complex routing and processing capabilities on the host side. Also you have often multiple digital domains with sample-rate converters between them.
Yet still at the core ASoC keeps the CPU/CODEC/platform concept. DPCM e.g. tries to work with these concepts by introducing frontend and backend DAIs and use dummy components to compensate for when the software model does not match the hardware model. This makes it code more complicated than it has to be and less efficient than it can be.
I agree to your opinion. OTOH, we would like to use/keep existing current all drivers. Thus, I think we need super many small and slow steps. Or, we need new ASoC2 ?
I can agree that we should get rid of current CPU/Codec/Platform, but, removing all of them is a little bit over-kill for me. I think ALSA SoC "framework" should care "component" only, and it doesn't care what it was. OTOH "driver" side can use existing CPU/Codec/Platform and/or AUX/compr etc as helper ? (I'm not sure detail of AUX/compr actually...) And each "component" has "dai".
My image is like this. This allows many / few components, and many / few DAIs. Current DPCM style is automatically supported, and it is easy to add new style device. What do you think ?
/* * DAI has parent (= component) pointer * and rtd interface list_head */ struct snd_soc_dai { ... struct snd_soc_component *component; /* parent */ struct list_head *dai_node; /* struct snd_soc_pcm_runtime */ };
/* * Each component has at least 1 DAI * * CPU/Codec will have many DAIs * Card/Platform and other will have dummy DAI as interface */ struct snd_soc_component { ... struct snd_soc_dai *dais; };
/* * We can use Card/CPU/Codec/Platform/AUX/COMPR helper, * all includes "component". * Of course each driver can create original one, * or don't use helper is no problem */ struct snd_soc_card { ... struct snd_soc_component component; };
struct snd_soc_cpu { ... struct snd_soc_component component; };
struct snd_soc_codec { ... struct snd_soc_component component; };
struct snd_soc_platform { ... struct snd_soc_component component; };
struct snd_soc_aux { ... struct snd_soc_component component; }; struct snd_soc_compr { ... struct snd_soc_component component; };
...
/* * rtd has each DAI interface list. * But it doesn't care what it was */ struct snd_soc_pcm_runtime { ... struct list_head *dai_node_head; /* struct snd_soc_dai */ }
/* * each function just call dai or component function * it doesn't care what it was */ static int soc_pcm_trigger(struct snd_pcm_substream *substream, int cmd) { struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_component *component; struct snd_soc_dai *dai; int ret = 0;
/* * call each component's ops */ list_for_each_entry(dai, rtd->xxx) { component = snd_soc_dai_to_component(dai); ret = component->ops->trigger(dai, xxx); if (ret < 0) goto trigger_end; }
trigger_end: return ret; }