|
@@ -336,6 +336,61 @@ static void config_acp_dma(void __iomem *acp_mmio,
|
|
|
rtd->dma_dscr_idx_2, asic_type);
|
|
|
}
|
|
|
|
|
|
+static void acp_dma_cap_channel_enable(void __iomem *acp_mmio,
|
|
|
+ u16 cap_channel)
|
|
|
+{
|
|
|
+ u32 val, ch_reg, imr_reg, res_reg;
|
|
|
+
|
|
|
+ switch (cap_channel) {
|
|
|
+ case CAP_CHANNEL1:
|
|
|
+ ch_reg = mmACP_I2SMICSP_RER1;
|
|
|
+ res_reg = mmACP_I2SMICSP_RCR1;
|
|
|
+ imr_reg = mmACP_I2SMICSP_IMR1;
|
|
|
+ break;
|
|
|
+ case CAP_CHANNEL0:
|
|
|
+ default:
|
|
|
+ ch_reg = mmACP_I2SMICSP_RER0;
|
|
|
+ res_reg = mmACP_I2SMICSP_RCR0;
|
|
|
+ imr_reg = mmACP_I2SMICSP_IMR0;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ val = acp_reg_read(acp_mmio,
|
|
|
+ mmACP_I2S_16BIT_RESOLUTION_EN);
|
|
|
+ if (val & ACP_I2S_MIC_16BIT_RESOLUTION_EN) {
|
|
|
+ acp_reg_write(0x0, acp_mmio, ch_reg);
|
|
|
+ /* Set 16bit resolution on capture */
|
|
|
+ acp_reg_write(0x2, acp_mmio, res_reg);
|
|
|
+ }
|
|
|
+ val = acp_reg_read(acp_mmio, imr_reg);
|
|
|
+ val &= ~ACP_I2SMICSP_IMR1__I2SMICSP_RXDAM_MASK;
|
|
|
+ val &= ~ACP_I2SMICSP_IMR1__I2SMICSP_RXFOM_MASK;
|
|
|
+ acp_reg_write(val, acp_mmio, imr_reg);
|
|
|
+ acp_reg_write(0x1, acp_mmio, ch_reg);
|
|
|
+}
|
|
|
+
|
|
|
+static void acp_dma_cap_channel_disable(void __iomem *acp_mmio,
|
|
|
+ u16 cap_channel)
|
|
|
+{
|
|
|
+ u32 val, ch_reg, imr_reg;
|
|
|
+
|
|
|
+ switch (cap_channel) {
|
|
|
+ case CAP_CHANNEL1:
|
|
|
+ imr_reg = mmACP_I2SMICSP_IMR1;
|
|
|
+ ch_reg = mmACP_I2SMICSP_RER1;
|
|
|
+ break;
|
|
|
+ case CAP_CHANNEL0:
|
|
|
+ default:
|
|
|
+ imr_reg = mmACP_I2SMICSP_IMR0;
|
|
|
+ ch_reg = mmACP_I2SMICSP_RER0;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ val = acp_reg_read(acp_mmio, imr_reg);
|
|
|
+ val |= ACP_I2SMICSP_IMR1__I2SMICSP_RXDAM_MASK;
|
|
|
+ val |= ACP_I2SMICSP_IMR1__I2SMICSP_RXFOM_MASK;
|
|
|
+ acp_reg_write(val, acp_mmio, imr_reg);
|
|
|
+ acp_reg_write(0x0, acp_mmio, ch_reg);
|
|
|
+}
|
|
|
+
|
|
|
/* Start a given DMA channel transfer */
|
|
|
static void acp_dma_start(void __iomem *acp_mmio, u16 ch_num)
|
|
|
{
|
|
@@ -773,8 +828,10 @@ static int acp_dma_hw_params(struct snd_pcm_substream *substream,
|
|
|
if (WARN_ON(!rtd))
|
|
|
return -EINVAL;
|
|
|
|
|
|
- if (pinfo)
|
|
|
+ if (pinfo) {
|
|
|
rtd->i2s_instance = pinfo->i2s_instance;
|
|
|
+ rtd->capture_channel = pinfo->capture_channel;
|
|
|
+ }
|
|
|
if (adata->asic_type == CHIP_STONEY) {
|
|
|
val = acp_reg_read(adata->acp_mmio,
|
|
|
mmACP_I2S_16BIT_RESOLUTION_EN);
|
|
@@ -990,6 +1047,18 @@ static int acp_dma_trigger(struct snd_pcm_substream *substream, int cmd)
|
|
|
acp_dma_start(rtd->acp_mmio, rtd->ch1);
|
|
|
acp_dma_start(rtd->acp_mmio, rtd->ch2);
|
|
|
} else {
|
|
|
+ if (rtd->capture_channel == CAP_CHANNEL0) {
|
|
|
+ acp_dma_cap_channel_disable(rtd->acp_mmio,
|
|
|
+ CAP_CHANNEL1);
|
|
|
+ acp_dma_cap_channel_enable(rtd->acp_mmio,
|
|
|
+ CAP_CHANNEL0);
|
|
|
+ }
|
|
|
+ if (rtd->capture_channel == CAP_CHANNEL1) {
|
|
|
+ acp_dma_cap_channel_disable(rtd->acp_mmio,
|
|
|
+ CAP_CHANNEL0);
|
|
|
+ acp_dma_cap_channel_enable(rtd->acp_mmio,
|
|
|
+ CAP_CHANNEL1);
|
|
|
+ }
|
|
|
acp_dma_start(rtd->acp_mmio, rtd->ch2);
|
|
|
acp_dma_start(rtd->acp_mmio, rtd->ch1);
|
|
|
}
|