forked from Minki/linux
ADD legacy audio driver support for rembrandt
Merge series from V sujith kumar Reddy <Vsujithkumar.Reddy@amd.com>: Add Generic driver to support multiple platform, ADD HS control instance for Rembrandt platform. Add nau8825,max98560 and rt5682s,rt1019 combination support for legacy platform.
This commit is contained in:
commit
61b23b6b7b
@ -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
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
@ -199,6 +300,7 @@ static int acp_i2s_prepare(struct snd_pcm_substream *substream, struct snd_soc_d
|
||||
{
|
||||
struct device *dev = dai->component->dev;
|
||||
struct acp_dev_data *adata = dev_get_drvdata(dev);
|
||||
struct acp_resource *rsrc = adata->rsrc;
|
||||
struct acp_stream *stream = substream->runtime->private_data;
|
||||
u32 reg_dma_size = 0, reg_fifo_size = 0, reg_fifo_addr = 0;
|
||||
u32 phy_addr = 0, acp_fifo_addr = 0, ext_int_ctrl;
|
||||
@ -208,7 +310,7 @@ static int acp_i2s_prepare(struct snd_pcm_substream *substream, struct snd_soc_d
|
||||
case I2S_SP_INSTANCE:
|
||||
if (dir == SNDRV_PCM_STREAM_PLAYBACK) {
|
||||
reg_dma_size = ACP_I2S_TX_DMA_SIZE;
|
||||
acp_fifo_addr = ACP_SRAM_PTE_OFFSET +
|
||||
acp_fifo_addr = rsrc->sram_pte_offset +
|
||||
SP_PB_FIFO_ADDR_OFFSET;
|
||||
reg_fifo_addr = ACP_I2S_TX_FIFOADDR;
|
||||
reg_fifo_size = ACP_I2S_TX_FIFOSIZE;
|
||||
@ -217,7 +319,7 @@ static int acp_i2s_prepare(struct snd_pcm_substream *substream, struct snd_soc_d
|
||||
writel(phy_addr, adata->acp_base + ACP_I2S_TX_RINGBUFADDR);
|
||||
} else {
|
||||
reg_dma_size = ACP_I2S_RX_DMA_SIZE;
|
||||
acp_fifo_addr = ACP_SRAM_PTE_OFFSET +
|
||||
acp_fifo_addr = rsrc->sram_pte_offset +
|
||||
SP_CAPT_FIFO_ADDR_OFFSET;
|
||||
reg_fifo_addr = ACP_I2S_RX_FIFOADDR;
|
||||
reg_fifo_size = ACP_I2S_RX_FIFOSIZE;
|
||||
@ -228,7 +330,7 @@ static int acp_i2s_prepare(struct snd_pcm_substream *substream, struct snd_soc_d
|
||||
case I2S_BT_INSTANCE:
|
||||
if (dir == SNDRV_PCM_STREAM_PLAYBACK) {
|
||||
reg_dma_size = ACP_BT_TX_DMA_SIZE;
|
||||
acp_fifo_addr = ACP_SRAM_PTE_OFFSET +
|
||||
acp_fifo_addr = rsrc->sram_pte_offset +
|
||||
BT_PB_FIFO_ADDR_OFFSET;
|
||||
reg_fifo_addr = ACP_BT_TX_FIFOADDR;
|
||||
reg_fifo_size = ACP_BT_TX_FIFOSIZE;
|
||||
@ -237,7 +339,7 @@ static int acp_i2s_prepare(struct snd_pcm_substream *substream, struct snd_soc_d
|
||||
writel(phy_addr, adata->acp_base + ACP_BT_TX_RINGBUFADDR);
|
||||
} else {
|
||||
reg_dma_size = ACP_BT_RX_DMA_SIZE;
|
||||
acp_fifo_addr = ACP_SRAM_PTE_OFFSET +
|
||||
acp_fifo_addr = rsrc->sram_pte_offset +
|
||||
BT_CAPT_FIFO_ADDR_OFFSET;
|
||||
reg_fifo_addr = ACP_BT_RX_FIFOADDR;
|
||||
reg_fifo_size = ACP_BT_RX_FIFOSIZE;
|
||||
@ -246,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;
|
||||
@ -255,11 +378,15 @@ static int acp_i2s_prepare(struct snd_pcm_substream *substream, struct snd_soc_d
|
||||
writel(acp_fifo_addr, adata->acp_base + reg_fifo_addr);
|
||||
writel(FIFO_SIZE, adata->acp_base + reg_fifo_size);
|
||||
|
||||
ext_int_ctrl = readl(adata->acp_base + ACP_EXTERNAL_INTR_CNTL);
|
||||
ext_int_ctrl |= BIT(I2S_RX_THRESHOLD) | BIT(BT_RX_THRESHOLD)
|
||||
| BIT(I2S_TX_THRESHOLD) | BIT(BT_TX_THRESHOLD);
|
||||
ext_int_ctrl = readl(ACP_EXTERNAL_INTR_CNTL(adata, rsrc->irqp_used));
|
||||
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(HS_RX_THRESHOLD(rsrc->offset)) |
|
||||
BIT(HS_TX_THRESHOLD(rsrc->offset));
|
||||
|
||||
writel(ext_int_ctrl, adata->acp_base + ACP_EXTERNAL_INTR_CNTL);
|
||||
writel(ext_int_ctrl, ACP_EXTERNAL_INTR_CNTL(adata, rsrc->irqp_used));
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -268,32 +395,45 @@ static int acp_i2s_startup(struct snd_pcm_substream *substream, struct snd_soc_d
|
||||
{
|
||||
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;
|
||||
unsigned int dir = substream->stream;
|
||||
unsigned int irq_bit = 0;
|
||||
|
||||
switch (dai->driver->id) {
|
||||
case I2S_SP_INSTANCE:
|
||||
if (dir == SNDRV_PCM_STREAM_PLAYBACK) {
|
||||
irq_bit = BIT(I2S_TX_THRESHOLD);
|
||||
irq_bit = BIT(I2S_TX_THRESHOLD(rsrc->offset));
|
||||
stream->pte_offset = ACP_SRAM_SP_PB_PTE_OFFSET;
|
||||
stream->fifo_offset = SP_PB_FIFO_ADDR_OFFSET;
|
||||
} else {
|
||||
irq_bit = BIT(I2S_RX_THRESHOLD);
|
||||
irq_bit = BIT(I2S_RX_THRESHOLD(rsrc->offset));
|
||||
stream->pte_offset = ACP_SRAM_SP_CP_PTE_OFFSET;
|
||||
stream->fifo_offset = SP_CAPT_FIFO_ADDR_OFFSET;
|
||||
}
|
||||
break;
|
||||
case I2S_BT_INSTANCE:
|
||||
if (dir == SNDRV_PCM_STREAM_PLAYBACK) {
|
||||
irq_bit = BIT(BT_TX_THRESHOLD);
|
||||
irq_bit = BIT(BT_TX_THRESHOLD(rsrc->offset));
|
||||
stream->pte_offset = ACP_SRAM_BT_PB_PTE_OFFSET;
|
||||
stream->fifo_offset = BT_PB_FIFO_ADDR_OFFSET;
|
||||
} else {
|
||||
irq_bit = BIT(BT_RX_THRESHOLD);
|
||||
irq_bit = BIT(BT_RX_THRESHOLD(rsrc->offset));
|
||||
stream->pte_offset = ACP_SRAM_BT_CP_PTE_OFFSET;
|
||||
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;
|
||||
@ -319,6 +459,7 @@ int asoc_acp_i2s_probe(struct snd_soc_dai *dai)
|
||||
{
|
||||
struct device *dev = dai->component->dev;
|
||||
struct acp_dev_data *adata = dev_get_drvdata(dev);
|
||||
struct acp_resource *rsrc = adata->rsrc;
|
||||
unsigned int val;
|
||||
|
||||
if (!adata->acp_base) {
|
||||
@ -326,8 +467,8 @@ int asoc_acp_i2s_probe(struct snd_soc_dai *dai)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
val = readl(adata->acp_base + ACP_I2S_PIN_CONFIG);
|
||||
if (val != I2S_MODE) {
|
||||
val = readl(adata->acp_base + rsrc->i2s_pin_cfg_offset);
|
||||
if (val != rsrc->i2s_mode) {
|
||||
dev_err(dev, "I2S Mode not supported val %x\n", val);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
@ -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");
|
||||
|
@ -313,9 +313,6 @@ static const struct snd_soc_ops acp_card_dmic_ops = {
|
||||
SND_SOC_DAILINK_DEF(rt1019,
|
||||
DAILINK_COMP_ARRAY(COMP_CODEC("i2c-10EC1019:00", "rt1019-aif"),
|
||||
COMP_CODEC("i2c-10EC1019:01", "rt1019-aif")));
|
||||
SND_SOC_DAILINK_DEF(rt1019_1,
|
||||
DAILINK_COMP_ARRAY(COMP_CODEC("i2c-10EC1019:02", "rt1019-aif"),
|
||||
COMP_CODEC("i2c-10EC1019:01", "rt1019-aif")));
|
||||
|
||||
static const struct snd_soc_dapm_route rt1019_map_lr[] = {
|
||||
{ "Left Spk", NULL, "Left SPO" },
|
||||
@ -333,17 +330,6 @@ static struct snd_soc_codec_conf rt1019_conf[] = {
|
||||
},
|
||||
};
|
||||
|
||||
static struct snd_soc_codec_conf rt1019_1_conf[] = {
|
||||
{
|
||||
.dlc = COMP_CODEC_CONF("i2c-10EC1019:02"),
|
||||
.name_prefix = "Left",
|
||||
},
|
||||
{
|
||||
.dlc = COMP_CODEC_CONF("i2c-10EC1019:01"),
|
||||
.name_prefix = "Right",
|
||||
},
|
||||
};
|
||||
|
||||
static int acp_card_rt1019_init(struct snd_soc_pcm_runtime *rtd)
|
||||
{
|
||||
struct snd_soc_card *card = rtd->card;
|
||||
@ -559,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",
|
||||
@ -567,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,
|
||||
@ -716,10 +710,6 @@ int acp_sofdsp_dai_links_create(struct snd_soc_card *card)
|
||||
links[i].init = acp_card_rt1019_init;
|
||||
card->codec_conf = rt1019_conf;
|
||||
card->num_configs = ARRAY_SIZE(rt1019_conf);
|
||||
links[i].codecs = rt1019_1;
|
||||
links[i].num_codecs = ARRAY_SIZE(rt1019_1);
|
||||
card->codec_conf = rt1019_1_conf;
|
||||
card->num_configs = ARRAY_SIZE(rt1019_1_conf);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
@ -792,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;
|
||||
@ -822,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;
|
||||
@ -835,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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -160,9 +160,9 @@ static int acp_dmic_dai_startup(struct snd_pcm_substream *substream,
|
||||
stream->reg_offset = ACP_REGION2_OFFSET;
|
||||
|
||||
/* Enable DMIC Interrupts */
|
||||
ext_int_ctrl = readl(adata->acp_base + ACP_EXTERNAL_INTR_CNTL);
|
||||
ext_int_ctrl = readl(ACP_EXTERNAL_INTR_CNTL(adata, 0));
|
||||
ext_int_ctrl |= PDM_DMA_INTR_MASK;
|
||||
writel(ext_int_ctrl, adata->acp_base + ACP_EXTERNAL_INTR_CNTL);
|
||||
writel(ext_int_ctrl, ACP_EXTERNAL_INTR_CNTL(adata, 0));
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -175,9 +175,9 @@ static void acp_dmic_dai_shutdown(struct snd_pcm_substream *substream,
|
||||
u32 ext_int_ctrl;
|
||||
|
||||
/* Disable DMIC interrupts */
|
||||
ext_int_ctrl = readl(adata->acp_base + ACP_EXTERNAL_INTR_CNTL);
|
||||
ext_int_ctrl = readl(ACP_EXTERNAL_INTR_CNTL(adata, 0));
|
||||
ext_int_ctrl |= ~PDM_DMA_INTR_MASK;
|
||||
writel(ext_int_ctrl, adata->acp_base + ACP_EXTERNAL_INTR_CNTL);
|
||||
writel(ext_int_ctrl, ACP_EXTERNAL_INTR_CNTL(adata, 0));
|
||||
}
|
||||
|
||||
const struct snd_soc_dai_ops acp_dmic_dai_ops = {
|
||||
|
@ -91,25 +91,38 @@ EXPORT_SYMBOL_NS_GPL(acp_machine_select, SND_SOC_ACP_COMMON);
|
||||
static irqreturn_t i2s_irq_handler(int irq, void *data)
|
||||
{
|
||||
struct acp_dev_data *adata = 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;
|
||||
|
||||
val = readl(adata->acp_base + ACP_EXTERNAL_INTR_STAT);
|
||||
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++) {
|
||||
stream = adata->stream[i];
|
||||
if (stream && (val & stream->irq_bit)) {
|
||||
writel(stream->irq_bit, adata->acp_base + ACP_EXTERNAL_INTR_STAT);
|
||||
writel(stream->irq_bit,
|
||||
ACP_EXTERNAL_INTR_STAT(adata, rsrc->irqp_used));
|
||||
snd_pcm_period_elapsed(stream->substream);
|
||||
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;
|
||||
|
||||
@ -118,6 +131,7 @@ static irqreturn_t i2s_irq_handler(int irq, void *data)
|
||||
|
||||
static void config_pte_for_stream(struct acp_dev_data *adata, struct acp_stream *stream)
|
||||
{
|
||||
struct acp_resource *rsrc = adata->rsrc;
|
||||
u32 pte_reg, pte_size, reg_val;
|
||||
|
||||
/* Use ATU base Group5 */
|
||||
@ -126,15 +140,17 @@ static void config_pte_for_stream(struct acp_dev_data *adata, struct acp_stream
|
||||
stream->reg_offset = 0x02000000;
|
||||
|
||||
/* Group Enable */
|
||||
reg_val = ACP_SRAM_PTE_OFFSET;
|
||||
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)
|
||||
{
|
||||
struct acp_stream *stream = adata->stream[cpu_id];
|
||||
struct snd_pcm_substream *substream = stream->substream;
|
||||
struct acp_resource *rsrc = adata->rsrc;
|
||||
dma_addr_t addr = substream->dma_buffer.addr;
|
||||
int num_pages = (PAGE_ALIGN(size) >> PAGE_SHIFT);
|
||||
u32 low, high, val;
|
||||
@ -146,9 +162,9 @@ static void config_acp_dma(struct acp_dev_data *adata, int cpu_id, int size)
|
||||
/* Load the low address of page int ACP SRAM through SRBM */
|
||||
low = lower_32_bits(addr);
|
||||
high = upper_32_bits(addr);
|
||||
writel(low, adata->acp_base + ACP_SCRATCH_REG_0 + val);
|
||||
writel(low, adata->acp_base + rsrc->scratch_reg_offset + val);
|
||||
high |= BIT(31);
|
||||
writel(high, adata->acp_base + ACP_SCRATCH_REG_0 + val + 4);
|
||||
writel(high, adata->acp_base + rsrc->scratch_reg_offset + val + 4);
|
||||
|
||||
/* Move to next physically contiguous page */
|
||||
val += 8;
|
||||
@ -187,7 +203,7 @@ static int acp_dma_open(struct snd_soc_component *component, struct snd_pcm_subs
|
||||
}
|
||||
runtime->private_data = stream;
|
||||
|
||||
writel(1, adata->acp_base + ACP_EXTERNAL_INTR_ENB);
|
||||
writel(1, ACP_EXTERNAL_INTR_ENB(adata));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
401
sound/soc/amd/acp/acp-rembrandt.c
Normal file
401
sound/soc/amd/acp/acp-rembrandt.c
Normal file
@ -0,0 +1,401 @@
|
||||
// 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 int rmb_acp_init(void __iomem *base);
|
||||
static int rmb_acp_deinit(void __iomem *base);
|
||||
|
||||
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 = &_max,
|
||||
},
|
||||
{
|
||||
.id = "AMDI0007",
|
||||
.drv_name = "rembrandt-acp",
|
||||
},
|
||||
{
|
||||
.id = "RTL5682",
|
||||
.drv_name = "rmb-rt5682s-rt1019",
|
||||
.machine_quirk = snd_soc_acpi_codec_list,
|
||||
.quirk_data = &_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));
|
||||
}
|
||||
|
||||
static 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;
|
||||
}
|
||||
|
||||
static 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);
|
@ -39,6 +39,17 @@
|
||||
#define ACP_ERROR_MASK 0x20000000
|
||||
#define ACP_EXT_INTR_STAT_CLEAR_MASK 0xFFFFFFFF
|
||||
|
||||
static struct acp_resource rsrc = {
|
||||
.offset = 20,
|
||||
.no_of_ctrls = 1,
|
||||
.irqp_used = 0,
|
||||
.irq_reg_offset = 0x1800,
|
||||
.i2s_pin_cfg_offset = 0x1400,
|
||||
.i2s_mode = 0x04,
|
||||
.scratch_reg_offset = 0x12800,
|
||||
.sram_pte_offset = 0x02052800,
|
||||
};
|
||||
|
||||
static struct snd_soc_acpi_codecs amp_rt1019 = {
|
||||
.num_codecs = 1,
|
||||
.codecs = {"10EC1019"}
|
||||
@ -186,20 +197,24 @@ static int acp3x_reset(void __iomem *base)
|
||||
return readl_poll_timeout(base + ACP_SOFT_RESET, val, !val, DELAY_US, ACP_TIMEOUT);
|
||||
}
|
||||
|
||||
static void acp3x_enable_interrupts(void __iomem *base)
|
||||
static void acp3x_enable_interrupts(struct acp_dev_data *adata)
|
||||
{
|
||||
struct acp_resource *rsrc = adata->rsrc;
|
||||
u32 ext_intr_ctrl;
|
||||
|
||||
writel(0x01, base + ACP_EXTERNAL_INTR_ENB);
|
||||
ext_intr_ctrl = readl(base + ACP_EXTERNAL_INTR_CNTL);
|
||||
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, base + ACP_EXTERNAL_INTR_CNTL);
|
||||
writel(ext_intr_ctrl, ACP_EXTERNAL_INTR_CNTL(adata, rsrc->irqp_used));
|
||||
}
|
||||
|
||||
static void acp3x_disable_interrupts(void __iomem *base)
|
||||
static void acp3x_disable_interrupts(struct acp_dev_data *adata)
|
||||
{
|
||||
writel(ACP_EXT_INTR_STAT_CLEAR_MASK, base + ACP_EXTERNAL_INTR_STAT);
|
||||
writel(0x00, base + ACP_EXTERNAL_INTR_ENB);
|
||||
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));
|
||||
}
|
||||
|
||||
static int rn_acp_init(void __iomem *base)
|
||||
@ -218,8 +233,6 @@ static int rn_acp_init(void __iomem *base)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
acp3x_enable_interrupts(base);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -227,8 +240,6 @@ static int rn_acp_deinit(void __iomem *base)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
acp3x_disable_interrupts(base);
|
||||
|
||||
/* Reset */
|
||||
ret = acp3x_reset(base);
|
||||
if (ret)
|
||||
@ -290,11 +301,13 @@ static int renoir_audio_probe(struct platform_device *pdev)
|
||||
adata->dev = dev;
|
||||
adata->dai_driver = acp_renoir_dai;
|
||||
adata->num_dai = ARRAY_SIZE(acp_renoir_dai);
|
||||
adata->rsrc = &rsrc;
|
||||
|
||||
adata->machines = snd_soc_acpi_amd_acp_machines;
|
||||
acp_machine_select(adata);
|
||||
|
||||
dev_set_drvdata(dev, adata);
|
||||
acp3x_enable_interrupts(adata);
|
||||
acp_platform_register(dev);
|
||||
|
||||
return 0;
|
||||
@ -303,11 +316,14 @@ static int renoir_audio_probe(struct platform_device *pdev)
|
||||
static int renoir_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;
|
||||
int ret;
|
||||
|
||||
chip = dev_get_platdata(&pdev->dev);
|
||||
|
||||
acp3x_disable_interrupts(adata);
|
||||
|
||||
ret = rn_acp_deinit(chip->base);
|
||||
if (ret)
|
||||
dev_err(&pdev->dev, "ACP de-init Failed (%pe)\n", ERR_PTR(ret));
|
||||
|
@ -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
|
||||
|
||||
@ -32,30 +34,37 @@
|
||||
#define ACP3x_I2STDM_REG_END 0x1242410
|
||||
#define ACP3x_BT_TDM_REG_START 0x1242800
|
||||
#define ACP3x_BT_TDM_REG_END 0x1242810
|
||||
#define I2S_MODE 0x04
|
||||
#define I2S_RX_THRESHOLD 27
|
||||
#define I2S_TX_THRESHOLD 28
|
||||
#define BT_TX_THRESHOLD 26
|
||||
#define BT_RX_THRESHOLD 25
|
||||
|
||||
#define ACP_SRAM_PTE_OFFSET 0x02052800
|
||||
#define THRESHOLD(bit, base) ((bit) + (base))
|
||||
#define I2S_RX_THRESHOLD(base) THRESHOLD(7, base)
|
||||
#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
|
||||
@ -73,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 */
|
||||
@ -92,6 +101,18 @@ struct acp_stream {
|
||||
u32 fifo_offset;
|
||||
};
|
||||
|
||||
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;
|
||||
u64 scratch_reg_offset;
|
||||
u64 sram_pte_offset;
|
||||
};
|
||||
|
||||
struct acp_dev_data {
|
||||
char *name;
|
||||
struct device *dev;
|
||||
@ -106,6 +127,22 @@ 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;
|
||||
@ -134,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;
|
||||
@ -148,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);
|
||||
@ -163,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
|
||||
|
@ -20,11 +20,13 @@
|
||||
#define ACP_SOFT_RESET 0x1000
|
||||
#define ACP_CONTROL 0x1004
|
||||
|
||||
#define ACP_EXTERNAL_INTR_ENB 0x1800
|
||||
#define ACP_EXTERNAL_INTR_CNTL 0x1804
|
||||
#define ACP_EXTERNAL_INTR_STAT 0x1808
|
||||
#define ACP_I2S_PIN_CONFIG 0x1400
|
||||
#define ACP_SCRATCH_REG_0 0x12800
|
||||
#define ACP_EXTERNAL_INTR_REG_ADDR(adata, offset, ctrl) \
|
||||
(adata->acp_base + adata->rsrc->irq_reg_offset + offset + (ctrl * 0x04))
|
||||
|
||||
#define ACP_EXTERNAL_INTR_ENB(adata) ACP_EXTERNAL_INTR_REG_ADDR(adata, 0x0, 0x0)
|
||||
#define ACP_EXTERNAL_INTR_CNTL(adata, ctrl) ACP_EXTERNAL_INTR_REG_ADDR(adata, 0x4, ctrl)
|
||||
#define ACP_EXTERNAL_INTR_STAT(adata, ctrl) ACP_EXTERNAL_INTR_REG_ADDR(adata, \
|
||||
(0x4 + (adata->rsrc->no_of_ctrls * 0x04)), ctrl)
|
||||
|
||||
/* Registers from ACP_AUDIO_BUFFERS block */
|
||||
|
||||
@ -64,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
|
||||
@ -79,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
|
||||
@ -99,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
|
||||
|
Loading…
Reference in New Issue
Block a user