static int sunxi_i2s_preapre(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { u32 reg_val = 0; if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { reg_val = SUNXI_TXCHSEL_CHNUM(substream->runtime->channels); /*confige i2s ap tx channel */ codec_wr_control(SUNXI_DA_TXCHSEL, 0x7, TX_CHSEL, reg_val); if(substream->runtime->channels == 1) { reg_val = 0x00; } else { reg_val = 0x10; } /*confige i2s ap tx channel mapping*/ codec_wr_control(SUNXI_DA_TXCHMAP, 0x7, TX_CH0_MAP, reg_val); /*SDO ON*/ codec_wr_control(SUNXI_DA_CTL, 0x1, SDO_EN, 1); /* I2S0 TX ENABLE */ codec_wr_control(SUNXI_DA_CTL, 0x1, TXEN, 1); } else { reg_val = SUNXI_RXCHSEL_CHNUM(substream->runtime->channels); /*confige i2s ap rx channel */ codec_wr_control(SUNXI_DA_RXCHSEL, 0x7, RX_CHSEL, reg_val); if(substream->runtime->channels == 1) { reg_val = 0x00; } else { reg_val = 0x10; } /*confige i2s ap rx channel mapping*/ codec_wr_control(SUNXI_DA_RXCHMAP, 0x7, RX_CH0_MAP, reg_val); /* I2S0 RX ENABLE */ codec_wr_control(SUNXI_DA_CTL, 0x1, RXEN, 1); } return 0; }
void sunxi_snd_txctrl_i2s(struct snd_pcm_substream *substream, int on) { u32 reg_val; reg_val = readl(sunxi_iis.regs + SUNXI_TXCHSEL); reg_val &= ~0x7; reg_val |= SUNXI_TXCHSEL_CHNUM(substream->runtime->channels); writel(reg_val, sunxi_iis.regs + SUNXI_TXCHSEL); reg_val = readl(sunxi_iis.regs + SUNXI_TXCHMAP); reg_val = 0; if (sunxi_is_sun4i()) { if(substream->runtime->channels == 1) { reg_val = 0x76543200; } else { reg_val = 0x76543210; } } else { if(substream->runtime->channels == 1) { reg_val = 0x00000000; } else { reg_val = 0x00000010; } } writel(reg_val, sunxi_iis.regs + SUNXI_TXCHMAP); reg_val = readl(sunxi_iis.regs + SUNXI_IISCTL); if (sunxi_is_sun4i()) { reg_val &= ~SUNXI_IISCTL_SDO3EN; reg_val &= ~SUNXI_IISCTL_SDO2EN; reg_val &= ~SUNXI_IISCTL_SDO1EN; reg_val &= ~SUNXI_IISCTL_SDO0EN; switch(substream->runtime->channels) { case 1: case 2: reg_val |= SUNXI_IISCTL_SDO0EN; break; case 3: case 4: reg_val |= SUNXI_IISCTL_SDO0EN; reg_val |= SUNXI_IISCTL_SDO1EN; break; case 5: case 6: reg_val |= SUNXI_IISCTL_SDO0EN; reg_val |= SUNXI_IISCTL_SDO1EN; reg_val |= SUNXI_IISCTL_SDO2EN; break; case 7: case 8: reg_val |= SUNXI_IISCTL_SDO0EN; reg_val |= SUNXI_IISCTL_SDO1EN; reg_val |= SUNXI_IISCTL_SDO2EN; reg_val |= SUNXI_IISCTL_SDO3EN; break; default: reg_val |= SUNXI_IISCTL_SDO0EN; } } else { reg_val |= SUNXI_IISCTL_SDO0EN; } writel(reg_val, sunxi_iis.regs + SUNXI_IISCTL); //flush TX FIFO reg_val = readl(sunxi_iis.regs + SUNXI_IISFCTL); reg_val |= SUNXI_IISFCTL_FTX; writel(reg_val, sunxi_iis.regs + SUNXI_IISFCTL); //clear TX counter writel(0, sunxi_iis.regs + SUNXI_IISTXCNT); if (on) { /* IIS TX ENABLE */ reg_val = readl(sunxi_iis.regs + SUNXI_IISCTL); reg_val |= SUNXI_IISCTL_TXEN; writel(reg_val, sunxi_iis.regs + SUNXI_IISCTL); /* enable DMA DRQ mode for play */ reg_val = readl(sunxi_iis.regs + SUNXI_IISINT); reg_val |= SUNXI_IISINT_TXDRQEN; writel(reg_val, sunxi_iis.regs + SUNXI_IISINT); //Global Enable Digital Audio Interface reg_val = readl(sunxi_iis.regs + SUNXI_IISCTL); reg_val |= SUNXI_IISCTL_GEN; writel(reg_val, sunxi_iis.regs + SUNXI_IISCTL); } else { /* IIS TX DISABLE */ reg_val = readl(sunxi_iis.regs + SUNXI_IISCTL); reg_val &= ~SUNXI_IISCTL_TXEN; writel(reg_val, sunxi_iis.regs + SUNXI_IISCTL); /* DISBALE dma DRQ mode */ reg_val = readl(sunxi_iis.regs + SUNXI_IISINT); reg_val &= ~SUNXI_IISINT_TXDRQEN; writel(reg_val, sunxi_iis.regs + SUNXI_IISINT); //Global disable Digital Audio Interface reg_val = readl(sunxi_iis.regs + SUNXI_IISCTL); reg_val &= ~SUNXI_IISCTL_GEN; writel(reg_val, sunxi_iis.regs + SUNXI_IISCTL); } }
static void sunxi_snd_txctrl_i2s1(struct snd_pcm_substream *substream, int on) { u32 reg_val; reg_val = readl(sunxi_i2s1.regs + SUNXI_TXCHSEL); reg_val &= ~0x7; reg_val |= SUNXI_TXCHSEL_CHNUM(substream->runtime->channels); writel(reg_val, sunxi_i2s1.regs + SUNXI_TXCHSEL); reg_val = readl(sunxi_i2s1.regs + SUNXI_TXCHMAP); reg_val = 0; if(substream->runtime->channels == 1) { reg_val = 0x76543200; } else { reg_val = 0x76543210; } writel(reg_val, sunxi_i2s1.regs + SUNXI_TXCHMAP); reg_val = readl(sunxi_i2s1.regs + SUNXI_I2S1CTL); reg_val &= ~SUNXI_I2S1CTL_SDO3EN; reg_val &= ~SUNXI_I2S1CTL_SDO2EN; reg_val &= ~SUNXI_I2S1CTL_SDO1EN; reg_val &= ~SUNXI_I2S1CTL_SDO0EN; switch(substream->runtime->channels) { case 1: case 2: reg_val |= SUNXI_I2S1CTL_SDO0EN; break; case 3: case 4: reg_val |= SUNXI_I2S1CTL_SDO0EN | SUNXI_I2S1CTL_SDO1EN; break; case 5: case 6: reg_val |= SUNXI_I2S1CTL_SDO0EN | SUNXI_I2S1CTL_SDO1EN | SUNXI_I2S1CTL_SDO2EN; break; case 7: case 8: reg_val |= SUNXI_I2S1CTL_SDO0EN | SUNXI_I2S1CTL_SDO1EN | SUNXI_I2S1CTL_SDO2EN | SUNXI_I2S1CTL_SDO3EN; break; default: reg_val |= SUNXI_I2S1CTL_SDO0EN; break; } writel(reg_val, sunxi_i2s1.regs + SUNXI_I2S1CTL); /*flush TX FIFO*/ reg_val = readl(sunxi_i2s1.regs + SUNXI_I2S1FCTL); reg_val |= SUNXI_I2S1FCTL_FTX; writel(reg_val, sunxi_i2s1.regs + SUNXI_I2S1FCTL); /*clear TX counter*/ writel(0, sunxi_i2s1.regs + SUNXI_I2S1TXCNT); if (on) { /* I2S1 TX ENABLE */ reg_val = readl(sunxi_i2s1.regs + SUNXI_I2S1CTL); reg_val |= SUNXI_I2S1CTL_TXEN; writel(reg_val, sunxi_i2s1.regs + SUNXI_I2S1CTL); /* enable DMA DRQ mode for play */ reg_val = readl(sunxi_i2s1.regs + SUNXI_I2S1INT); reg_val |= SUNXI_I2S1INT_TXDRQEN; writel(reg_val, sunxi_i2s1.regs + SUNXI_I2S1INT); } else { /* I2S1 TX DISABLE */ reg_val = readl(sunxi_i2s1.regs + SUNXI_I2S1CTL); reg_val &= ~SUNXI_I2S1CTL_TXEN; writel(reg_val, sunxi_i2s1.regs + SUNXI_I2S1CTL); /* DISBALE dma DRQ mode */ reg_val = readl(sunxi_i2s1.regs + SUNXI_I2S1INT); reg_val &= ~SUNXI_I2S1INT_TXDRQEN; writel(reg_val, sunxi_i2s1.regs + SUNXI_I2S1INT); } }