On Fri, May 17, 2024 at 04:03:50PM GMT, Mark Brown wrote: > On Fri, May 17, 2024 at 02:58:05PM +0200, Alvin Šipraga wrote: > > > +++ b/sound/soc/codecs/ad24xx-codec.c > > @@ -0,0 +1,665 @@ > > +// SPDX-License-Identifier: GPL-2.0-only > > +/* > > + * AD24xx codec driver > > Please make the whole comment a C++ comment. OK > > > +static const char *const ad24xx_codec_slot_size_text[] = { > > + "8 bits", "12 bits", "16 bits", "20 bits", > > + "24 bits", "28 bits", "32 bits", > > +}; > > Why is this configured by the user rather than via set_tdm_slot(), and > how would one usefully use this at runtime? This configures the slot size of A2B data slots, not the slot size on the TDM interface. Typically one would expect it to be the same, so your question is valid. But it is not a strict requirement as far as the A2B bus and hardware is concerned. To give a concrete example, the TDM interface might run with a TDM slot size of 32 bits, but the PCM data is in reality 24 bits padded to 32 bits. In this case, A2B bus bandwidth can be saved by configuring the "{Up,Down}stream Slot Size" kcontrol to "24 bits". More detailed information can be found in the manual in [1] section 3-22 "I2S/TDM Port Programming Concepts", where an analogous example is given. > > > +static int ad24xx_codec_slot_config_put(struct snd_kcontrol *kcontrol, > > + struct snd_ctl_elem_value *ucontrol) > > +{ > > > + } else if (priv == &ad24xx_codec_up_slot_format_enum || > > + priv == &ad24xx_codec_dn_slot_format_enum) { > > + if (val >= ARRAY_SIZE(ad24xx_codec_slot_format_text)) > > + return -EINVAL; > > + slot_config->format[direction] = val; > > + } else > > + return -ENOENT; > > If one side has {} both sides should, see coding-style.rst. OK > > > + > > + return 0; > > +} > > This won't flag changes by returning 1 which will mean no events are > generated and break some UIs. Please show the output of the mixer-test > selftest on new submissions, it will check for this and other issues. OK, I will have a go. Thanks! > > > + /* Main node must be BCLK/FSYNC consumer, subordinate node provider */ > > + if ((fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) != > > + (is_a2b_main(adc->node) ? SND_SOC_DAIFMT_CBC_CFC : > > + SND_SOC_DAIFMT_CBP_CFP)) > > + return -EINVAL; > > Please don't use the ternery operator like this, it just makes things > harder to read. > > > + val = bclk_invert ? A2B_I2SCFG_RXBCLKINV_MASK : > > + A2B_I2SCFG_TXBCLKINV_MASK; > > Similarly, please use normal conditional statements. OK to both. > > > +static int ad24xx_codec_hw_params(struct snd_pcm_substream *substream, > > + struct snd_pcm_hw_params *params, > > + struct snd_soc_dai *dai) > > > + > > + /* Finally, request slots */ > > + ret = a2b_node_request_slots(adc->node, &slot_req); > > + if (ret) > > + return ret; > > Note that hw_params() can be called multiple times before starting the > audio stream, will this leak? I will take another look before sending v2. > > > + struct snd_soc_dai *dai) > > +{ > > + struct snd_soc_component *component = dai->component; > > + struct ad24xx_codec *adc = snd_soc_component_get_drvdata(component); > > + int ret; > > + > > + ret = a2b_node_free_slots(adc->node); > > + if (ret) > > + return ret; > > What if we close without having called hw_params()? Ditto. > > > +static const struct snd_soc_dai_driver ad24xx_codec_dai_drv[] = { > > + [AD24XX_DAI_I2S] = { > > + .name = "ad24xx-i2s", > > + .playback = { > > + .stream_name = "I2S Playback", > > + .channels_min = 1, > > + .channels_max = 32, > > + }, > > + .capture = { > > + .stream_name = "I2S Capture", > > + .channels_min = 1, > > + .channels_max = 32, > > + }, > > + .ops = &ad24xx_codec_dai_ops, > > + .symmetric_rate = 1, > > + }, > > +}; > > Why is this an array? It needn't be, will flatten it. > > > +static const struct regmap_config ad24xx_codec_regmap_config = { > > + .reg_bits = 8, > > + .val_bits = 8, > > + .cache_type = REGCACHE_RBTREE, > > +}; > > New code should use _MAPLE unless there's a strong reason to use > something else. OK