Skip to contentSkip to conversation

ASoC: codecs: add support for the TI SRC4392 codec

PATCH Superseded Matt Flax 3 participants 3 messages Aug 8, 2022

Subsystems (2)

v1 of 3 Superseded Latest is v3 →

lore
Share & tools
lore

Matt Flax

author
#0 lore raw

PATCH 1/1 ASoC: codecs: add support for the TI SRC4392 codec

The src4xxx keyword is used for future capability to integrate
other codecs similar to the src4392 to the same code base.

---
 sound/soc/codecs/Kconfig       |  13 +
 sound/soc/codecs/Makefile      |   4 +
 sound/soc/codecs/src4xxx-i2c.c |  55 ++++
 sound/soc/codecs/src4xxx.c     | 538 +++++++++++++++++++++++++++++++++
 sound/soc/codecs/src4xxx.h     | 115 +++++++
 5 files changed, 725 insertions(+)
 create mode 100644 sound/soc/codecs/src4xxx-i2c.c
 create mode 100644 sound/soc/codecs/src4xxx.c
 create mode 100644 sound/soc/codecs/src4xxx.h
sound/soc/codecs/Kconfig +13 -0
index d16b4efb88a7..44c19d973ef3 100644
@@ -205,6 +205,7 @@ config SND_SOC_ALL_CODECS
 	imply SND_SOC_SIMPLE_AMPLIFIER
 	imply SND_SOC_SIMPLE_MUX
 	imply SND_SOC_SPDIF
+	imply SND_SOC_SRC4XXX_I2C
 	imply SND_SOC_SSM2305
 	imply SND_SOC_SSM2518
 	imply SND_SOC_SSM2602_SPI
@@ -1471,6 +1472,18 @@ config SND_SOC_SIMPLE_MUX
 config SND_SOC_SPDIF
 	tristate "S/PDIF CODEC"
 
+config SND_SOC_SRC4XXX_I2C
+	tristate
+	depends on I2C
+	select SND_SOC_SRC4XXX
+
+config SND_SOC_SRC4XXX
+	tristate "Texas Instruments SRC4XXX DIR/DIT and SRC codecs"
+	help
+		Enable support for the TI SRC4XXX family of codecs. These include the
+		scr4392 which has digital receivers, transmitters, and
+		a sample rate converter, including numerous ports.
+
 config SND_SOC_SSM2305
 	tristate "Analog Devices SSM2305 Class-D Amplifier"
 	help
sound/soc/codecs/Makefile +4 -0
index 92fd441d426a..a599b727c65b 100644
@@ -231,6 +231,8 @@ snd-soc-sigmadsp-regmap-objs := sigmadsp-regmap.o
 snd-soc-si476x-objs := si476x.o
 snd-soc-spdif-tx-objs := spdif_transmitter.o
 snd-soc-spdif-rx-objs := spdif_receiver.o
+snd-soc-src4xxx-objs := src4xxx.o
+snd-soc-src4xxx-i2c-objs := src4xxx-i2c.o
 snd-soc-ssm2305-objs := ssm2305.o
 snd-soc-ssm2518-objs := ssm2518.o
 snd-soc-ssm2602-objs := ssm2602.o
@@ -579,6 +581,8 @@ obj-$(CONFIG_SND_SOC_SIGMADSP_I2C)	+= snd-soc-sigmadsp-i2c.o
 obj-$(CONFIG_SND_SOC_SIGMADSP_REGMAP)	+= snd-soc-sigmadsp-regmap.o
 obj-$(CONFIG_SND_SOC_SI476X)	+= snd-soc-si476x.o
 obj-$(CONFIG_SND_SOC_SPDIF)	+= snd-soc-spdif-rx.o snd-soc-spdif-tx.o
+obj-$(CONFIG_SND_SOC_SRC4XXX)	+= snd-soc-src4xxx.o
+obj-$(CONFIG_SND_SOC_SRC4XXX_I2C)	+= snd-soc-src4xxx-i2c.o
 obj-$(CONFIG_SND_SOC_SSM2305)	+= snd-soc-ssm2305.o
 obj-$(CONFIG_SND_SOC_SSM2518)	+= snd-soc-ssm2518.o
 obj-$(CONFIG_SND_SOC_SSM2602)	+= snd-soc-ssm2602.o
sound/soc/codecs/src4xxx-i2c.c new file +55 -0

55 lines not on this page · raw message

sound/soc/codecs/src4xxx.c new file +538 -0

538 lines not on this page · raw message

sound/soc/codecs/src4xxx.h new file +115 -0

115 lines not on this page · raw message

--
2.34.1

maintainer
#1 lore raw
Quoted 2 lines · Matt Flax

The src4xxx keyword is used for future capability to integrate
other codecs similar to the src4392 to the same code base.

Formating here is really weird.

sound/soc/codecs/Kconfig config SND_SOC_SIMPLE_MUX · line 1485

Quoted 5 lines
sound/soc/codecs/Kconfig +5 -0
+	tristate "Texas Instruments SRC4XXX DIR/DIT and SRC codecs"
+	help
+		Enable support for the TI SRC4XXX family of codecs. These include the
+		scr4392 which has digital receivers, transmitters, and
+		a sample rate converter, including numerous ports.

Please keep this to 80 columns.

sound/soc/codecs/src4xxx-i2c.c line 6

Quoted 7 lines
sound/soc/codecs/src4xxx-i2c.c new file +6 -0
@@ -0,0 +1,55 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Driver for SRC4XXX codecs
+ *
+ * Copyright 2021-2022 Deqx Pty Ltd
+ * Author: Natt Flax <[email protected]>

Please make the entire comment a C++ one so things look more intentional.

sound/soc/codecs/src4xxx-i2c.c line 39

Quoted 5 lines
sound/soc/codecs/src4xxx-i2c.c new file +5 -0
+static const struct of_device_id src4xxx_of_match[] = {
+	{ .compatible = "ti,src4392", },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, src4xxx_of_match);

This is adding a DT binding, that binding should be documented.

sound/soc/codecs/src4xxx.c line 50

Quoted 2 lines
sound/soc/codecs/src4xxx.c new file +2 -0
+static const struct snd_kcontrol_new dit_mux_control =
+	SOC_DAPM_ENUM("Dig. Out src", dit_mux_enum);

Please write words out fully as is idiomatic for ALSA.

sound/soc/codecs/src4xxx.c line 64

Quoted 7 lines
sound/soc/codecs/src4xxx.c new file +7 -0
+static const char * const src_mclk_text[] = {
+	"Master (MCLK)", "Master (RXCLKI)", "Recovered receiver clk",
+};
+static SOC_ENUM_SINGLE_DECL(src_mclk_enum, SRC4XXX_SCR_CTL_2D, 2,
+	src_mclk_text);
+static const struct snd_kcontrol_new src_mclk_control =
+	SOC_DAPM_ENUM("SRC master clock select", src_mclk_enum);

I would normally expect this to be controlled by the machine driver - why expose it to userspace?

sound/soc/codecs/src4xxx.c line 172

Quoted 8 lines
sound/soc/codecs/src4xxx.c new file +8 -0
+static int src4xxx_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt)
+{
+	struct snd_soc_component *component = dai->component;
+	struct src4xxx *src4xxx = snd_soc_component_get_drvdata(component);
+	unsigned int ctrl;
+
+	dev_info(dai->dev, "__func__ enter 0x%x id=%d\n",
+		fmt, dai->id);

This is way too noisy, in general this sort of print is redundant and it certainly shouldn't be something like dev_info() which is often printed to the console by default. In general the driver should be silent in normal operation, especially on the console.

sound/soc/codecs/src4xxx.c line 192

Quoted 6 lines
sound/soc/codecs/src4xxx.c new file +6 -0
+	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+	case SND_SOC_DAIFMT_I2S:
+	ctrl |= SRC4XXX_BUS_I2S;
+		break;
+	case SND_SOC_DAIFMT_LEFT_J:
+		ctrl |= SRC4XXX_BUS_LEFT_J;

The indentation here is weird and inconsistent...

sound/soc/codecs/src4xxx.c line 240

Quoted 5 lines
sound/soc/codecs/src4xxx.c new file +5 -0
+	int reg = SRC4XXX_PORTA_CTL_04;
+	int ret;
+
+	if (dai->id == SRC4XXX_PORTB)
+		reg = SRC4XXX_PORTB_CTL_06;

Write a switch statement to select the register, it would be a lot clearer.

sound/soc/codecs/src4xxx.c line 274

Quoted 3 lines
sound/soc/codecs/src4xxx.c new file +3 -0
+		if (ret) {
+			dev_err(component->dev,
+		"Couldn't set the TX's div register to %d << %d = 0x%x\n",

Again really strange indentation.

sound/soc/codecs/src4xxx.c line 459

Quoted 8 lines
sound/soc/codecs/src4xxx.c new file +8 -0
+	/* enable the BTI and TSLIP interrupts */
+	ret = regmap_update_bits(src4xxx->regmap, SRC4XXX_SRC_DIT_IRQ_MSK_0B,
+		SRC4XXX_SRC_BTI_EN | SRC4XXX_SRC_TSLIP_EN,
+		SRC4XXX_SRC_BTI_EN | SRC4XXX_SRC_TSLIP_EN);
+	if (ret < 0)
+		dev_err(dev,
+			"Failed to enable BTI and TSLIP interrupts : %d\n",
+			ret);

The driver never requests an interrupt?

sound/soc/codecs/src4xxx.c line 481

Quoted 5 lines
sound/soc/codecs/src4xxx.c new file +5 -0
+	if (ret == 0)
+		dev_info(dev, "src4392 probe ok %d\n", ret);
+	return ret;
+}
+EXPORT_SYMBOL(src4xxx_probe);

This is using _GPL() APIs from ASoC and regmap, it should be _GPL too.

sound/soc/codecs/src4xxx.c line 487

Quoted 5 lines
sound/soc/codecs/src4xxx.c new file +5 -0
+void src4xxx_remove(struct device *dev)
+{
+	dev_info(dev, "__func__\n");
+}
+EXPORT_SYMBOL(src4xxx_remove);

This is just noise, remove the function entirely.

#2 lore raw
In reply to Matt Flax
Thank you for the patch! Perhaps something to improve:

Hi Matt,

Thank you for the patch! Perhaps something to improve:

[auto build test WARNING on broonie-sound/for-next]
[also build test WARNING on tiwai-sound/for-next linus/master v5.19 next-20220808] [If your patch is applied to the wrong git tree, kindly drop us a note. And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Matt-Flax/ASoC-codecs-add-support-for-the-TI-SRC4392-codec/20220808-152201
base:   https://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git for-next
config: riscv-randconfig-r042-20220808 (https://download.01.org/0day-ci/archive/20220809/[email protected]/config)
compiler: clang version 16.0.0 (https://github.com/llvm/llvm-project 5f1c7e2cc5a3c07cbc2412e851a7283c1841f520)

reproduce (this is a W=1 build):
wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross chmod +x ~/bin/make.cross
# install riscv cross compiling tool for clang build
# apt-get install binutils-riscv64-linux-gnu
# https://github.com/intel-lab-lkp/linux/commit/34effe739961486f8c9451714111ee6ad4df8dbd
git remote add linux-review https://github.com/intel-lab-lkp/linux
git fetch --no-tags linux-review Matt-Flax/ASoC-codecs-add-support-for-the-TI-SRC4392-codec/20220808-152201 git checkout 34effe739961486f8c9451714111ee6ad4df8dbd
# save the config file
mkdir build_dir && cp config build_dir/.config
COMPILER_INSTALL_PATH=$HOME/0day COMPILER=clang make.cross W=1 O=build_dir ARCH=riscv SHELL=/bin/bash sound/soc/codecs/

If you fix the issue, kindly add following tag where applicable

All warnings (new ones prefixed by >>):

>> sound/soc/codecs/src4xxx.c:292:3: warning: variable 'd' is used uninitialized whenever switch default is taken [-Wsometimes-uninitialized]
                   default:
                   ^~~~~~~
   sound/soc/codecs/src4xxx.c:309:59: note: uninitialized use occurs here
                   ret = regmap_write(src4xxx->regmap, SRC4XXX_RCV_PLL_11, d);
                                                                           ^
   sound/soc/codecs/src4xxx.c:235:20: note: initialize the variable 'd' to silence this warning
           int val, pj, jd, d;
                             ^
                              = 0
>> sound/soc/codecs/src4xxx.c:292:3: warning: variable 'jd' is used uninitialized whenever switch default is taken [-Wsometimes-uninitialized]
                   default:
                   ^~~~~~~
   sound/soc/codecs/src4xxx.c:304:59: note: uninitialized use occurs here
                   ret = regmap_write(src4xxx->regmap, SRC4XXX_RCV_PLL_10, jd);
                                                                           ^~
   sound/soc/codecs/src4xxx.c:235:17: note: initialize the variable 'jd' to silence this warning
           int val, pj, jd, d;
                          ^
                           = 0
>> sound/soc/codecs/src4xxx.c:292:3: warning: variable 'pj' is used uninitialized whenever switch default is taken [-Wsometimes-uninitialized]
                   default:
                   ^~~~~~~
   sound/soc/codecs/src4xxx.c:299:59: note: uninitialized use occurs here
                   ret = regmap_write(src4xxx->regmap, SRC4XXX_RCV_PLL_0F, pj);
                                                                           ^~
   sound/soc/codecs/src4xxx.c:235:13: note: initialize the variable 'pj' to silence this warning
           int val, pj, jd, d;
                      ^
                       = 0

3 warnings generated.

vim +/d +292 sound/soc/codecs/src4xxx.c

227
228 static int src4xxx_hw_params(struct snd_pcm_substream *substream,
229 struct snd_pcm_hw_params *params,
230 struct snd_soc_dai *dai)
231 {
232 struct snd_soc_component *component = dai->component;
233 struct src4xxx *src4xxx = snd_soc_component_get_drvdata(component);
234 unsigned int mclk_div;
235 int val, pj, jd, d;
236 int reg = SRC4XXX_PORTA_CTL_04;
237 int ret;
238
239 if (dai->id == SRC4XXX_PORTB)
240 reg = SRC4XXX_PORTB_CTL_06;
241
242 dev_info(dai->dev, "__func__ enter for dai %d\n", dai->id);
243
244 if (src4xxx->master[dai->id]) {
245 mclk_div = src4xxx->mclk_hz/params_rate(params);
246 if (src4xxx->mclk_hz != mclk_div*params_rate(params)) {
247 dev_err(component->dev,
248 "mclk %d / rate %d has a remainder.\n",
249 src4xxx->mclk_hz, params_rate(params));
250 return -EINVAL;
251 }
252
253 dev_info(dai->dev, "__func__ mclk %d rate %d div %d\n",
254 src4xxx->mclk_hz, params_rate(params), mclk_div);
255 val = ((int)mclk_div - 128) / 128;
256 dev_info(dai->dev,
257 "__func__ register value = %d\n", val);
258 if ((val < 0) | (val > 3)) {
259 dev_err(component->dev,
260 "div register setting %d is out of range\n",
261 val);
262 dev_err(component->dev,
263 "unsupported sample rate %d Hz for the master clock of %d Hz\n",
264 params_rate(params), src4xxx->mclk_hz);
265 return -EINVAL;
266 }
267
268 /* set the TX DIV */
269 ret = regmap_update_bits(src4xxx->regmap,
270 SRC4XXX_TX_CTL_07, SRC4XXX_TX_MCLK_DIV_MASK,
271 val<<SRC4XXX_TX_MCLK_DIV_SHIFT);
272 if (ret) {
273 dev_err(component->dev,
274 "Couldn't set the TX's div register to %d << %d = 0x%x\n",
275 val, SRC4XXX_TX_MCLK_DIV_SHIFT,
276 val<<SRC4XXX_TX_MCLK_DIV_SHIFT);
277 return ret;
278 }
279
280 /* set the PLL for the digital receiver */
281 switch (src4xxx->mclk_hz) {
282 case 24576000:
283 pj = 0x22;
284 jd = 0x00;
285 d = 0x00;
286 break;
287 case 22579200:
288 pj = 0x22;
289 jd = 0x1b;
290 d = 0xa3;
291 break;

 > 292			default:

293 /* don't error out here,
294 * other parts of the chip are still functional
295 */
296 dev_info(component->dev,
297 "Couldn't set the RCV PLL as this master clock rate is unknown\n");
298 }
299 ret = regmap_write(src4xxx->regmap, SRC4XXX_RCV_PLL_0F, pj);
300 if (ret < 0)
301 dev_err(component->dev,
302 "Failed to update PLL register 0x%x\n",
303 SRC4XXX_RCV_PLL_0F);
304 ret = regmap_write(src4xxx->regmap, SRC4XXX_RCV_PLL_10, jd);
305 if (ret < 0)
306 dev_err(component->dev,
307 "Failed to update PLL register 0x%x\n",
308 SRC4XXX_RCV_PLL_10);
309 ret = regmap_write(src4xxx->regmap, SRC4XXX_RCV_PLL_11, d);
310 if (ret < 0)
311 dev_err(component->dev,
312 "Failed to update PLL register 0x%x\n",
313 SRC4XXX_RCV_PLL_11);
314
315 ret = regmap_update_bits(src4xxx->regmap,
316 SRC4XXX_TX_CTL_07, SRC4XXX_TX_MCLK_DIV_MASK,
317 val<<SRC4XXX_TX_MCLK_DIV_SHIFT);
318 if (ret < 0) {
319 dev_err(component->dev,
320 "Couldn't set the TX's div register to %d << %d = 0x%x\n",
321 val, SRC4XXX_TX_MCLK_DIV_SHIFT,
322 val<<SRC4XXX_TX_MCLK_DIV_SHIFT);
323 return ret;
324 }
325
326 return regmap_update_bits(src4xxx->regmap, reg,
327 SRC4XXX_MCLK_DIV_MASK, val);
328 } else
329 dev_info(dai->dev, "not setting up MCLK as not master\n");
330
331 return 0;
332 };
333

Signature · 2 lines
0-DAY CI Kernel Test Service
https://01.org/lkp