Devicetree
 help / color / mirror / Atom feed
From: sashiko-bot@kernel.org
To: joakim.zhang@cixtech.com
Cc: linux-sound@vger.kernel.org, devicetree@vger.kernel.org,
	robh@kernel.org, conor+dt@kernel.org
Subject: Re: [PATCH v5 4/4] ASoC: cdns: Add Cadence I2S-MC controller driver
Date: Fri, 06 Nov 2026 11:11:07 +0000	[thread overview]
Message-ID: <sashiko-outbox-201269@kernel.org> (raw)
In-Reply-To: <20261106105208.1246554-5-joakim.zhang@cixtech.com>

Thank you for your contribution! Sashiko AI review found 2 potential
issues to consider:
- [High] ASoC: cdns: premature -EBUSY in cdns_i2s_mc_hw_params() when
  peer DAI is open
- [Low] ASoC: cdns: i2s-mc: un-gated data pin clocks in
  cdns_i2s_mc_dai_probe()
--

commit 020a5d5318e146daa2dd788c38c07f592ec9d4bb
Author: Joakim Zhang <joakim.zhang@cixtech.com>

ASoC: cdns: Add Cadence I2S-MC controller driver

This commit adds an ASoC driver for the Cadence I2S-MC multi-channel
controller in the CIX SKY1 audio subsystem.

> diff --git a/sound/soc/cdns/cdns-i2s-mc.c b/sound/soc/cdns/cdns-i2s-mc.c
> new file mode 100644
> index 0000000000000..5bbac98101449
> --- /dev/null
> +++ b/sound/soc/cdns/cdns-i2s-mc.c
> @@ -0,0 +1,1152 @@

[ ... ]

> +static bool cdns_i2s_mc_other_dai_active(struct snd_soc_dai *cpu_dai)
> +{
> +	struct snd_soc_dai *dai;
> +
> +	for_each_component_dais(cpu_dai->component, dai) {
> +		if (dai == cpu_dai)
> +			continue;
> +		if (snd_soc_dai_active(dai))
> +			return true;
> +	}
> +
> +	return false;
> +}
> +
> +static int cdns_i2s_mc_hw_params(struct snd_pcm_substream *substream,
> +				 struct snd_pcm_hw_params *params,
> +				 struct snd_soc_dai *cpu_dai)
> +{
> +	struct cdns_i2s_mc_priv *i2s_mc_priv = snd_soc_dai_get_drvdata(cpu_dai);
> +	struct device *dev = i2s_mc_priv->dev;
> +	u32 rate, sample_rate = 0;
> +	u32 slots, slot_width, resolution, ctrl;
> +	unsigned long i2s_clk_rate;
> +	u8 pin_tx_num, pin_rx_num;
> +	struct clk *clk_parent;
> +	bool is_master_mode;
> +	int ret;
> +
> +	rate = params_rate(params);
> +	slot_width = i2s_mc_priv->devtype_data->data_width;
> +	dev_dbg(dev, "rate = %d, slot_width = %d\n", rate, slot_width);
> +
> +	/* switch clk mux to select the appropriate clk parent */
> +	if (rate % 8000 == 0) {
> +		/* Sampling rate is a multiple of 8KHz, select "audio-clk0" */
> +		clk_parent = i2s_mc_priv->clks[AUDIO_CLK0];
> +	} else if (rate % 11025 == 0) {
> +		/* Sampling rate is a multiple of 11.025KHz, select "audio-clk2" */
> +		clk_parent = i2s_mc_priv->clks[AUDIO_CLK2];
> +	} else {
> +		dev_err(i2s_mc_priv->dev, "Invalid sample rate\n");
> +		return -EINVAL;
> +	}
> +
> +	if (cdns_i2s_mc_other_dai_active(cpu_dai) &&
> +	    !clk_is_match(clk_get_parent(i2s_mc_priv->clk_i2s), clk_parent)) {
> +		dev_err(dev,
> +			"i2s clock parent conflicts with active stream on the other DAI\n");
> +		return -EBUSY;
> +	}

[Severity: High]
Does checking snd_soc_dai_active(dai) here cause cdns_i2s_mc_hw_params() to
fail with -EBUSY whenever both playback and capture substreams are opened
before hw_params is configured?

__soc_pcm_open() increments the DAI active count via
snd_soc_runtime_activate() at open time and keeps it non-zero across
soc_pcm_hw_free() until close.  When an audio server opens both playback
and capture PCM substreams before calling snd_pcm_hw_params() on either,
both DAIs are already marked active; if the requested rate requires
switching clk_i2s to the other parent clock, cdns_i2s_mc_hw_params()
rejects both streams with -EBUSY.  Should cdns_i2s_mc_other_dai_active()
check whether the peer DAI actually has hardware parameters configured (for
example via snd_soc_dai_get_symmetric_rate(dai) or driver state tracked in
hw_params and hw_free) instead of snd_soc_dai_active()?

[ ... ]

> +static int cdns_i2s_mc_dai_probe(struct snd_soc_dai *cpu_dai)
> +{
> +	struct cdns_i2s_mc_priv *i2s_mc_priv = snd_soc_dai_get_drvdata(cpu_dai);
> +	u32 ctrl = 0, cid_ctrl = 0;
> +
> +	/*
> +	 * Transceiver disable
> +	 * Transceiver clock disable
> +	 * All interrupts masked
> +	 * Reset for transmitter synchronizing unit
> +	 * Reset for receiver synchronizing unit
> +	 */
> +	ctrl |= FIELD_PREP(I2S_CTRL_I2S_EN, 0);
> +	ctrl &= ~(I2S_CTRL_TSYNC_RST | I2S_CTRL_RSYNC_RST);
> +	cid_ctrl |= I2S_CID_CTRL_STROBE_TS | I2S_CID_CTRL_STROBE_RS;
> +	cid_ctrl &= ~I2S_CID_CTRL_INTREQ_MASK;
> +
> +	regmap_update_bits(i2s_mc_priv->regmap, I2S_CTRL,
> +			   I2S_CTRL_I2S_EN | I2S_CTRL_TSYNC_RST | I2S_CTRL_RSYNC_RST, ctrl);
> +	regmap_update_bits(i2s_mc_priv->regmap, I2S_CID_CTRL,
> +			   I2S_CID_CTRL_STROBE_TS | I2S_CID_CTRL_STROBE_RS |
> +			   I2S_CID_CTRL_INTREQ_MASK, cid_ctrl);

[Severity: Low]
Should cdns_i2s_mc_dai_probe() also set I2S_CID_CTRL_I2S_STROBE in
I2S_CID_CTRL to gate the per-pin clocks initially?

I2S_CID_CTRL resets to 0x00000000 (all clock strobes enabled), and
cdns_i2s_mc_rxtx_config() only clears and sets the I2S_CID_CTRL_I2S_STROBE
bits matching pin_tx_mask_adjust or pin_rx_mask_adjust, leaving unwired or
unused pins with their clock gates enabled.

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20261106105208.1246554-1-joakim.zhang@cixtech.com?part=4

  reply	other threads:[~2026-11-06 11:11 UTC|newest]

Thread overview: 10+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-11-06 10:52 [PATCH v5 0/4] ASoC: cdns: Add Cadence I2S-SC and I2S-MC controller support joakim.zhang
2026-11-06 10:52 ` [PATCH v5 1/4] ASoC: dt-bindings: Add Cadence I2S-SC controller joakim.zhang
2026-11-06 10:52 ` [PATCH v5 2/4] ASoC: cdns: Add Cadence I2S-SC controller driver joakim.zhang
2026-11-07 14:46   ` Mark Brown
2026-11-06 10:52 ` [PATCH v5 3/4] ASoC: dt-bindings: Add Cadence I2S-MC controller joakim.zhang
2026-11-06 10:52 ` [PATCH v5 4/4] ASoC: cdns: Add Cadence I2S-MC controller driver joakim.zhang
2026-11-06 11:11   ` sashiko-bot [this message]
2026-11-07 14:46 ` [PATCH v5 0/4] ASoC: cdns: Add Cadence I2S-SC and I2S-MC controller support Mark Brown
2026-11-11  1:51   ` Joakim  Zhang
2026-11-07 14:47 ` Mark Brown

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=sashiko-outbox-201269@kernel.org \
    --to=sashiko-bot@kernel.org \
    --cc=conor+dt@kernel.org \
    --cc=devicetree@vger.kernel.org \
    --cc=joakim.zhang@cixtech.com \
    --cc=linux-sound@vger.kernel.org \
    --cc=robh@kernel.org \
    --cc=sashiko-reviews@lists.linux.dev \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox