コード例 #1
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); 
#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;
}
コード例 #2
0
ファイル: sun4i-i2s.c プロジェクト: mantrid/linux-allwinner
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;
}