public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/2] Support Tegra I2S client format conversion
@ 2024-05-20 11:49 Sameer Pujar
  2024-05-20 11:49 ` [PATCH 1/2] ASoC: simple-card-utils: Split simple_fixup_sample_fmt func Sameer Pujar
  2024-05-20 11:49 ` [PATCH 2/2] ASoC: tegra: I2S client convert formats handling Sameer Pujar
  0 siblings, 2 replies; 4+ messages in thread
From: Sameer Pujar @ 2024-05-20 11:49 UTC (permalink / raw)
  To: broonie, linux-sound, alsa-devel
  Cc: linux-tegra, linux-kernel, lgirdwood, thierry.reding, jonathanh,
	mkumard, spujar

The AHUB HW modules are interconnected with CIF which are capable of
supporting Channel and Sample bit format conversion. Due to this, the
I2S Client can have different Channel and Sample bit from the hw_params()
and this config is passed from CIF port of I2S DT node which can help to
perform this conversion.

- First change to split simple_fixup_sample_fmt to support returning
  sample format value
- Second patch to support Tegra I2S client channel and sample format
  programming based on CIF port from DT node.

Mohan Kumar (2):
  ASoC: simple-card-utils: Split simple_fixup_sample_fmt func
  ASoC: tegra: I2S client convert formats handling

 include/sound/simple_card_utils.h     |  2 +
 sound/soc/generic/simple-card-utils.c | 26 +++++++---
 sound/soc/tegra/tegra210_i2s.c        | 71 +++++++++++++++++++++++++--
 sound/soc/tegra/tegra210_i2s.h        |  2 +
 4 files changed, 91 insertions(+), 10 deletions(-)

-- 
2.45.1


^ permalink raw reply	[flat|nested] 4+ messages in thread

* [PATCH 1/2] ASoC: simple-card-utils: Split simple_fixup_sample_fmt func
  2024-05-20 11:49 [PATCH 0/2] Support Tegra I2S client format conversion Sameer Pujar
@ 2024-05-20 11:49 ` Sameer Pujar
  2024-05-20 11:49 ` [PATCH 2/2] ASoC: tegra: I2S client convert formats handling Sameer Pujar
  1 sibling, 0 replies; 4+ messages in thread
From: Sameer Pujar @ 2024-05-20 11:49 UTC (permalink / raw)
  To: broonie, linux-sound, alsa-devel
  Cc: linux-tegra, linux-kernel, lgirdwood, thierry.reding, jonathanh,
	mkumard, spujar

From: Mohan Kumar <mkumard@nvidia.com>

Split the simple_fixup_sample_fmt() into two functions by adding
one more function named simple_util_get_sample_fmt() to return
the sample format value.

This is useful for drivers that wish to simply get the sample format
without setting the mask.

Signed-off-by: Mohan Kumar <mkumard@nvidia.com>
Signed-off-by: Sameer Pujar <spujar@nvidia.com>
---
 include/sound/simple_card_utils.h     |  2 ++
 sound/soc/generic/simple-card-utils.c | 26 ++++++++++++++++++++------
 2 files changed, 22 insertions(+), 6 deletions(-)

diff --git a/include/sound/simple_card_utils.h b/include/sound/simple_card_utils.h
index ad67957b7b48..2c2279d082ec 100644
--- a/include/sound/simple_card_utils.h
+++ b/include/sound/simple_card_utils.h
@@ -174,6 +174,8 @@ void simple_util_parse_convert(struct device_node *np, char *prefix,
 			       struct simple_util_data *data);
 bool simple_util_is_convert_required(const struct simple_util_data *data);
 
+int simple_util_get_sample_fmt(struct simple_util_data *data);
+
 int simple_util_parse_routing(struct snd_soc_card *card,
 				      char *prefix);
 int simple_util_parse_widgets(struct snd_soc_card *card,
diff --git a/sound/soc/generic/simple-card-utils.c b/sound/soc/generic/simple-card-utils.c
index 81077d16d22f..f1f5a1c025fc 100644
--- a/sound/soc/generic/simple-card-utils.c
+++ b/sound/soc/generic/simple-card-utils.c
@@ -13,12 +13,11 @@
 #include <sound/pcm_params.h>
 #include <sound/simple_card_utils.h>
 
-static void simple_fixup_sample_fmt(struct simple_util_data *data,
-					 struct snd_pcm_hw_params *params)
+int simple_util_get_sample_fmt(struct simple_util_data *data)
 {
 	int i;
-	struct snd_mask *mask = hw_param_mask(params,
-					      SNDRV_PCM_HW_PARAM_FORMAT);
+	int val = -EINVAL;
+
 	struct {
 		char *fmt;
 		u32 val;
@@ -33,11 +32,26 @@ static void simple_fixup_sample_fmt(struct simple_util_data *data,
 	for (i = 0; i < ARRAY_SIZE(of_sample_fmt_table); i++) {
 		if (!strcmp(data->convert_sample_format,
 			    of_sample_fmt_table[i].fmt)) {
-			snd_mask_none(mask);
-			snd_mask_set(mask, of_sample_fmt_table[i].val);
+			val = of_sample_fmt_table[i].val;
 			break;
 		}
 	}
+	return val;
+}
+EXPORT_SYMBOL_GPL(simple_util_get_sample_fmt);
+
+static void simple_fixup_sample_fmt(struct simple_util_data *data,
+				    struct snd_pcm_hw_params *params)
+{
+	int val;
+	struct snd_mask *mask = hw_param_mask(params,
+					      SNDRV_PCM_HW_PARAM_FORMAT);
+
+	val = simple_util_get_sample_fmt(data);
+	if (val >= 0) {
+		snd_mask_none(mask);
+		snd_mask_set(mask, val);
+	}
 }
 
 void simple_util_parse_convert(struct device_node *np,
-- 
2.45.1


^ permalink raw reply related	[flat|nested] 4+ messages in thread

* [PATCH 2/2] ASoC: tegra: I2S client convert formats handling
  2024-05-20 11:49 [PATCH 0/2] Support Tegra I2S client format conversion Sameer Pujar
  2024-05-20 11:49 ` [PATCH 1/2] ASoC: simple-card-utils: Split simple_fixup_sample_fmt func Sameer Pujar
@ 2024-05-20 11:49 ` Sameer Pujar
  2024-05-21 10:45   ` kernel test robot
  1 sibling, 1 reply; 4+ messages in thread
From: Sameer Pujar @ 2024-05-20 11:49 UTC (permalink / raw)
  To: broonie, linux-sound, alsa-devel
  Cc: linux-tegra, linux-kernel, lgirdwood, thierry.reding, jonathanh,
	mkumard, spujar

From: Mohan Kumar <mkumard@nvidia.com>

The AHUB HW modules are interconnected with CIF which are capable of
supporting Channel and Sample bit format conversion. Due to this, the
I2S Client can have different Channel and Sample bit from the hw_params()
and this config is passed from CIF port of I2S DT node which can help to
perform this conversion.

For e.g. HFP usecase consists of BT SCO with 1ch and 8k audio data
which needs to be converted and mixed with external codec playback and
capture path which is of 2ch and 48k format.

For HFP Playback:
  The path includes mono to stereo and 8k to 48k conversion
    _ _ _ _       _ _ _          _ _ _        _ _ _ _ _       _ _ _ _ _ _
   |       |1ch  |      | 1ch   |     |2ch   | SFC     | 2ch |           |
   |BT SCO |---->| I2Sx |------>| CIF |----->| 8k->48k |---->| Codec I2Sy|
   |_ _ _ _|     |_ _ __|client |_ _ _|audio |_ _ _ _ _|     |_ _ _ _ _ _|

For HFP Capture:
  The path includes stereo to mono and 48k to 8k conversion
    _ _ _ _ _ _       _ _ _ _ _        _ _ _         _ _ _ _       _ _ _ _
   |           | 2ch | SFC     | 2ch  |     | 1ch   |       | 1ch |       |
   | codec I2Sy|---->| 48k->8k |----->| CIF |------>| I2Sx  |---->| BT SCO|
   |_ _ _ _ _ _|     |_ _ _ _ _| audio|_ _ _|client |_ _ _ _|     |_ _ _ _|

For above two path, I2S client channel uses existing DT binding to pass
channels and format conversion in I2Sx CIF Port.

Signed-off-by: Mohan Kumar <mkumard@nvidia.com>
Signed-off-by: Sameer Pujar <spujar@nvidia.com>
---
 sound/soc/tegra/tegra210_i2s.c | 71 ++++++++++++++++++++++++++++++++--
 sound/soc/tegra/tegra210_i2s.h |  2 +
 2 files changed, 69 insertions(+), 4 deletions(-)

diff --git a/sound/soc/tegra/tegra210_i2s.c b/sound/soc/tegra/tegra210_i2s.c
index ba7fdd7405ac..454719126ad2 100644
--- a/sound/soc/tegra/tegra210_i2s.c
+++ b/sound/soc/tegra/tegra210_i2s.c
@@ -8,11 +8,13 @@
 #include <linux/device.h>
 #include <linux/mod_devicetable.h>
 #include <linux/module.h>
+#include <linux/of_graph.h>
 #include <linux/platform_device.h>
 #include <linux/pm_runtime.h>
 #include <linux/regmap.h>
 #include <sound/core.h>
 #include <sound/pcm_params.h>
+#include <sound/simple_card_utils.h>
 #include <sound/soc.h>
 #include "tegra210_i2s.h"
 #include "tegra_cif.h"
@@ -603,6 +605,7 @@ static int tegra210_i2s_hw_params(struct snd_pcm_substream *substream,
 	struct tegra210_i2s *i2s = snd_soc_dai_get_drvdata(dai);
 	unsigned int sample_size, channels, srate, val, reg, path;
 	struct tegra_cif_conf cif_conf;
+	unsigned int sample_format;
 
 	memset(&cif_conf, 0, sizeof(struct tegra_cif_conf));
 
@@ -615,28 +618,51 @@ static int tegra210_i2s_hw_params(struct snd_pcm_substream *substream,
 
 	cif_conf.audio_ch = channels;
 	cif_conf.client_ch = channels;
+	if (i2s->client_channels)
+		cif_conf.client_ch = i2s->client_channels;
 
+	/* AHUB CIF Audio bits configs */
 	switch (params_format(params)) {
+	case SNDRV_PCM_FORMAT_S8:
+		cif_conf.audio_bits = TEGRA_ACIF_BITS_8;
+		break;
+	case SNDRV_PCM_FORMAT_S16_LE:
+		cif_conf.audio_bits = TEGRA_ACIF_BITS_16;
+		break;
+	case SNDRV_PCM_FORMAT_S32_LE:
+		cif_conf.audio_bits = TEGRA_ACIF_BITS_32;
+		break;
+	default:
+		dev_err(dev, "unsupported params audio bit format!\n");
+		return -EOPNOTSUPP;
+	}
+
+	sample_format = params_format(params);
+	if (i2s->client_sample_format >= 0)
+		sample_format = i2s->client_sample_format;
+
+	/*
+	 * Format of the I2S for sending/receiving the audio
+	 * to/from external device.
+	 */
+	switch (sample_format) {
 	case SNDRV_PCM_FORMAT_S8:
 		val = I2S_BITS_8;
 		sample_size = 8;
-		cif_conf.audio_bits = TEGRA_ACIF_BITS_8;
 		cif_conf.client_bits = TEGRA_ACIF_BITS_8;
 		break;
 	case SNDRV_PCM_FORMAT_S16_LE:
 		val = I2S_BITS_16;
 		sample_size = 16;
-		cif_conf.audio_bits = TEGRA_ACIF_BITS_16;
 		cif_conf.client_bits = TEGRA_ACIF_BITS_16;
 		break;
 	case SNDRV_PCM_FORMAT_S32_LE:
 		val = I2S_BITS_32;
 		sample_size = 32;
-		cif_conf.audio_bits = TEGRA_ACIF_BITS_32;
 		cif_conf.client_bits = TEGRA_ACIF_BITS_32;
 		break;
 	default:
-		dev_err(dev, "unsupported format!\n");
+		dev_err(dev, "unsupported client bit format!\n");
 		return -EOPNOTSUPP;
 	}
 
@@ -872,6 +898,40 @@ static const struct regmap_config tegra210_i2s_regmap_config = {
 	.cache_type		= REGCACHE_FLAT,
 };
 
+/*
+ * The AHUB HW modules are interconnected with CIF which are capable of
+ * supporting Channel and Sample bit format conversion. This needs different
+ * CIF Audio and client configuration. As one of the config comes from
+ * params_channels() or params_format(), the extra configuration is passed from
+ * CIF Port of DT I2S node which can help to perform this conversion.
+ *
+ *    4ch          audio = 4ch      client = 2ch       2ch
+ *   -----> ADMAIF -----------> CIF -------------> I2S ---->
+ */
+static void tegra210_parse_client_convert(struct device *dev)
+{
+	struct tegra210_i2s *i2s = dev_get_drvdata(dev);
+	struct device_node *ports, *ep;
+	struct simple_util_data data = {};
+	int cif_port = 0;
+
+	ports = of_get_child_by_name(dev->of_node, "ports");
+	if (ports) {
+		ep = of_graph_get_endpoint_by_regs(ports, cif_port, -1);
+		if (ep) {
+			simple_util_parse_convert(ep, NULL, &data);
+			of_node_put(ep);
+		}
+		of_node_put(ports);
+	}
+
+	if (data.convert_channels)
+		i2s->client_channels = data.convert_channels;
+
+	if (data.convert_sample_format)
+		i2s->client_sample_format = simple_util_get_sample_fmt(&data);
+}
+
 static int tegra210_i2s_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
@@ -887,6 +947,7 @@ static int tegra210_i2s_probe(struct platform_device *pdev)
 	i2s->tx_mask = DEFAULT_I2S_SLOT_MASK;
 	i2s->rx_mask = DEFAULT_I2S_SLOT_MASK;
 	i2s->loopback = false;
+	i2s->client_sample_format = -EINVAL;
 
 	dev_set_drvdata(dev, i2s);
 
@@ -916,6 +977,8 @@ static int tegra210_i2s_probe(struct platform_device *pdev)
 		return PTR_ERR(i2s->regmap);
 	}
 
+	tegra210_parse_client_convert(dev);
+
 	regcache_cache_only(i2s->regmap, true);
 
 	err = devm_snd_soc_register_component(dev, &tegra210_i2s_cmpnt,
diff --git a/sound/soc/tegra/tegra210_i2s.h b/sound/soc/tegra/tegra210_i2s.h
index 030d70c45e18..fe478f3d8435 100644
--- a/sound/soc/tegra/tegra210_i2s.h
+++ b/sound/soc/tegra/tegra210_i2s.h
@@ -112,6 +112,8 @@ struct tegra210_i2s {
 	struct clk *clk_i2s;
 	struct clk *clk_sync_input;
 	struct regmap *regmap;
+	int client_sample_format;
+	unsigned int client_channels;
 	unsigned int stereo_to_mono[I2S_PATHS];
 	unsigned int mono_to_stereo[I2S_PATHS];
 	unsigned int dai_fmt;
-- 
2.45.1


^ permalink raw reply related	[flat|nested] 4+ messages in thread

* Re: [PATCH 2/2] ASoC: tegra: I2S client convert formats handling
  2024-05-20 11:49 ` [PATCH 2/2] ASoC: tegra: I2S client convert formats handling Sameer Pujar
@ 2024-05-21 10:45   ` kernel test robot
  0 siblings, 0 replies; 4+ messages in thread
From: kernel test robot @ 2024-05-21 10:45 UTC (permalink / raw)
  To: Sameer Pujar, broonie, linux-sound, alsa-devel
  Cc: oe-kbuild-all, linux-tegra, linux-kernel, lgirdwood,
	thierry.reding, jonathanh, mkumard, spujar

Hi Sameer,

kernel test robot noticed the following build warnings:

[auto build test WARNING on broonie-sound/for-next]
[also build test WARNING on tegra/for-next tiwai-sound/for-next tiwai-sound/for-linus linus/master v6.9 next-20240521]
[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/Sameer-Pujar/ASoC-simple-card-utils-Split-simple_fixup_sample_fmt-func/20240520-195311
base:   https://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git for-next
patch link:    https://lore.kernel.org/r/20240520114902.1663695-3-spujar%40nvidia.com
patch subject: [PATCH 2/2] ASoC: tegra: I2S client convert formats handling
config: arm-randconfig-r122-20240521 (https://download.01.org/0day-ci/archive/20240521/202405211805.UMAdiH0d-lkp@intel.com/config)
compiler: clang version 15.0.7 (https://github.com/llvm/llvm-project 8dfdcc7b7bf66834a761bd8de445840ef68e4d1a)
reproduce: (https://download.01.org/0day-ci/archive/20240521/202405211805.UMAdiH0d-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202405211805.UMAdiH0d-lkp@intel.com/

sparse warnings: (new ones prefixed by >>)
>> sound/soc/tegra/tegra210_i2s.c:640:23: sparse: sparse: incorrect type in assignment (different base types) @@     expected unsigned int sample_format @@     got restricted snd_pcm_format_t @@
   sound/soc/tegra/tegra210_i2s.c:640:23: sparse:     expected unsigned int sample_format
   sound/soc/tegra/tegra210_i2s.c:640:23: sparse:     got restricted snd_pcm_format_t
>> sound/soc/tegra/tegra210_i2s.c:649:14: sparse: sparse: restricted snd_pcm_format_t degrades to integer
   sound/soc/tegra/tegra210_i2s.c:654:14: sparse: sparse: restricted snd_pcm_format_t degrades to integer
   sound/soc/tegra/tegra210_i2s.c:659:14: sparse: sparse: restricted snd_pcm_format_t degrades to integer

vim +640 sound/soc/tegra/tegra210_i2s.c

   599	
   600	static int tegra210_i2s_hw_params(struct snd_pcm_substream *substream,
   601					  struct snd_pcm_hw_params *params,
   602					  struct snd_soc_dai *dai)
   603	{
   604		struct device *dev = dai->dev;
   605		struct tegra210_i2s *i2s = snd_soc_dai_get_drvdata(dai);
   606		unsigned int sample_size, channels, srate, val, reg, path;
   607		struct tegra_cif_conf cif_conf;
   608		unsigned int sample_format;
   609	
   610		memset(&cif_conf, 0, sizeof(struct tegra_cif_conf));
   611	
   612		channels = params_channels(params);
   613		if (channels < 1) {
   614			dev_err(dev, "invalid I2S %d channel configuration\n",
   615				channels);
   616			return -EINVAL;
   617		}
   618	
   619		cif_conf.audio_ch = channels;
   620		cif_conf.client_ch = channels;
   621		if (i2s->client_channels)
   622			cif_conf.client_ch = i2s->client_channels;
   623	
   624		/* AHUB CIF Audio bits configs */
   625		switch (params_format(params)) {
   626		case SNDRV_PCM_FORMAT_S8:
   627			cif_conf.audio_bits = TEGRA_ACIF_BITS_8;
   628			break;
   629		case SNDRV_PCM_FORMAT_S16_LE:
   630			cif_conf.audio_bits = TEGRA_ACIF_BITS_16;
   631			break;
   632		case SNDRV_PCM_FORMAT_S32_LE:
   633			cif_conf.audio_bits = TEGRA_ACIF_BITS_32;
   634			break;
   635		default:
   636			dev_err(dev, "unsupported params audio bit format!\n");
   637			return -EOPNOTSUPP;
   638		}
   639	
 > 640		sample_format = params_format(params);
   641		if (i2s->client_sample_format >= 0)
   642			sample_format = i2s->client_sample_format;
   643	
   644		/*
   645		 * Format of the I2S for sending/receiving the audio
   646		 * to/from external device.
   647		 */
   648		switch (sample_format) {
 > 649		case SNDRV_PCM_FORMAT_S8:
   650			val = I2S_BITS_8;
   651			sample_size = 8;
   652			cif_conf.client_bits = TEGRA_ACIF_BITS_8;
   653			break;
   654		case SNDRV_PCM_FORMAT_S16_LE:
   655			val = I2S_BITS_16;
   656			sample_size = 16;
   657			cif_conf.client_bits = TEGRA_ACIF_BITS_16;
   658			break;
   659		case SNDRV_PCM_FORMAT_S32_LE:
   660			val = I2S_BITS_32;
   661			sample_size = 32;
   662			cif_conf.client_bits = TEGRA_ACIF_BITS_32;
   663			break;
   664		default:
   665			dev_err(dev, "unsupported client bit format!\n");
   666			return -EOPNOTSUPP;
   667		}
   668	
   669		/* Program sample size */
   670		regmap_update_bits(i2s->regmap, TEGRA210_I2S_CTRL,
   671				   I2S_CTRL_BIT_SIZE_MASK, val);
   672	
   673		srate = params_rate(params);
   674	
   675		/* For playback I2S RX-CIF and for capture TX-CIF is used */
   676		if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
   677			path = I2S_RX_PATH;
   678		else
   679			path = I2S_TX_PATH;
   680	
   681		if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
   682			unsigned int max_th;
   683	
   684			/* FIFO threshold in terms of frames */
   685			max_th = (I2S_RX_FIFO_DEPTH / cif_conf.audio_ch) - 1;
   686	
   687			if (i2s->rx_fifo_th > max_th)
   688				i2s->rx_fifo_th = max_th;
   689	
   690			cif_conf.threshold = i2s->rx_fifo_th;
   691	
   692			reg = TEGRA210_I2S_RX_CIF_CTRL;
   693		} else {
   694			reg = TEGRA210_I2S_TX_CIF_CTRL;
   695		}
   696	
   697		cif_conf.mono_conv = i2s->mono_to_stereo[path];
   698		cif_conf.stereo_conv = i2s->stereo_to_mono[path];
   699	
   700		tegra_set_cif(i2s->regmap, reg, &cif_conf);
   701	
   702		return tegra210_i2s_set_timing_params(dev, sample_size, srate,
   703						      cif_conf.client_ch);
   704	}
   705	

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2024-05-21 10:46 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-05-20 11:49 [PATCH 0/2] Support Tegra I2S client format conversion Sameer Pujar
2024-05-20 11:49 ` [PATCH 1/2] ASoC: simple-card-utils: Split simple_fixup_sample_fmt func Sameer Pujar
2024-05-20 11:49 ` [PATCH 2/2] ASoC: tegra: I2S client convert formats handling Sameer Pujar
2024-05-21 10:45   ` kernel test robot

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox