linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v2] ASoC: amd: acp: Add TDM support for acp i2s stream
@ 2022-08-05  6:04 Venkata Prasad Potturu
  2022-08-07  7:05 ` kernel test robot
  2022-08-16 13:48 ` Mark Brown
  0 siblings, 2 replies; 3+ messages in thread
From: Venkata Prasad Potturu @ 2022-08-05  6:04 UTC (permalink / raw)
  To: broonie, alsa-devel
  Cc: vsujithkumar.reddy, Vijendar.Mukunda, Basavaraj.Hiregoudar,
	Sunil-kumar.Dommati, ssabakar, Venkata Prasad Potturu,
	Liam Girdwood, Jaroslav Kysela, Takashi Iwai,
	V sujith kumar Reddy, Ajit Kumar Pandey, open list

Add callback and code changes to enable ACP I2S controller in TDM
mode. Add new fields in acp_stream and acp_dev_data struct to configure
tdm related registers for ACP i2s controllers.

Signed-off-by: Venkata Prasad Potturu <venkataprasad.potturu@amd.com>
---

Depends on:-
    -- https://patchwork.kernel.org/project/alsa-devel/patch/20220804072556.601396-1-venkataprasad.potturu@amd.com/
    -- https://patchwork.kernel.org/project/alsa-devel/patch/20220801063501.51439-1-venkataprasad.potturu@amd.com/

Changes since v1:
    -- Add spin lock where linked list is referring.
    
 sound/soc/amd/acp/acp-i2s.c | 80 ++++++++++++++++++++++++++++++++++++-
 sound/soc/amd/acp/amd.h     | 12 ++++++
 2 files changed, 91 insertions(+), 1 deletion(-)

diff --git a/sound/soc/amd/acp/acp-i2s.c b/sound/soc/amd/acp/acp-i2s.c
index 393f729ef561..ac416572db0d 100644
--- a/sound/soc/amd/acp/acp-i2s.c
+++ b/sound/soc/amd/acp/acp-i2s.c
@@ -25,6 +25,65 @@
 
 #define DRV_NAME "acp_i2s_playcap"
 
+static int acp_i2s_set_fmt(struct snd_soc_dai *cpu_dai,
+			   unsigned int fmt)
+{
+	struct acp_dev_data *adata = snd_soc_dai_get_drvdata(cpu_dai);
+	int mode;
+
+	mode = fmt & SND_SOC_DAIFMT_FORMAT_MASK;
+	switch (mode) {
+	case SND_SOC_DAIFMT_I2S:
+		adata->tdm_mode = TDM_DISABLE;
+		break;
+	case SND_SOC_DAIFMT_DSP_A:
+		adata->tdm_mode = TDM_ENABLE;
+		break;
+	default:
+		return -EINVAL;
+	}
+	return 0;
+}
+
+static int acp_i2s_set_tdm_slot(struct snd_soc_dai *dai, u32 tx_mask, u32 rx_mask,
+				int slots, int slot_width)
+{
+	struct device *dev = dai->component->dev;
+	struct acp_dev_data *adata = snd_soc_dai_get_drvdata(dai);
+	struct acp_stream *stream;
+	int slot_len;
+
+	switch (slot_width) {
+	case SLOT_WIDTH_8:
+		slot_len = 8;
+		break;
+	case SLOT_WIDTH_16:
+		slot_len = 16;
+		break;
+	case SLOT_WIDTH_24:
+		slot_len = 24;
+		break;
+	case SLOT_WIDTH_32:
+		slot_len = 0;
+		break;
+	default:
+		dev_err(dev, "Unsupported bitdepth %d\n", slot_width);
+		return -EINVAL;
+	}
+
+	spin_lock_irq(&adata->acp_lock);
+	list_for_each_entry(stream, &adata->stream_list, list) {
+		if (tx_mask && stream->dir == SNDRV_PCM_STREAM_PLAYBACK)
+			adata->tdm_tx_fmt[stream->dai_id - 1] =
+					FRM_LEN | (slots << 15) | (slot_len << 18);
+		else if (rx_mask && stream->dir == SNDRV_PCM_STREAM_CAPTURE)
+			adata->tdm_rx_fmt[stream->dai_id - 1] =
+					FRM_LEN | (slots << 15) | (slot_len << 18);
+	}
+	spin_unlock_irq(&adata->acp_lock);
+	return 0;
+}
+
 static int acp_i2s_hwparams(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params,
 			    struct snd_soc_dai *dai)
 {
@@ -33,7 +92,7 @@ static int acp_i2s_hwparams(struct snd_pcm_substream *substream, struct snd_pcm_
 	struct acp_resource *rsrc;
 	u32 val;
 	u32 xfer_resolution;
-	u32 reg_val;
+	u32 reg_val, fmt_reg, tdm_fmt;
 	u32 lrclk_div_val, bclk_div_val;
 
 	adata = snd_soc_dai_get_drvdata(dai);
@@ -62,12 +121,15 @@ static int acp_i2s_hwparams(struct snd_pcm_substream *substream, struct snd_pcm_
 		switch (dai->driver->id) {
 		case I2S_BT_INSTANCE:
 			reg_val = ACP_BTTDM_ITER;
+			fmt_reg = ACP_BTTDM_TXFRMT;
 			break;
 		case I2S_SP_INSTANCE:
 			reg_val = ACP_I2STDM_ITER;
+			fmt_reg = ACP_I2STDM_TXFRMT;
 			break;
 		case I2S_HS_INSTANCE:
 			reg_val = ACP_HSTDM_ITER;
+			fmt_reg = ACP_HSTDM_TXFRMT;
 			break;
 		default:
 			dev_err(dev, "Invalid dai id %x\n", dai->driver->id);
@@ -77,12 +139,15 @@ static int acp_i2s_hwparams(struct snd_pcm_substream *substream, struct snd_pcm_
 		switch (dai->driver->id) {
 		case I2S_BT_INSTANCE:
 			reg_val = ACP_BTTDM_IRER;
+			fmt_reg = ACP_BTTDM_RXFRMT;
 			break;
 		case I2S_SP_INSTANCE:
 			reg_val = ACP_I2STDM_IRER;
+			fmt_reg = ACP_I2STDM_RXFRMT;
 			break;
 		case I2S_HS_INSTANCE:
 			reg_val = ACP_HSTDM_IRER;
+			fmt_reg = ACP_HSTDM_RXFRMT;
 			break;
 		default:
 			dev_err(dev, "Invalid dai id %x\n", dai->driver->id);
@@ -95,6 +160,16 @@ static int acp_i2s_hwparams(struct snd_pcm_substream *substream, struct snd_pcm_
 	val = val | (xfer_resolution  << 3);
 	writel(val, adata->acp_base + reg_val);
 
+	if (adata->tdm_mode) {
+		val = readl(adata->acp_base + reg_val);
+		writel(val | BIT(1), adata->acp_base + reg_val);
+		if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+			tdm_fmt = adata->tdm_tx_fmt[dai->driver->id - 1];
+		else
+			tdm_fmt = adata->tdm_rx_fmt[dai->driver->id - 1];
+		writel(tdm_fmt, adata->acp_base + fmt_reg);
+	}
+
 	if (rsrc->soc_mclk) {
 		switch (params_format(params)) {
 		case SNDRV_PCM_FORMAT_S16_LE:
@@ -443,6 +518,7 @@ static int acp_i2s_startup(struct snd_pcm_substream *substream, struct snd_soc_d
 	stream->id = dai->driver->id + dir;
 	stream->dai_id = dai->driver->id;
 	stream->irq_bit = irq_bit;
+	stream->dir = substream->stream;
 
 	return 0;
 }
@@ -452,6 +528,8 @@ const struct snd_soc_dai_ops asoc_acp_cpu_dai_ops = {
 	.hw_params = acp_i2s_hwparams,
 	.prepare = acp_i2s_prepare,
 	.trigger = acp_i2s_trigger,
+	.set_fmt = acp_i2s_set_fmt,
+	.set_tdm_slot = acp_i2s_set_tdm_slot,
 };
 EXPORT_SYMBOL_NS_GPL(asoc_acp_cpu_dai_ops, SND_SOC_ACP_COMMON);
 
diff --git a/sound/soc/amd/acp/amd.h b/sound/soc/amd/acp/amd.h
index be8bb8247c4e..5f2119f42271 100644
--- a/sound/soc/amd/acp/amd.h
+++ b/sound/soc/amd/acp/amd.h
@@ -84,6 +84,14 @@
 
 #define ACP_MAX_STREAM			8
 
+#define TDM_ENABLE	1
+#define TDM_DISABLE	0
+
+#define SLOT_WIDTH_8	0x8
+#define SLOT_WIDTH_16	0x10
+#define SLOT_WIDTH_24	0x18
+#define SLOT_WIDTH_32	0x20
+
 struct acp_chip_info {
 	char *name;		/* Platform name */
 	unsigned int acp_rev;	/* ACP Revision id */
@@ -96,6 +104,7 @@ struct acp_stream {
 	int irq_bit;
 	int dai_id;
 	int id;
+	int dir;
 	u64 bytescount;
 	u32 reg_offset;
 	u32 pte_offset;
@@ -120,6 +129,7 @@ struct acp_dev_data {
 	void __iomem *acp_base;
 	unsigned int i2s_irq;
 
+	bool tdm_mode;
 	/* SOC specific dais */
 	struct snd_soc_dai_driver *dai_driver;
 	int num_dai;
@@ -134,6 +144,8 @@ struct acp_dev_data {
 	u32 lrclk_div;
 
 	struct acp_resource *rsrc;
+	u32 tdm_tx_fmt[3];
+	u32 tdm_rx_fmt[3];
 };
 
 union acp_i2stdm_mstrclkgen {
-- 
2.25.1


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

* Re: [PATCH v2] ASoC: amd: acp: Add TDM support for acp i2s stream
  2022-08-05  6:04 [PATCH v2] ASoC: amd: acp: Add TDM support for acp i2s stream Venkata Prasad Potturu
@ 2022-08-07  7:05 ` kernel test robot
  2022-08-16 13:48 ` Mark Brown
  1 sibling, 0 replies; 3+ messages in thread
From: kernel test robot @ 2022-08-07  7:05 UTC (permalink / raw)
  To: Venkata Prasad Potturu, broonie, alsa-devel
  Cc: kbuild-all, vsujithkumar.reddy, Vijendar.Mukunda,
	Basavaraj.Hiregoudar, Sunil-kumar.Dommati, ssabakar,
	Venkata Prasad Potturu, Liam Girdwood, Jaroslav Kysela,
	Takashi Iwai, Ajit Kumar Pandey, open list

Hi Venkata,

Thank you for the patch! Yet something to improve:

[auto build test ERROR on broonie-sound/for-next]
[also build test ERROR on linus/master next-20220805]
[cannot apply to v5.19]
[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/Venkata-Prasad-Potturu/ASoC-amd-acp-Add-TDM-support-for-acp-i2s-stream/20220805-140248
base:   https://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git for-next
config: x86_64-allmodconfig (https://download.01.org/0day-ci/archive/20220807/202208071454.7YeHuTDb-lkp@intel.com/config)
compiler: gcc-11 (Debian 11.3.0-3) 11.3.0
reproduce (this is a W=1 build):
        # https://github.com/intel-lab-lkp/linux/commit/c603f9570621784501d7ce7f5099be37983cb810
        git remote add linux-review https://github.com/intel-lab-lkp/linux
        git fetch --no-tags linux-review Venkata-Prasad-Potturu/ASoC-amd-acp-Add-TDM-support-for-acp-i2s-stream/20220805-140248
        git checkout c603f9570621784501d7ce7f5099be37983cb810
        # save the config file
        mkdir build_dir && cp config build_dir/.config
        make W=1 O=build_dir ARCH=x86_64 SHELL=/bin/bash sound/soc/

If you fix the issue, kindly add following tag where applicable
Reported-by: kernel test robot <lkp@intel.com>

All errors (new ones prefixed by >>):

   sound/soc/amd/acp/acp-i2s.c: In function 'acp_i2s_set_tdm_slot':
>> sound/soc/amd/acp/acp-i2s.c:74:29: error: 'struct acp_dev_data' has no member named 'acp_lock'
      74 |         spin_lock_irq(&adata->acp_lock);
         |                             ^~
   In file included from include/linux/kernel.h:21,
                    from arch/x86/include/asm/percpu.h:27,
                    from arch/x86/include/asm/current.h:6,
                    from include/linux/sched.h:12,
                    from include/linux/ratelimit.h:6,
                    from include/linux/dev_printk.h:16,
                    from include/linux/device.h:15,
                    from include/linux/platform_device.h:13,
                    from sound/soc/amd/acp/acp-i2s.c:15:
   sound/soc/amd/acp/acp-i2s.c:75:43: error: 'struct acp_dev_data' has no member named 'stream_list'
      75 |         list_for_each_entry(stream, &adata->stream_list, list) {
         |                                           ^~
   include/linux/container_of.h:18:33: note: in definition of macro 'container_of'
      18 |         void *__mptr = (void *)(ptr);                                   \
         |                                 ^~~
   include/linux/list.h:531:9: note: in expansion of macro 'list_entry'
     531 |         list_entry((ptr)->next, type, member)
         |         ^~~~~~~~~~
   include/linux/list.h:674:20: note: in expansion of macro 'list_first_entry'
     674 |         for (pos = list_first_entry(head, typeof(*pos), member);        \
         |                    ^~~~~~~~~~~~~~~~
   sound/soc/amd/acp/acp-i2s.c:75:9: note: in expansion of macro 'list_for_each_entry'
      75 |         list_for_each_entry(stream, &adata->stream_list, list) {
         |         ^~~~~~~~~~~~~~~~~~~
   In file included from include/linux/bits.h:22,
                    from include/linux/ratelimit_types.h:5,
                    from include/linux/ratelimit.h:5,
                    from include/linux/dev_printk.h:16,
                    from include/linux/device.h:15,
                    from include/linux/platform_device.h:13,
                    from sound/soc/amd/acp/acp-i2s.c:15:
   sound/soc/amd/acp/acp-i2s.c:75:43: error: 'struct acp_dev_data' has no member named 'stream_list'
      75 |         list_for_each_entry(stream, &adata->stream_list, list) {
         |                                           ^~
   include/linux/build_bug.h:78:56: note: in definition of macro '__static_assert'
      78 | #define __static_assert(expr, msg, ...) _Static_assert(expr, msg)
         |                                                        ^~~~
   include/linux/container_of.h:19:9: note: in expansion of macro 'static_assert'
      19 |         static_assert(__same_type(*(ptr), ((type *)0)->member) ||       \
         |         ^~~~~~~~~~~~~
   include/linux/container_of.h:19:23: note: in expansion of macro '__same_type'
      19 |         static_assert(__same_type(*(ptr), ((type *)0)->member) ||       \
         |                       ^~~~~~~~~~~
   include/linux/list.h:520:9: note: in expansion of macro 'container_of'
     520 |         container_of(ptr, type, member)
         |         ^~~~~~~~~~~~
   include/linux/list.h:531:9: note: in expansion of macro 'list_entry'
     531 |         list_entry((ptr)->next, type, member)
         |         ^~~~~~~~~~
   include/linux/list.h:674:20: note: in expansion of macro 'list_first_entry'
     674 |         for (pos = list_first_entry(head, typeof(*pos), member);        \
         |                    ^~~~~~~~~~~~~~~~
   sound/soc/amd/acp/acp-i2s.c:75:9: note: in expansion of macro 'list_for_each_entry'
      75 |         list_for_each_entry(stream, &adata->stream_list, list) {
         |         ^~~~~~~~~~~~~~~~~~~
   include/linux/container_of.h:19:54: error: 'struct acp_stream' has no member named 'list'
      19 |         static_assert(__same_type(*(ptr), ((type *)0)->member) ||       \
         |                                                      ^~
   include/linux/build_bug.h:78:56: note: in definition of macro '__static_assert'
      78 | #define __static_assert(expr, msg, ...) _Static_assert(expr, msg)
         |                                                        ^~~~
   include/linux/container_of.h:19:9: note: in expansion of macro 'static_assert'
      19 |         static_assert(__same_type(*(ptr), ((type *)0)->member) ||       \
         |         ^~~~~~~~~~~~~
   include/linux/container_of.h:19:23: note: in expansion of macro '__same_type'
      19 |         static_assert(__same_type(*(ptr), ((type *)0)->member) ||       \
         |                       ^~~~~~~~~~~
   include/linux/list.h:520:9: note: in expansion of macro 'container_of'
     520 |         container_of(ptr, type, member)
         |         ^~~~~~~~~~~~
   include/linux/list.h:531:9: note: in expansion of macro 'list_entry'
     531 |         list_entry((ptr)->next, type, member)
         |         ^~~~~~~~~~
   include/linux/list.h:674:20: note: in expansion of macro 'list_first_entry'
     674 |         for (pos = list_first_entry(head, typeof(*pos), member);        \
         |                    ^~~~~~~~~~~~~~~~
   sound/soc/amd/acp/acp-i2s.c:75:9: note: in expansion of macro 'list_for_each_entry'
      75 |         list_for_each_entry(stream, &adata->stream_list, list) {
         |         ^~~~~~~~~~~~~~~~~~~
   sound/soc/amd/acp/acp-i2s.c:75:43: error: 'struct acp_dev_data' has no member named 'stream_list'
      75 |         list_for_each_entry(stream, &adata->stream_list, list) {
         |                                           ^~
   include/linux/build_bug.h:78:56: note: in definition of macro '__static_assert'
      78 | #define __static_assert(expr, msg, ...) _Static_assert(expr, msg)
         |                                                        ^~~~
   include/linux/container_of.h:19:9: note: in expansion of macro 'static_assert'
      19 |         static_assert(__same_type(*(ptr), ((type *)0)->member) ||       \
         |         ^~~~~~~~~~~~~
   include/linux/container_of.h:20:23: note: in expansion of macro '__same_type'
      20 |                       __same_type(*(ptr), void),                        \
         |                       ^~~~~~~~~~~
   include/linux/list.h:520:9: note: in expansion of macro 'container_of'
     520 |         container_of(ptr, type, member)
         |         ^~~~~~~~~~~~
   include/linux/list.h:531:9: note: in expansion of macro 'list_entry'
     531 |         list_entry((ptr)->next, type, member)
         |         ^~~~~~~~~~
   include/linux/list.h:674:20: note: in expansion of macro 'list_first_entry'


vim +74 sound/soc/amd/acp/acp-i2s.c

    47	
    48	static int acp_i2s_set_tdm_slot(struct snd_soc_dai *dai, u32 tx_mask, u32 rx_mask,
    49					int slots, int slot_width)
    50	{
    51		struct device *dev = dai->component->dev;
    52		struct acp_dev_data *adata = snd_soc_dai_get_drvdata(dai);
    53		struct acp_stream *stream;
    54		int slot_len;
    55	
    56		switch (slot_width) {
    57		case SLOT_WIDTH_8:
    58			slot_len = 8;
    59			break;
    60		case SLOT_WIDTH_16:
    61			slot_len = 16;
    62			break;
    63		case SLOT_WIDTH_24:
    64			slot_len = 24;
    65			break;
    66		case SLOT_WIDTH_32:
    67			slot_len = 0;
    68			break;
    69		default:
    70			dev_err(dev, "Unsupported bitdepth %d\n", slot_width);
    71			return -EINVAL;
    72		}
    73	
  > 74		spin_lock_irq(&adata->acp_lock);
    75		list_for_each_entry(stream, &adata->stream_list, list) {
    76			if (tx_mask && stream->dir == SNDRV_PCM_STREAM_PLAYBACK)
    77				adata->tdm_tx_fmt[stream->dai_id - 1] =
    78						FRM_LEN | (slots << 15) | (slot_len << 18);
    79			else if (rx_mask && stream->dir == SNDRV_PCM_STREAM_CAPTURE)
    80				adata->tdm_rx_fmt[stream->dai_id - 1] =
    81						FRM_LEN | (slots << 15) | (slot_len << 18);
    82		}
    83		spin_unlock_irq(&adata->acp_lock);
    84		return 0;
    85	}
    86	

-- 
0-DAY CI Kernel Test Service
https://01.org/lkp

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

* Re: [PATCH v2] ASoC: amd: acp: Add TDM support for acp i2s stream
  2022-08-05  6:04 [PATCH v2] ASoC: amd: acp: Add TDM support for acp i2s stream Venkata Prasad Potturu
  2022-08-07  7:05 ` kernel test robot
@ 2022-08-16 13:48 ` Mark Brown
  1 sibling, 0 replies; 3+ messages in thread
From: Mark Brown @ 2022-08-16 13:48 UTC (permalink / raw)
  To: alsa-devel, Venkata Prasad Potturu
  Cc: vsujithkumar.reddy, ssabakar, Liam Girdwood, Ajit Kumar Pandey,
	Basavaraj.Hiregoudar, Sunil-kumar.Dommati, open list,
	V sujith kumar Reddy, Vijendar.Mukunda, Jaroslav Kysela,
	Takashi Iwai

On Fri, 5 Aug 2022 11:34:12 +0530, Venkata Prasad Potturu wrote:
> Add callback and code changes to enable ACP I2S controller in TDM
> mode. Add new fields in acp_stream and acp_dev_data struct to configure
> tdm related registers for ACP i2s controllers.
> 
> 

Applied to

   https://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git for-next

Thanks!

[1/1] ASoC: amd: acp: Add TDM support for acp i2s stream
      commit: 12229b7e50cfa95fda55b83a2617eafd6ac4c8c5

All being well this means that it will be integrated into the linux-next
tree (usually sometime in the next 24 hours) and sent to Linus during
the next merge window (or sooner if it is a bug fix), however if
problems are discovered then the patch may be dropped or reverted.

You may get further e-mails resulting from automated or manual testing
and review of the tree, please engage with people reporting problems and
send followup patches addressing any issues that are reported if needed.

If any updates are required or you are submitting further changes they
should be sent as incremental updates against current git, existing
patches will not be replaced.

Please add any relevant lists and maintainers to the CCs when replying
to this mail.

Thanks,
Mark

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

end of thread, other threads:[~2022-08-16 13:48 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-08-05  6:04 [PATCH v2] ASoC: amd: acp: Add TDM support for acp i2s stream Venkata Prasad Potturu
2022-08-07  7:05 ` kernel test robot
2022-08-16 13:48 ` Mark Brown

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).