aboutsummaryrefslogtreecommitdiffstats
path: root/common/recipes-kernel/linux/linux-yocto-4.19.8/0581-amd-i2s-i2s-audio-driver-for-raven-family.patch
diff options
context:
space:
mode:
Diffstat (limited to 'common/recipes-kernel/linux/linux-yocto-4.19.8/0581-amd-i2s-i2s-audio-driver-for-raven-family.patch')
-rw-r--r--common/recipes-kernel/linux/linux-yocto-4.19.8/0581-amd-i2s-i2s-audio-driver-for-raven-family.patch2045
1 files changed, 2045 insertions, 0 deletions
diff --git a/common/recipes-kernel/linux/linux-yocto-4.19.8/0581-amd-i2s-i2s-audio-driver-for-raven-family.patch b/common/recipes-kernel/linux/linux-yocto-4.19.8/0581-amd-i2s-i2s-audio-driver-for-raven-family.patch
new file mode 100644
index 00000000..8ae6f1a1
--- /dev/null
+++ b/common/recipes-kernel/linux/linux-yocto-4.19.8/0581-amd-i2s-i2s-audio-driver-for-raven-family.patch
@@ -0,0 +1,2045 @@
+From df835d22aab1da078631052550420c55b55e3900 Mon Sep 17 00:00:00 2001
+From: Sudheesh Mavila <sudheesh.mavila@amd.com>
+Date: Thu, 24 Jan 2019 11:01:14 +0530
+Subject: [PATCH 0581/2940] amd-i2s i2s audio driver for raven family
+
+Signed-off-by: Sudheesh Mavila <sudheesh.mavila@amd.com>
+---
+ sound/soc/amd/Kconfig | 5 +
+ sound/soc/amd/Makefile | 2 +
+ sound/soc/amd/raven/Makefile | 8 +
+ sound/soc/amd/raven/acp3x-dummy5102.c | 161 +++++
+ sound/soc/amd/raven/acp3x-pcm-dma.c | 797 +++++++++++++++++++++++++
+ sound/soc/amd/raven/acp3x.h | 34 ++
+ sound/soc/amd/raven/chip_offset_byte.h | 655 ++++++++++++++++++++
+ sound/soc/amd/raven/dummy-w5102.c | 93 +++
+ sound/soc/amd/raven/pci-acp3x.c | 192 ++++++
+ 9 files changed, 1947 insertions(+)
+ mode change 100644 => 100755 sound/soc/amd/Kconfig
+ mode change 100644 => 100755 sound/soc/amd/Makefile
+ create mode 100755 sound/soc/amd/raven/Makefile
+ create mode 100755 sound/soc/amd/raven/acp3x-dummy5102.c
+ create mode 100755 sound/soc/amd/raven/acp3x-pcm-dma.c
+ create mode 100755 sound/soc/amd/raven/acp3x.h
+ create mode 100755 sound/soc/amd/raven/chip_offset_byte.h
+ create mode 100755 sound/soc/amd/raven/dummy-w5102.c
+ create mode 100755 sound/soc/amd/raven/pci-acp3x.c
+
+diff --git a/sound/soc/amd/Kconfig b/sound/soc/amd/Kconfig
+old mode 100644
+new mode 100755
+index 58c1dcb4d255..4daaf50fa0ef
+--- a/sound/soc/amd/Kconfig
++++ b/sound/soc/amd/Kconfig
+@@ -2,6 +2,11 @@ config SND_SOC_AMD_ACP
+ tristate "AMD Audio Coprocessor support"
+ help
+ This option enables ACP DMA support on AMD platform.
++
++config SND_SOC_AMD_ACP3x
++ tristate "AMD Audio Coprocessor-v3.x support"
++ help
++ This option enables ACP v3.x I2S support on AMD platform.
+
+ config SND_SOC_AMD_CZ_DA7219MX98357_MACH
+ tristate "AMD CZ support for DA7219 and MAX9835"
+diff --git a/sound/soc/amd/Makefile b/sound/soc/amd/Makefile
+old mode 100644
+new mode 100755
+index 79b0622fa5d3..0bd6628cd9cf
+--- a/sound/soc/amd/Makefile
++++ b/sound/soc/amd/Makefile
+@@ -2,6 +2,8 @@ acp_audio_dma-objs := acp-pcm-dma.o
+ snd-soc-acp-da7219mx98357-mach-objs := acp-da7219-max98357a.o
+ snd-soc-acp-rt5645-mach-objs := acp-rt5645.o
+
++obj-$(CONFIG_SND_SOC_AMD_ACP3x) += raven/
++
+ obj-$(CONFIG_SND_SOC_AMD_ACP) += acp_audio_dma.o
+ obj-$(CONFIG_SND_SOC_AMD_CZ_DA7219MX98357_MACH) += snd-soc-acp-da7219mx98357-mach.o
+ obj-$(CONFIG_SND_SOC_AMD_CZ_RT5645_MACH) += snd-soc-acp-rt5645-mach.o
+diff --git a/sound/soc/amd/raven/Makefile b/sound/soc/amd/raven/Makefile
+new file mode 100755
+index 000000000000..5db3afcb80bc
+--- /dev/null
++++ b/sound/soc/amd/raven/Makefile
+@@ -0,0 +1,8 @@
++snd-pci-acp3x-objs := pci-acp3x.o
++snd-acp3x-pcm-dma-objs := acp3x-pcm-dma.o
++snd-soc-dummy-w5102-objs := dummy-w5102.o
++snd-soc-acp3x-mach-objs := acp3x-dummy5102.o
++obj-$(CONFIG_SND_SOC_AMD_ACP3x) += snd-pci-acp3x.o
++obj-$(CONFIG_SND_SOC_AMD_ACP3x) += snd-acp3x-pcm-dma.o
++obj-$(CONFIG_SND_SOC_AMD_ACP3x) += snd-soc-dummy-w5102.o
++obj-$(CONFIG_SND_SOC_AMD_ACP3x) += snd-soc-acp3x-mach.o
+diff --git a/sound/soc/amd/raven/acp3x-dummy5102.c b/sound/soc/amd/raven/acp3x-dummy5102.c
+new file mode 100755
+index 000000000000..5ea717f26a4c
+--- /dev/null
++++ b/sound/soc/amd/raven/acp3x-dummy5102.c
+@@ -0,0 +1,161 @@
++/*
++ * Machine driver for AMD ACP Audio engine using dummy codec
++ *
++ * Copyright 2016 Advanced Micro Devices, Inc.
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining a
++ * copy of this software and associated documentation files (the "Software"),
++ * to deal in the Software without restriction, including without limitation
++ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
++ * and/or sell copies of the Software, and to permit persons to whom the
++ * Software is furnished to do so, subject to the following conditions:
++ *
++ * The above copyright notice and this permission notice shall be included in
++ * all copies or substantial portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
++ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
++ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
++ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
++ * OTHER DEALINGS IN THE SOFTWARE.
++ *
++ *
++ */
++
++#include <sound/soc.h>
++#include <sound/soc-dapm.h>
++#include <linux/module.h>
++#include <sound/pcm.h>
++#include <sound/pcm_params.h>
++
++static int acp3x_hw_params(struct snd_pcm_substream *substream,
++ struct snd_pcm_hw_params *params)
++
++{
++ struct snd_soc_pcm_runtime *rtd = substream->private_data;
++ struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
++ unsigned int fmt;
++ unsigned int slot_width;
++ unsigned int channels;
++ int ret = 0;
++
++ fmt = params_format(params);
++ switch (fmt) {
++ case SNDRV_PCM_FORMAT_S16_LE:
++ slot_width = 16;
++ break;
++ case SNDRV_PCM_FORMAT_S24_LE:
++ slot_width = 32;
++ break;
++ case SNDRV_PCM_FORMAT_S32_LE:
++ slot_width = 32;
++ break;
++ default:
++ printk(KERN_WARNING "acp3x: unsupported PCM format");
++ return -EINVAL;
++ }
++
++ channels = params_channels(params);
++
++ if (channels == 0x04) {
++ ret = snd_soc_dai_set_tdm_slot(cpu_dai, 0x3, 0x3, 4, slot_width);
++ if (ret < 0)
++ return ret;
++ } else {
++ ret = snd_soc_dai_set_tdm_slot(cpu_dai, 0x3, 0x3, 2, slot_width);
++ if (ret < 0)
++ return ret;
++ }
++ return 0;
++}
++
++static struct snd_soc_ops acp3x_wm5102_ops = {
++ .hw_params = acp3x_hw_params,
++};
++
++static int acp3x_init(struct snd_soc_pcm_runtime *rtd)
++{
++ return 0;
++}
++
++static struct snd_soc_dai_link acp3x_dai_w5102[] = {
++ {
++ .name = "RV-W5102-PLAY",
++ .stream_name = "Playback",
++ .platform_name = "acp3x_rv_i2s.0",
++ .cpu_dai_name = "acp3x_rv_i2s.0",
++ .codec_dai_name = "dummy_w5102_dai",
++ .codec_name = "dummy_w5102.0",
++ .dai_fmt = SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_NB_NF
++ | SND_SOC_DAIFMT_CBM_CFM,
++ .ops = &acp3x_wm5102_ops,
++ .init = acp3x_init,
++ },
++};
++
++static const struct snd_soc_dapm_widget acp3x_widgets[] = {
++ SND_SOC_DAPM_HP("Headphones", NULL),
++ SND_SOC_DAPM_MIC("Analog Mic", NULL),
++};
++
++static const struct snd_soc_dapm_route acp3x_audio_route[] = {
++ {"Headphones", NULL, "HPO L"},
++ {"Headphones", NULL, "HPO R"},
++ {"MIC1", NULL, "Analog Mic"},
++};
++
++static struct snd_soc_card acp3x_card = {
++ .name = "acp3x",
++ .owner = THIS_MODULE,
++ .dai_link = acp3x_dai_w5102,
++ .num_links = 1,
++};
++
++static int acp3x_probe(struct platform_device *pdev)
++{
++ int ret;
++ struct acp_wm5102 *machine = NULL;
++ struct snd_soc_card *card;
++
++ card = &acp3x_card;
++ acp3x_card.dev = &pdev->dev;
++
++ platform_set_drvdata(pdev, card);
++ snd_soc_card_set_drvdata(card, machine);
++
++ ret = devm_snd_soc_register_card(&pdev->dev, card);
++ if (ret) {
++ dev_err(&pdev->dev,
++ "snd_soc_register_card(%s) failed: %d\n",
++ acp3x_card.name, ret);
++ return ret;
++ }
++ return 0;
++}
++
++static struct platform_driver acp3x_mach_driver = {
++ .driver = {
++ .name = "acp3x_w5102_mach",
++ .pm = &snd_soc_pm_ops,
++ },
++ .probe = acp3x_probe,
++};
++
++static int __init acp3x_audio_init(void)
++{
++ platform_driver_register(&acp3x_mach_driver);
++ return 0;
++}
++
++static void __exit acp3x_audio_exit(void)
++{
++ platform_driver_unregister(&acp3x_mach_driver);
++}
++
++module_init(acp3x_audio_init);
++module_exit(acp3x_audio_exit);
++
++MODULE_AUTHOR("Maruthi.Bayyavarapu@amd.com");
++MODULE_LICENSE("GPL v2");
+diff --git a/sound/soc/amd/raven/acp3x-pcm-dma.c b/sound/soc/amd/raven/acp3x-pcm-dma.c
+new file mode 100755
+index 000000000000..3faf3456e35b
+--- /dev/null
++++ b/sound/soc/amd/raven/acp3x-pcm-dma.c
+@@ -0,0 +1,797 @@
++/*
++ * AMD ALSA SoC PCM Driver
++ *
++ * Copyright 2016 Advanced Micro Devices, Inc.
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms and conditions of the GNU General Public License,
++ * version 2, as published by the Free Software Foundation.
++ *
++ * This program is distributed in the hope it will be useful, but WITHOUT
++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
++ * more details.
++ */
++
++#include <linux/platform_device.h>
++#include <linux/module.h>
++#include <linux/err.h>
++#include <linux/pm_runtime.h>
++#include <linux/io.h>
++
++#include <sound/pcm.h>
++#include <sound/pcm_params.h>
++#include <sound/soc.h>
++#include <sound/soc-dai.h>
++
++#include "acp3x.h"
++#define DRV_NAME "acp3x-i2s-audio"
++
++struct i2s_dev_data {
++ bool tdm_mode;
++ unsigned int i2s_irq;
++ u32 tdm_fmt;
++ void __iomem *acp3x_base;
++ struct snd_pcm_substream *play_stream;
++ struct snd_pcm_substream *capture_stream;
++};
++
++struct i2s_stream_instance {
++ u16 num_pages;
++ u16 channels;
++ u32 xfer_resolution;
++ u32 val;
++ struct page *pg;
++ void __iomem *acp3x_base;
++};
++
++static const struct snd_pcm_hardware acp3x_pcm_hardware_playback = {
++ .info = SNDRV_PCM_INFO_INTERLEAVED |
++ SNDRV_PCM_INFO_BLOCK_TRANSFER |
++ SNDRV_PCM_INFO_BATCH |
++ SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME,
++ .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8 |
++ SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S24_LE |
++ SNDRV_PCM_FMTBIT_S32_LE,
++ .channels_min = 2,
++ .channels_max = 6,
++ .rates = SNDRV_PCM_RATE_8000_96000,
++ .rate_min = 8000,
++ .rate_max = 96000,
++ .buffer_bytes_max = PLAYBACK_MAX_NUM_PERIODS * PLAYBACK_MAX_PERIOD_SIZE,
++ .period_bytes_min = PLAYBACK_MIN_PERIOD_SIZE,
++ .period_bytes_max = PLAYBACK_MAX_PERIOD_SIZE,
++ .periods_min = PLAYBACK_MIN_NUM_PERIODS,
++ .periods_max = PLAYBACK_MAX_NUM_PERIODS,
++};
++
++static const struct snd_pcm_hardware acp3x_pcm_hardware_capture = {
++ .info = SNDRV_PCM_INFO_INTERLEAVED |
++ SNDRV_PCM_INFO_BLOCK_TRANSFER |
++ SNDRV_PCM_INFO_BATCH |
++ SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME,
++ .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8 |
++ SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S24_LE |
++ SNDRV_PCM_FMTBIT_S32_LE,
++ .channels_min = 2,
++ .channels_max = 2,
++ .rates = SNDRV_PCM_RATE_8000_48000,
++ .rate_min = 8000,
++ .rate_max = 48000,
++ .buffer_bytes_max = CAPTURE_MAX_NUM_PERIODS * CAPTURE_MAX_PERIOD_SIZE,
++ .period_bytes_min = CAPTURE_MIN_PERIOD_SIZE,
++ .period_bytes_max = CAPTURE_MAX_PERIOD_SIZE,
++ .periods_min = CAPTURE_MIN_NUM_PERIODS,
++ .periods_max = CAPTURE_MAX_NUM_PERIODS,
++};
++
++static int acp3x_power_on(void __iomem *acp3x_base, bool on)
++{
++ u16 val, mask;
++ u32 timeout;
++
++ if (on == true) {
++ val = 1;
++ mask = 0;
++ } else {
++ val = 0;
++ mask = 2;
++ }
++
++ rv_writel(val, acp3x_base + mmACP_PGFSM_CONTROL);
++ timeout = 0;
++ while (true) {
++ val = rv_readl(acp3x_base + mmACP_PGFSM_STATUS);
++ if ((val & 0x3) == mask)
++ break;
++ if (timeout > 100) {
++ pr_err("ACP3x power state change failure\n");
++ return -ENODEV;
++ }
++ timeout++;
++ cpu_relax();
++ }
++ return 0;
++}
++
++static int acp3x_reset(void __iomem *acp3x_base)
++{
++ u32 val, timeout;
++
++ rv_writel(1, acp3x_base + mmACP_SOFT_RESET);
++ timeout = 0;
++ while (true) {
++ val = rv_readl(acp3x_base + mmACP_SOFT_RESET);
++ if ((val & 0x00010001) || timeout > 100) {
++ if (val & 0x00010001)
++ break;
++ return -ENODEV;
++ }
++ timeout++;
++ cpu_relax();
++ }
++
++ rv_writel(0, acp3x_base + mmACP_SOFT_RESET);
++ timeout = 0;
++ while (true) {
++ val = rv_readl(acp3x_base + mmACP_SOFT_RESET);
++ if (!val || timeout > 100) {
++ if (!val)
++ break;
++ return -ENODEV;
++ }
++ timeout++;
++ cpu_relax();
++ }
++ return 0;
++}
++
++static int acp3x_init(void __iomem *acp3x_base)
++{
++ int ret;
++
++ /* power on */
++ ret = acp3x_power_on(acp3x_base, true);
++ if (ret) {
++ pr_err("ACP3x power on failed\n");
++ return ret;
++ }
++
++ /* Reset */
++ ret = acp3x_reset(acp3x_base);
++ if (ret) {
++ pr_err("ACP3x reset failed\n");
++ return ret;
++ }
++
++ pr_info("ACP Initialized\n");
++ return 0;
++}
++
++static int acp3x_deinit(void __iomem *acp3x_base)
++{
++ int ret;
++
++ /* Reset */
++ ret = acp3x_reset(acp3x_base);
++ if (ret) {
++ pr_err("ACP3x reset failed\n");
++ return ret;
++ }
++
++ /* power off */
++ ret = acp3x_power_on(acp3x_base, false);
++ if (ret) {
++ pr_err("ACP3x power off failed\n");
++ return ret;
++ }
++
++ pr_info("ACP De-Initialized\n");
++ return 0;
++}
++
++static irqreturn_t i2s_irq_handler(int irq, void *dev_id)
++{
++ u16 play_flag, cap_flag;
++ u32 val;
++ struct i2s_dev_data *rv_i2s_data = dev_id;
++
++ if (rv_i2s_data == NULL)
++ return IRQ_NONE;
++
++ play_flag = cap_flag = 0;
++
++ val = rv_readl(rv_i2s_data->acp3x_base + mmACP_EXTERNAL_INTR_STAT);
++ if ((val & BIT(BT_TX_THRESHOLD)) && (rv_i2s_data->play_stream)) {
++ rv_writel(BIT(BT_TX_THRESHOLD), rv_i2s_data->acp3x_base +
++ mmACP_EXTERNAL_INTR_STAT);
++ snd_pcm_period_elapsed(rv_i2s_data->play_stream);
++ play_flag = 1;
++ }
++
++ if ((val & BIT(BT_RX_THRESHOLD)) && rv_i2s_data->capture_stream) {
++ rv_writel(BIT(BT_RX_THRESHOLD), rv_i2s_data->acp3x_base +
++ mmACP_EXTERNAL_INTR_STAT);
++ snd_pcm_period_elapsed(rv_i2s_data->capture_stream);
++ cap_flag = 1;
++ }
++
++ if (play_flag | cap_flag)
++ return IRQ_HANDLED;
++ else
++ return IRQ_NONE;
++}
++
++static void config_acp3x_dma(struct i2s_stream_instance *rtd, int direction)
++{
++ u16 page_idx;
++ u64 addr;
++ u32 low, high, val, acp_fifo_addr;
++ struct page *pg = rtd->pg;
++
++ /* 8 scratch registers used to map one 64 bit address.
++ * For 2 pages (8192 * 2 bytes), it will be 16 registers.
++ */
++ if (direction == SNDRV_PCM_STREAM_PLAYBACK)
++ val = 0;
++ else
++ val = rtd->num_pages * 8;
++
++ for (page_idx = 0; page_idx < rtd->num_pages; page_idx++) {
++ /* Load the low address of page int ACP SRAM through SRBM */
++ addr = page_to_phys(pg);
++ low = lower_32_bits(addr);
++ high = upper_32_bits(addr);
++
++ rv_writel(low, rtd->acp3x_base + mmACP_SCRATCH_REG_0 + val);
++ high |= BIT(31);
++ rv_writel(high, rtd->acp3x_base + mmACP_SCRATCH_REG_0 + val
++ + 4);
++ /* Move to next physically contiguos page */
++ val += 8;
++ pg++;
++ }
++
++ if (direction == SNDRV_PCM_STREAM_PLAYBACK) {
++ /* Config ringbuffer */
++ rv_writel(MEM_WINDOW_START, rtd->acp3x_base +
++ mmACP_BT_TX_RINGBUFADDR);
++ rv_writel(MAX_BUFFER, rtd->acp3x_base +
++ mmACP_BT_TX_RINGBUFSIZE);
++ rv_writel(0x40, rtd->acp3x_base + mmACP_BT_TX_DMA_SIZE);
++
++ /* Config audio fifo */
++ acp_fifo_addr = ACP_SRAM_PTE_OFFSET + (rtd->num_pages * 8)
++ + 1024;
++ rv_writel(acp_fifo_addr, rtd->acp3x_base +
++ mmACP_BT_TX_FIFOADDR);
++ rv_writel(256, rtd->acp3x_base + mmACP_BT_TX_FIFOSIZE);
++ rv_writel(PLAYBACK_MIN_PERIOD_SIZE, rtd->acp3x_base +
++ mmACP_BT_TX_INTR_WATERMARK_SIZE);
++ } else {
++ /* Config ringbuffer */
++ rv_writel(MEM_WINDOW_START + MAX_BUFFER, rtd->acp3x_base +
++ mmACP_BT_RX_RINGBUFADDR);
++ rv_writel(MAX_BUFFER, rtd->acp3x_base +
++ mmACP_BT_RX_RINGBUFSIZE);
++ rv_writel(0x40, rtd->acp3x_base + mmACP_BT_RX_DMA_SIZE);
++
++ /* Config audio fifo */
++ acp_fifo_addr = ACP_SRAM_PTE_OFFSET +
++ (rtd->num_pages * 8) + 1024 + 256;
++ rv_writel(acp_fifo_addr, rtd->acp3x_base +
++ mmACP_BT_RX_FIFOADDR);
++ rv_writel(256, rtd->acp3x_base + mmACP_BT_RX_FIFOSIZE);
++ rv_writel(CAPTURE_MIN_PERIOD_SIZE, rtd->acp3x_base +
++ mmACP_BT_RX_INTR_WATERMARK_SIZE);
++ }
++
++ /* Enable watermark/period interrupt to host */
++ rv_writel(BIT(BT_TX_THRESHOLD) | BIT(BT_RX_THRESHOLD),
++ rtd->acp3x_base + mmACP_EXTERNAL_INTR_CNTL);
++ rv_writel(BIT(0), rtd->acp3x_base + mmACPAXI2AXI_ATU_CTRL);
++}
++
++static int acp3x_dma_open(struct snd_pcm_substream *substream)
++{
++ int ret = 0;
++
++ struct snd_pcm_runtime *runtime = substream->runtime;
++ struct snd_soc_pcm_runtime *prtd = substream->private_data;
++ struct snd_soc_component *component = snd_soc_rtdcom_lookup(prtd,
++ DRV_NAME);
++ struct i2s_dev_data *adata = dev_get_drvdata(component->dev);
++
++ struct i2s_stream_instance *i2s_data = kzalloc(sizeof(
++ struct i2s_stream_instance), GFP_KERNEL);
++ if (i2s_data == NULL)
++ return -EINVAL;
++
++ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
++ runtime->hw = acp3x_pcm_hardware_playback;
++ else
++ runtime->hw = acp3x_pcm_hardware_capture;
++
++ ret = snd_pcm_hw_constraint_integer(runtime,
++ SNDRV_PCM_HW_PARAM_PERIODS);
++ if (ret < 0) {
++ dev_err(component->dev, "set integer constraint failed\n");
++ return ret;
++ }
++
++ if (!adata->play_stream && !adata->capture_stream)
++ rv_writel(1, adata->acp3x_base + mmACP_EXTERNAL_INTR_ENB);
++
++ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
++ adata->play_stream = substream;
++ else
++ adata->capture_stream = substream;
++
++ i2s_data->acp3x_base = adata->acp3x_base;
++ runtime->private_data = i2s_data;
++ return 0;
++}
++
++static int acp3x_dma_hw_params(struct snd_pcm_substream *substream,
++ struct snd_pcm_hw_params *params)
++{
++ int status;
++ uint64_t size;
++ struct snd_dma_buffer *dma_buffer;
++ struct page *pg;
++ struct i2s_stream_instance *rtd = substream->runtime->private_data;
++
++ if (rtd == NULL)
++ return -EINVAL;
++
++ dma_buffer = &substream->dma_buffer;
++ size = params_buffer_bytes(params);
++ status = snd_pcm_lib_malloc_pages(substream, size);
++ if (status < 0)
++ return status;
++
++ memset(substream->runtime->dma_area, 0, params_buffer_bytes(params));
++ pg = virt_to_page(substream->dma_buffer.area);
++ if (pg != NULL) {
++ rtd->pg = pg;
++ rtd->num_pages = (PAGE_ALIGN(size) >> PAGE_SHIFT);
++ config_acp3x_dma(rtd, substream->stream);
++ status = 0;
++ } else {
++ status = -ENOMEM;
++ }
++ return status;
++}
++
++static snd_pcm_uframes_t acp3x_dma_pointer(struct snd_pcm_substream *substream)
++{
++ u32 pos = 0;
++ struct i2s_stream_instance *rtd = substream->runtime->private_data;
++
++ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
++ pos = rv_readl(rtd->acp3x_base +
++ mmACP_BT_TX_LINKPOSITIONCNTR);
++ else
++ pos = rv_readl(rtd->acp3x_base +
++ mmACP_BT_RX_LINKPOSITIONCNTR);
++
++ if (pos >= MAX_BUFFER)
++ pos = 0;
++
++ return bytes_to_frames(substream->runtime, pos);
++}
++
++static int acp3x_dma_new(struct snd_soc_pcm_runtime *rtd)
++{
++ return snd_pcm_lib_preallocate_pages_for_all(rtd->pcm,
++ SNDRV_DMA_TYPE_DEV,
++ NULL, MIN_BUFFER,
++ MAX_BUFFER);
++}
++
++static int acp3x_dma_hw_free(struct snd_pcm_substream *substream)
++{
++ return snd_pcm_lib_free_pages(substream);
++}
++
++static int acp3x_dma_mmap(struct snd_pcm_substream *substream,
++ struct vm_area_struct *vma)
++{
++ return snd_pcm_lib_default_mmap(substream, vma);
++}
++
++static int acp3x_dma_close(struct snd_pcm_substream *substream)
++{
++ struct snd_soc_pcm_runtime *prtd = substream->private_data;
++ struct snd_soc_component *component = snd_soc_rtdcom_lookup(prtd,
++ DRV_NAME);
++ struct i2s_dev_data *adata = dev_get_drvdata(component->dev);
++ struct i2s_stream_instance *rtd = substream->runtime->private_data;
++
++ kfree(rtd);
++
++ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
++ adata->play_stream = NULL;
++ else
++ adata->capture_stream = NULL;
++
++ /* Disable ACP irq, when the current stream is being closed and
++ * another stream is also not active.
++ */
++ if (!adata->play_stream && !adata->capture_stream)
++ rv_writel(0, adata->acp3x_base + mmACP_EXTERNAL_INTR_ENB);
++
++ return 0;
++}
++
++static struct snd_pcm_ops acp3x_dma_ops = {
++ .open = acp3x_dma_open,
++ .close = acp3x_dma_close,
++ .ioctl = snd_pcm_lib_ioctl,
++ .hw_params = acp3x_dma_hw_params,
++ .hw_free = acp3x_dma_hw_free,
++ .pointer = acp3x_dma_pointer,
++ .mmap = acp3x_dma_mmap,
++};
++
++static int acp3x_dai_i2s_set_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt)
++{
++
++ struct i2s_dev_data *adata = snd_soc_dai_get_drvdata(cpu_dai);
++
++ switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
++ case SND_SOC_DAIFMT_I2S:
++ adata->tdm_mode = false;
++ break;
++ case SND_SOC_DAIFMT_DSP_A:
++ adata->tdm_mode = true;
++ break;
++ default:
++ return -EINVAL;
++ }
++
++ return 0;
++}
++
++static int acp3x_dai_set_tdm_slot(struct snd_soc_dai *cpu_dai, u32 tx_mask,
++ u32 rx_mask, int slots, int slot_width)
++{
++ u32 val = 0;
++ u16 slot_len;
++
++ struct i2s_dev_data *adata = snd_soc_dai_get_drvdata(cpu_dai);
++
++ switch (slot_width) {
++ case 8:
++ slot_len = 8;
++ break;
++ case 16:
++ slot_len = 16;
++ break;
++ case 24:
++ slot_len = 24;
++ break;
++ case 32:
++ slot_len = 0;
++ break;
++ default:
++ return -EINVAL;
++ break;
++ }
++
++ val = rv_readl(adata->acp3x_base + mmACP_BTTDM_ITER);
++ rv_writel((val | 0x2), adata->acp3x_base + mmACP_BTTDM_ITER);
++ val = rv_readl(adata->acp3x_base + mmACP_BTTDM_IRER);
++ rv_writel((val | 0x2), adata->acp3x_base + mmACP_BTTDM_IRER);
++
++ val = (FRM_LEN | ((slots) << 15) | (slot_len << 18));
++ rv_writel(val, adata->acp3x_base + mmACP_BTTDM_TXFRMT);
++ rv_writel(val, adata->acp3x_base + mmACP_BTTDM_RXFRMT);
++
++ adata->tdm_fmt = val;
++ return 0;
++}
++
++static int acp3x_dai_i2s_hwparams(struct snd_pcm_substream *substream,
++ struct snd_pcm_hw_params *params,
++ struct snd_soc_dai *dai)
++{
++ u32 val = 0;
++ struct i2s_stream_instance *rtd = substream->runtime->private_data;
++
++ switch (params_format(params)) {
++ case SNDRV_PCM_FORMAT_U8:
++ case SNDRV_PCM_FORMAT_S8:
++ rtd->xfer_resolution = 0x0;
++ break;
++ case SNDRV_PCM_FORMAT_S16_LE:
++ rtd->xfer_resolution = 0x02;
++ break;
++
++ case SNDRV_PCM_FORMAT_S24_LE:
++ rtd->xfer_resolution = 0x04;
++ break;
++ case SNDRV_PCM_FORMAT_S32_LE:
++ rtd->xfer_resolution = 0x05;
++ break;
++ default:
++ return -EINVAL;
++ }
++
++ val = rv_readl(rtd->acp3x_base + mmACP_BTTDM_ITER);
++ val = val | (rtd->xfer_resolution << 3);
++ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
++ rv_writel(val, rtd->acp3x_base + mmACP_BTTDM_ITER);
++ else
++ rv_writel(val, rtd->acp3x_base + mmACP_BTTDM_IRER);
++
++ return 0;
++}
++
++static int acp3x_dai_i2s_trigger(struct snd_pcm_substream *substream,
++ int cmd, struct snd_soc_dai *dai)
++{
++ int ret = 0;
++ struct i2s_stream_instance *rtd = substream->runtime->private_data;
++ u32 val;
++
++ switch (cmd) {
++ case SNDRV_PCM_TRIGGER_START:
++ case SNDRV_PCM_TRIGGER_RESUME:
++ case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
++ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
++ val = rv_readl(rtd->acp3x_base + mmACP_BTTDM_ITER);
++ val = val | BIT(0);
++ rv_writel(val, rtd->acp3x_base + mmACP_BTTDM_ITER);
++ } else {
++ val = rv_readl(rtd->acp3x_base + mmACP_BTTDM_IRER);
++ val = val | BIT(0);
++ rv_writel(val, rtd->acp3x_base + mmACP_BTTDM_IRER);
++ }
++ rv_writel(1, rtd->acp3x_base + mmACP_BTTDM_IER);
++ break;
++
++ case SNDRV_PCM_TRIGGER_STOP:
++ case SNDRV_PCM_TRIGGER_SUSPEND:
++ case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
++ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
++ val = rv_readl(rtd->acp3x_base + mmACP_BTTDM_ITER);
++ val = val & ~BIT(0);
++ rv_writel(val, rtd->acp3x_base + mmACP_BTTDM_ITER);
++ } else {
++ val = rv_readl(rtd->acp3x_base + mmACP_BTTDM_IRER);
++ val = val & ~BIT(0);
++ rv_writel(val, rtd->acp3x_base + mmACP_BTTDM_IRER);
++ }
++ rv_writel(0, rtd->acp3x_base + mmACP_BTTDM_IER);
++ break;
++ default:
++ ret = -EINVAL;
++ break;
++ }
++
++ return ret;
++}
++
++struct snd_soc_dai_ops acp3x_dai_i2s_ops = {
++ .hw_params = acp3x_dai_i2s_hwparams,
++ .trigger = acp3x_dai_i2s_trigger,
++ .set_fmt = acp3x_dai_i2s_set_fmt,
++ .set_tdm_slot = acp3x_dai_set_tdm_slot,
++};
++
++static struct snd_soc_dai_driver acp3x_i2s_dai_driver = {
++ .playback = {
++ .rates = SNDRV_PCM_RATE_8000_96000,
++ .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8 |
++ SNDRV_PCM_FMTBIT_U8 |
++ SNDRV_PCM_FMTBIT_S24_LE |
++ SNDRV_PCM_FMTBIT_S32_LE,
++ .channels_min = 2,
++ .channels_max = 8,
++
++ .rate_min = 8000,
++ .rate_max = 96000,
++ },
++ .capture = {
++ .rates = SNDRV_PCM_RATE_8000_48000,
++ .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8 |
++ SNDRV_PCM_FMTBIT_U8 |
++ SNDRV_PCM_FMTBIT_S24_LE |
++ SNDRV_PCM_FMTBIT_S32_LE,
++ .channels_min = 2,
++ .channels_max = 2,
++ .rate_min = 8000,
++ .rate_max = 48000,
++ },
++ .ops = &acp3x_dai_i2s_ops,
++};
++
++static const struct snd_soc_component_driver acp3x_i2s_component = {
++ .name = DRV_NAME,
++ .ops = &acp3x_dma_ops,
++ .pcm_new = acp3x_dma_new,
++};
++
++static int acp3x_audio_probe(struct platform_device *pdev)
++{
++ int status;
++ struct resource *res;
++ struct i2s_dev_data *adata;
++ unsigned int irqflags;
++
++ if (pdev->dev.platform_data == NULL) {
++ dev_err(&pdev->dev, "platform_data not retrieved\n");
++ return -ENODEV;
++ }
++ irqflags = *((unsigned int *)(pdev->dev.platform_data));
++
++ adata = devm_kzalloc(&pdev->dev, sizeof(struct i2s_dev_data),
++ GFP_KERNEL);
++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++ if (!res) {
++ dev_err(&pdev->dev, "IORESOURCE_IRQ FAILED\n");
++ return -ENODEV;
++ }
++
++ adata->acp3x_base = devm_ioremap(&pdev->dev, res->start,
++ resource_size(res));
++
++ res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
++ if (!res) {
++ dev_err(&pdev->dev, "IORESOURCE_IRQ FAILED\n");
++ return -ENODEV;
++ }
++
++ adata->i2s_irq = res->start;
++ adata->play_stream = NULL;
++ adata->capture_stream = NULL;
++
++ dev_set_drvdata(&pdev->dev, adata);
++ /* Initialize ACP */
++ status = acp3x_init(adata->acp3x_base);
++ if (status)
++ return -ENODEV;
++ /* Group Enable */
++ rv_writel(ACP_SRAM_PTE_OFFSET | BIT(31), adata->acp3x_base +
++ mmACPAXI2AXI_ATU_BASE_ADDR_GRP_1);
++ rv_writel(PAGE_SIZE_4K_ENABLE, adata->acp3x_base +
++ mmACPAXI2AXI_ATU_PAGE_SIZE_GRP_1);
++
++ status = devm_snd_soc_register_component(&pdev->dev,
++ &acp3x_i2s_component, &acp3x_i2s_dai_driver, 1);
++ if (status != 0) {
++ dev_err(&pdev->dev, "Fail to register acp i2s dai\n");
++ goto dev_err;
++ }
++
++ status = devm_request_irq(&pdev->dev, adata->i2s_irq, i2s_irq_handler,
++ irqflags, "ACP3x_I2S_IRQ", adata);
++ if (status) {
++ dev_err(&pdev->dev, "ACP3x I2S IRQ request failed\n");
++ goto dev_err;
++ }
++
++ pm_runtime_set_autosuspend_delay(&pdev->dev, 10000);
++ pm_runtime_use_autosuspend(&pdev->dev);
++ pm_runtime_enable(&pdev->dev);
++ return 0;
++dev_err:
++ status = acp3x_deinit(adata->acp3x_base);
++ if (status)
++ dev_err(&pdev->dev, "ACP de-init failed\n");
++ else
++ dev_info(&pdev->dev, "ACP de-initialized\n");
++ /*ignore device status and return driver probe error*/
++ return -ENODEV;
++}
++
++static int acp3x_audio_remove(struct platform_device *pdev)
++{
++ int ret;
++ struct i2s_dev_data *adata = dev_get_drvdata(&pdev->dev);
++
++ ret = acp3x_deinit(adata->acp3x_base);
++ if (ret)
++ dev_err(&pdev->dev, "ACP de-init failed\n");
++ else
++ dev_info(&pdev->dev, "ACP de-initialized\n");
++
++ pm_runtime_disable(&pdev->dev);
++ return 0;
++}
++
++static int acp3x_resume(struct device *dev)
++{
++ int status;
++ u32 val;
++ struct i2s_dev_data *adata = dev_get_drvdata(dev);
++
++ status = acp3x_init(adata->acp3x_base);
++ if (status)
++ return -ENODEV;
++
++ if (adata->play_stream && adata->play_stream->runtime) {
++ struct i2s_stream_instance *rtd =
++ adata->play_stream->runtime->private_data;
++ config_acp3x_dma(rtd, SNDRV_PCM_STREAM_PLAYBACK);
++ rv_writel((rtd->xfer_resolution << 3),
++ rtd->acp3x_base + mmACP_BTTDM_ITER);
++ if (adata->tdm_mode == true) {
++ rv_writel(adata->tdm_fmt, adata->acp3x_base +
++ mmACP_BTTDM_TXFRMT);
++ val = rv_readl(adata->acp3x_base + mmACP_BTTDM_ITER);
++ rv_writel((val | 0x2), adata->acp3x_base +
++ mmACP_BTTDM_ITER);
++ }
++ }
++
++ if (adata->capture_stream && adata->capture_stream->runtime) {
++ struct i2s_stream_instance *rtd =
++ adata->capture_stream->runtime->private_data;
++ config_acp3x_dma(rtd, SNDRV_PCM_STREAM_CAPTURE);
++ rv_writel((rtd->xfer_resolution << 3),
++ rtd->acp3x_base + mmACP_BTTDM_IRER);
++ if (adata->tdm_mode == true) {
++ rv_writel(adata->tdm_fmt, adata->acp3x_base +
++ mmACP_BTTDM_RXFRMT);
++ val = rv_readl(adata->acp3x_base + mmACP_BTTDM_IRER);
++ rv_writel((val | 0x2), adata->acp3x_base +
++ mmACP_BTTDM_IRER);
++ }
++ }
++
++ rv_writel(1, adata->acp3x_base + mmACP_EXTERNAL_INTR_ENB);
++ return 0;
++}
++
++
++static int acp3x_pcm_runtime_suspend(struct device *dev)
++{
++ int status;
++ struct i2s_dev_data *adata = dev_get_drvdata(dev);
++
++ status = acp3x_deinit(adata->acp3x_base);
++ if (status)
++ dev_err(dev, "ACP de-init failed\n");
++ else
++ dev_info(dev, "ACP de-initialized\n");
++
++ rv_writel(0, adata->acp3x_base + mmACP_EXTERNAL_INTR_ENB);
++
++ return 0;
++}
++
++static int acp3x_pcm_runtime_resume(struct device *dev)
++{
++ int status;
++ struct i2s_dev_data *adata = dev_get_drvdata(dev);
++
++ status = acp3x_init(adata->acp3x_base);
++ if (status)
++ return -ENODEV;
++ rv_writel(1, adata->acp3x_base + mmACP_EXTERNAL_INTR_ENB);
++ return 0;
++}
++
++static const struct dev_pm_ops acp3x_pm_ops = {
++ .runtime_suspend = acp3x_pcm_runtime_suspend,
++ .runtime_resume = acp3x_pcm_runtime_resume,
++ .resume = acp3x_resume,
++};
++
++static struct platform_driver acp3x_dma_driver = {
++ .probe = acp3x_audio_probe,
++ .remove = acp3x_audio_remove,
++ .driver = {
++ .name = "acp3x_rv_i2s",
++ .pm = &acp3x_pm_ops,
++ },
++};
++
++module_platform_driver(acp3x_dma_driver);
++
++MODULE_AUTHOR("Maruthi.Bayyavarapu@amd.com");
++MODULE_DESCRIPTION("AMD ACP 3.x PCM Driver");
++MODULE_LICENSE("GPL v2");
++MODULE_ALIAS("platform:"DRV_NAME);
+diff --git a/sound/soc/amd/raven/acp3x.h b/sound/soc/amd/raven/acp3x.h
+new file mode 100755
+index 000000000000..2e901ee60287
+--- /dev/null
++++ b/sound/soc/amd/raven/acp3x.h
+@@ -0,0 +1,34 @@
++#include "chip_offset_byte.h"
++
++#define ACP3x_PHY_BASE_ADDRESS 0x1240000
++#define ACP3x_I2S_MODE 0
++#define ACP3x_REG_START 0x1240000
++#define ACP3x_REG_END 0x1250200
++#define BT_TX_THRESHOLD 26
++#define BT_RX_THRESHOLD 25
++#define ACP_SRAM_PTE_OFFSET 0x02050000
++#define PAGE_SIZE_4K_ENABLE 0x2
++#define MEM_WINDOW_START 0x4000000
++#define FRM_LEN 256
++
++#define PLAYBACK_MIN_NUM_PERIODS 8
++#define PLAYBACK_MAX_NUM_PERIODS 8
++#define PLAYBACK_MAX_PERIOD_SIZE 8192
++#define PLAYBACK_MIN_PERIOD_SIZE 8192
++#define CAPTURE_MIN_NUM_PERIODS 8
++#define CAPTURE_MAX_NUM_PERIODS 8
++#define CAPTURE_MAX_PERIOD_SIZE 8192
++#define CAPTURE_MIN_PERIOD_SIZE 8192
++
++#define MAX_BUFFER (PLAYBACK_MAX_PERIOD_SIZE * PLAYBACK_MAX_NUM_PERIODS)
++#define MIN_BUFFER MAX_BUFFER
++
++static inline u32 rv_readl(void __iomem *base_addr)
++{
++ return readl(base_addr - ACP3x_PHY_BASE_ADDRESS);
++}
++
++static inline void rv_writel(u32 val, void __iomem *base_addr)
++{
++ writel(val, base_addr - ACP3x_PHY_BASE_ADDRESS);
++}
+diff --git a/sound/soc/amd/raven/chip_offset_byte.h b/sound/soc/amd/raven/chip_offset_byte.h
+new file mode 100755
+index 000000000000..3ce4c361d644
+--- /dev/null
++++ b/sound/soc/amd/raven/chip_offset_byte.h
+@@ -0,0 +1,655 @@
++/*
++ * ACP 3.0 Register documentation
++ *
++ * Copyright (C) 2016 Advanced Micro Devices, Inc.
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining a
++ * copy of this software and associated documentation files (the "Software"),
++ * to deal in the Software without restriction, including without limitation
++ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
++ * and/or sell copies of the Software, and to permit persons to whom the
++ * Software is furnished to do so, subject to the following conditions:
++ *
++ * The above copyright notice and this permission notice shall be included
++ * in all copies or substantial portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
++ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
++ * THE COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
++ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
++ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
++ */
++
++#ifndef _acp_ip_OFFSET_HEADER
++#define _acp_ip_OFFSET_HEADER
++// Registers from ACP_DMA block
++
++#define mmACP_DMA_CNTL_0 0x1240000
++#define mmACP_DMA_CNTL_1 0x1240004
++#define mmACP_DMA_CNTL_2 0x1240008
++#define mmACP_DMA_CNTL_3 0x124000C
++#define mmACP_DMA_CNTL_4 0x1240010
++#define mmACP_DMA_CNTL_5 0x1240014
++#define mmACP_DMA_CNTL_6 0x1240018
++#define mmACP_DMA_CNTL_7 0x124001C
++#define mmACP_DMA_DSCR_STRT_IDX_0 0x1240020
++#define mmACP_DMA_DSCR_STRT_IDX_1 0x1240024
++#define mmACP_DMA_DSCR_STRT_IDX_2 0x1240028
++#define mmACP_DMA_DSCR_STRT_IDX_3 0x124002C
++#define mmACP_DMA_DSCR_STRT_IDX_4 0x1240030
++#define mmACP_DMA_DSCR_STRT_IDX_5 0x1240034
++#define mmACP_DMA_DSCR_STRT_IDX_6 0x1240038
++#define mmACP_DMA_DSCR_STRT_IDX_7 0x124003C
++#define mmACP_DMA_DSCR_CNT_0 0x1240040
++#define mmACP_DMA_DSCR_CNT_1 0x1240044
++#define mmACP_DMA_DSCR_CNT_2 0x1240048
++#define mmACP_DMA_DSCR_CNT_3 0x124004C
++#define mmACP_DMA_DSCR_CNT_4 0x1240050
++#define mmACP_DMA_DSCR_CNT_5 0x1240054
++#define mmACP_DMA_DSCR_CNT_6 0x1240058
++#define mmACP_DMA_DSCR_CNT_7 0x124005C
++#define mmACP_DMA_PRIO_0 0x1240060
++#define mmACP_DMA_PRIO_1 0x1240064
++#define mmACP_DMA_PRIO_2 0x1240068
++#define mmACP_DMA_PRIO_3 0x124006C
++#define mmACP_DMA_PRIO_4 0x1240070
++#define mmACP_DMA_PRIO_5 0x1240074
++#define mmACP_DMA_PRIO_6 0x1240078
++#define mmACP_DMA_PRIO_7 0x124007C
++#define mmACP_DMA_CUR_DSCR_0 0x1240080
++#define mmACP_DMA_CUR_DSCR_1 0x1240084
++#define mmACP_DMA_CUR_DSCR_2 0x1240088
++#define mmACP_DMA_CUR_DSCR_3 0x124008C
++#define mmACP_DMA_CUR_DSCR_4 0x1240090
++#define mmACP_DMA_CUR_DSCR_5 0x1240094
++#define mmACP_DMA_CUR_DSCR_6 0x1240098
++#define mmACP_DMA_CUR_DSCR_7 0x124009C
++#define mmACP_DMA_CUR_TRANS_CNT_0 0x12400A0
++#define mmACP_DMA_CUR_TRANS_CNT_1 0x12400A4
++#define mmACP_DMA_CUR_TRANS_CNT_2 0x12400A8
++#define mmACP_DMA_CUR_TRANS_CNT_3 0x12400AC
++#define mmACP_DMA_CUR_TRANS_CNT_4 0x12400B0
++#define mmACP_DMA_CUR_TRANS_CNT_5 0x12400B4
++#define mmACP_DMA_CUR_TRANS_CNT_6 0x12400B8
++#define mmACP_DMA_CUR_TRANS_CNT_7 0x12400BC
++#define mmACP_DMA_ERR_STS_0 0x12400C0
++#define mmACP_DMA_ERR_STS_1 0x12400C4
++#define mmACP_DMA_ERR_STS_2 0x12400C8
++#define mmACP_DMA_ERR_STS_3 0x12400CC
++#define mmACP_DMA_ERR_STS_4 0x12400D0
++#define mmACP_DMA_ERR_STS_5 0x12400D4
++#define mmACP_DMA_ERR_STS_6 0x12400D8
++#define mmACP_DMA_ERR_STS_7 0x12400DC
++#define mmACP_DMA_DESC_BASE_ADDR 0x12400E0
++#define mmACP_DMA_DESC_MAX_NUM_DSCR 0x12400E4
++#define mmACP_DMA_CH_STS 0x12400E8
++#define mmACP_DMA_CH_GROUP 0x12400EC
++#define mmACP_DMA_CH_RST_STS 0x12400F0
++
++
++// Registers from ACP_AXI2AXIATU block
++
++#define mmACPAXI2AXI_ATU_PAGE_SIZE_GRP_1 0x1240C00
++#define mmACPAXI2AXI_ATU_BASE_ADDR_GRP_1 0x1240C04
++#define mmACPAXI2AXI_ATU_PAGE_SIZE_GRP_2 0x1240C08
++#define mmACPAXI2AXI_ATU_BASE_ADDR_GRP_2 0x1240C0C
++#define mmACPAXI2AXI_ATU_PAGE_SIZE_GRP_3 0x1240C10
++#define mmACPAXI2AXI_ATU_BASE_ADDR_GRP_3 0x1240C14
++#define mmACPAXI2AXI_ATU_PAGE_SIZE_GRP_4 0x1240C18
++#define mmACPAXI2AXI_ATU_BASE_ADDR_GRP_4 0x1240C1C
++#define mmACPAXI2AXI_ATU_PAGE_SIZE_GRP_5 0x1240C20
++#define mmACPAXI2AXI_ATU_BASE_ADDR_GRP_5 0x1240C24
++#define mmACPAXI2AXI_ATU_PAGE_SIZE_GRP_6 0x1240C28
++#define mmACPAXI2AXI_ATU_BASE_ADDR_GRP_6 0x1240C2C
++#define mmACPAXI2AXI_ATU_PAGE_SIZE_GRP_7 0x1240C30
++#define mmACPAXI2AXI_ATU_BASE_ADDR_GRP_7 0x1240C34
++#define mmACPAXI2AXI_ATU_PAGE_SIZE_GRP_8 0x1240C38
++#define mmACPAXI2AXI_ATU_BASE_ADDR_GRP_8 0x1240C3C
++#define mmACPAXI2AXI_ATU_CTRL 0x1240C40
++
++
++// Registers from ACP_CLKRST block
++
++#define mmACP_SOFT_RESET 0x1241000
++#define mmACP_CONTROL 0x1241004
++#define mmACP_STATUS 0x1241008
++#define mmACP_DSP0_OCD_HALT_ON_RST 0x124100C
++#define mmACP_DYNAMIC_CG_MASTER_CONTROL 0x1241010
++
++
++// Registers from ACP_MISC block
++
++#define mmACP_EXTERNAL_INTR_ENB 0x1241800
++#define mmACP_EXTERNAL_INTR_CNTL 0x1241804
++#define mmACP_EXTERNAL_INTR_STAT 0x1241808
++#define mmACP_DSP0_INTR_CNTL 0x124180C
++#define mmACP_DSP0_INTR_STAT 0x1241810
++#define mmACP_DSP_SW_INTR_CNTL 0x1241814
++#define mmACP_DSP_SW_INTR_STAT 0x1241818
++#define mmACP_SW_INTR_TRIG 0x124181C
++#define mmACP_SMU_MAILBOX 0x1241820
++#define mmDSP_INTERRUPT_ROUTING_CTRL 0x1241824
++#define mmACP_DSP0_WATCHDOG_TIMER_CNTL 0x1241828
++#define mmACP_DSP0_EXT_TIMER1_CNTL 0x124182C
++#define mmACP_DSP0_EXT_TIMER2_CNTL 0x1241830
++#define mmACP_DSP0_EXT_TIMER3_CNTL 0x1241834
++#define mmACP_DSP0_EXT_TIMER4_CNTL 0x1241838
++#define mmACP_DSP0_EXT_TIMER5_CNTL 0x124183C
++#define mmACP_DSP0_EXT_TIMER6_CNTL 0x1241840
++#define mmACP_DSP0_EXT_TIMER1_CURR_VALUE 0x1241844
++#define mmACP_DSP0_EXT_TIMER2_CURR_VALUE 0x1241848
++#define mmACP_DSP0_EXT_TIMER3_CURR_VALUE 0x124184C
++#define mmACP_DSP0_EXT_TIMER4_CURR_VALUE 0x1241850
++#define mmACP_DSP0_EXT_TIMER5_CURR_VALUE 0x1241854
++#define mmACP_DSP0_EXT_TIMER6_CURR_VALUE 0x1241858
++#define mmACP_FW_STATUS 0x124185C
++#define mmACP_TIMER 0x1241874
++#define mmACP_TIMER_CNTL 0x1241878
++#define mmACP_PGMEM_CTRL 0x12418C0
++#define mmACP_ERROR_STATUS 0x12418C4
++#define mmACP_SW_I2S_ERROR_REASON 0x12418C8
++#define mmACP_MEM_PG_STS 0x12418CC
++
++
++// Registers from ACP_PGFSM block
++
++#define mmACP_I2S_PIN_CONFIG 0x1241400
++#define mmACP_PAD_PULLUP_PULLDOWN_CTRL 0x1241404
++#define mmACP_PAD_DRIVE_STRENGTH_CTRL 0x1241408
++#define mmACP_SW_PAD_KEEPER_EN 0x124140C
++#define mmACP_SW_WAKE_EN 0x1241410
++#define mmACP_I2S_WAKE_EN 0x1241414
++#define mmACP_PME_EN 0x1241418
++#define mmACP_PGFSM_CONTROL 0x124141C
++#define mmACP_PGFSM_STATUS 0x1241420
++
++
++// Registers from ACP_SCRATCH block
++
++#define mmACP_SCRATCH_REG_0 0x1250000
++#define mmACP_SCRATCH_REG_1 0x1250004
++#define mmACP_SCRATCH_REG_2 0x1250008
++#define mmACP_SCRATCH_REG_3 0x125000C
++#define mmACP_SCRATCH_REG_4 0x1250010
++#define mmACP_SCRATCH_REG_5 0x1250014
++#define mmACP_SCRATCH_REG_6 0x1250018
++#define mmACP_SCRATCH_REG_7 0x125001C
++#define mmACP_SCRATCH_REG_8 0x1250020
++#define mmACP_SCRATCH_REG_9 0x1250024
++#define mmACP_SCRATCH_REG_10 0x1250028
++#define mmACP_SCRATCH_REG_11 0x125002C
++#define mmACP_SCRATCH_REG_12 0x1250030
++#define mmACP_SCRATCH_REG_13 0x1250034
++#define mmACP_SCRATCH_REG_14 0x1250038
++#define mmACP_SCRATCH_REG_15 0x125003C
++#define mmACP_SCRATCH_REG_16 0x1250040
++#define mmACP_SCRATCH_REG_17 0x1250044
++#define mmACP_SCRATCH_REG_18 0x1250048
++#define mmACP_SCRATCH_REG_19 0x125004C
++#define mmACP_SCRATCH_REG_20 0x1250050
++#define mmACP_SCRATCH_REG_21 0x1250054
++#define mmACP_SCRATCH_REG_22 0x1250058
++#define mmACP_SCRATCH_REG_23 0x125005C
++#define mmACP_SCRATCH_REG_24 0x1250060
++#define mmACP_SCRATCH_REG_25 0x1250064
++#define mmACP_SCRATCH_REG_26 0x1250068
++#define mmACP_SCRATCH_REG_27 0x125006C
++#define mmACP_SCRATCH_REG_28 0x1250070
++#define mmACP_SCRATCH_REG_29 0x1250074
++#define mmACP_SCRATCH_REG_30 0x1250078
++#define mmACP_SCRATCH_REG_31 0x125007C
++#define mmACP_SCRATCH_REG_32 0x1250080
++#define mmACP_SCRATCH_REG_33 0x1250084
++#define mmACP_SCRATCH_REG_34 0x1250088
++#define mmACP_SCRATCH_REG_35 0x125008C
++#define mmACP_SCRATCH_REG_36 0x1250090
++#define mmACP_SCRATCH_REG_37 0x1250094
++#define mmACP_SCRATCH_REG_38 0x1250098
++#define mmACP_SCRATCH_REG_39 0x125009C
++#define mmACP_SCRATCH_REG_40 0x12500A0
++#define mmACP_SCRATCH_REG_41 0x12500A4
++#define mmACP_SCRATCH_REG_42 0x12500A8
++#define mmACP_SCRATCH_REG_43 0x12500AC
++#define mmACP_SCRATCH_REG_44 0x12500B0
++#define mmACP_SCRATCH_REG_45 0x12500B4
++#define mmACP_SCRATCH_REG_46 0x12500B8
++#define mmACP_SCRATCH_REG_47 0x12500BC
++#define mmACP_SCRATCH_REG_48 0x12500C0
++#define mmACP_SCRATCH_REG_49 0x12500C4
++#define mmACP_SCRATCH_REG_50 0x12500C8
++#define mmACP_SCRATCH_REG_51 0x12500CC
++#define mmACP_SCRATCH_REG_52 0x12500D0
++#define mmACP_SCRATCH_REG_53 0x12500D4
++#define mmACP_SCRATCH_REG_54 0x12500D8
++#define mmACP_SCRATCH_REG_55 0x12500DC
++#define mmACP_SCRATCH_REG_56 0x12500E0
++#define mmACP_SCRATCH_REG_57 0x12500E4
++#define mmACP_SCRATCH_REG_58 0x12500E8
++#define mmACP_SCRATCH_REG_59 0x12500EC
++#define mmACP_SCRATCH_REG_60 0x12500F0
++#define mmACP_SCRATCH_REG_61 0x12500F4
++#define mmACP_SCRATCH_REG_62 0x12500F8
++#define mmACP_SCRATCH_REG_63 0x12500FC
++#define mmACP_SCRATCH_REG_64 0x1250100
++#define mmACP_SCRATCH_REG_65 0x1250104
++#define mmACP_SCRATCH_REG_66 0x1250108
++#define mmACP_SCRATCH_REG_67 0x125010C
++#define mmACP_SCRATCH_REG_68 0x1250110
++#define mmACP_SCRATCH_REG_69 0x1250114
++#define mmACP_SCRATCH_REG_70 0x1250118
++#define mmACP_SCRATCH_REG_71 0x125011C
++#define mmACP_SCRATCH_REG_72 0x1250120
++#define mmACP_SCRATCH_REG_73 0x1250124
++#define mmACP_SCRATCH_REG_74 0x1250128
++#define mmACP_SCRATCH_REG_75 0x125012C
++#define mmACP_SCRATCH_REG_76 0x1250130
++#define mmACP_SCRATCH_REG_77 0x1250134
++#define mmACP_SCRATCH_REG_78 0x1250138
++#define mmACP_SCRATCH_REG_79 0x125013C
++#define mmACP_SCRATCH_REG_80 0x1250140
++#define mmACP_SCRATCH_REG_81 0x1250144
++#define mmACP_SCRATCH_REG_82 0x1250148
++#define mmACP_SCRATCH_REG_83 0x125014C
++#define mmACP_SCRATCH_REG_84 0x1250150
++#define mmACP_SCRATCH_REG_85 0x1250154
++#define mmACP_SCRATCH_REG_86 0x1250158
++#define mmACP_SCRATCH_REG_87 0x125015C
++#define mmACP_SCRATCH_REG_88 0x1250160
++#define mmACP_SCRATCH_REG_89 0x1250164
++#define mmACP_SCRATCH_REG_90 0x1250168
++#define mmACP_SCRATCH_REG_91 0x125016C
++#define mmACP_SCRATCH_REG_92 0x1250170
++#define mmACP_SCRATCH_REG_93 0x1250174
++#define mmACP_SCRATCH_REG_94 0x1250178
++#define mmACP_SCRATCH_REG_95 0x125017C
++#define mmACP_SCRATCH_REG_96 0x1250180
++#define mmACP_SCRATCH_REG_97 0x1250184
++#define mmACP_SCRATCH_REG_98 0x1250188
++#define mmACP_SCRATCH_REG_99 0x125018C
++#define mmACP_SCRATCH_REG_100 0x1250190
++#define mmACP_SCRATCH_REG_101 0x1250194
++#define mmACP_SCRATCH_REG_102 0x1250198
++#define mmACP_SCRATCH_REG_103 0x125019C
++#define mmACP_SCRATCH_REG_104 0x12501A0
++#define mmACP_SCRATCH_REG_105 0x12501A4
++#define mmACP_SCRATCH_REG_106 0x12501A8
++#define mmACP_SCRATCH_REG_107 0x12501AC
++#define mmACP_SCRATCH_REG_108 0x12501B0
++#define mmACP_SCRATCH_REG_109 0x12501B4
++#define mmACP_SCRATCH_REG_110 0x12501B8
++#define mmACP_SCRATCH_REG_111 0x12501BC
++#define mmACP_SCRATCH_REG_112 0x12501C0
++#define mmACP_SCRATCH_REG_113 0x12501C4
++#define mmACP_SCRATCH_REG_114 0x12501C8
++#define mmACP_SCRATCH_REG_115 0x12501CC
++#define mmACP_SCRATCH_REG_116 0x12501D0
++#define mmACP_SCRATCH_REG_117 0x12501D4
++#define mmACP_SCRATCH_REG_118 0x12501D8
++#define mmACP_SCRATCH_REG_119 0x12501DC
++#define mmACP_SCRATCH_REG_120 0x12501E0
++#define mmACP_SCRATCH_REG_121 0x12501E4
++#define mmACP_SCRATCH_REG_122 0x12501E8
++#define mmACP_SCRATCH_REG_123 0x12501EC
++#define mmACP_SCRATCH_REG_124 0x12501F0
++#define mmACP_SCRATCH_REG_125 0x12501F4
++#define mmACP_SCRATCH_REG_126 0x12501F8
++#define mmACP_SCRATCH_REG_127 0x12501FC
++#define mmACP_SCRATCH_REG_128 0x1250200
++
++
++// Registers from ACP_SW_ACLK block
++
++#define mmSW_CORB_Base_Address 0x1243200
++#define mmSW_CORB_Write_Pointer 0x1243204
++#define mmSW_CORB_Read_Pointer 0x1243208
++#define mmSW_CORB_Control 0x124320C
++#define mmSW_CORB_Size 0x1243214
++#define mmSW_RIRB_Base_Address 0x1243218
++#define mmSW_RIRB_Write_Pointer 0x124321C
++#define mmSW_RIRB_Response_Interrupt_Count 0x1243220
++#define mmSW_RIRB_Control 0x1243224
++#define mmSW_RIRB_Size 0x1243228
++#define mmSW_RIRB_FIFO_MIN_THDL 0x124322C
++#define mmSW_imm_cmd_UPPER_WORD 0x1243230
++#define mmSW_imm_cmd_LOWER_QWORD 0x1243234
++#define mmSW_imm_resp_UPPER_WORD 0x1243238
++#define mmSW_imm_resp_LOWER_QWORD 0x124323C
++#define mmSW_imm_cmd_sts 0x1243240
++#define mmSW_BRA_BASE_ADDRESS 0x1243244
++#define mmSW_BRA_TRANSFER_SIZE 0x1243248
++#define mmSW_BRA_DMA_BUSY 0x124324C
++#define mmSW_BRA_RESP 0x1243250
++#define mmSW_BRA_RESP_FRAME_ADDR 0x1243254
++#define mmSW_BRA_CURRENT_TRANSFER_SIZE 0x1243258
++#define mmSW_STATE_CHANGE_STATUS_0TO7 0x124325C
++#define mmSW_STATE_CHANGE_STATUS_8TO11 0x1243260
++#define mmSW_STATE_CHANGE_STATUS_MASK_0to7 0x1243264
++#define mmSW_STATE_CHANGE_STATUS_MASK_8to11 0x1243268
++#define mmSW_CLK_FREQUENCY_CTRL 0x124326C
++#define mmSW_ERROR_INTR_MASK 0x1243270
++#define mmSW_PHY_TEST_MODE_DATA_OFF 0x1243274
++
++
++// Registers from ACP_SW_SWCLK block
++
++#define mmACP_SW_EN 0x1243000
++#define mmACP_SW_EN_STATUS 0x1243004
++#define mmACP_SW_FRAMESIZE 0x1243008
++#define mmACP_SW_SSP_Counter 0x124300C
++#define mmACP_SW_Audio_TX_EN 0x1243010
++#define mmACP_SW_Audio_TX_EN_STATUS 0x1243014
++#define mmACP_SW_Audio_TX_Frame_Format 0x1243018
++#define mmACP_SW_Audio_TX_SampleInterval 0x124301C
++#define mmACP_SW_Audio_TX_Hctrl_DP0 0x1243020
++#define mmACP_SW_Audio_TX_Hctrl_DP1 0x1243024
++#define mmACP_SW_Audio_TX_Hctrl_DP2 0x1243028
++#define mmACP_SW_Audio_TX_Hctrl_DP3 0x124302C
++#define mmACP_SW_Audio_TX_offset_DP0 0x1243030
++#define mmACP_SW_Audio_TX_offset_DP1 0x1243034
++#define mmACP_SW_Audio_TX_offset_DP2 0x1243038
++#define mmACP_SW_Audio_TX_offset_DP3 0x124303C
++#define mmACP_SW_Audio_TX_Channel_Enable_DP0 0x1243040
++#define mmACP_SW_Audio_TX_Channel_Enable_DP1 0x1243044
++#define mmACP_SW_Audio_TX_Channel_Enable_DP2 0x1243048
++#define mmACP_SW_Audio_TX_Channel_Enable_DP3 0x124304C
++#define mmACP_SW_BT_TX_EN 0x1243050
++#define mmACP_SW_BT_TX_EN_STATUS 0x1243054
++#define mmACP_SW_BT_TX_Frame_Format 0x1243058
++#define mmACP_SW_BT_TX_SampleInterval 0x124305C
++#define mmACP_SW_BT_TX_Hctrl 0x1243060
++#define mmACP_SW_BT_TX_offset 0x1243064
++#define mmACP_SW_BT_TX_Channel_Enable_DP0 0x1243068
++#define mmACP_SW_Headset_TX_EN 0x124306C
++#define mmACP_SW_Headset_TX_EN_STATUS 0x1243070
++#define mmACP_SW_Headset_TX_Frame_Format 0x1243074
++#define mmACP_SW_Headset_TX_SampleInterval 0x1243078
++#define mmACP_SW_Headset_TX_Hctrl 0x124307C
++#define mmACP_SW_Headset_TX_offset 0x1243080
++#define mmACP_SW_Headset_TX_Channel_Enable_DP0 0x1243084
++#define mmACP_SW_Audio_RX_EN 0x1243088
++#define mmACP_SW_Audio_RX_EN_STATUS 0x124308C
++#define mmACP_SW_Audio_RX_Frame_Format 0x1243090
++#define mmACP_SW_Audio_RX_SampleInterval 0x1243094
++#define mmACP_SW_Audio_RX_Hctrl_DP0 0x1243098
++#define mmACP_SW_Audio_RX_Hctrl_DP1 0x124309C
++#define mmACP_SW_Audio_RX_Hctrl_DP2 0x1243100
++#define mmACP_SW_Audio_RX_Hctrl_DP3 0x1243104
++#define mmACP_SW_Audio_RX_offset_DP0 0x1243108
++#define mmACP_SW_Audio_RX_offset_DP1 0x124310C
++#define mmACP_SW_Audio_RX_offset_DP2 0x1243110
++#define mmACP_SW_Audio_RX_offset_DP3 0x1243114
++#define mmACP_SW_Audio_RX_Channel_Enable_DP0 0x1243118
++#define mmACP_SW_Audio_RX_Channel_Enable_DP1 0x124311C
++#define mmACP_SW_Audio_RX_Channel_Enable_DP2 0x1243120
++#define mmACP_SW_Audio_RX_Channel_Enable_DP3 0x1243124
++#define mmACP_SW_BT_RX_EN 0x1243128
++#define mmACP_SW_BT_RX_EN_STATUS 0x124312C
++#define mmACP_SW_BT_RX_Frame_Format 0x1243130
++#define mmACP_SW_BT_RX_SampleInterval 0x1243134
++#define mmACP_SW_BT_RX_Hctrl 0x1243138
++#define mmACP_SW_BT_RX_offset 0x124313C
++#define mmACP_SW_BT_RX_Channel_Enable_DP0 0x1243140
++#define mmACP_SW_Headset_RX_EN 0x1243144
++#define mmACP_SW_Headset_RX_EN_STATUS 0x1243148
++#define mmACP_SW_Headset_RX_Frame_Format 0x124314C
++#define mmACP_SW_Headset_RX_SampleInterval 0x1243150
++#define mmACP_SW_Headset_RX_Hctrl 0x1243154
++#define mmACP_SW_Headset_RX_offset 0x1243158
++#define mmACP_SW_Headset_RX_Channel_Enable_DP0 0x124315C
++#define mmACP_SW_BPT_PORT_EN 0x1243160
++#define mmACP_SW_BPT_PORT_EN_STATUS 0x1243164
++#define mmACP_SW_BPT_PORT_Frame_Format 0x1243168
++#define mmACP_SW_BPT_PORT_SampleInterval 0x124316C
++#define mmACP_SW_BPT_PORT_Hctrl 0x1243170
++#define mmACP_SW_BPT_PORT_offset 0x1243174
++#define mmACP_SW_BPT_PORT_Channel_Enable 0x1243178
++#define mmACP_SW_BPT_PORT_First_byte_addr 0x124317C
++#define mmACP_SW_CLK_RESUME_CTRL 0x1243180
++#define mmACP_SW_CLK_RESUME_Delay_Cntr 0x1243184
++#define mmACP_SW_BUS_RESET_CTRL 0x1243188
++#define mmACP_SW_PRBS_ERR_STATUS 0x124318C
++
++
++// Registers from ACP_AUDIO_BUFFERS block
++
++#define mmACP_I2S_RX_RINGBUFADDR 0x1242000
++#define mmACP_I2S_RX_RINGBUFSIZE 0x1242004
++#define mmACP_I2S_RX_LINKPOSITIONCNTR 0x1242008
++#define mmACP_I2S_RX_FIFOADDR 0x124200C
++#define mmACP_I2S_RX_FIFOSIZE 0x1242010
++#define mmACP_I2S_RX_DMA_SIZE 0x1242014
++#define mmACP_I2S_RX_LINEARPOSITIONCNTR_HIGH 0x1242018
++#define mmACP_I2S_RX_LINEARPOSITIONCNTR_LOW 0x124201C
++#define mmACP_I2S_RX_INTR_WATERMARK_SIZE 0x1242020
++#define mmACP_I2S_TX_RINGBUFADDR 0x1242024
++#define mmACP_I2S_TX_RINGBUFSIZE 0x1242028
++#define mmACP_I2S_TX_LINKPOSITIONCNTR 0x124202C
++#define mmACP_I2S_TX_FIFOADDR 0x1242030
++#define mmACP_I2S_TX_FIFOSIZE 0x1242034
++#define mmACP_I2S_TX_DMA_SIZE 0x1242038
++#define mmACP_I2S_TX_LINEARPOSITIONCNTR_HIGH 0x124203C
++#define mmACP_I2S_TX_LINEARPOSITIONCNTR_LOW 0x1242040
++#define mmACP_I2S_TX_INTR_WATERMARK_SIZE 0x1242044
++#define mmACP_BT_RX_RINGBUFADDR 0x1242048
++#define mmACP_BT_RX_RINGBUFSIZE 0x124204C
++#define mmACP_BT_RX_LINKPOSITIONCNTR 0x1242050
++#define mmACP_BT_RX_FIFOADDR 0x1242054
++#define mmACP_BT_RX_FIFOSIZE 0x1242058
++#define mmACP_BT_RX_DMA_SIZE 0x124205C
++#define mmACP_BT_RX_LINEARPOSITIONCNTR_HIGH 0x1242060
++#define mmACP_BT_RX_LINEARPOSITIONCNTR_LOW 0x1242064
++#define mmACP_BT_RX_INTR_WATERMARK_SIZE 0x1242068
++#define mmACP_BT_TX_RINGBUFADDR 0x124206C
++#define mmACP_BT_TX_RINGBUFSIZE 0x1242070
++#define mmACP_BT_TX_LINKPOSITIONCNTR 0x1242074
++#define mmACP_BT_TX_FIFOADDR 0x1242078
++#define mmACP_BT_TX_FIFOSIZE 0x124207C
++#define mmACP_BT_TX_DMA_SIZE 0x1242080
++#define mmACP_BT_TX_LINEARPOSITIONCNTR_HIGH 0x1242084
++#define mmACP_BT_TX_LINEARPOSITIONCNTR_LOW 0x1242088
++#define mmACP_BT_TX_INTR_WATERMARK_SIZE 0x124208C
++#define mmACP_HS_RX_RINGBUFADDR 0x1242090
++#define mmACP_HS_RX_RINGBUFSIZE 0x1242094
++#define mmACP_HS_RX_LINKPOSITIONCNTR 0x1242098
++#define mmACP_HS_RX_FIFOADDR 0x124209C
++#define mmACP_HS_RX_FIFOSIZE 0x12420A0
++#define mmACP_HS_RX_DMA_SIZE 0x12420A4
++#define mmACP_HS_RX_LINEARPOSITIONCNTR_HIGH 0x12420A8
++#define mmACP_HS_RX_LINEARPOSITIONCNTR_LOW 0x12420AC
++#define mmACP_HS_RX_INTR_WATERMARK_SIZE 0x12420B0
++#define mmACP_HS_TX_RINGBUFADDR 0x12420B4
++#define mmACP_HS_TX_RINGBUFSIZE 0x12420B8
++#define mmACP_HS_TX_LINKPOSITIONCNTR 0x12420BC
++#define mmACP_HS_TX_FIFOADDR 0x12420C0
++#define mmACP_HS_TX_FIFOSIZE 0x12420C4
++#define mmACP_HS_TX_DMA_SIZE 0x12420C8
++#define mmACP_HS_TX_LINEARPOSITIONCNTR_HIGH 0x12420CC
++#define mmACP_HS_TX_LINEARPOSITIONCNTR_LOW 0x12420D0
++#define mmACP_HS_TX_INTR_WATERMARK_SIZE 0x12420D4
++
++
++// Registers from ACP_I2S_TDM block
++
++#define mmACP_I2STDM_IER 0x1242400
++#define mmACP_I2STDM_IRER 0x1242404
++#define mmACP_I2STDM_RXFRMT 0x1242408
++#define mmACP_I2STDM_ITER 0x124240C
++#define mmACP_I2STDM_TXFRMT 0x1242410
++
++
++// Registers from ACP_BT_TDM block
++
++#define mmACP_BTTDM_IER 0x1242800
++#define mmACP_BTTDM_IRER 0x1242804
++#define mmACP_BTTDM_RXFRMT 0x1242808
++#define mmACP_BTTDM_ITER 0x124280C
++#define mmACP_BTTDM_TXFRMT 0x1242810
++
++
++// Registers from AZALIA_IP block
++
++#define mmAudio_Az_Global_Capabilities 0x1200000
++#define mmAudio_Az_Minor_Version 0x1200002
++#define mmAudio_Az_Major_Version 0x1200003
++#define mmAudio_Az_Output_Payload_Capability 0x1200004
++#define mmAudio_Az_Input_Payload_Capability 0x1200006
++#define mmAudio_Az_Global_Control 0x1200008
++#define mmAudio_Az_Wake_Enable 0x120000C
++#define mmAudio_Az_State_Change_Status 0x120000E
++#define mmAudio_Az_Global_Status 0x1200010
++#define mmAudio_Az_Linked_List_Capability_Header 0x1200014
++#define mmAudio_Az_Output_Stream_Payload_Capability 0x1200018
++#define mmAudio_Az_Input_Stream_Payload_Capability 0x120001A
++#define mmAudio_Az_Interrupt_Control 0x1200020
++#define mmAudio_Az_Interrupt_Status 0x1200024
++#define mmAudio_Az_Wall_Clock_Counter 0x1200030
++#define mmAudio_Az_Stream_Synchronization 0x1200038
++#define mmAudio_Az_CORB_Lower_Base_Address 0x1200040
++#define mmAudio_Az_CORB_Upper_Base_Address 0x1200044
++#define mmAudio_Az_CORB_Write_Pointer 0x1200048
++#define mmAudio_Az_CORB_Read_Pointer 0x120004A
++#define mmAudio_Az_CORB_Control 0x120004C
++#define mmAudio_Az_CORB_Status 0x120004D
++#define mmAudio_Az_CORB_Size 0x120004E
++#define mmAudio_Az_RIRB_Lower_Base_Address 0x1200050
++#define mmAudio_Az_RIRB_Upper_Base_Address 0x1200054
++#define mmAudio_Az_RIRB_Write_Pointer 0x1200058
++#define mmAudio_Az_RIRB_Response_Interrupt_Count 0x120005A
++#define mmAudio_Az_RIRB_Control 0x120005C
++#define mmAudio_Az_RIRB_Status 0x120005D
++#define mmAudio_Az_RIRB_Size 0x120005E
++#define mmAudio_Az_Immediate_Command_Output_Interface 0x1200060
++#define mmAudio_Az_Immediate_Response_Input_Interface 0x1200064
++#define mmAudio_Az_Immediate_Command_Status 0x1200068
++#define mmAudio_Az_DPLBASE 0x1200070
++#define mmAudio_Az_DPUBASE 0x1200074
++#define mmAudio_Az_Input_SD0CTL_and_STS 0x1200080
++#define mmAudio_Az_Input_SD0LPIB 0x1200084
++#define mmAudio_Az_Input_SD0CBL 0x1200088
++#define mmAudio_Az_Input_SD0LVI 0x120008C
++#define mmAudio_Az_Input_SD0FIFOS 0x1200090
++#define mmAudio_Az_Input_SD0FMT 0x1200092
++#define mmAudio_Az_Input_SD0BDPL 0x1200098
++#define mmAudio_Az_Input_SD0BDPU 0x120009C
++#define mmAudio_Az_Input_SD1CTL_and_STS 0x12000A0
++#define mmAudio_Az_Input_SD1LPIB 0x12000A4
++#define mmAudio_Az_Input_SD1CBL 0x12000A8
++#define mmAudio_Az_Input_SD1LVI 0x12000AC
++#define mmAudio_Az_Input_SD1FIFOS 0x12000B0
++#define mmAudio_Az_Input_SD1FMT 0x12000B2
++#define mmAudio_Az_Input_SD1BDPL 0x12000B8
++#define mmAudio_Az_Input_SD1BDPU 0x12000BC
++#define mmAudio_Az_Input_SD2CTL_and_STS 0x12000C0
++#define mmAudio_Az_Input_SD2LPIB 0x12000C4
++#define mmAudio_Az_Input_SD2CBL 0x12000C8
++#define mmAudio_Az_Input_SD2LVI 0x12000CC
++#define mmAudio_Az_Input_SD2FIFOS 0x12000D0
++#define mmAudio_Az_Input_SD2FMT 0x12000D2
++#define mmAudio_Az_Input_SD2BDPL 0x12000D8
++#define mmAudio_Az_Input_SD2BDPU 0x12000DC
++#define mmAudio_Az_Input_SD3CTL_and_STS 0x12000E0
++#define mmAudio_Az_Input_SD3LPIB 0x12000E4
++#define mmAudio_Az_Input_SD3CBL 0x12000E8
++#define mmAudio_Az_Input_SD3LVI 0x12000EC
++#define mmAudio_Az_Input_SD3FIFOS 0x12000F0
++#define mmAudio_Az_Input_SD3FMT 0x12000F2
++#define mmAudio_Az_Input_SD3BDPL 0x12000F8
++#define mmAudio_Az_Input_SD3BDPU 0x12000FC
++#define mmAudio_Az_Output_SD0CTL_and_STS 0x1200100
++#define mmAudio_Az_Output_SD0LPIB 0x1200104
++#define mmAudio_Az_Output_SD0CBL 0x1200108
++#define mmAudio_Az_Output_SD0LVI 0x120010C
++#define mmAudio_Az_Output_SD0FIFOS 0x1200110
++#define mmAudio_Az_Output_SD0FMT 0x1200112
++#define mmAudio_Az_Output_SD0BDPL 0x1200118
++#define mmAudio_Az_Output_SD0BDPU 0x120011C
++#define mmAudio_Az_Output_SD1CTL_and_STS 0x1200120
++#define mmAudio_Az_Output_SD1LPIB 0x1200124
++#define mmAudio_Az_Output_SD1CBL 0x1200128
++#define mmAudio_Az_Output_SD1LVI 0x120012C
++#define mmAudio_Az_Output_SD1FIFOS 0x1200130
++#define mmAudio_Az_Output_SD1FMT 0x1200132
++#define mmAudio_Az_Output_SD1BDPL 0x1200138
++#define mmAudio_Az_Output_SD1BDPU 0x120013C
++#define mmAudio_Az_Output_SD2CTL_and_STS 0x1200140
++#define mmAudio_Az_Output_SD2LPIB 0x1200144
++#define mmAudio_Az_Output_SD2CBL 0x1200148
++#define mmAudio_Az_Output_SD2LVI 0x120014C
++#define mmAudio_Az_Output_SD2FIFOS 0x1200150
++#define mmAudio_Az_Output_SD2FMT 0x1200152
++#define mmAudio_Az_Output_SD2BDPL 0x1200158
++#define mmAudio_Az_Output_SD2BDPU 0x120015C
++#define mmAudio_Az_Output_SD3CTL_and_STS 0x1200160
++#define mmAudio_Az_Output_SD3LPIB 0x1200164
++#define mmAudio_Az_Output_SD3CBL 0x1200168
++#define mmAudio_Az_Output_SD3LVI 0x120016C
++#define mmAudio_Az_Output_SD3FIFOS 0x1200170
++#define mmAudio_Az_Output_SD3FMT 0x1200172
++#define mmAudio_Az_Output_SD3BDPL 0x1200178
++#define mmAudio_Az_Output_SD3BDPU 0x120017C
++#define mmAudioAZ_Misc_Control_Register_1 0x1200180
++#define mmAudioAZ_Misc_Control_Register_2 0x1200182
++#define mmAudioAZ_Misc_Control_Register_3 0x1200183
++#define mmAudio_AZ_Multiple_Links_Capability_Header 0x1200200
++#define mmAudio_AZ_Multiple_Links_Capability_Declaration 0x1200204
++#define mmAudio_AZ_Link0_Capabilities 0x1200240
++#define mmAudio_AZ_Link0_Control 0x1200244
++#define mmAudio_AZ_Link0_Output_Stream_ID 0x1200248
++#define mmAudio_AZ_Link0_SDI_Identifier 0x120024C
++#define mmAudio_AZ_Link0_Per_Stream_Overhead 0x1200250
++#define mmAudio_AZ_Link0_Wall_Frame_Counter 0x1200258
++#define mmAudio_AZ_Link0_Output_Payload_Capability_L 0x1200260
++#define mmAudio_AZ_Link0_Output_Payload_Capability_U 0x1200264
++#define mmAudio_AZ_Link0_Input_Payload_Capability_L 0x1200270
++#define mmAudio_AZ_Link0_Input_Payload_Capability_U 0x1200274
++#define mmAudio_Az_Input_SD0LICBA 0x1202084
++#define mmAudio_Az_Input_SD1LICBA 0x12020A4
++#define mmAudio_Az_Input_SD2LICBA 0x12020C4
++#define mmAudio_Az_Input_SD3LICBA 0x12020E4
++#define mmAudio_Az_Output_SD0LICBA 0x1202104
++#define mmAudio_Az_Output_SD1LICBA 0x1202124
++#define mmAudio_Az_Output_SD2LICBA 0x1202144
++#define mmAudio_Az_Output_SD3LICBA 0x1202164
++#define mmAUDIO_AZ_POWER_MANAGEMENT_CONTROL 0x1204000
++#define mmAUDIO_AZ_IOC_SOFTRST_CONTROL 0x1204004
++#define mmAUDIO_AZ_IOC_CLKGATE_CONTROL 0x1204008
++
++
++// Registers from ACP_AZALIA block
++
++#define mmACP_AZ_PAGE0_LBASE_ADDR 0x1243800
++#define mmACP_AZ_PAGE0_UBASE_ADDR 0x1243804
++#define mmACP_AZ_PAGE0_PGEN_SIZE 0x1243808
++#define mmACP_AZ_PAGE0_OFFSET 0x124380C
++#define mmACP_AZ_PAGE1_LBASE_ADDR 0x1243810
++#define mmACP_AZ_PAGE1_UBASE_ADDR 0x1243814
++#define mmACP_AZ_PAGE1_PGEN_SIZE 0x1243818
++#define mmACP_AZ_PAGE1_OFFSET 0x124381C
++#define mmACP_AZ_PAGE2_LBASE_ADDR 0x1243820
++#define mmACP_AZ_PAGE2_UBASE_ADDR 0x1243824
++#define mmACP_AZ_PAGE2_PGEN_SIZE 0x1243828
++#define mmACP_AZ_PAGE2_OFFSET 0x124382C
++#define mmACP_AZ_PAGE3_LBASE_ADDR 0x1243830
++#define mmACP_AZ_PAGE3_UBASE_ADDR 0x1243834
++#define mmACP_AZ_PAGE3_PGEN_SIZE 0x1243838
++#define mmACP_AZ_PAGE3_OFFSET 0x124383C
++#define mmACP_AZ_PAGE4_LBASE_ADDR 0x1243840
++#define mmACP_AZ_PAGE4_UBASE_ADDR 0x1243844
++#define mmACP_AZ_PAGE4_PGEN_SIZE 0x1243848
++#define mmACP_AZ_PAGE4_OFFSET 0x124384C
++#define mmACP_AZ_PAGE5_LBASE_ADDR 0x1243850
++#define mmACP_AZ_PAGE5_UBASE_ADDR 0x1243854
++#define mmACP_AZ_PAGE5_PGEN_SIZE 0x1243858
++#define mmACP_AZ_PAGE5_OFFSET 0x124385C
++#define mmACP_AZ_PAGE6_LBASE_ADDR 0x1243860
++#define mmACP_AZ_PAGE6_UBASE_ADDR 0x1243864
++#define mmACP_AZ_PAGE6_PGEN_SIZE 0x1243868
++#define mmACP_AZ_PAGE6_OFFSET 0x124386C
++#define mmACP_AZ_PAGE7_LBASE_ADDR 0x1243870
++#define mmACP_AZ_PAGE7_UBASE_ADDR 0x1243874
++#define mmACP_AZ_PAGE7_PGEN_SIZE 0x1243878
++#define mmACP_AZ_PAGE7_OFFSET 0x124387C
++
++
++#endif
+diff --git a/sound/soc/amd/raven/dummy-w5102.c b/sound/soc/amd/raven/dummy-w5102.c
+new file mode 100755
+index 000000000000..f766c112f559
+--- /dev/null
++++ b/sound/soc/amd/raven/dummy-w5102.c
+@@ -0,0 +1,93 @@
++/*
++ * dummy audio codec driver
++ *
++ * Copyright 2016 Advanced Micro Devices, Inc.
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining a
++ * copy of this software and associated documentation files (the "Software"),
++ * to deal in the Software without restriction, including without limitation
++ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
++ * and/or sell copies of the Software, and to permit persons to whom the
++ * Software is furnished to do so, subject to the following conditions:
++ *
++ * The above copyright notice and this permission notice shall be included in
++ * all copies or substantial portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
++ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
++ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
++ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
++ * OTHER DEALINGS IN THE SOFTWARE.
++ *
++ *
++ */
++
++#include <linux/module.h>
++#include <sound/soc.h>
++
++#define W5102_RATES SNDRV_PCM_RATE_8000_96000
++#define W5102_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \
++ SNDRV_PCM_FMTBIT_S32_LE | \
++ SNDRV_PCM_FMTBIT_S24_LE)
++
++static const struct snd_soc_dapm_widget w5102_widgets[] = {
++ SND_SOC_DAPM_OUTPUT("dummy-w5102-out"),
++ SND_SOC_DAPM_INPUT("dummy-w5102-in"),
++};
++
++static const struct snd_soc_dapm_route w5102_routes[] = {
++ { "dummy-w5102-out", NULL, "Playback" },
++ { "Capture", NULL, "dummy-w5102-in" },
++};
++
++static struct snd_soc_dai_driver w5102_stub_dai = {
++ .name = "dummy_w5102_dai",
++ .playback = {
++ .stream_name = "Playback",
++ .channels_min = 2,
++ .channels_max = 6,
++ .rates = W5102_RATES,
++ .formats = W5102_FORMATS,
++ },
++ .capture = {
++ .stream_name = "Capture",
++ .channels_min = 2,
++ .channels_max = 2,
++ .rates = W5102_RATES,
++ .formats = W5102_FORMATS,
++ },
++
++};
++
++static const struct snd_soc_component_driver soc_component_wm5102_dummy = {
++ .dapm_widgets = w5102_widgets,
++ .num_dapm_widgets = ARRAY_SIZE(w5102_widgets),
++ .dapm_routes = w5102_routes,
++ .num_dapm_routes = ARRAY_SIZE(w5102_routes),
++};
++
++static int dummy_w5102_probe(struct platform_device *pdev)
++{
++ int ret;
++
++ ret = devm_snd_soc_register_component(&pdev->dev,
++ &soc_component_wm5102_dummy,
++ &w5102_stub_dai, 1);
++ return ret;
++}
++
++static struct platform_driver dummy_w5102_driver = {
++ .probe = dummy_w5102_probe,
++ .driver = {
++ .name = "dummy_w5102",
++ .owner = THIS_MODULE,
++ },
++};
++
++module_platform_driver(dummy_w5102_driver);
++
++MODULE_DESCRIPTION("dummy-w5102 dummy codec driver");
++MODULE_LICENSE("GPL v2");
++MODULE_ALIAS("platform: dummy_w5102");
+diff --git a/sound/soc/amd/raven/pci-acp3x.c b/sound/soc/amd/raven/pci-acp3x.c
+new file mode 100755
+index 000000000000..0d39aa8a8015
+--- /dev/null
++++ b/sound/soc/amd/raven/pci-acp3x.c
+@@ -0,0 +1,192 @@
++/*
++ * AMD ALSA SoC PCM Driver
++ *
++ * Copyright 2016 Advanced Micro Devices, Inc.
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms and conditions of the GNU General Public License,
++ * version 2, as published by the Free Software Foundation.
++ *
++ * This program is distributed in the hope it will be useful, but WITHOUT
++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
++ * more details.
++ */
++
++#include <linux/pci.h>
++#include <linux/module.h>
++#include <linux/platform_device.h>
++#include <linux/interrupt.h>
++
++#include "acp3x.h"
++
++struct acp3x_dev_data {
++ void __iomem *acp3x_base;
++ bool acp3x_audio_mode;
++ struct resource *res;
++ struct platform_device *pdev[3];
++};
++
++static int snd_acp3x_probe(struct pci_dev *pci,
++ const struct pci_device_id *pci_id)
++{
++ int ret;
++ u32 addr, val;
++ struct acp3x_dev_data *adata;
++ struct platform_device_info pdevinfo;
++ unsigned int irqflags;
++
++ if (pci_enable_device(pci)) {
++ dev_err(&pci->dev, "pci_enable_device failed\n");
++ return -ENODEV;
++ }
++
++ ret = pci_request_regions(pci, "AMD ACP3x audio");
++ if (ret < 0) {
++ dev_err(&pci->dev, "pci_request_regions failed\n");
++ goto disable_pci;
++ }
++
++ adata = devm_kzalloc(&pci->dev, sizeof(struct acp3x_dev_data),
++ GFP_KERNEL);
++ if (adata == NULL) {
++ ret = -ENOMEM;
++ goto release_regions;
++ }
++
++ /* check for msi interrupt support */
++ ret = pci_enable_msi(pci);
++ if (ret)
++ /* msi is not enabled */
++ irqflags = IRQF_SHARED;
++ else
++ /* msi is enabled */
++ irqflags = 0;
++
++ addr = pci_resource_start(pci, 0);
++ adata->acp3x_base = ioremap(addr, pci_resource_len(pci, 0));
++ if (adata->acp3x_base == NULL) {
++ ret = -ENOMEM;
++ goto release_regions;
++ }
++
++ /* set pci bus-mastering */
++ pci_set_master(pci);
++
++ pci_set_drvdata(pci, adata);
++
++ val = rv_readl(adata->acp3x_base + mmACP_I2S_PIN_CONFIG);
++ if (val == 0x4) {
++ adata->res = devm_kzalloc(&pci->dev,
++ sizeof(struct resource) * 2,
++ GFP_KERNEL);
++ if (adata->res == NULL) {
++ ret = -ENOMEM;
++ goto unmap_mmio;
++ }
++
++ adata->res[0].name = "acp3x_i2s_iomem";
++ adata->res[0].flags = IORESOURCE_MEM;
++ adata->res[0].start = addr;
++ adata->res[0].end = addr + (ACP3x_REG_END - ACP3x_REG_START);
++
++ adata->res[1].name = "acp3x_i2s_irq";
++ adata->res[1].flags = IORESOURCE_IRQ;
++ adata->res[1].start = pci->irq;
++ adata->res[1].end = pci->irq;
++
++ adata->acp3x_audio_mode = ACP3x_I2S_MODE;
++
++ memset(&pdevinfo, 0, sizeof(pdevinfo));
++ pdevinfo.name = "acp3x_rv_i2s";
++ pdevinfo.id = 0;
++ pdevinfo.parent = &pci->dev;
++ pdevinfo.num_res = 2;
++ pdevinfo.res = adata->res;
++ pdevinfo.data = &irqflags;
++ pdevinfo.size_data = sizeof(irqflags);
++
++ adata->pdev[0] = platform_device_register_full(&pdevinfo);
++ if (adata->pdev[0] == NULL) {
++ dev_err(&pci->dev, "cannot register %s device\n",
++ pdevinfo.name);
++ ret = -ENODEV;
++ goto unmap_mmio;
++ }
++
++ /* create dummy codec device */
++ adata->pdev[1] = platform_device_register_simple("dummy_w5102",
++ 0, NULL, 0);
++ if (IS_ERR(adata->pdev[1])) {
++ dev_err(&pci->dev, "Cannot register dummy_w5102\n");
++ ret = -ENODEV;
++ goto unregister_pdev0;
++ }
++ /* create dummy mach device */
++ adata->pdev[2] = platform_device_register_simple(
++ "acp3x_w5102_mach", 0, NULL, 0);
++ if (IS_ERR(adata->pdev[2])) {
++ dev_err(&pci->dev, "Cannot register acp3x_w5102_mach\n");
++ ret = -ENODEV;
++ goto unregister_pdev1;
++ }
++ } else {
++ dev_err(&pci->dev, "Inavlid ACP audio mode : %d\n", val);
++ ret = -ENODEV;
++ goto unmap_mmio;
++ }
++
++ return 0;
++
++unregister_pdev1:
++ platform_device_unregister(adata->pdev[1]);
++unregister_pdev0:
++ platform_device_unregister(adata->pdev[0]);
++unmap_mmio:
++ pci_disable_msi(pci);
++ iounmap(adata->acp3x_base);
++release_regions:
++ pci_release_regions(pci);
++disable_pci:
++ pci_disable_device(pci);
++
++ return ret;
++}
++
++static void snd_acp3x_remove(struct pci_dev *pci)
++{
++ int i;
++ struct acp3x_dev_data *adata = pci_get_drvdata(pci);
++
++ if (adata->acp3x_audio_mode == ACP3x_I2S_MODE) {
++ for (i = 2; i >= 0; i--)
++ platform_device_unregister(adata->pdev[i]);
++ }
++
++ iounmap(adata->acp3x_base);
++
++ pci_disable_msi(pci);
++ pci_release_regions(pci);
++ pci_disable_device(pci);
++}
++
++static const struct pci_device_id snd_acp3x_ids[] = {
++ { PCI_DEVICE(PCI_VENDOR_ID_AMD, 0x15e2),
++ .class = PCI_CLASS_MULTIMEDIA_OTHER << 8,
++ .class_mask = 0xffffff },
++ { 0, },
++};
++MODULE_DEVICE_TABLE(pci, snd_acp3x_ids);
++
++static struct pci_driver acp3x_driver = {
++ .name = KBUILD_MODNAME,
++ .id_table = snd_acp3x_ids,
++ .probe = snd_acp3x_probe,
++ .remove = snd_acp3x_remove,
++};
++
++module_pci_driver(acp3x_driver);
++
++MODULE_AUTHOR("Maruthi.Bayyavarapu@amd.com");
++MODULE_DESCRIPTION("AMD ACP3x PCI driver");
++MODULE_LICENSE("GPL v2");
+--
+2.17.1
+