Linux Sound subsystem development
 help / color / mirror / Atom feed
From: sashiko-bot@kernel.org
To: "Xing Zheng" <zhengxing@rock-chips.com>, linux-sound@vger.kernel.org
Cc: devicetree@vger.kernel.org, robh@kernel.org, conor+dt@kernel.org
Subject: Re: [PATCH v2 3/3] arm64: dts: rockchip: restore RK3308 codec detection resources
Date: Sun, 01 Nov 2026 05:01:50 +0000	[thread overview]
Message-ID: <sashiko-outbox-192275@kernel.org> (raw)
In-Reply-To: <20261101044149.2018744-4-zhengxing@rock-chips.com>

Thank you for your contribution! Sashiko AI review found 3 potential issue(s) to consider:
- [High] ASoC: codecs: rk3308: dangling dac_analog and component pointers on unbind
- [Medium] ASoC: codecs: rk3308: rk3308_codec_adc_event() overwrites MIC mute state
- [Medium] ASoC: codecs: rk3308: leaked devm_kmemdup() widget array on component probe
--

commit a099049aa9bf21b04f0558d74e37572e81c21ec8
Author: Xing Zheng <zhengxing@rock-chips.com>

ASoC: codecs: rk3308: restore audio and headphone support

This commit restores the vendor analog enable/disable sequences, reference
current ramps, headphone detection, and output routing for the RK3308 audio
codec across revisions A, B, and C.

> diff --git a/sound/soc/codecs/rk3308_codec.c b/sound/soc/codecs/rk3308_codec.c
> index a3d41cd8150d0..1894e1a93fbf8 100644
> --- a/sound/soc/codecs/rk3308_codec.c
> +++ b/sound/soc/codecs/rk3308_codec.c

[ ... ]

> +static int rk3308_codec_adc_event(struct snd_soc_dapm_widget *w,
> +				  struct snd_kcontrol *kcontrol, int event)
> +{
> +	struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
> +	struct rk3308_codec_priv *rk3308 = snd_soc_component_get_drvdata(component);
> +	unsigned int grp = w->shift;
> +	unsigned int zerocross;
> +
> +	if (event == SND_SOC_DAPM_PRE_PMU) {
> +		regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON07(grp),
> +				   RK3308_ADC_CH1_IN_SEL_MSK | RK3308_ADC_CH2_IN_SEL_MSK,
> +				   RK3308_ADC_CH1_IN_MIC | RK3308_ADC_CH2_IN_MIC);
> +		regmap_set_bits(rk3308->regmap, RK3308_ADC_ANA_CON00(grp),
> +				RK3308_ADC_CH1_MIC_UNMUTE | RK3308_ADC_CH2_MIC_UNMUTE);

[Severity: Medium]
Does rk3308_codec_adc_event() overwrite the user-configured microphone mute
state when capture starts?

Bits 3 (RK3308_ADC_CH1_MIC_UNMUTE) and 7 (RK3308_ADC_CH2_MIC_UNMUTE) of
RK3308_ADC_ANA_CON00(grp) directly back the MIC1..8 Capture Switch controls
in rk3308_codec_controls:

	SOC_SINGLE("MIC1 Capture Switch", RK3308_ADC_ANA_CON00(0), 3, 1, 0),
	SOC_SINGLE("MIC2 Capture Switch", RK3308_ADC_ANA_CON00(0), 7, 1, 0),

And rk3308_codec_initialize() already sets the initial unmuted default after
codec reset:

	/* Match the vendor analog defaults; controls remain adjustable. */
	for (grp = 0; grp < ADC_LR_GROUP_MAX; grp++)
		regmap_set_bits(rk3308->regmap, RK3308_ADC_ANA_CON00(grp),
				BIT(3) | BIT(7));

If userspace mutes a microphone channel via MIC1..8 Capture Switch while
capture is idle and then starts a capture stream, DAPM powers up the
ADC_CURRENT_EN12..78 supply widgets and runs rk3308_codec_adc_event() with
SND_SOC_DAPM_PRE_PMU, which unconditionally sets RK3308_ADC_CH1_MIC_UNMUTE |
RK3308_ADC_CH2_MIC_UNMUTE and clobbers the mute setting.

[ ... ]

> +static int rk3308_codec_add_widgets(struct snd_soc_component *component)
> +{
> +	struct snd_soc_dapm_widget *widgets;
> +	int i, grp, ret;
> +
> +	widgets = devm_kmemdup(component->dev, rk3308_codec_dapm_widgets,
> +			       sizeof(rk3308_codec_dapm_widgets), GFP_KERNEL);
> +	if (!widgets)
> +		return -ENOMEM;

[ ... ]

> +	ret = snd_soc_dapm_new_controls(snd_soc_component_to_dapm(component),
> +					widgets, ARRAY_SIZE(rk3308_codec_dapm_widgets));
> +	if (ret)
> +		return ret;

[Severity: Medium]
Does rk3308_codec_add_widgets() leak the widgets template array across
component probe cycles?

snd_soc_dapm_new_controls() -> snd_soc_dapm_new_control_unlocked() ->
dapm_cnew_widget() duplicates each widget individually with kmemdup() and
does not retain a pointer to the input widgets array after returning.

Because rk3308_codec_add_widgets() runs from the component probe callback
rk3308_codec_probe() and allocates widgets with devm_kmemdup() on the
underlying platform device (component->dev), the temporary array remains
allocated for the lifetime of the platform device and allocates another copy
on every sound card unbind/rebind or deferred probe cycle. Could this use
kmemdup() and kfree() (or __free(kfree)) instead?

[ ... ]

>  static int rk3308_codec_probe(struct snd_soc_component *component)
>  {
>  	struct rk3308_codec_priv *rk3308 = snd_soc_component_get_drvdata(component);
> +	int ret;
>  
> +	ret = rk3308_codec_add_widgets(component);
> +	if (ret)
> +		return ret;
>  	rk3308->component = component;
> +	rk3308->dac_output = 11;
> +	rk3308->output_routes_mask = 3;
>  
>  	rk3308_codec_reset(component);
>  	rk3308_codec_initialize(rk3308);
>  
> -	return 0;
> +	return rk3308_codec_add_mic_boost_controls(component);
>  }

[ ... ]

> +static void rk3308_codec_remove(struct snd_soc_component *component)
> +{
> +	struct rk3308_codec_priv *rk3308 = snd_soc_component_get_drvdata(component);
> +
> +	rk3308_codec_set_jack(component, NULL, NULL);
> +	mutex_lock(&rk3308->io_lock);
> +	rk3308->component = NULL;
> +	mutex_unlock(&rk3308->io_lock);
> +}

[Severity: High]
Can rk3308->dac_analog and rk3308->component become dangling pointers across
sound card unbind/rebind or component probe failure?

In rk3308_codec_dac_event(), the driver caches the component's DAC_CURRENT_EN
DAPM widget pointer:

	rk3308->dac_analog = w;

When the sound card is unbound, snd_soc_component_remove() calls
rk3308_codec_remove() and then snd_soc_dapm_free(), which frees all DAPM
widgets belonging to the component. Neither rk3308_codec_remove() nor
rk3308_codec_probe() clears rk3308->dac_analog. If the card is rebound and
rk3308_codec_output_event() runs before rk3308_codec_dac_event(), it will
see a non-NULL rk3308->dac_analog and dereference the freed widget:

	if (!rk3308->dac_analog)
		return 0;
	...
	if (event == SND_SOC_DAPM_PRE_PMD && !rk3308->dac_analog->new_power)
		return 0;

Additionally, in rk3308_codec_probe(), rk3308->component is set before
calling rk3308_codec_add_mic_boost_controls(component). If that call fails,
snd_soc_component_probe() aborts before marking the component as probed, so
rk3308_codec_remove() is not called during error cleanup and
rk3308->component is left pointing to an unprobed component.

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20261101044149.2018744-1-zhengxing@rock-chips.com?part=3

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

Thread overview: 15+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-11-01  4:01 [PATCH v1 0/6] RK3308 codec configuration and headphone detection Xing Zheng
2026-11-01  4:01 ` [PATCH v1 1/6] ASoC: codecs: rk3308: restore MICBIAS voltage after reset Xing Zheng
2026-11-01  4:01 ` [PATCH v1 2/6] ASoC: codecs: rk3308: expose per-channel microphone boost Xing Zheng
2026-11-01  4:13   ` sashiko-bot
2026-11-01  4:01 ` [PATCH v1 3/6] ASoC: dt-bindings: rk3308-codec: describe ADC routing and jack detection Xing Zheng
2026-11-01  4:01 ` [PATCH v1 4/6] ASoC: codecs: rk3308: support ADC stereo-group routing Xing Zheng
2026-11-01  4:01 ` [PATCH v1 5/6] ASoC: codecs: rk3308: report B/C headphone detection through set_jack Xing Zheng
2026-11-01  4:01 ` [PATCH v1 6/6] arm64: dts: rockchip: describe RK3308 codec detection resources Xing Zheng
2026-11-01  4:41 ` [PATCH v2 0/3] RK3308 codec audio sequencing and headphone support Xing Zheng
2026-11-01  4:41   ` [PATCH v2 1/3] ASoC: dt-bindings: rk3308-codec: describe detection and ADC routing Xing Zheng
2026-11-01 22:45     ` Mark Brown
2026-11-01  4:41   ` [PATCH v2 2/3] ASoC: codecs: rk3308: restore audio and headphone support Xing Zheng
2026-11-01  5:11     ` sashiko-bot
2026-11-01  4:41   ` [PATCH v2 3/3] arm64: dts: rockchip: restore RK3308 codec detection resources Xing Zheng
2026-11-01  5:01     ` sashiko-bot [this message]

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-192275@kernel.org \
    --to=sashiko-bot@kernel.org \
    --cc=conor+dt@kernel.org \
    --cc=devicetree@vger.kernel.org \
    --cc=linux-sound@vger.kernel.org \
    --cc=robh@kernel.org \
    --cc=sashiko-reviews@lists.linux.dev \
    --cc=zhengxing@rock-chips.com \
    /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