diff mbox series

[3/3] ASoC: amd: acp: Add legacy audio driver support for Rembrandt platform

Message ID 20220624194821.287462-4-Vsujithkumar.Reddy@amd.com (mailing list archive)
State Superseded
Headers show
Series ADD legacy audio driver support for rembrandt | expand

Commit Message

V sujith kumar Reddy June 24, 2022, 7:48 p.m. UTC
Add i2s and dmic support for Rembrandt platform,
Add machine support for nau8825, max98360 and rt5682s,rt1019 codec
in legacy driver for rembrandt platform.
Here codec is in a slave mode.

Signed-off-by: V sujith kumar Reddy <Vsujithkumar.Reddy@amd.com>
---
 sound/soc/amd/acp/Kconfig            |  11 +
 sound/soc/amd/acp/Makefile           |   2 +
 sound/soc/amd/acp/acp-i2s.c          | 137 ++++++++-
 sound/soc/amd/acp/acp-legacy-mach.c  |  32 +++
 sound/soc/amd/acp/acp-mach-common.c  |  86 +++++-
 sound/soc/amd/acp/acp-mach.h         |   6 +
 sound/soc/amd/acp/acp-pci.c          |   6 +
 sound/soc/amd/acp/acp-platform.c     |  16 +-
 sound/soc/amd/acp/acp-rembrandt.c    | 397 +++++++++++++++++++++++++++
 sound/soc/amd/acp/amd.h              |  62 ++++-
 sound/soc/amd/acp/chip_offset_byte.h |  28 ++
 11 files changed, 777 insertions(+), 6 deletions(-)
 create mode 100644 sound/soc/amd/acp/acp-rembrandt.c

Comments

Randy Dunlap June 24, 2022, 11:04 p.m. UTC | #1
Hi--

On 6/24/22 12:48, V sujith kumar Reddy wrote:
> diff --git a/sound/soc/amd/acp/Kconfig b/sound/soc/amd/acp/Kconfig
> index 7e56d2644105..abc089f38b6c 100644
> --- a/sound/soc/amd/acp/Kconfig
> +++ b/sound/soc/amd/acp/Kconfig
> @@ -40,6 +40,17 @@ config SND_AMD_ASOC_RENOIR
>  	help
>  	  This option enables Renoir I2S support on AMD platform.
>  
> +config SND_AMD_ASOC_REMBRANDT
> +        tristate "AMD ACP ASOC Rembrandt Support"
> +        select SND_SOC_AMD_ACP_PCM
> +        select SND_SOC_AMD_ACP_I2S
> +        select SND_SOC_AMD_ACP_PDM
> +        depends on X86 && PCI
> +        help
> +          This option enables Rembrandt I2S support on AMD platform.
> +	  Say Y if you want to enable AUDIO on Rembrandt
> +	  If unsure select "N".

Documentation/process/coding-style.rst says:

10) Kconfig configuration files
-------------------------------

For all of the Kconfig* configuration files throughout the source tree,
the indentation is somewhat different.  Lines under a ``config`` definition
are indented with one tab, while help text is indented an additional two
spaces.


so please indent as expected, and consistently.
V sujith kumar Reddy July 7, 2022, 4:05 p.m. UTC | #2
On 6/25/2022 8:29 AM, kernel test robot wrote:
> [CAUTION: External Email]
>
> Hi sujith,
>
> Thank you for the patch! Perhaps something to improve:
>
> [auto build test WARNING on broonie-sound/for-next]
> [also build test WARNING on next-20220624]
> [cannot apply to linus/master v5.19-rc3]
> [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://nam11.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgit-scm.com%2Fdocs%2Fgit-format-patch&amp;data=05%7C01%7CVsujithkumar.Reddy%40amd.com%7C76b71f6bc0b64a93432508da5656c7e4%7C3dd8961fe4884e608e11a82d994e183d%7C0%7C0%7C637917228020649435%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C3000%7C%7C%7C&amp;sdata=dMgKJPdC1Wozc8Fyvb%2BCGvAkKb4dxwlC%2BcEIsLTUwd0%3D&amp;reserved=0]
>
> url:https://nam11.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgithub.com%2Fintel-lab-lkp%2Flinux%2Fcommits%2FV-sujith-kumar-Reddy%2FADD-legacy-audio-driver-support-for-rembrandt%2F20220625-035009&amp;data=05%7C01%7CVsujithkumar.Reddy%40amd.com%7C76b71f6bc0b64a93432508da5656c7e4%7C3dd8961fe4884e608e11a82d994e183d%7C0%7C0%7C637917228020649435%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C3000%7C%7C%7C&amp;sdata=hzTz9xhAhBAJ9usYOfc1IN0cmHiHREgtttyvUlDOoJs%3D&amp;reserved=0
> base:https://nam11.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgit.kernel.org%2Fpub%2Fscm%2Flinux%2Fkernel%2Fgit%2Fbroonie%2Fsound.git&amp;data=05%7C01%7CVsujithkumar.Reddy%40amd.com%7C76b71f6bc0b64a93432508da5656c7e4%7C3dd8961fe4884e608e11a82d994e183d%7C0%7C0%7C637917228020649435%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C3000%7C%7C%7C&amp;sdata=awvLx0T4gFToItcVHMNqkUZ%2FaS120MOg15Jr1PGsumA%3D&amp;reserved=0  for-next
> config: i386-allyesconfig
> compiler: gcc-11 (Debian 11.3.0-3) 11.3.0
> reproduce (this is a W=1 build):
>          #https://nam11.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgithub.com%2Fintel-lab-lkp%2Flinux%2Fcommit%2F32f53f63fb2ba0bbf7e8e145879a7340f28ebfbd&amp;data=05%7C01%7CVsujithkumar.Reddy%40amd.com%7C76b71f6bc0b64a93432508da5656c7e4%7C3dd8961fe4884e608e11a82d994e183d%7C0%7C0%7C637917228020649435%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C3000%7C%7C%7C&amp;sdata=4t5GdErDyUSzvhP1uW8KdxwCoE6MUPS1mjsg7HjDbYo%3D&amp;reserved=0
>          git remote add linux-reviewhttps://nam11.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgithub.com%2Fintel-lab-lkp%2Flinux&amp;data=05%7C01%7CVsujithkumar.Reddy%40amd.com%7C76b71f6bc0b64a93432508da5656c7e4%7C3dd8961fe4884e608e11a82d994e183d%7C0%7C0%7C637917228020649435%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C3000%7C%7C%7C&amp;sdata=UjYTqFiuuaxQkLTThINcEzgzwCB%2Fl87%2B%2FYIiHGfCIl0%3D&amp;reserved=0
>          git fetch --no-tags linux-review V-sujith-kumar-Reddy/ADD-legacy-audio-driver-support-for-rembrandt/20220625-035009
>          git checkout 32f53f63fb2ba0bbf7e8e145879a7340f28ebfbd
>          # save the config file
>          mkdir build_dir && cp config build_dir/.config
>          make W=1 O=build_dir ARCH=i386 SHELL=/bin/bash sound/soc/amd/acp/
>
> If you fix the issue, kindly add following tag where applicable
> Reported-by: kernel test robot<lkp@intel.com>
>
> All warnings (new ones prefixed by >>):
>
>>> sound/soc/amd/acp/acp-rembrandt.c:264:5: warning: no previous prototype for 'rmb_acp_init' [-Wmissing-prototypes]
>       264 | int rmb_acp_init(void __iomem *base)
>           |     ^~~~~~~~~~~~


Done

>>> sound/soc/amd/acp/acp-rembrandt.c:286:5: warning: no previous prototype for 'rmb_acp_deinit' [-Wmissing-prototypes]
>       286 | int rmb_acp_deinit(void __iomem *base)
>           |     ^~~~~~~~~~~~~~
>
Done
> vim +/rmb_acp_init +264 sound/soc/amd/acp/acp-rembrandt.c
>
>     263
>   > 264  int rmb_acp_init(void __iomem *base)
>     265  {
>     266          int ret;
>     267
>     268          /* power on */
>     269          ret = acp6x_power_on(base);
>     270          if (ret) {
>     271                  pr_err("ACP power on failed\n");
>     272                  return ret;
>     273          }
>     274          writel(0x01, base + ACP_CONTROL);
>     275
>     276          /* Reset */
>     277          ret = acp6x_reset(base);
>     278          if (ret) {
>     279                  pr_err("ACP reset failed\n");
>     280                  return ret;
>     281          }
>     282
>     283          return 0;
>     284  }
>     285
>   > 286  int rmb_acp_deinit(void __iomem *base)
>     287  {
>     288          int ret = 0;
>     289
>     290          /* Reset */
>     291          ret = acp6x_reset(base);
>     292          if (ret) {
>     293                  pr_err("ACP reset failed\n");
>     294                  return ret;
>     295          }
>     296
>     297          writel(0x00, base + ACP_CONTROL);
>     298
>     299          /* power off */
>     300          ret = acp6x_power_off(base);
>     301          if (ret) {
>     302                  pr_err("ACP power off failed\n");
>     303                  return ret;
>     304          }
>     305
>     306          return 0;
>     307  }
>     308
>
> --
> 0-DAY CI Kernel Test Service
> https://nam11.safelinks.protection.outlook.com/?url=https%3A%2F%2F01.org%2Flkp&amp;data=05%7C01%7CVsujithkumar.Reddy%40amd.com%7C76b71f6bc0b64a93432508da5656c7e4%7C3dd8961fe4884e608e11a82d994e183d%7C0%7C0%7C637917228020649435%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C3000%7C%7C%7C&amp;sdata=H4qJDbhtyu9BGhMCtQvEe%2FvVZiueS2j%2F%2Fda%2BpwUOuLo%3D&amp;reserved=0
V sujith kumar Reddy July 7, 2022, 4:05 p.m. UTC | #3
On 6/25/2022 4:34 AM, Randy Dunlap wrote:
> [CAUTION: External Email]
>
> Hi--
>
> On 6/24/22 12:48, V sujith kumar Reddy wrote:
>> diff --git a/sound/soc/amd/acp/Kconfig b/sound/soc/amd/acp/Kconfig
>> index 7e56d2644105..abc089f38b6c 100644
>> --- a/sound/soc/amd/acp/Kconfig
>> +++ b/sound/soc/amd/acp/Kconfig
>> @@ -40,6 +40,17 @@ config SND_AMD_ASOC_RENOIR
>>        help
>>          This option enables Renoir I2S support on AMD platform.
>>
>> +config SND_AMD_ASOC_REMBRANDT
>> +        tristate "AMD ACP ASOC Rembrandt Support"
>> +        select SND_SOC_AMD_ACP_PCM
>> +        select SND_SOC_AMD_ACP_I2S
>> +        select SND_SOC_AMD_ACP_PDM
>> +        depends on X86 && PCI
>> +        help
>> +          This option enables Rembrandt I2S support on AMD platform.
>> +       Say Y if you want to enable AUDIO on Rembrandt
>> +       If unsure select "N".
>
Done
> Documentation/process/coding-style.rst says:
>
> 10) Kconfig configuration files
> -------------------------------
>
> For all of the Kconfig* configuration files throughout the source tree,
> the indentation is somewhat different.  Lines under a ``config`` definition
> are indented with one tab, while help text is indented an additional two
> spaces.
>
>
> so please indent as expected, and consistently.
>
> --
> ~Randy
diff mbox series

Patch

diff --git a/sound/soc/amd/acp/Kconfig b/sound/soc/amd/acp/Kconfig
index 7e56d2644105..abc089f38b6c 100644
--- a/sound/soc/amd/acp/Kconfig
+++ b/sound/soc/amd/acp/Kconfig
@@ -40,6 +40,17 @@  config SND_AMD_ASOC_RENOIR
 	help
 	  This option enables Renoir I2S support on AMD platform.
 
+config SND_AMD_ASOC_REMBRANDT
+        tristate "AMD ACP ASOC Rembrandt Support"
+        select SND_SOC_AMD_ACP_PCM
+        select SND_SOC_AMD_ACP_I2S
+        select SND_SOC_AMD_ACP_PDM
+        depends on X86 && PCI
+        help
+          This option enables Rembrandt I2S support on AMD platform.
+	  Say Y if you want to enable AUDIO on Rembrandt
+	  If unsure select "N".
+
 config SND_SOC_AMD_MACH_COMMON
 	tristate
 	depends on X86 && PCI && I2C
diff --git a/sound/soc/amd/acp/Makefile b/sound/soc/amd/acp/Makefile
index 657ddfadf0bb..d9abb0ee5218 100644
--- a/sound/soc/amd/acp/Makefile
+++ b/sound/soc/amd/acp/Makefile
@@ -12,6 +12,7 @@  snd-acp-pci-objs     := acp-pci.o
 
 #platform specific driver
 snd-acp-renoir-objs     := acp-renoir.o
+snd-acp-rembrandt-objs  := acp-rembrandt.o
 
 #machine specific driver
 snd-acp-mach-objs     := acp-mach-common.o
@@ -24,6 +25,7 @@  obj-$(CONFIG_SND_SOC_AMD_ACP_PDM) += snd-acp-pdm.o
 obj-$(CONFIG_SND_SOC_AMD_ACP_PCI) += snd-acp-pci.o
 
 obj-$(CONFIG_SND_AMD_ASOC_RENOIR) += snd-acp-renoir.o
+obj-$(CONFIG_SND_AMD_ASOC_REMBRANDT) += snd-acp-rembrandt.o
 
 obj-$(CONFIG_SND_SOC_AMD_MACH_COMMON) += snd-acp-mach.o
 obj-$(CONFIG_SND_SOC_AMD_LEGACY_MACH) += snd-acp-legacy-mach.o
diff --git a/sound/soc/amd/acp/acp-i2s.c b/sound/soc/amd/acp/acp-i2s.c
index a736c00db86e..393f729ef561 100644
--- a/sound/soc/amd/acp/acp-i2s.c
+++ b/sound/soc/amd/acp/acp-i2s.c
@@ -30,11 +30,14 @@  static int acp_i2s_hwparams(struct snd_pcm_substream *substream, struct snd_pcm_
 {
 	struct device *dev = dai->component->dev;
 	struct acp_dev_data *adata;
+	struct acp_resource *rsrc;
 	u32 val;
 	u32 xfer_resolution;
 	u32 reg_val;
+	u32 lrclk_div_val, bclk_div_val;
 
 	adata = snd_soc_dai_get_drvdata(dai);
+	rsrc = adata->rsrc;
 
 	/* These values are as per Hardware Spec */
 	switch (params_format(params)) {
@@ -63,6 +66,9 @@  static int acp_i2s_hwparams(struct snd_pcm_substream *substream, struct snd_pcm_
 		case I2S_SP_INSTANCE:
 			reg_val = ACP_I2STDM_ITER;
 			break;
+		case I2S_HS_INSTANCE:
+			reg_val = ACP_HSTDM_ITER;
+			break;
 		default:
 			dev_err(dev, "Invalid dai id %x\n", dai->driver->id);
 			return -EINVAL;
@@ -75,6 +81,9 @@  static int acp_i2s_hwparams(struct snd_pcm_substream *substream, struct snd_pcm_
 		case I2S_SP_INSTANCE:
 			reg_val = ACP_I2STDM_IRER;
 			break;
+		case I2S_HS_INSTANCE:
+			reg_val = ACP_HSTDM_IRER;
+			break;
 		default:
 			dev_err(dev, "Invalid dai id %x\n", dai->driver->id);
 			return -EINVAL;
@@ -86,6 +95,74 @@  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 (rsrc->soc_mclk) {
+		switch (params_format(params)) {
+		case SNDRV_PCM_FORMAT_S16_LE:
+			switch (params_rate(params)) {
+			case 8000:
+				bclk_div_val = 768;
+				break;
+			case 16000:
+				bclk_div_val = 384;
+				break;
+			case 24000:
+				bclk_div_val = 256;
+				break;
+			case 32000:
+				bclk_div_val = 192;
+				break;
+			case 44100:
+			case 48000:
+				bclk_div_val = 128;
+				break;
+			case 88200:
+			case 96000:
+				bclk_div_val = 64;
+				break;
+			case 192000:
+				bclk_div_val = 32;
+				break;
+			default:
+				return -EINVAL;
+			}
+			lrclk_div_val = 32;
+			break;
+		case SNDRV_PCM_FORMAT_S32_LE:
+			switch (params_rate(params)) {
+			case 8000:
+				bclk_div_val = 384;
+				break;
+			case 16000:
+				bclk_div_val = 192;
+				break;
+			case 24000:
+				bclk_div_val = 128;
+				break;
+			case 32000:
+				bclk_div_val = 96;
+				break;
+			case 44100:
+			case 48000:
+				bclk_div_val = 64;
+				break;
+			case 88200:
+			case 96000:
+				bclk_div_val = 32;
+				break;
+			case 192000:
+				bclk_div_val = 16;
+				break;
+			default:
+				return -EINVAL;
+			}
+			lrclk_div_val = 64;
+			break;
+		default:
+			return -EINVAL;
+		}
+		adata->lrclk_div = lrclk_div_val;
+		adata->bclk_div = bclk_div_val;
+	}
 	return 0;
 }
 
@@ -94,6 +171,7 @@  static int acp_i2s_trigger(struct snd_pcm_substream *substream, int cmd, struct
 	struct acp_stream *stream = substream->runtime->private_data;
 	struct device *dev = dai->component->dev;
 	struct acp_dev_data *adata = dev_get_drvdata(dev);
+	struct acp_resource *rsrc = adata->rsrc;
 	u32 val, period_bytes, reg_val, ier_val, water_val, buf_size, buf_reg;
 
 	period_bytes = frames_to_bytes(substream->runtime, substream->runtime->period_size);
@@ -118,6 +196,12 @@  static int acp_i2s_trigger(struct snd_pcm_substream *substream, int cmd, struct
 				ier_val = ACP_I2STDM_IER;
 				buf_reg = ACP_I2S_TX_RINGBUFSIZE;
 				break;
+			case I2S_HS_INSTANCE:
+				water_val = ACP_HS_TX_INTR_WATERMARK_SIZE;
+				reg_val = ACP_HSTDM_ITER;
+				ier_val = ACP_HSTDM_IER;
+				buf_reg = ACP_HS_TX_RINGBUFSIZE;
+				break;
 			default:
 				dev_err(dev, "Invalid dai id %x\n", dai->driver->id);
 				return -EINVAL;
@@ -136,6 +220,12 @@  static int acp_i2s_trigger(struct snd_pcm_substream *substream, int cmd, struct
 				ier_val = ACP_I2STDM_IER;
 				buf_reg = ACP_I2S_RX_RINGBUFSIZE;
 				break;
+			case I2S_HS_INSTANCE:
+				water_val = ACP_HS_RX_INTR_WATERMARK_SIZE;
+				reg_val = ACP_HSTDM_IRER;
+				ier_val = ACP_HSTDM_IER;
+				buf_reg = ACP_HS_RX_RINGBUFSIZE;
+				break;
 			default:
 				dev_err(dev, "Invalid dai id %x\n", dai->driver->id);
 				return -EINVAL;
@@ -147,6 +237,8 @@  static int acp_i2s_trigger(struct snd_pcm_substream *substream, int cmd, struct
 		val = val | BIT(0);
 		writel(val, adata->acp_base + reg_val);
 		writel(1, adata->acp_base + ier_val);
+		if (rsrc->soc_mclk)
+			acp_set_i2s_clk(adata, dai->driver->id);
 		return 0;
 	case SNDRV_PCM_TRIGGER_STOP:
 	case SNDRV_PCM_TRIGGER_SUSPEND:
@@ -159,6 +251,9 @@  static int acp_i2s_trigger(struct snd_pcm_substream *substream, int cmd, struct
 			case I2S_SP_INSTANCE:
 				reg_val = ACP_I2STDM_ITER;
 				break;
+			case I2S_HS_INSTANCE:
+				reg_val = ACP_HSTDM_ITER;
+				break;
 			default:
 				dev_err(dev, "Invalid dai id %x\n", dai->driver->id);
 				return -EINVAL;
@@ -172,6 +267,9 @@  static int acp_i2s_trigger(struct snd_pcm_substream *substream, int cmd, struct
 			case I2S_SP_INSTANCE:
 				reg_val = ACP_I2STDM_IRER;
 				break;
+			case I2S_HS_INSTANCE:
+				reg_val = ACP_HSTDM_IRER;
+				break;
 			default:
 				dev_err(dev, "Invalid dai id %x\n", dai->driver->id);
 				return -EINVAL;
@@ -187,6 +285,9 @@  static int acp_i2s_trigger(struct snd_pcm_substream *substream, int cmd, struct
 		if (!(readl(adata->acp_base + ACP_I2STDM_ITER) & BIT(0)) &&
 		    !(readl(adata->acp_base + ACP_I2STDM_IRER) & BIT(0)))
 			writel(0, adata->acp_base + ACP_I2STDM_IER);
+		if (!(readl(adata->acp_base + ACP_HSTDM_ITER) & BIT(0)) &&
+		    !(readl(adata->acp_base + ACP_HSTDM_IRER) & BIT(0)))
+			writel(0, adata->acp_base + ACP_HSTDM_IER);
 		return 0;
 	default:
 		return -EINVAL;
@@ -247,6 +348,27 @@  static int acp_i2s_prepare(struct snd_pcm_substream *substream, struct snd_soc_d
 			writel(phy_addr, adata->acp_base + ACP_BT_RX_RINGBUFADDR);
 		}
 		break;
+	case I2S_HS_INSTANCE:
+		if (dir == SNDRV_PCM_STREAM_PLAYBACK) {
+			reg_dma_size = ACP_HS_TX_DMA_SIZE;
+			acp_fifo_addr = rsrc->sram_pte_offset +
+				HS_PB_FIFO_ADDR_OFFSET;
+			reg_fifo_addr = ACP_HS_TX_FIFOADDR;
+			reg_fifo_size = ACP_HS_TX_FIFOSIZE;
+
+			phy_addr = I2S_HS_TX_MEM_WINDOW_START + stream->reg_offset;
+			writel(phy_addr, adata->acp_base + ACP_HS_TX_RINGBUFADDR);
+		} else {
+			reg_dma_size = ACP_HS_RX_DMA_SIZE;
+			acp_fifo_addr = rsrc->sram_pte_offset +
+					HS_CAPT_FIFO_ADDR_OFFSET;
+			reg_fifo_addr = ACP_HS_RX_FIFOADDR;
+			reg_fifo_size = ACP_HS_RX_FIFOSIZE;
+
+			phy_addr = I2S_HS_RX_MEM_WINDOW_START + stream->reg_offset;
+			writel(phy_addr, adata->acp_base + ACP_HS_RX_RINGBUFADDR);
+		}
+		break;
 	default:
 		dev_err(dev, "Invalid dai id %x\n", dai->driver->id);
 		return -EINVAL;
@@ -260,7 +382,9 @@  static int acp_i2s_prepare(struct snd_pcm_substream *substream, struct snd_soc_d
 	ext_int_ctrl |= BIT(I2S_RX_THRESHOLD(rsrc->offset)) |
 			BIT(BT_RX_THRESHOLD(rsrc->offset)) |
 			BIT(I2S_TX_THRESHOLD(rsrc->offset)) |
-			BIT(BT_TX_THRESHOLD(rsrc->offset));
+			BIT(BT_TX_THRESHOLD(rsrc->offset)) |
+			BIT(HS_RX_THRESHOLD(rsrc->offset)) |
+			BIT(HS_TX_THRESHOLD(rsrc->offset));
 
 	writel(ext_int_ctrl, ACP_EXTERNAL_INTR_CNTL(adata, rsrc->irqp_used));
 
@@ -299,6 +423,17 @@  static int acp_i2s_startup(struct snd_pcm_substream *substream, struct snd_soc_d
 			stream->fifo_offset = BT_CAPT_FIFO_ADDR_OFFSET;
 		}
 		break;
+	case I2S_HS_INSTANCE:
+		if (dir == SNDRV_PCM_STREAM_PLAYBACK) {
+			irq_bit = BIT(HS_TX_THRESHOLD(rsrc->offset));
+			stream->pte_offset = ACP_SRAM_HS_PB_PTE_OFFSET;
+			stream->fifo_offset = HS_PB_FIFO_ADDR_OFFSET;
+		} else {
+			irq_bit = BIT(HS_RX_THRESHOLD(rsrc->offset));
+			stream->pte_offset = ACP_SRAM_HS_CP_PTE_OFFSET;
+			stream->fifo_offset = HS_CAPT_FIFO_ADDR_OFFSET;
+		}
+		break;
 	default:
 		dev_err(dev, "Invalid dai id %x\n", dai->driver->id);
 		return -EINVAL;
diff --git a/sound/soc/amd/acp/acp-legacy-mach.c b/sound/soc/amd/acp/acp-legacy-mach.c
index 7f04a048ca3a..1f4878ff7d37 100644
--- a/sound/soc/amd/acp/acp-legacy-mach.c
+++ b/sound/soc/amd/acp/acp-legacy-mach.c
@@ -47,6 +47,28 @@  static struct acp_card_drvdata rt5682s_rt1019_data = {
 	.dmic_codec_id = DMIC,
 };
 
+static struct acp_card_drvdata max_nau8825_data = {
+	.hs_cpu_id = I2S_HS,
+	.amp_cpu_id = I2S_HS,
+	.dmic_cpu_id = DMIC,
+	.hs_codec_id = NAU8825,
+	.amp_codec_id = MAX98360A,
+	.dmic_codec_id = DMIC,
+	.soc_mclk = true,
+	.platform = REMBRANDT,
+};
+
+static struct acp_card_drvdata rt5682s_rt1019_rmb_data = {
+	.hs_cpu_id = I2S_HS,
+	.amp_cpu_id = I2S_HS,
+	.dmic_cpu_id = DMIC,
+	.hs_codec_id = RT5682S,
+	.amp_codec_id = RT1019,
+	.dmic_codec_id = DMIC,
+	.soc_mclk = true,
+	.platform = REMBRANDT,
+};
+
 static const struct snd_kcontrol_new acp_controls[] = {
 	SOC_DAPM_PIN_SWITCH("Headphone Jack"),
 	SOC_DAPM_PIN_SWITCH("Headset Mic"),
@@ -112,6 +134,14 @@  static const struct platform_device_id board_ids[] = {
 		.name = "acp3xalc5682s1019",
 		.driver_data = (kernel_ulong_t)&rt5682s_rt1019_data,
 	},
+	{
+		.name = "rmb-nau8825-max",
+		.driver_data = (kernel_ulong_t)&max_nau8825_data,
+	},
+	{
+		.name = "rmb-rt5682s-rt1019",
+		.driver_data = (kernel_ulong_t)&rt5682s_rt1019_rmb_data,
+	},
 	{ }
 };
 static struct platform_driver acp_asoc_audio = {
@@ -130,4 +160,6 @@  MODULE_DESCRIPTION("ACP chrome audio support");
 MODULE_ALIAS("platform:acp3xalc56821019");
 MODULE_ALIAS("platform:acp3xalc5682sm98360");
 MODULE_ALIAS("platform:acp3xalc5682s1019");
+MODULE_ALIAS("platform:rmb-nau8825-max");
+MODULE_ALIAS("platform:rmb-rt5682s-rt1019");
 MODULE_LICENSE("GPL v2");
diff --git a/sound/soc/amd/acp/acp-mach-common.c b/sound/soc/amd/acp/acp-mach-common.c
index 86145398fa25..f0c49127aad1 100644
--- a/sound/soc/amd/acp/acp-mach-common.c
+++ b/sound/soc/amd/acp/acp-mach-common.c
@@ -545,6 +545,12 @@  static struct snd_soc_dai_link_component platform_component[] = {
 	}
 };
 
+static struct snd_soc_dai_link_component platform_rmb_component[] = {
+	{
+		.name = "acp_asoc_rembrandt.0",
+	}
+};
+
 static struct snd_soc_dai_link_component sof_component[] = {
 	{
 		 .name = "0000:04:00.5",
@@ -553,6 +559,8 @@  static struct snd_soc_dai_link_component sof_component[] = {
 
 SND_SOC_DAILINK_DEF(i2s_sp,
 	DAILINK_COMP_ARRAY(COMP_CPU("acp-i2s-sp")));
+SND_SOC_DAILINK_DEF(i2s_hs,
+		    DAILINK_COMP_ARRAY(COMP_CPU("acp-i2s-hs")));
 SND_SOC_DAILINK_DEF(sof_sp,
 	DAILINK_COMP_ARRAY(COMP_CPU("acp-sof-sp")));
 SND_SOC_DAILINK_DEF(sof_hs,
@@ -774,6 +782,40 @@  int acp_legacy_dai_links_create(struct snd_soc_card *card)
 		i++;
 	}
 
+	if (drv_data->hs_cpu_id == I2S_HS) {
+		links[i].name = "acp-headset-codec";
+		links[i].id = HEADSET_BE_ID;
+		links[i].cpus = i2s_hs;
+		links[i].num_cpus = ARRAY_SIZE(i2s_hs);
+		if (drv_data->platform == REMBRANDT) {
+			links[i].platforms = platform_rmb_component;
+			links[i].num_platforms = ARRAY_SIZE(platform_rmb_component);
+		} else {
+			links[i].platforms = platform_component;
+			links[i].num_platforms = ARRAY_SIZE(platform_component);
+		}
+		links[i].dpcm_playback = 1;
+		links[i].dpcm_capture = 1;
+		if (!drv_data->hs_codec_id) {
+			/* Use dummy codec if codec id not specified */
+			links[i].codecs = dummy_codec;
+			links[i].num_codecs = ARRAY_SIZE(dummy_codec);
+		}
+		if (drv_data->hs_codec_id == NAU8825) {
+			links[i].codecs = nau8825;
+			links[i].num_codecs = ARRAY_SIZE(nau8825);
+			links[i].init = acp_card_nau8825_init;
+			links[i].ops = &acp_card_nau8825_ops;
+		}
+		if (drv_data->hs_codec_id == RT5682S) {
+			links[i].codecs = rt5682s;
+			links[i].num_codecs = ARRAY_SIZE(rt5682s);
+			links[i].init = acp_card_rt5682s_init;
+			links[i].ops = &acp_card_rt5682s_ops;
+		}
+		i++;
+	}
+
 	if (drv_data->amp_cpu_id == I2S_SP) {
 		links[i].name = "acp-amp-codec";
 		links[i].id = AMP_BE_ID;
@@ -804,6 +846,41 @@  int acp_legacy_dai_links_create(struct snd_soc_card *card)
 		i++;
 	}
 
+	if (drv_data->amp_cpu_id == I2S_HS) {
+		links[i].name = "acp-amp-codec";
+		links[i].id = AMP_BE_ID;
+		links[i].cpus = i2s_hs;
+		links[i].num_cpus = ARRAY_SIZE(i2s_hs);
+		if (drv_data->platform == REMBRANDT) {
+			links[i].platforms = platform_rmb_component;
+			links[i].num_platforms = ARRAY_SIZE(platform_rmb_component);
+		} else {
+			links[i].platforms = platform_component;
+			links[i].num_platforms = ARRAY_SIZE(platform_component);
+		}
+		links[i].dpcm_playback = 1;
+		if (!drv_data->amp_codec_id) {
+			/* Use dummy codec if codec id not specified */
+			links[i].codecs = dummy_codec;
+			links[i].num_codecs = ARRAY_SIZE(dummy_codec);
+		}
+		if (drv_data->amp_codec_id == MAX98360A) {
+			links[i].codecs = max98360a;
+			links[i].num_codecs = ARRAY_SIZE(max98360a);
+			links[i].ops = &acp_card_maxim_ops;
+			links[i].init = acp_card_maxim_init;
+		}
+		if (drv_data->amp_codec_id == RT1019) {
+			links[i].codecs = rt1019;
+			links[i].num_codecs = ARRAY_SIZE(rt1019);
+			links[i].ops = &acp_card_rt1019_ops;
+			links[i].init = acp_card_rt1019_init;
+			card->codec_conf = rt1019_conf;
+			card->num_configs = ARRAY_SIZE(rt1019_conf);
+		}
+		i++;
+	}
+
 	if (drv_data->dmic_cpu_id == DMIC) {
 		links[i].name = "acp-dmic-codec";
 		links[i].id = DMIC_BE_ID;
@@ -817,8 +894,13 @@  int acp_legacy_dai_links_create(struct snd_soc_card *card)
 		}
 		links[i].cpus = pdm_dmic;
 		links[i].num_cpus = ARRAY_SIZE(pdm_dmic);
-		links[i].platforms = platform_component;
-		links[i].num_platforms = ARRAY_SIZE(platform_component);
+		if (drv_data->platform == REMBRANDT) {
+			links[i].platforms = platform_rmb_component;
+			links[i].num_platforms = ARRAY_SIZE(platform_rmb_component);
+		} else {
+			links[i].platforms = platform_component;
+			links[i].num_platforms = ARRAY_SIZE(platform_component);
+		}
 		links[i].ops = &acp_card_dmic_ops;
 		links[i].dpcm_capture = 1;
 	}
diff --git a/sound/soc/amd/acp/acp-mach.h b/sound/soc/amd/acp/acp-mach.h
index c95ee1c52eb1..20583ef902df 100644
--- a/sound/soc/amd/acp/acp-mach.h
+++ b/sound/soc/amd/acp/acp-mach.h
@@ -41,6 +41,11 @@  enum codec_endpoints {
 	NAU8825,
 };
 
+enum platform_end_point {
+	RENOIR = 0,
+	REMBRANDT,
+};
+
 struct acp_card_drvdata {
 	unsigned int hs_cpu_id;
 	unsigned int amp_cpu_id;
@@ -49,6 +54,7 @@  struct acp_card_drvdata {
 	unsigned int amp_codec_id;
 	unsigned int dmic_codec_id;
 	unsigned int dai_fmt;
+	unsigned int platform;
 	struct clk *wclk;
 	struct clk *bclk;
 	bool soc_mclk;
diff --git a/sound/soc/amd/acp/acp-pci.c b/sound/soc/amd/acp/acp-pci.c
index c893963ee2d0..c03bcd31fc95 100644
--- a/sound/soc/amd/acp/acp-pci.c
+++ b/sound/soc/amd/acp/acp-pci.c
@@ -82,6 +82,12 @@  static int acp_pci_probe(struct pci_dev *pci, const struct pci_device_id *pci_id
 		chip->name = "acp_asoc_renoir";
 		chip->acp_rev = ACP3X_DEV;
 		break;
+	case 0x6f:
+		res_acp = acp3x_res;
+		num_res = ARRAY_SIZE(acp3x_res);
+		chip->name = "acp_asoc_rembrandt";
+		chip->acp_rev = ACP6X_DEV;
+		break;
 	default:
 		dev_err(dev, "Unsupported device revision:0x%x\n", pci->revision);
 		return -EINVAL;
diff --git a/sound/soc/amd/acp/acp-platform.c b/sound/soc/amd/acp/acp-platform.c
index bdf98c77cc2f..016400a2a8de 100644
--- a/sound/soc/amd/acp/acp-platform.c
+++ b/sound/soc/amd/acp/acp-platform.c
@@ -94,11 +94,14 @@  static irqreturn_t i2s_irq_handler(int irq, void *data)
 	struct acp_resource *rsrc = adata->rsrc;
 	struct acp_stream *stream;
 	u16 i2s_flag = 0;
-	u32 val, i;
+	u32 val, val1, i;
 
 	if (!adata)
 		return IRQ_NONE;
 
+	if (adata->rsrc->no_of_ctrls == 2)
+		val1 = readl(ACP_EXTERNAL_INTR_STAT(adata, (rsrc->irqp_used - 1)));
+
 	val = readl(ACP_EXTERNAL_INTR_STAT(adata, rsrc->irqp_used));
 
 	for (i = 0; i < ACP_MAX_STREAM; i++) {
@@ -110,8 +113,16 @@  static irqreturn_t i2s_irq_handler(int irq, void *data)
 			i2s_flag = 1;
 			break;
 		}
+		if (adata->rsrc->no_of_ctrls == 2) {
+			if (stream && (val1 & stream->irq_bit)) {
+				writel(stream->irq_bit, ACP_EXTERNAL_INTR_STAT(adata,
+				       (rsrc->irqp_used - 1)));
+				snd_pcm_period_elapsed(stream->substream);
+				i2s_flag = 1;
+				break;
+			}
+		}
 	}
-
 	if (i2s_flag)
 		return IRQ_HANDLED;
 
@@ -132,6 +143,7 @@  static void config_pte_for_stream(struct acp_dev_data *adata, struct acp_stream
 	reg_val = rsrc->sram_pte_offset;
 	writel(reg_val | BIT(31), adata->acp_base + pte_reg);
 	writel(PAGE_SIZE_4K_ENABLE,  adata->acp_base + pte_size);
+	writel(0x01, adata->acp_base + ACPAXI2AXI_ATU_CTRL);
 }
 
 static void config_acp_dma(struct acp_dev_data *adata, int cpu_id, int size)
diff --git a/sound/soc/amd/acp/acp-rembrandt.c b/sound/soc/amd/acp/acp-rembrandt.c
new file mode 100644
index 000000000000..74d6cfc59d83
--- /dev/null
+++ b/sound/soc/amd/acp/acp-rembrandt.c
@@ -0,0 +1,397 @@ 
+// SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause)
+//
+// This file is provided under a dual BSD/GPLv2 license. When using or
+// redistributing this file, you may do so under either license.
+//
+// Copyright(c) 2022 Advanced Micro Devices, Inc.
+//
+// Authors: Ajit Kumar Pandey <AjitKumar.Pandey@amd.com>
+//          V sujith kumar Reddy <Vsujithkumar.Reddy@amd.com>
+/*
+ * Hardware interface for Renoir ACP block
+ */
+
+#include <linux/platform_device.h>
+#include <linux/module.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/soc-dai.h>
+#include <linux/dma-mapping.h>
+
+#include "amd.h"
+
+#define DRV_NAME "acp_asoc_rembrandt"
+
+#define ACP6X_PGFSM_CONTROL			0x1024
+#define ACP6X_PGFSM_STATUS			0x1028
+
+#define ACP_SOFT_RESET_SOFTRESET_AUDDONE_MASK	0x00010001
+
+#define ACP_PGFSM_CNTL_POWER_ON_MASK		0x01
+#define ACP_PGFSM_CNTL_POWER_OFF_MASK		0x00
+#define ACP_PGFSM_STATUS_MASK			0x03
+#define ACP_POWERED_ON				0x00
+#define ACP_POWER_ON_IN_PROGRESS		0x01
+#define ACP_POWERED_OFF				0x02
+#define ACP_POWER_OFF_IN_PROGRESS		0x03
+
+#define ACP_ERROR_MASK				0x20000000
+#define ACP_EXT_INTR_STAT_CLEAR_MASK		0xFFFFFFFF
+
+static struct acp_resource rsrc = {
+	.offset = 0,
+	.no_of_ctrls = 2,
+	.irqp_used = 1,
+	.soc_mclk = true,
+	.irq_reg_offset = 0x1a00,
+	.i2s_pin_cfg_offset = 0x1440,
+	.i2s_mode = 0x0a,
+	.scratch_reg_offset = 0x12800,
+	.sram_pte_offset = 0x03802800,
+};
+
+static struct snd_soc_acpi_codecs amp_rt1019 = {
+	.num_codecs = 1,
+	.codecs = {"10EC1019"}
+};
+
+static struct snd_soc_acpi_codecs amp_max = {
+	.num_codecs = 1,
+	.codecs = {"MX98360A"}
+};
+
+static struct snd_soc_acpi_mach snd_soc_acpi_amd_rmb_acp_machines[] = {
+	{
+		.id = "10508825",
+		.drv_name = "rmb-nau8825-max",
+		.machine_quirk = snd_soc_acpi_codec_list,
+		.quirk_data = &amp_max,
+	},
+	{
+		.id = "AMDI0007",
+		.drv_name = "rembrandt-acp",
+	},
+	{
+		.id = "RTL5682",
+		.drv_name = "rmb-rt5682s-rt1019",
+		.machine_quirk = snd_soc_acpi_codec_list,
+		.quirk_data = &amp_rt1019,
+	},
+	{},
+};
+
+static struct snd_soc_dai_driver acp_rmb_dai[] = {
+{
+	.name = "acp-i2s-sp",
+	.id = I2S_SP_INSTANCE,
+	.playback = {
+		.stream_name = "I2S SP Playback",
+		.rates = SNDRV_PCM_RATE_8000_96000,
+		.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8 |
+			   SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S32_LE,
+		.channels_min = 2,
+		.channels_max = 8,
+		.rate_min = 8000,
+		.rate_max = 96000,
+	},
+	.capture = {
+		.stream_name = "I2S SP Capture",
+		.rates = SNDRV_PCM_RATE_8000_48000,
+		.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8 |
+			   SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S32_LE,
+		.channels_min = 2,
+		.channels_max = 2,
+		.rate_min = 8000,
+		.rate_max = 48000,
+	},
+	.ops = &asoc_acp_cpu_dai_ops,
+	.probe = &asoc_acp_i2s_probe,
+},
+{
+	.name = "acp-i2s-bt",
+	.id = I2S_BT_INSTANCE,
+	.playback = {
+		.stream_name = "I2S BT Playback",
+		.rates = SNDRV_PCM_RATE_8000_96000,
+		.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8 |
+			   SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S32_LE,
+		.channels_min = 2,
+		.channels_max = 8,
+		.rate_min = 8000,
+		.rate_max = 96000,
+	},
+	.capture = {
+		.stream_name = "I2S BT Capture",
+		.rates = SNDRV_PCM_RATE_8000_48000,
+		.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8 |
+			   SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S32_LE,
+		.channels_min = 2,
+		.channels_max = 2,
+		.rate_min = 8000,
+		.rate_max = 48000,
+	},
+	.ops = &asoc_acp_cpu_dai_ops,
+	.probe = &asoc_acp_i2s_probe,
+},
+{
+	.name = "acp-i2s-hs",
+	.id = I2S_HS_INSTANCE,
+	.playback = {
+		.stream_name = "I2S HS Playback",
+		.rates = SNDRV_PCM_RATE_8000_96000,
+		.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8 |
+			   SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S32_LE,
+		.channels_min = 2,
+		.channels_max = 8,
+		.rate_min = 8000,
+		.rate_max = 96000,
+	},
+	.capture = {
+		.stream_name = "I2S HS Capture",
+		.rates = SNDRV_PCM_RATE_8000_48000,
+		.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8 |
+			   SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S32_LE,
+		.channels_min = 2,
+		.channels_max = 8,
+		.rate_min = 8000,
+		.rate_max = 48000,
+	},
+	.ops = &asoc_acp_cpu_dai_ops,
+	.probe = &asoc_acp_i2s_probe,
+},
+{
+	.name = "acp-pdm-dmic",
+	.id = DMIC_INSTANCE,
+	.capture = {
+		.rates = SNDRV_PCM_RATE_8000_48000,
+		.formats = SNDRV_PCM_FMTBIT_S32_LE,
+		.channels_min = 2,
+		.channels_max = 2,
+		.rate_min = 8000,
+		.rate_max = 48000,
+	},
+	.ops = &acp_dmic_dai_ops,
+},
+};
+
+static int acp6x_power_on(void __iomem *base)
+{
+	u32 val;
+	int timeout;
+
+	val = readl(base + ACP6X_PGFSM_STATUS);
+
+	if (val == ACP_POWERED_ON)
+		return 0;
+
+	if ((val & ACP_PGFSM_STATUS_MASK) !=
+				ACP_POWER_ON_IN_PROGRESS)
+		writel(ACP_PGFSM_CNTL_POWER_ON_MASK,
+		       base + ACP6X_PGFSM_CONTROL);
+	timeout = 0;
+	while (++timeout < 500) {
+		val = readl(base + ACP6X_PGFSM_STATUS);
+		if (!val)
+			return 0;
+		udelay(1);
+	}
+	return -ETIMEDOUT;
+}
+
+static int acp6x_power_off(void __iomem *base)
+{
+	u32 val;
+	int timeout;
+
+	writel(ACP_PGFSM_CNTL_POWER_OFF_MASK,
+	       base + ACP6X_PGFSM_CONTROL);
+	timeout = 0;
+	while (++timeout < 500) {
+		val = readl(base + ACP6X_PGFSM_STATUS);
+		if ((val & ACP_PGFSM_STATUS_MASK) == ACP_POWERED_OFF)
+			return 0;
+		udelay(1);
+	}
+	return -ETIMEDOUT;
+}
+
+static int acp6x_reset(void __iomem *base)
+{
+	u32 val;
+	int timeout;
+
+	writel(1, base + ACP_SOFT_RESET);
+	timeout = 0;
+	while (++timeout < 500) {
+		val = readl(base + ACP_SOFT_RESET);
+		if (val & ACP_SOFT_RESET_SOFTRESET_AUDDONE_MASK)
+			break;
+		cpu_relax();
+	}
+	writel(0, base + ACP_SOFT_RESET);
+	timeout = 0;
+	while (++timeout < 500) {
+		val = readl(base + ACP_SOFT_RESET);
+		if (!val)
+			return 0;
+		cpu_relax();
+	}
+	return -ETIMEDOUT;
+}
+
+static void acp6x_enable_interrupts(struct acp_dev_data *adata)
+{
+	struct acp_resource *rsrc = adata->rsrc;
+	u32 ext_intr_ctrl;
+
+	writel(0x01, ACP_EXTERNAL_INTR_ENB(adata));
+	ext_intr_ctrl = readl(ACP_EXTERNAL_INTR_CNTL(adata, rsrc->irqp_used));
+	ext_intr_ctrl |= ACP_ERROR_MASK;
+	writel(ext_intr_ctrl, ACP_EXTERNAL_INTR_CNTL(adata, rsrc->irqp_used));
+}
+
+static void acp6x_disable_interrupts(struct acp_dev_data *adata)
+{
+	struct acp_resource *rsrc = adata->rsrc;
+
+	writel(ACP_EXT_INTR_STAT_CLEAR_MASK,
+	       ACP_EXTERNAL_INTR_STAT(adata, rsrc->irqp_used));
+	writel(0x00, ACP_EXTERNAL_INTR_ENB(adata));
+}
+
+int rmb_acp_init(void __iomem *base)
+{
+	int ret;
+
+	/* power on */
+	ret = acp6x_power_on(base);
+	if (ret) {
+		pr_err("ACP power on failed\n");
+		return ret;
+	}
+	writel(0x01, base + ACP_CONTROL);
+
+	/* Reset */
+	ret = acp6x_reset(base);
+	if (ret) {
+		pr_err("ACP reset failed\n");
+		return ret;
+	}
+
+	return 0;
+}
+
+int rmb_acp_deinit(void __iomem *base)
+{
+	int ret = 0;
+
+	/* Reset */
+	ret = acp6x_reset(base);
+	if (ret) {
+		pr_err("ACP reset failed\n");
+		return ret;
+	}
+
+	writel(0x00, base + ACP_CONTROL);
+
+	/* power off */
+	ret = acp6x_power_off(base);
+	if (ret) {
+		pr_err("ACP power off failed\n");
+		return ret;
+	}
+
+	return 0;
+}
+
+static int rembrandt_audio_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct acp_chip_info *chip;
+	struct acp_dev_data *adata;
+	struct resource *res;
+
+	chip = dev_get_platdata(&pdev->dev);
+	if (!chip || !chip->base) {
+		dev_err(&pdev->dev, "ACP chip data is NULL\n");
+		return -ENODEV;
+	}
+
+	if (chip->acp_rev != ACP6X_DEV) {
+		dev_err(&pdev->dev, "Un-supported ACP Revision %d\n", chip->acp_rev);
+		return -ENODEV;
+	}
+
+	rmb_acp_init(chip->base);
+
+	adata = devm_kzalloc(dev, sizeof(struct acp_dev_data), GFP_KERNEL);
+	if (!adata)
+		return -ENOMEM;
+
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "acp_mem");
+	if (!res) {
+		dev_err(&pdev->dev, "IORESOURCE_MEM FAILED\n");
+		return -ENODEV;
+	}
+
+	adata->acp_base = devm_ioremap(&pdev->dev, res->start, resource_size(res));
+	if (!adata->acp_base)
+		return -ENOMEM;
+
+	res = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "acp_dai_irq");
+	if (!res) {
+		dev_err(&pdev->dev, "IORESOURCE_IRQ FAILED\n");
+		return -ENODEV;
+	}
+
+	adata->i2s_irq = res->start;
+	adata->dev = dev;
+	adata->dai_driver = acp_rmb_dai;
+	adata->num_dai = ARRAY_SIZE(acp_rmb_dai);
+	adata->rsrc = &rsrc;
+
+	adata->machines = snd_soc_acpi_amd_rmb_acp_machines;
+	acp_machine_select(adata);
+
+	dev_set_drvdata(dev, adata);
+	acp6x_enable_interrupts(adata);
+	acp_platform_register(dev);
+
+	return 0;
+}
+
+static int rembrandt_audio_remove(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct acp_dev_data *adata = dev_get_drvdata(dev);
+	struct acp_chip_info *chip;
+
+	chip = dev_get_platdata(&pdev->dev);
+	if (!chip || !chip->base) {
+		dev_err(&pdev->dev, "ACP chip data is NULL\n");
+		return -ENODEV;
+	}
+
+	rmb_acp_deinit(chip->base);
+
+	acp6x_disable_interrupts(adata);
+	acp_platform_unregister(dev);
+	return 0;
+}
+
+static struct platform_driver rembrandt_driver = {
+	.probe = rembrandt_audio_probe,
+	.remove = rembrandt_audio_remove,
+	.driver = {
+		.name = "acp_asoc_rembrandt",
+	},
+};
+
+module_platform_driver(rembrandt_driver);
+
+MODULE_DESCRIPTION("AMD ACP Rembrandt Driver");
+MODULE_IMPORT_NS(SND_SOC_ACP_COMMON);
+MODULE_LICENSE("Dual BSD/GPL");
+MODULE_ALIAS("platform:" DRV_NAME);
diff --git a/sound/soc/amd/acp/amd.h b/sound/soc/amd/acp/amd.h
index 186cb8b26175..af9603724a68 100644
--- a/sound/soc/amd/acp/amd.h
+++ b/sound/soc/amd/acp/amd.h
@@ -19,10 +19,12 @@ 
 #include "chip_offset_byte.h"
 
 #define ACP3X_DEV			3
+#define ACP6X_DEV			6
 
 #define I2S_SP_INSTANCE			0x00
 #define I2S_BT_INSTANCE			0x01
 #define DMIC_INSTANCE			0x02
+#define I2S_HS_INSTANCE			0x03
 
 #define MEM_WINDOW_START		0x4080000
 
@@ -38,23 +40,31 @@ 
 #define I2S_TX_THRESHOLD(base)	THRESHOLD(8, base)
 #define BT_TX_THRESHOLD(base)	THRESHOLD(6, base)
 #define BT_RX_THRESHOLD(base)	THRESHOLD(5, base)
+#define HS_TX_THRESHOLD(base)	THRESHOLD(4, base)
+#define HS_RX_THRESHOLD(base)	THRESHOLD(3, base)
 
 #define ACP_SRAM_SP_PB_PTE_OFFSET	0x0
 #define ACP_SRAM_SP_CP_PTE_OFFSET	0x100
 #define ACP_SRAM_BT_PB_PTE_OFFSET	0x200
 #define ACP_SRAM_BT_CP_PTE_OFFSET	0x300
 #define ACP_SRAM_PDM_PTE_OFFSET		0x400
+#define ACP_SRAM_HS_PB_PTE_OFFSET       0x500
+#define ACP_SRAM_HS_CP_PTE_OFFSET       0x600
 #define PAGE_SIZE_4K_ENABLE		0x2
 
 #define I2S_SP_TX_MEM_WINDOW_START	0x4000000
 #define I2S_SP_RX_MEM_WINDOW_START	0x4020000
 #define I2S_BT_TX_MEM_WINDOW_START	0x4040000
 #define I2S_BT_RX_MEM_WINDOW_START	0x4060000
+#define I2S_HS_TX_MEM_WINDOW_START      0x40A0000
+#define I2S_HS_RX_MEM_WINDOW_START      0x40C0000
 
 #define SP_PB_FIFO_ADDR_OFFSET		0x500
 #define SP_CAPT_FIFO_ADDR_OFFSET	0x700
 #define BT_PB_FIFO_ADDR_OFFSET		0x900
 #define BT_CAPT_FIFO_ADDR_OFFSET	0xB00
+#define HS_PB_FIFO_ADDR_OFFSET		0xD00
+#define HS_CAPT_FIFO_ADDR_OFFSET	0xF00
 #define PLAYBACK_MIN_NUM_PERIODS	2
 #define PLAYBACK_MAX_NUM_PERIODS	8
 #define PLAYBACK_MAX_PERIOD_SIZE	8192
@@ -72,7 +82,7 @@ 
 
 #define ACP3x_ITER_IRER_SAMP_LEN_MASK	0x38
 
-#define ACP_MAX_STREAM			6
+#define ACP_MAX_STREAM			8
 
 struct acp_chip_info {
 	char *name;		/* Platform name */
@@ -95,6 +105,7 @@  struct acp_resource {
 	int offset;
 	int no_of_ctrls;
 	int irqp_used;
+	bool soc_mclk;
 	u32 irq_reg_offset;
 	u32 i2s_pin_cfg_offset;
 	int i2s_mode;
@@ -117,9 +128,23 @@  struct acp_dev_data {
 	struct snd_soc_acpi_mach *machines;
 	struct platform_device *mach_dev;
 
+	u32 bclk_div;
+	u32 lrclk_div;
+
 	struct acp_resource *rsrc;
 };
 
+union acp_i2stdm_mstrclkgen {
+	struct {
+		u32 i2stdm_master_mode : 1;
+		u32 i2stdm_format_mode : 1;
+		u32 i2stdm_lrclk_div_val : 9;
+		u32 i2stdm_bclk_div_val : 11;
+		u32:10;
+	} bitfields, bits;
+	u32  u32_all;
+};
+
 extern const struct snd_soc_dai_ops asoc_acp_cpu_dai_ops;
 extern const struct snd_soc_dai_ops acp_dmic_dai_ops;
 
@@ -146,6 +171,10 @@  static inline u64 acp_get_byte_count(struct acp_dev_data *adata, int dai_id, int
 			high = readl(adata->acp_base + ACP_I2S_TX_LINEARPOSITIONCNTR_HIGH);
 			low = readl(adata->acp_base + ACP_I2S_TX_LINEARPOSITIONCNTR_LOW);
 			break;
+		case I2S_HS_INSTANCE:
+			high = readl(adata->acp_base + ACP_HS_TX_LINEARPOSITIONCNTR_HIGH);
+			low = readl(adata->acp_base + ACP_HS_TX_LINEARPOSITIONCNTR_LOW);
+			break;
 		default:
 			dev_err(adata->dev, "Invalid dai id %x\n", dai_id);
 			return -EINVAL;
@@ -160,6 +189,10 @@  static inline u64 acp_get_byte_count(struct acp_dev_data *adata, int dai_id, int
 			high = readl(adata->acp_base + ACP_I2S_RX_LINEARPOSITIONCNTR_HIGH);
 			low = readl(adata->acp_base + ACP_I2S_RX_LINEARPOSITIONCNTR_LOW);
 			break;
+		case I2S_HS_INSTANCE:
+			high = readl(adata->acp_base + ACP_HS_RX_LINEARPOSITIONCNTR_HIGH);
+			low = readl(adata->acp_base + ACP_HS_RX_LINEARPOSITIONCNTR_LOW);
+			break;
 		case DMIC_INSTANCE:
 			high = readl(adata->acp_base + ACP_WOV_RX_LINEARPOSITIONCNTR_HIGH);
 			low = readl(adata->acp_base + ACP_WOV_RX_LINEARPOSITIONCNTR_LOW);
@@ -175,4 +208,31 @@  static inline u64 acp_get_byte_count(struct acp_dev_data *adata, int dai_id, int
 	return byte_count;
 }
 
+static inline void acp_set_i2s_clk(struct acp_dev_data *adata, int dai_id)
+{
+	union acp_i2stdm_mstrclkgen mclkgen;
+	u32 master_reg;
+
+	switch (dai_id) {
+	case I2S_SP_INSTANCE:
+		master_reg = ACP_I2STDM0_MSTRCLKGEN;
+		break;
+	case I2S_BT_INSTANCE:
+		master_reg = ACP_I2STDM1_MSTRCLKGEN;
+		break;
+	case I2S_HS_INSTANCE:
+		master_reg = ACP_I2STDM2_MSTRCLKGEN;
+		break;
+	default:
+		master_reg = ACP_I2STDM0_MSTRCLKGEN;
+		break;
+	}
+
+	mclkgen.bits.i2stdm_master_mode = 0x1;
+	mclkgen.bits.i2stdm_format_mode = 0x00;
+
+	mclkgen.bits.i2stdm_bclk_div_val = adata->bclk_div;
+	mclkgen.bits.i2stdm_lrclk_div_val = adata->lrclk_div;
+	writel(mclkgen.u32_all, adata->acp_base + master_reg);
+}
 #endif
diff --git a/sound/soc/amd/acp/chip_offset_byte.h b/sound/soc/amd/acp/chip_offset_byte.h
index fff7e80475ba..ce3948e0679c 100644
--- a/sound/soc/amd/acp/chip_offset_byte.h
+++ b/sound/soc/amd/acp/chip_offset_byte.h
@@ -66,6 +66,24 @@ 
 #define ACP_BT_TX_LINEARPOSITIONCNTR_HIGH             0x2084
 #define ACP_BT_TX_LINEARPOSITIONCNTR_LOW              0x2088
 #define ACP_BT_TX_INTR_WATERMARK_SIZE                 0x208C
+#define ACP_HS_RX_RINGBUFADDR			      0x3A90
+#define ACP_HS_RX_RINGBUFSIZE			      0x3A94
+#define ACP_HS_RX_LINKPOSITIONCNTR		      0x3A98
+#define ACP_HS_RX_FIFOADDR			      0x3A9C
+#define ACP_HS_RX_FIFOSIZE			      0x3AA0
+#define ACP_HS_RX_DMA_SIZE			      0x3AA4
+#define ACP_HS_RX_LINEARPOSITIONCNTR_HIGH	      0x3AA8
+#define ACP_HS_RX_LINEARPOSITIONCNTR_LOW	      0x3AAC
+#define ACP_HS_RX_INTR_WATERMARK_SIZE		      0x3AB0
+#define ACP_HS_TX_RINGBUFADDR			      0x3AB4
+#define ACP_HS_TX_RINGBUFSIZE			      0x3AB8
+#define ACP_HS_TX_LINKPOSITIONCNTR		      0x3ABC
+#define ACP_HS_TX_FIFOADDR			      0x3AC0
+#define ACP_HS_TX_FIFOSIZE			      0x3AC4
+#define ACP_HS_TX_DMA_SIZE			      0x3AC8
+#define ACP_HS_TX_LINEARPOSITIONCNTR_HIGH	      0x3ACC
+#define ACP_HS_TX_LINEARPOSITIONCNTR_LOW	      0x3AD0
+#define ACP_HS_TX_INTR_WATERMARK_SIZE		      0x3AD4
 
 #define ACP_I2STDM_IER                                0x2400
 #define ACP_I2STDM_IRER                               0x2404
@@ -81,6 +99,13 @@ 
 #define ACP_BTTDM_ITER                                0x280C
 #define ACP_BTTDM_TXFRMT                              0x2810
 
+/* Registers from ACP_HS_TDM block */
+#define ACP_HSTDM_IER                                 0x2814
+#define ACP_HSTDM_IRER                                0x2818
+#define ACP_HSTDM_RXFRMT                              0x281C
+#define ACP_HSTDM_ITER                                0x2820
+#define ACP_HSTDM_TXFRMT                              0x2824
+
 /* Registers from ACP_WOV_PDM block */
 
 #define ACP_WOV_PDM_ENABLE                            0x2C04
@@ -101,4 +126,7 @@ 
 #define ACP_PDM_VAD_DYNAMIC_CLK_GATING_EN             0x2C64
 #define ACP_WOV_ERROR_STATUS_REGISTER                 0x2C68
 
+#define ACP_I2STDM0_MSTRCLKGEN			      0x2414
+#define ACP_I2STDM1_MSTRCLKGEN			      0x2418
+#define ACP_I2STDM2_MSTRCLKGEN			      0x241C
 #endif