static int sun4i_i2s_set_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt) { u32 reg_val; u32 reg_val1; //SDO ON reg_val = readl(sun4i_iis.regs + SUN4I_IISCTL); reg_val |= (SUN4I_IISCTL_SDO0EN | SUN4I_IISCTL_SDO1EN | SUN4I_IISCTL_SDO2EN | SUN4I_IISCTL_SDO3EN); #ifdef PCM_COMMUNICATION reg_val |= SUN4I_IISCTL_PCM; #endif writel(reg_val, sun4i_iis.regs + SUN4I_IISCTL); /* master or slave selection */ reg_val = readl(sun4i_iis.regs + SUN4I_IISCTL); switch(fmt & SND_SOC_DAIFMT_MASTER_MASK){ case SND_SOC_DAIFMT_CBM_CFM: /* codec clk & frm master */ reg_val |= SUN4I_IISCTL_MS; break; case SND_SOC_DAIFMT_CBS_CFS: /* codec clk & frm slave */ reg_val &= ~SUN4I_IISCTL_MS; break; default: return -EINVAL; } writel(reg_val, sun4i_iis.regs + SUN4I_IISCTL); /* pcm or i2s mode selection */ reg_val = readl(sun4i_iis.regs + SUN4I_IISCTL); reg_val1 = readl(sun4i_iis.regs + SUN4I_IISFAT0); reg_val1 &= ~SUN4I_IISFAT0_FMT_RVD; switch(fmt & SND_SOC_DAIFMT_FORMAT_MASK){ case SND_SOC_DAIFMT_I2S: /* I2S mode */ reg_val &= ~SUN4I_IISCTL_PCM; reg_val1 |= SUN4I_IISFAT0_FMT_I2S; break; case SND_SOC_DAIFMT_RIGHT_J: /* Right Justified mode */ reg_val &= ~SUN4I_IISCTL_PCM; reg_val1 |= SUN4I_IISFAT0_FMT_RGT; break; case SND_SOC_DAIFMT_LEFT_J: /* Left Justified mode */ reg_val &= ~SUN4I_IISCTL_PCM; reg_val1 |= SUN4I_IISFAT0_FMT_LFT; break; case SND_SOC_DAIFMT_DSP_A: /* L data msb after FRM LRC */ reg_val |= SUN4I_IISCTL_PCM; reg_val1 &= ~SUN4I_IISFAT0_LRCP; break; case SND_SOC_DAIFMT_DSP_B: /* L data msb during FRM LRC */ reg_val |= SUN4I_IISCTL_PCM; reg_val1 |= SUN4I_IISFAT0_LRCP; break; default: return -EINVAL; } writel(reg_val, sun4i_iis.regs + SUN4I_IISCTL); writel(reg_val1, sun4i_iis.regs + SUN4I_IISFAT0); /* DAI signal inversions */ reg_val1 = readl(sun4i_iis.regs + SUN4I_IISFAT0); switch(fmt & SND_SOC_DAIFMT_INV_MASK){ case SND_SOC_DAIFMT_NB_NF: /* normal bit clock + frame */ reg_val1 &= ~SUN4I_IISFAT0_LRCP; reg_val1 &= ~SUN4I_IISFAT0_BCP; break; case SND_SOC_DAIFMT_NB_IF: /* normal bclk + inv frm */ reg_val1 |= SUN4I_IISFAT0_LRCP; reg_val1 &= ~SUN4I_IISFAT0_BCP; break; case SND_SOC_DAIFMT_IB_NF: /* invert bclk + nor frm */ reg_val1 &= ~SUN4I_IISFAT0_LRCP; reg_val1 |= SUN4I_IISFAT0_BCP; break; case SND_SOC_DAIFMT_IB_IF: /* invert bclk + frm */ reg_val1 |= SUN4I_IISFAT0_LRCP; reg_val1 |= SUN4I_IISFAT0_BCP; break; } writel(reg_val1, sun4i_iis.regs + SUN4I_IISFAT0); /* set FIFO control register */ reg_val = 1 & 0x3; reg_val |= (1 & 0x1)<<2; reg_val |= SUN4I_IISFCTL_RXTL(0xf); //RX FIFO trigger level reg_val |= SUN4I_IISFCTL_TXTL(0x40); //TX FIFO empty trigger level writel(reg_val, sun4i_iis.regs + SUN4I_IISFCTL); return 0; }
static int sun4i_i2s_set_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt) { u32 reg_val; u32 reg_val1; //SDO ON reg_val = readl(sun4i_iis.regs + SUN4I_IISCTL); reg_val |= (SUN4I_IISCTL_SDO0EN | SUN4I_IISCTL_SDO1EN | SUN4I_IISCTL_SDO2EN | SUN4I_IISCTL_SDO3EN); writel(reg_val, sun4i_iis.regs + SUN4I_IISCTL); /* master or slave selection */ reg_val = readl(sun4i_iis.regs + SUN4I_IISCTL); switch(fmt & SND_SOC_DAIFMT_MASTER_MASK){ case SND_SOC_DAIFMT_CBM_CFM: /* codec clk & frm master */ reg_val |= SUN4I_IISCTL_MS; break; case SND_SOC_DAIFMT_CBS_CFS: /* codec clk & frm slave */ reg_val &= ~SUN4I_IISCTL_MS; break; default: return -EINVAL; } writel(reg_val, sun4i_iis.regs + SUN4I_IISCTL); /* pcm or i2s mode selection */ reg_val = readl(sun4i_iis.regs + SUN4I_IISCTL); reg_val1 = readl(sun4i_iis.regs + SUN4I_IISFAT0); reg_val1 &= ~SUN4I_IISFAT0_FMT_RVD; switch(fmt & SND_SOC_DAIFMT_FORMAT_MASK){ case SND_SOC_DAIFMT_I2S: /* I2S mode */ reg_val &= ~SUN4I_IISCTL_PCM; reg_val1 |= SUN4I_IISFAT0_FMT_I2S; break; case SND_SOC_DAIFMT_RIGHT_J: /* Right Justified mode */ reg_val &= ~SUN4I_IISCTL_PCM; reg_val1 |= SUN4I_IISFAT0_FMT_RGT; break; case SND_SOC_DAIFMT_LEFT_J: /* Left Justified mode */ reg_val &= ~SUN4I_IISCTL_PCM; reg_val1 |= SUN4I_IISFAT0_FMT_LFT; break; case SND_SOC_DAIFMT_DSP_A: /* L data msb after FRM LRC */ reg_val |= SUN4I_IISCTL_PCM; reg_val1 &= ~SUN4I_IISFAT0_LRCP; break; case SND_SOC_DAIFMT_DSP_B: /* L data msb during FRM LRC */ reg_val |= SUN4I_IISCTL_PCM; reg_val1 |= SUN4I_IISFAT0_LRCP; break; default: return -EINVAL; } writel(reg_val, sun4i_iis.regs + SUN4I_IISCTL); writel(reg_val1, sun4i_iis.regs + SUN4I_IISFAT0); /* DAI signal inversions */ reg_val1 = readl(sun4i_iis.regs + SUN4I_IISFAT0); switch(fmt & SND_SOC_DAIFMT_INV_MASK){ case SND_SOC_DAIFMT_NB_NF: /* normal bit clock + frame */ reg_val1 &= ~SUN4I_IISFAT0_LRCP; reg_val1 &= ~SUN4I_IISFAT0_BCP; break; case SND_SOC_DAIFMT_NB_IF: /* normal bclk + inv frm */ reg_val1 |= SUN4I_IISFAT0_LRCP; reg_val1 &= ~SUN4I_IISFAT0_BCP; break; case SND_SOC_DAIFMT_IB_NF: /* invert bclk + nor frm */ reg_val1 &= ~SUN4I_IISFAT0_LRCP; reg_val1 |= SUN4I_IISFAT0_BCP; break; case SND_SOC_DAIFMT_IB_IF: /* invert bclk + frm */ reg_val1 |= SUN4I_IISFAT0_LRCP; reg_val1 |= SUN4I_IISFAT0_BCP; break; } writel(reg_val1, sun4i_iis.regs + SUN4I_IISFAT0); /* word select size */ reg_val = readl(sun4i_iis.regs + SUN4I_IISFAT0); reg_val &= ~SUN4I_IISFAT0_WSS_32BCLK; if(sun4i_iis.ws_size == 16) reg_val |= SUN4I_IISFAT0_WSS_16BCLK; else if(sun4i_iis.ws_size == 20) reg_val |= SUN4I_IISFAT0_WSS_20BCLK; else if(sun4i_iis.ws_size == 24) reg_val |= SUN4I_IISFAT0_WSS_24BCLK; else reg_val |= SUN4I_IISFAT0_WSS_32BCLK; writel(reg_val, sun4i_iis.regs + SUN4I_IISFAT0); /* PCM REGISTER setup */ reg_val = sun4i_iis.pcm_txtype&0x3; reg_val |= sun4i_iis.pcm_rxtype<<2; if(!sun4i_iis.pcm_sync_type) reg_val |= SUN4I_IISFAT1_SSYNC; //short sync if(sun4i_iis.pcm_sw == 16) reg_val |= SUN4I_IISFAT1_SW; reg_val |=((sun4i_iis.pcm_start_slot - 1)&0x3)<<6; //start slot index reg_val |= sun4i_iis.pcm_lsb_first<<9; //MSB or LSB first if(sun4i_iis.pcm_sync_period == 256) reg_val |= 0x4<<12; else if (sun4i_iis.pcm_sync_period == 128) reg_val |= 0x3<<12; else if (sun4i_iis.pcm_sync_period == 64) reg_val |= 0x2<<12; else if (sun4i_iis.pcm_sync_period == 32) reg_val |= 0x1<<12; writel(reg_val, sun4i_iis.regs + SUN4I_IISFAT1); /* set FIFO control register */ reg_val = 0 & 0x3; reg_val |= (1 & 0x1)<<2; reg_val |= SUN4I_IISFCTL_RXTL(0xf); //RX FIFO trigger level reg_val |= SUN4I_IISFCTL_TXTL(0x40); //TX FIFO empty trigger level writel(reg_val, sun4i_iis.regs + SUN4I_IISFCTL); return 0; }