Re: [RFC PATCH 1/8] ASoC: SDCA: hw_params: program upstream Input Terminals for OT DAI
From: Srinivas Kandagatla
Date: Mon Jul 27 2026 - 08:43:50 EST
On 7/27/26 9:33 AM, Charles Keepax wrote:
> On Fri, Jul 24, 2026 at 05:35:36PM +0100, Srinivas Kandagatla wrote:
>> On 7/24/26 2:14 PM, Charles Keepax wrote:
>>> On Thu, Jul 23, 2026 at 12:42:11AM +0100, Srinivas Kandagatla wrote:
>>>> For a capture stream the DAI is the Output Terminal so
>>>> sdca_asoc_hw_params() only programs the OT itself: cluster, clock
>>>> and Usage. The upstream Input Terminals that actually source the
>>>> audio never get their Usage, ClusterIndex or clock programmed, so
>>>> the power domain comes up but no samples are produced.
>>>>
>>>> Walk the source graph from the OT and program every Input Terminal
>>>> reachable through it.
>>>
>>> What was the thinking with respect to the units in the middle?
>>
>> As per $6.3.2.1 and 6.3.2.2
>> FUs does not modify the cluster, its transparent to cluster, Output Pin
>> uses same cluster as input pin
>
> But that section is specific to FUs, all the other units I
> listed below do appear to allow cluster changes:
>
Yes, other units will not preserve the wire format, this is what I was
planning to send as v2 which will stop traversing at any other units
that do not preserve the wire format.
+/*
+ * For a capture stream the ASoC DAI is the Output Terminal, so
+ * hw_params only programs the OT itself. The upstream Input
+ * Terminal(s) that actually source the audio (e.g. a mic input
+ * behind a power-domain entity) never get their Usage /
+ * ClusterIndex / clock programmed and stay inactive, so the
+ * power domain comes up but no samples are produced. Walk the
+ * source graph from the OT and program every Input Terminal we
+ * reach.
+ *
+ * The walk propagates the OT's channels/rate/width to the IT,
+ * so it is only safe to descend through entities that preserve
+ * the wire format on their upstream path (PDE / FU). Stop at
+ * any other entity type: source-selecting or format-transforming
+ * units (SU, MU, CRU, UDMPU, MFPU, PPU, XU) would either clobber
+ * an inactive branch or program mismatched parameters, and a
+ * codec with such topology needs a smarter walk than this one.
+ *
+ * Depth is bounded by the number of entities to defend against
+ * a malformed graph with a cycle.
+ */
+static int
+set_input_terminal_sources(struct device *dev, struct regmap *regmap,
+ struct sdca_function_data *function,
+ struct sdca_entity *entity,
+ int channels, int rate, int width,
+ unsigned int depth)
+{
+ int i, ret;
+
+ if (depth > function->num_entities) {
+ dev_err(dev,
+ "%s: source graph too deep, possible cycle\n",
+ entity->label);
+ return -ELOOP;
+ }
+
+ for (i = 0; i < entity->num_sources; i++) {
+ struct sdca_entity *src = entity->sources[i];
+
+ switch (src->type) {
+ case SDCA_ENTITY_TYPE_IT:
+ ret = set_cluster(dev, regmap, function,
+ src, channels);
+ if (ret)
+ return ret;
+
+ if (src->iot.clock) {
+ ret = set_clock(dev, regmap, function,
+ src->iot.clock, rate);
+ if (ret)
+ return ret;
+ }
+
+ ret = set_usage(dev, regmap, function, src,
+ SDCA_CTL_IT_USAGE, rate, width);
+ if (ret)
+ return ret;
+ continue;
+ case SDCA_ENTITY_TYPE_PDE:
+ case SDCA_ENTITY_TYPE_FU:
+ ret = set_input_terminal_sources(dev, regmap,
+ function, src,
+ channels, rate,
+ width, depth + 1);
+ if (ret)
+ return ret;
+ break;
+ default:
+ dev_dbg(dev,
+ "%s: not walking past %s (type %#x)\n",
+ entity->label, src->label, src->type);
+ break;
+ }
+ }
+
+ return 0;
+}
+
>> entities in the middle could change the cluster, such as CRUs,
>>> MPFUs, UDMPUs. Also possibly SUs to consider too, since they
>
> Thanks,
> Charles