mbox series

[0/8] Add support for the internal RK3308 audio codec

Message ID 20220907142124.2532620-1-luca.ceresoli@bootlin.com
Headers show
Series Add support for the internal RK3308 audio codec | expand

Message

Luca Ceresoli Sept. 7, 2022, 2:21 p.m. UTC
From: Luca Ceresoli <luca.ceresoli@bootlin.com>

This series of patches adds support to use the internal audio codec of the
Rockchip RK3308 SoC. This codec is internally connected to the I2S
peripherals on the same chip, and it has some peculiarities arising from
that interconnection.

For proper bidirectional operation with the internal codec, the I2S
peripheral needs two clock sources (tx and rx), while connection with an
external codec commonly needs only one. Since v5.16 there is a driver for
the I2S in sound/soc/rockchip/rockchip_i2s_tdm.c, but it does not correctly
handle receiving those two clocks via the .set_sysclk op. Patch 5 fixes
that.

However the simple-audio-card and audio-graph-card sound card drivers do
not support calling .set_sysclk twice, thus patch 6 makes the .init op of
struct asoc_simple_priv overridable by a driver in order to be able to call
.set_sysclk twice and thus configure both clocks.

Patch 7 adds the codec driver and patch 8 builds on top of all the above by
implementing a simple RK3308-specific audio card, based on
audio-graph-card. This card sets all the I2S input clocks.

Patches 1-2 add DT bindings for the codec and the card. Patches 3-4 add to
the SoC DT file two I2S controllers (those which are internally connected
to the internal codec) and the codec itself.

Luca

Luca Ceresoli (8):
  ASoC: rockchip: rk3308: add internal audio codec bindings
  ASoC: rockchip: rk3308: add audio card bindings
  arm64: dts: rockchip: add i2s_8ch_2 and i2s_8ch_3
  arm64: dts: rockchip: add the internal audio codec
  ASoC: rockchip: i2s-tdm: Fix clk_id usage in .set_sysclk()
  ASoC: audio-graph: let dai_link->init be overridable
  ASoC: codecs: Add RK3308 internal audio codec driver
  ASoC: rockchip: add new RK3308 sound card

 .../rockchip,rk3308-audio-graph-card.yaml     |   50 +
 .../bindings/sound/rockchip,rk3308-codec.yaml |  102 +
 MAINTAINERS                                   |   14 +
 arch/arm64/boot/dts/rockchip/rk3308.dtsi      |   68 +
 .../dt-bindings/sound/rockchip,rk3308-codec.h |   15 +
 include/sound/simple_card_utils.h             |    1 +
 sound/soc/codecs/Kconfig                      |   11 +
 sound/soc/codecs/Makefile                     |    2 +
 sound/soc/codecs/rk3308_codec.c               | 2122 +++++++++++++++++
 sound/soc/codecs/rk3308_codec.h               |  648 +++++
 sound/soc/generic/audio-graph-card.c          |    2 +
 sound/soc/rockchip/Kconfig                    |   14 +
 sound/soc/rockchip/Makefile                   |    1 +
 sound/soc/rockchip/rockchip_i2s_tdm.c         |   18 +-
 sound/soc/rockchip/rockchip_rk3308_card.c     |   97 +
 15 files changed, 3159 insertions(+), 6 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/sound/rockchip,rk3308-audio-graph-card.yaml
 create mode 100644 Documentation/devicetree/bindings/sound/rockchip,rk3308-codec.yaml
 create mode 100644 include/dt-bindings/sound/rockchip,rk3308-codec.h
 create mode 100644 sound/soc/codecs/rk3308_codec.c
 create mode 100644 sound/soc/codecs/rk3308_codec.h
 create mode 100644 sound/soc/rockchip/rockchip_rk3308_card.c

Comments

Mark Brown Sept. 7, 2022, 3:41 p.m. UTC | #1
On Wed, Sep 07, 2022 at 04:21:16PM +0200, luca.ceresoli@bootlin.com wrote:

> Luca Ceresoli (8):
>   ASoC: rockchip: rk3308: add internal audio codec bindings
>   ASoC: rockchip: rk3308: add audio card bindings
>   arm64: dts: rockchip: add i2s_8ch_2 and i2s_8ch_3
>   arm64: dts: rockchip: add the internal audio codec
>   ASoC: rockchip: i2s-tdm: Fix clk_id usage in .set_sysclk()
>   ASoC: audio-graph: let dai_link->init be overridable
>   ASoC: codecs: Add RK3308 internal audio codec driver
>   ASoC: rockchip: add new RK3308 sound card

Please pay attention to the ordering of your serieses when posting:
generally any bug fixes should come first so that they can be easily
sent as fixes, and normally DTS updates are at the very end of the
series rather than mixed in the middle since they go via the platform
maintainer tree normally rather than with everything else.
Luca Ceresoli Sept. 7, 2022, 5:15 p.m. UTC | #2
Hello Mark,

thanks for the quick feedback!

On Wed, 7 Sep 2022 16:41:44 +0100
Mark Brown <broonie@kernel.org> wrote:

> On Wed, Sep 07, 2022 at 04:21:16PM +0200, luca.ceresoli@bootlin.com wrote:
> 
> > Luca Ceresoli (8):
> >   ASoC: rockchip: rk3308: add internal audio codec bindings
> >   ASoC: rockchip: rk3308: add audio card bindings
> >   arm64: dts: rockchip: add i2s_8ch_2 and i2s_8ch_3
> >   arm64: dts: rockchip: add the internal audio codec
> >   ASoC: rockchip: i2s-tdm: Fix clk_id usage in .set_sysclk()
> >   ASoC: audio-graph: let dai_link->init be overridable
> >   ASoC: codecs: Add RK3308 internal audio codec driver
> >   ASoC: rockchip: add new RK3308 sound card  
> 
> Please pay attention to the ordering of your serieses when posting:
> generally any bug fixes should come first so that they can be easily
> sent as fixes, and normally DTS updates are at the very end of the
> series rather than mixed in the middle since they go via the platform
> maintainer tree normally rather than with everything else.

Sorry about that. I've reordered the patches in my branch for the next
iteration.

Best regards,
Luca
Krzysztof Kozlowski Sept. 8, 2022, 11:53 a.m. UTC | #3
On 07/09/2022 16:21, luca.ceresoli@bootlin.com wrote:
> From: Luca Ceresoli <luca.ceresoli@bootlin.com>
> 
> The RK3308 has a built-in audio codec that connects internally to i2s_8ch_2
> or i2s_8ch_3.
> 
> Signed-off-by: Luca Ceresoli <luca.ceresoli@bootlin.com>
> ---
>  arch/arm64/boot/dts/rockchip/rk3308.dtsi | 14 ++++++++++++++
>  1 file changed, 14 insertions(+)
> 
> diff --git a/arch/arm64/boot/dts/rockchip/rk3308.dtsi b/arch/arm64/boot/dts/rockchip/rk3308.dtsi
> index 093b70563b23..221cde49dc98 100644
> --- a/arch/arm64/boot/dts/rockchip/rk3308.dtsi
> +++ b/arch/arm64/boot/dts/rockchip/rk3308.dtsi
> @@ -808,6 +808,20 @@ cru: clock-controller@ff500000 {
>  		assigned-clock-rates = <32768>;
>  	};
>  
> +	acodec: acodec@ff560000 {

Node names should be generic.
https://devicetree-specification.readthedocs.io/en/latest/chapter2-devicetree-basics.html#generic-names-recommendation


Best regards,
Krzysztof
Mark Brown Sept. 8, 2022, 4:27 p.m. UTC | #4
On Wed, Sep 07, 2022 at 04:21:23PM +0200, luca.ceresoli@bootlin.com wrote:

> +static const char *offon_text[2] = {
> +	[0] = "Off",
> +	[1] = "On",
> +};

Simple on/off controls should be normal switches, not enums.

> +/* ALC AGC Switch */
> +static const struct soc_enum rk3308_agc_enum_array[] = {
> +	SOC_ENUM_SINGLE(0, 0, ARRAY_SIZE(offon_text), offon_text),
> +	SOC_ENUM_SINGLE(0, 1, ARRAY_SIZE(offon_text), offon_text),

Do not index into arrays of enums with magic numbers, this is hard to
read and maintain.  Use named variables for the enums like other drivers
do.

> +static void rk3308_codec_update_zerocross(struct rk3308_codec_priv *rk3308)
> +{
> +	unsigned int agc_on, value;
> +	int grp;
> +
> +	/* 14: enable zero-cross detection if AGC enabled, else AGC won't work */
> +	for (grp = 0; grp < rk3308->used_adc_grps; grp++) {

If you're going to force zero cross on then you need to generate an
event on the zero cross control so that UIs get updated, however it
might be a bit more idiomatic to either just leave zero cross always on
and not offer user control or return an error if the user tries to
enable AGC without zero cross (or tries to disable zero cross without
AGC).  Given that there's very few use cases for disabling zero cross
with actual audio usage it may be best to just force it on and worry
about offering control for those other use cases later if someone
actually needs that, it's probably more trouble than it's worth to
handle.

> +static int rk3308_codec_agc_put(struct snd_kcontrol *kcontrol,
> +				struct snd_ctl_elem_value *ucontrol)
> +{
> +	struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
> +	struct rk3308_codec_priv *rk3308 = snd_soc_component_get_drvdata(component);
> +

> +	}
> +
> +	rk3308_codec_update_zerocross(rk3308);
> +
> +	return 0;
> +}

_put() operations need to return 1 if the value changed, please run the
mixer-test selftest on a system with your driver0 - it'll catch issues
like this for you.

> +	if (any_micbias_enabled) {
> +		regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON07(0),
> +				   RK3308_ADC_LEVEL_RANGE_MICBIAS_MSK,
> +				   rk3308->micbias_avdd_mult);
> +
> +		/* Wait until the VCMH keep stable */
> +		msleep(20);	/* estimated value */
> +
> +		regmap_set_bits(rk3308->regmap, RK3308_ADC_ANA_CON08(0),
> +				RK3308_ADC_MICBIAS_CURRENT_EN);
> +	}

This should probably be modelled as a SUPPLY widget for the micbiases
rather than open coding.

> +static int rk3308_codec_micbias_put(struct snd_kcontrol *kcontrol,
> +				    struct snd_ctl_elem_value *ucontrol)
> +{
> +	struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
> +	struct rk3308_codec_priv *rk3308 = snd_soc_component_get_drvdata(component);

There should be no reason to offer userspace control over micbiases,
they should be modelled as supply widgets like with other drivers.  If
there's some system specific reason for offering control then the
machine driver can handle it.

> +static int rk3308_codec_hpout_l_get_tlv(struct snd_kcontrol *kcontrol,
> +					struct snd_ctl_elem_value *ucontrol)
> +{
> +	return snd_soc_get_volsw_range(kcontrol, ucontrol);
> +}

Just use the generic function directly, no need for this wrapper.

> +static int rk3308_codec_hpout_r_put_tlv(struct snd_kcontrol *kcontrol,
> +					struct snd_ctl_elem_value *ucontrol)
> +{
> +	struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
> +	struct rk3308_codec_priv *rk3308 = snd_soc_component_get_drvdata(component);
> +	unsigned int dgain = ucontrol->value.integer.value[0];
> +
> +	rk3308->hpout_r_dgain = dgain;
> +
> +	return snd_soc_put_volsw_range(kcontrol, ucontrol);
> +}

Just model the headphone output as a stereo control.

> +	 * There are 8 ADCs and use the same SCLK and LRCK internal for master
> +	 * mode, We need to make sure that they are in effect at the same time,
> +	 * otherwise they will cause the abnormal clocks.
> +	 */
> +	if (is_master)
> +		regmap_clear_bits(rk3308->regmap, RK3308_GLB_CON, RK3308_ADC_DIG_WORK);
> +
> +	for (grp = 0; grp < ADC_LR_GROUP_MAX; grp++) {
> +		regmap_update_bits(rk3308->regmap, RK3308_ADC_DIG_CON01(grp),
> +				   RK3308_ADC_I2S_LRC_POL_REVERSAL |
> +				   RK3308_ADC_I2S_MODE_MSK,
> +				   adc_aif1);
> +		regmap_update_bits(rk3308->regmap, RK3308_ADC_DIG_CON02(grp),
> +				   RK3308_ADC_IO_MODE_MASTER |
> +				   RK3308_ADC_MODE_MASTER |
> +				   RK3308_ADC_I2S_BIT_CLK_POL_REVERSAL,
> +				   adc_aif2);
> +	}
> +
> +	/* Hold ADC Digital registers end at master mode */
> +	if (is_master)
> +		regmap_set_bits(rk3308->regmap, RK3308_GLB_CON, RK3308_ADC_DIG_WORK);

This looks like it might glitch other active streams, you should
probably have a check to see if the configuration is actually being
changed and skip updates entirely if not.

> +static int rk3308_mute_stream(struct snd_soc_dai *dai, int mute, int stream)
> +{
> +	struct snd_soc_component *component = dai->component;
> +	struct rk3308_codec_priv *rk3308 = snd_soc_component_get_drvdata(component);
> +
> +	if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
> +		int dgain;
> +
> +		if (mute) {
> +			for (dgain = 0x2; dgain <= 0x7; dgain++) {
> +				/*
> +				 * Keep the max -> min digital CIC interpolation
> +				 * filter gain step by step.
> +				 *
> +				 * loud: 0x2; whisper: 0x7
> +				 */
> +				regmap_update_bits(rk3308->regmap,
> +						   RK3308_DAC_DIG_CON04,
> +						   RK3308_DAC_CIC_IF_GAIN_MSK,
> +						   dgain);
> +				usleep_range(200, 300);  /* estimated value */
> +			}

I'm not clear why a volume ramp is required here?  Generally when the
mute operation happens there's no audio running so we'd just be ramping
up the noise floor, it's for masking glitches from the controller.

> +static int rk3308_codec_digital_fadein(struct rk3308_codec_priv *rk3308)
> +{
> +	unsigned int dgain, dgain_ref;
> +
> +	if (rk3308->hpout_l_dgain != rk3308->hpout_r_dgain) {
> +		pr_warn("HPOUT l_dgain: 0x%x != r_dgain: 0x%x\n",
> +			rk3308->hpout_l_dgain, rk3308->hpout_r_dgain);
> +		dgain_ref = min(rk3308->hpout_l_dgain, rk3308->hpout_r_dgain);
> +	} else {
> +		dgain_ref = rk3308->hpout_l_dgain;
> +	}

Does the device actively need this for masking some issue with clean
startup or is this just a nice to have?  It should be easy enough to
handle asymmatric volumes, you can just ramp by one step at once and
just stop ramping on whichever channel needs fewer steps whenever it
hits target.

If there's some other reason the gains absolutely must be identical just
offer a mono control.

> +	/*
> +	 * We'd better change the gain of the left and right channels
> +	 * at the same time to avoid different listening
> +	 */

Looks like it is working around a power up issue so it's fine to have
this.

> +static int rk3308_codec_dac_enable(struct rk3308_codec_priv *rk3308)
> +{

This looks way, way too open coded - you should be implementing a DAPM
graph for the device and splitting things up.

> +	/*
> +	 * 1. Set the ACODEC_DAC_ANA_CON0[0] to 0x1, to enable the current
> +	 * source of DAC
> +	 */
> +	regmap_set_bits(rk3308->regmap, RK3308_DAC_ANA_CON00,
> +			RK3308_DAC_CURRENT_EN);
> +
> +	usleep_range(20, 40);

This should be a DAC widget.

> +
> +	/*
> +	 * 2. Set the ACODEC_DAC_ANA_CON1[6] and ACODEC_DAC_ANA_CON1[2] to 0x1,
> +	 * to enable the reference voltage buffer
> +	 */
> +	regmap_set_bits(rk3308->regmap, RK3308_DAC_ANA_CON01,
> +			RK3308_DAC_BUF_REF_L_EN |
> +			RK3308_DAC_BUF_REF_R_EN);
> +
> +	/* Waiting the stable reference voltage */
> +	mdelay(1);

This should be a supply.

> +	/* Step 03 */
> +	regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON01,
> +			   RK3308_DAC_HPOUT_POP_SOUND_L_MSK |
> +			   RK3308_DAC_HPOUT_POP_SOUND_R_MSK,
> +			   RK3308_DAC_HPOUT_POP_SOUND_L_WORK |
> +			   RK3308_DAC_HPOUT_POP_SOUND_R_WORK);
> +
> +	usleep_range(20, 40);
> +

You can probably push preparatory work like this into a fake supply
widget, wm8994 has some stuff like that.

> +	/* Step 05 */
> +	regmap_set_bits(rk3308->regmap, RK3308_DAC_ANA_CON13,
> +			RK3308_DAC_L_HPMIX_EN |
> +			RK3308_DAC_R_HPMIX_EN);
> +
> +	/* Waiting the stable HPMIX */
> +	mdelay(1);
> +
> +	/* Step 06. Reset HPMIX and recover HPMIX gains */
> +	regmap_clear_bits(rk3308->regmap, RK3308_DAC_ANA_CON13,
> +			  RK3308_DAC_L_HPMIX_WORK |
> +			  RK3308_DAC_R_HPMIX_WORK);
> +	usleep_range(50, 100);
> +	regmap_set_bits(rk3308->regmap, RK3308_DAC_ANA_CON13,
> +			RK3308_DAC_L_HPMIX_WORK |
> +			RK3308_DAC_R_HPMIX_WORK);
> +
> +	usleep_range(20, 40);

These are mixers.

> +	if (rk3308->dac_output == DAC_LINEOUT ||
> +	    rk3308->dac_output == DAC_LINEOUT_HPOUT) {
> +		/* Step 07 */
> +		regmap_set_bits(rk3308->regmap, RK3308_DAC_ANA_CON04,
> +				RK3308_DAC_L_LINEOUT_EN |
> +				RK3308_DAC_R_LINEOUT_EN);
> +
> +		usleep_range(20, 40);
> +	}
> +
> +	if (rk3308->dac_output == DAC_HPOUT ||
> +	    rk3308->dac_output == DAC_LINEOUT_HPOUT) {
> +		/* Step 08 */
> +		regmap_set_bits(rk3308->regmap, RK3308_DAC_ANA_CON03,
> +				RK3308_DAC_L_HPOUT_EN |
> +				RK3308_DAC_R_HPOUT_EN);
> +
> +		usleep_range(20, 40);
> +
> +		/* Step 09 */
> +		regmap_set_bits(rk3308->regmap, RK3308_DAC_ANA_CON03,
> +				RK3308_DAC_L_HPOUT_WORK |
> +				RK3308_DAC_R_HPOUT_WORK);
> +
> +		usleep_range(20, 40);
> +	}
> +
> +	if (rk3308->codec_ver == ACODEC_VERSION_B) {
> +		/* Step 10 */
> +		regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON15,
> +				   RK3308_DAC_LINEOUT_POP_SOUND_L_MSK |
> +				   RK3308_DAC_LINEOUT_POP_SOUND_R_MSK,
> +				   RK3308_DAC_L_SEL_LINEOUT_FROM_INTERNAL |
> +				   RK3308_DAC_R_SEL_LINEOUT_FROM_INTERNAL);
> +
> +		usleep_range(20, 40);
> +	}
> +
> +	/* Step 11 */
> +	regmap_set_bits(rk3308->regmap, RK3308_DAC_ANA_CON02,
> +			RK3308_DAC_L_REF_EN | RK3308_DAC_R_REF_EN);
> +
> +	usleep_range(20, 40);
> +
> +	/* Step 12 */
> +	regmap_set_bits(rk3308->regmap, RK3308_DAC_ANA_CON02,
> +			RK3308_DAC_L_CLK_EN | RK3308_DAC_R_CLK_EN);
> +
> +	usleep_range(20, 40);
> +
> +	/* Step 13 */
> +	regmap_set_bits(rk3308->regmap, RK3308_DAC_ANA_CON02,
> +			RK3308_DAC_L_DAC_EN | RK3308_DAC_R_DAC_EN);
> +
> +	usleep_range(20, 40);
> +
> +	/* Step 14 */
> +	regmap_set_bits(rk3308->regmap, RK3308_DAC_ANA_CON02,
> +			RK3308_DAC_L_DAC_WORK | RK3308_DAC_R_DAC_WORK);
> +
> +	usleep_range(20, 40);
> +
> +	/* Step 15 */
> +	regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON12,
> +			   RK3308_DAC_L_HPMIX_SEL_MSK |
> +			   RK3308_DAC_R_HPMIX_SEL_MSK,
> +			   RK3308_DAC_L_HPMIX_I2S |
> +			   RK3308_DAC_R_HPMIX_I2S);
> +
> +	usleep_range(20, 40);
> +
> +	/* Step 16 */
> +	regmap_set_bits(rk3308->regmap, RK3308_DAC_ANA_CON13,
> +			RK3308_DAC_L_HPMIX_UNMUTE | RK3308_DAC_R_HPMIX_UNMUTE);
> +
> +	usleep_range(20, 40);
> +
> +	/* Step 17: Put configuration HPMIX Gain */
> +
> +	if (rk3308->dac_output == DAC_HPOUT ||
> +	    rk3308->dac_output == DAC_LINEOUT_HPOUT) {
> +		/* Step 18 */
> +		regmap_set_bits(rk3308->regmap, RK3308_DAC_ANA_CON03,
> +				RK3308_DAC_L_HPOUT_UNMUTE | RK3308_DAC_R_HPOUT_UNMUTE);
> +
> +		usleep_range(20, 40);
> +	}

These are all output drivers.

> +
> +	if (rk3308->dac_output == DAC_LINEOUT ||
> +	    rk3308->dac_output == DAC_LINEOUT_HPOUT) {
> +		/* Step 19 */
> +		regmap_set_bits(rk3308->regmap, RK3308_DAC_ANA_CON04,
> +				RK3308_DAC_L_LINEOUT_UNMUTE | RK3308_DAC_R_LINEOUT_UNMUTE);
> +		usleep_range(20, 40);
> +	}
> +
> +	/* Step 20, put configuration HPOUT gain control */
> +	/* Step 21, put configuration LINEOUT gain control */
> +
> +	if (rk3308->dac_output == DAC_HPOUT ||
> +	    rk3308->dac_output == DAC_LINEOUT_HPOUT) {
> +		/* Just for HPOUT */
> +		rk3308_codec_digital_fadein(rk3308);
> +	}

Use a _POST widget for this.

> +static int rk3308_codec_power_on(struct rk3308_codec_priv *rk3308)
> +{
> +	unsigned int v;
> +

> +static int rk3308_codec_power_off(struct rk3308_codec_priv *rk3308)
> +{
> +	unsigned int v;

This would normally be in set_bias_level() or a DAPM supply, probably
set_bias_level() as there's a few moderate delays.

> +static int rk3308_hw_params(struct snd_pcm_substream *substream,
> +			    struct snd_pcm_hw_params *params,
> +			    struct snd_soc_dai *dai)
> +{
> +	struct snd_soc_component *component = dai->component;
> +	struct rk3308_codec_priv *rk3308 = snd_soc_component_get_drvdata(component);
> +	int ret;
> +
> +	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
> +		/* DAC only supports 2 channels */
> +		rk3308_codec_dac_mclk_enable(rk3308);
> +		rk3308_codec_dac_enable(rk3308);
> +		rk3308_codec_dac_dig_config(rk3308, params);
> +	} else {
> +		rk3308_codec_micbias_apply(rk3308);
> +		rk3308_codec_adc_mclk_enable(rk3308);
> +		ret = rk3308_codec_update_adc_grps(rk3308, params);
> +		if (ret < 0)
> +			return ret;
> +
> +		rk3308_codec_open_capture(rk3308);
> +		rk3308_codec_agc_dig_config(rk3308, params);
> +		rk3308_codec_adc_dig_config(rk3308, params);
> +	}

Note that hw_params() can be called repeatedly before actually starting
the audio, you shouldn't be doing any refcounted operations.  There is
an open operation or again lots of this looks like powerup stuff which
could be moved to DAPM.

> +static int rk3308_codec_default_gains(struct rk3308_codec_priv *rk3308)
> +{

Use the hardware defaults, don't open code settings for things like
gains.  Your settings may not be appropriate for other systems.

> +static int rk3308_codec_prepare(struct rk3308_codec_priv *rk3308)
> +{
> +	/* Clear registers for ADC and DAC */
> +	rk3308_codec_dac_disable(rk3308);
> +	rk3308_codec_adc_ana_disable(rk3308, ADC_LR_GROUP_MAX);
> +	rk3308_codec_default_gains(rk3308);
> +	rk3308_codec_llp_down(rk3308);
> +	rk3308_codec_controls_prepare(rk3308);

This applies to settings in general, the exceptions are generally things
like zero cross where it's so overwhelmingly clear what makes sense and
the setting is more of a chicken bit than actually useful.
Mark Brown Sept. 8, 2022, 4:36 p.m. UTC | #5
On Wed, Sep 07, 2022 at 04:21:21PM +0200, luca.ceresoli@bootlin.com wrote:

> -static int rockchip_i2s_tdm_set_sysclk(struct snd_soc_dai *cpu_dai, int stream,
> +static int rockchip_i2s_tdm_set_sysclk(struct snd_soc_dai *cpu_dai, int clk_id,
>  				       unsigned int freq, int dir)
>  {
>  	struct rk_i2s_tdm_dev *i2s_tdm = to_info(cpu_dai);
> @@ -978,15 +981,18 @@ static int rockchip_i2s_tdm_set_sysclk(struct snd_soc_dai *cpu_dai, int stream,
>  	if (i2s_tdm->clk_trcm) {
>  		i2s_tdm->mclk_tx_freq = freq;
>  		i2s_tdm->mclk_rx_freq = freq;
> +
> +		dev_dbg(i2s_tdm->dev, "mclk freq: %u", freq);
>  	} else {
> -		if (stream == SNDRV_PCM_STREAM_PLAYBACK)
> +		if (clk_id == CLK_IDX_MCLK_TX)
>  			i2s_tdm->mclk_tx_freq = freq;
> -		else
> +		else if (clk_id == CLK_IDX_MCLK_RX)
>  			i2s_tdm->mclk_rx_freq = freq;
> -	}
> +		else
> +			return -ENOTSUPP;

This should be a switch statement for clarity and exensibility.
Luca Ceresoli Sept. 9, 2022, 5:11 p.m. UTC | #6
Hello Mark,

On Thu, 8 Sep 2022 17:27:36 +0100
Mark Brown <broonie@kernel.org> wrote:

> On Wed, Sep 07, 2022 at 04:21:23PM +0200, luca.ceresoli@bootlin.com wrote:

Thank you for taking the time to review my patch in such detail! This
is my first contribution to ALSA, and it was not clear to me which
parts of the existing vendor driver needed even more cleanups than I
have already done. I will probably get back to you with specific
questions later on, while addressing your comments.

Best regards,
Luca