/* *Turn on or off the transmission path. */ static void rockchip_snd_txctrl(struct rk30_i2s_info *i2s, int on) { u32 opr, xfer, clr; unsigned long flags; bool is_need_delay = false; int clr_error_count = I2S_CLR_ERROR_COUNT; spin_lock_irqsave(&lock, flags); opr = readl(&(pheadi2s->I2S_DMACR)); xfer = readl(&(pheadi2s->I2S_XFER)); clr = readl(&(pheadi2s->I2S_CLR)); I2S_DBG("rockchip_snd_txctrl: %s\n", on ? "on" : "off"); if (on) { if ((opr & I2S_TRAN_DMA_ENABLE) == 0) { opr |= I2S_TRAN_DMA_ENABLE; writel(opr, &(pheadi2s->I2S_DMACR)); } if ((xfer & I2S_TX_TRAN_START) == 0 || (xfer & I2S_RX_TRAN_START) == 0) { xfer |= I2S_TX_TRAN_START; xfer |= I2S_RX_TRAN_START; writel(xfer, &(pheadi2s->I2S_XFER)); } i2s->i2s_tx_status = 1; } else { //stop tx i2s->i2s_tx_status = 0; opr &= ~I2S_TRAN_DMA_ENABLE; writel(opr, &(pheadi2s->I2S_DMACR)); if (i2s->i2s_rx_status == 0 && hdmi_get_hotplug() == 0) { xfer &= ~I2S_TX_TRAN_START; xfer &= ~I2S_RX_TRAN_START; writel(xfer, &(pheadi2s->I2S_XFER)); clr |= I2S_TX_CLEAR; clr |= I2S_RX_CLEAR; writel(clr, &(pheadi2s->I2S_CLR)); is_need_delay = true; I2S_DBG("rockchip_snd_txctrl: stop xfer\n"); } } spin_unlock_irqrestore(&lock, flags); if (is_need_delay){ while(readl(&(pheadi2s->I2S_CLR)) && clr_error_count){ udelay(1); clr_error_count --; if(clr_error_count == 0) printk("%s: i2s clr reg warning =%d",__FUNCTION__,readl(&(pheadi2s->I2S_CLR))); } } }
//set mclk and bclk division static int sun7i_sndpcm_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { int ret = 0; u32 freq = 22579200; struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_dai *codec_dai = rtd->codec_dai; struct snd_soc_dai *cpu_dai = rtd->cpu_dai; unsigned long sample_rate = params_rate(params); switch (sample_rate) { case 8000: case 16000: case 32000: case 64000: case 128000: case 12000: case 24000: case 48000: case 96000: case 192000: freq = 24576000; break; } ret = snd_soc_dai_set_sysclk(cpu_dai, 0 , freq, i2s_pcm_select); if (ret < 0) { return ret; } ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_IB_NF | SND_SOC_DAIFMT_CBM_CFM); if (ret < 0) return ret; /* * codec clk & FRM master. AP as slave */ ret = snd_soc_dai_set_fmt(cpu_dai, (audio_format | (signal_inversion<<8) | (pcm_master<<12))); if (ret < 0) { return ret; } ret = snd_soc_dai_set_clkdiv(cpu_dai, 0, sample_rate); if (ret < 0) { return ret; } /* * audio_format == SND_SOC_DAIFMT_DSP_A * signal_inversion<<8 == SND_SOC_DAIFMT_IB_NF * i2s_master<<12 == SND_SOC_DAIFMT_CBM_CFM */ I2S_DBG("%s,line:%d,audio_format:%d,SND_SOC_DAIFMT_DSP_A:%d\n",\ __func__, __LINE__, audio_format, SND_SOC_DAIFMT_DSP_A); I2S_DBG("%s,line:%d,signal_inversion:%d,signal_inversion<<8:%d,SND_SOC_DAIFMT_IB_NF:%d\n",\ __func__, __LINE__, signal_inversion, signal_inversion<<8, SND_SOC_DAIFMT_IB_NF); I2S_DBG("%s,line:%d,i2s_master:%d,i2s_master<<12:%d,SND_SOC_DAIFMT_CBM_CFM:%d\n",\ __func__, __LINE__, pcm_master, pcm_master<<12, SND_SOC_DAIFMT_CBM_CFM); return 0; }
static int rockchip_i2s_resume_noirq(struct device *dev) { I2S_DBG("Enter %s, %d\n", __func__, __LINE__); //if((dev->pins->p)&&(dev->pins->sleep_state)) // pinctrl_select_state(dev->pins->p, dev->pins->default_state); return 0; }
/* * Set Rockchip I2S MCLK source */ static int rockchip_i2s_set_sysclk(struct snd_soc_dai *cpu_dai, int clk_id, unsigned int freq, int dir) { struct rk30_i2s_info *i2s = to_info(cpu_dai); I2S_DBG("Enter:%s, %d, i2s=0x%p, freq=%d\n", __FUNCTION__, __LINE__, i2s, freq); /*add scu clk source and enable clk*/ clk_set_rate(i2s->i2s_clk, freq); return 0; }
/* * Set Rockchip Clock dividers */ static int rockchip_i2s_set_clkdiv(struct snd_soc_dai *cpu_dai, int div_id, int div) { struct rk30_i2s_info *i2s; u32 reg; unsigned long flags; int ret = 0; i2s = to_info(cpu_dai); spin_lock_irqsave(&lock, flags); //stereo mode MCLK/SCK=4 reg = readl(&(pheadi2s->I2S_CKR)); I2S_DBG("Enter:%s, %d, div_id=0x%08X, div=0x%08X\n", __FUNCTION__, __LINE__, div_id, div); //when i2s in master mode ,must set codec pll div switch (div_id) { case ROCKCHIP_DIV_BCLK: reg &= ~I2S_TX_SCLK_DIV_MASK; reg |= I2S_TX_SCLK_DIV(div); reg &= ~I2S_RX_SCLK_DIV_MASK; reg |= I2S_RX_SCLK_DIV(div); break; case ROCKCHIP_DIV_MCLK: reg &= ~I2S_MCLK_DIV_MASK; reg |= I2S_MCLK_DIV(div); break; case ROCKCHIP_DIV_PRESCALER: break; default: ret = -EINVAL; goto out_; } writel(reg, &(pheadi2s->I2S_CKR)); out_: spin_unlock_irqrestore(&lock, flags); return ret; }
static int rockchip_i2s_trigger(struct snd_pcm_substream *substream, int cmd, struct snd_soc_dai *dai) { struct rk30_i2s_info *i2s = to_info(dai); int ret = 0; I2S_DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); switch (cmd) { case SNDRV_PCM_TRIGGER_START: case SNDRV_PCM_TRIGGER_RESUME: case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) rockchip_snd_rxctrl(i2s, 1); else { rockchip_snd_txctrl(i2s, 1); #ifdef CONFIG_RK_HDMI //hdmi_audio_mute(0); #endif } break; case SNDRV_PCM_TRIGGER_SUSPEND: case SNDRV_PCM_TRIGGER_STOP: case SNDRV_PCM_TRIGGER_PAUSE_PUSH: if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) rockchip_snd_rxctrl(i2s, 0); else { rockchip_snd_txctrl(i2s, 0); #ifdef CONFIG_RK_HDMI //hdmi_audio_mute(1); #endif } break; default: ret = -EINVAL; break; } return ret; }
static int sun6i_i2s_set_clkdiv(struct snd_soc_dai *cpu_dai, int div_id, int sample_rate) { u32 reg_val; u32 mclk; u32 mclk_div = 0; u32 bclk_div = 0; mclk = over_sample_rate; if (i2s_select) { /*mclk div calculate*/ switch(sample_rate) { case 8000: { switch(mclk) { case 128: mclk_div = 24; break; case 192: mclk_div = 16; break; case 256: mclk_div = 12; break; case 384: mclk_div = 8; break; case 512: mclk_div = 6; break; case 768: mclk_div = 4; break; } break; } case 16000: { switch(mclk) { case 128: mclk_div = 12; break; case 192: mclk_div = 8; break; case 256: mclk_div = 6; break; case 384: mclk_div = 4; break; case 768: mclk_div = 2; break; } break; } case 32000: { switch(mclk) { case 128: mclk_div = 6; break; case 192: mclk_div = 4; break; case 384: mclk_div = 2; break; case 768: mclk_div = 1; break; } break; } case 64000: { switch(mclk) { case 192: mclk_div = 2; break; case 384: mclk_div = 1; break; } break; } case 128000: { switch(mclk) { case 192: mclk_div = 1; break; } break; } case 11025: case 12000: { switch(mclk) { case 128: mclk_div = 16; break; case 256: mclk_div = 8; break; case 512: mclk_div = 4; break; } break; } case 22050: case 24000: { switch(mclk) { case 128: mclk_div = 8; break; case 256: mclk_div = 4; break; case 512: mclk_div = 2; break; } break; } case 44100: case 48000: { switch(mclk) { case 128: mclk_div = 4; break; case 256: mclk_div = 2; break; case 512: mclk_div = 1; break; } break; } case 88200: case 96000: { switch(mclk) { case 128: mclk_div = 2; break; case 256: mclk_div = 1; break; } break; } case 176400: case 192000: { mclk_div = 1; break; } } /*bclk div caculate*/ bclk_div = mclk/(2*word_select_size); } else { mclk_div = 2; bclk_div = 6; } /*calculate MCLK Divide Ratio*/ switch(mclk_div) { case 1: mclk_div = 0; break; case 2: mclk_div = 1; break; case 4: mclk_div = 2; break; case 6: mclk_div = 3; break; case 8: mclk_div = 4; break; case 12: mclk_div = 5; break; case 16: mclk_div = 6; break; case 24: mclk_div = 7; break; case 32: mclk_div = 8; break; case 48: mclk_div = 9; break; case 64: mclk_div = 0xA; break; } mclk_div &= 0xf; /*calculate BCLK Divide Ratio*/ switch(bclk_div) { case 2: bclk_div = 0; break; case 4: bclk_div = 1; break; case 6: bclk_div = 2; break; case 8: bclk_div = 3; break; case 12: bclk_div = 4; break; case 16: bclk_div = 5; break; case 32: bclk_div = 6; break; case 64: bclk_div = 7; break; } bclk_div &= 0x7; /*set mclk and bclk dividor register*/ reg_val = mclk_div; reg_val |= (bclk_div<<4); reg_val |= (0x1<<7); writel(reg_val, sun6i_iis.regs + SUN6I_IISCLKD); /* word select size */ reg_val = readl(sun6i_iis.regs + SUN6I_IISFAT0); sun6i_iis.ws_size = word_select_size; reg_val &= ~SUN6I_IISFAT0_WSS_32BCLK; if(sun6i_iis.ws_size == 16) reg_val |= SUN6I_IISFAT0_WSS_16BCLK; else if(sun6i_iis.ws_size == 20) reg_val |= SUN6I_IISFAT0_WSS_20BCLK; else if(sun6i_iis.ws_size == 24) reg_val |= SUN6I_IISFAT0_WSS_24BCLK; else reg_val |= SUN6I_IISFAT0_WSS_32BCLK; sun6i_iis.samp_res = sample_resolution; reg_val &= ~SUN6I_IISFAT0_SR_RVD; if(sun6i_iis.samp_res == 16) reg_val |= SUN6I_IISFAT0_SR_16BIT; else if(sun6i_iis.samp_res == 20) reg_val |= SUN6I_IISFAT0_SR_20BIT; else reg_val |= SUN6I_IISFAT0_SR_24BIT; writel(reg_val, sun6i_iis.regs + SUN6I_IISFAT0); /* PCM REGISTER setup */ sun6i_iis.pcm_txtype = tx_data_mode; sun6i_iis.pcm_rxtype = rx_data_mode; reg_val = sun6i_iis.pcm_txtype&0x3; reg_val |= sun6i_iis.pcm_rxtype<<2; sun6i_iis.pcm_sync_type = frame_width; if(sun6i_iis.pcm_sync_type) reg_val |= SUN6I_IISFAT1_SSYNC; sun6i_iis.pcm_sw = slot_width; if(sun6i_iis.pcm_sw == 16) reg_val |= SUN6I_IISFAT1_SW; sun6i_iis.pcm_start_slot = slot_index; reg_val |=(sun6i_iis.pcm_start_slot & 0x3)<<6; sun6i_iis.pcm_lsb_first = msb_lsb_first; reg_val |= sun6i_iis.pcm_lsb_first<<9; sun6i_iis.pcm_sync_period = pcm_sync_period; if(sun6i_iis.pcm_sync_period == 256) reg_val |= 0x4<<12; else if (sun6i_iis.pcm_sync_period == 128) reg_val |= 0x3<<12; else if (sun6i_iis.pcm_sync_period == 64) reg_val |= 0x2<<12; else if (sun6i_iis.pcm_sync_period == 32) reg_val |= 0x1<<12; writel(reg_val, sun6i_iis.regs + SUN6I_IISFAT1); I2S_DBG("%s, line:%d, slot_index:%d\n", __func__, __LINE__, slot_index); I2S_DBG("%s, line:%d, slot_width:%d\n", __func__, __LINE__, slot_width); I2S_DBG("%s, line:%d, i2s_select:%d\n", __func__, __LINE__, i2s_select); I2S_DBG("%s, line:%d, frame_width:%d\n", __func__, __LINE__, frame_width); I2S_DBG("%s, line:%d, sign_extend:%d\n", __func__, __LINE__, sign_extend); I2S_DBG("%s, line:%d, tx_data_mode:%d\n", __func__, __LINE__, tx_data_mode); I2S_DBG("%s, line:%d, rx_data_mode:%d\n", __func__, __LINE__, rx_data_mode); I2S_DBG("%s, line:%d, msb_lsb_first:%d\n", __func__, __LINE__, msb_lsb_first); I2S_DBG("%s, line:%d, pcm_sync_period:%d\n", __func__, __LINE__, pcm_sync_period); I2S_DBG("%s, line:%d, word_select_size:%d\n", __func__, __LINE__, word_select_size); I2S_DBG("%s, line:%d, over_sample_rate:%d\n", __func__, __LINE__, over_sample_rate); I2S_DBG("%s, line:%d, sample_resolution:%d\n", __func__, __LINE__, sample_resolution); return 0; }
static void __exit rk30_i2s_exit(void) { I2S_DBG("rk_i2s_exit\n"); platform_driver_unregister(&rockchip_i2s_driver); }
//module_platform_driver(rockchip_i2s_driver); static int __init rk30_i2s_init(void) { I2S_DBG("rk_i2s_init\n"); return platform_driver_register(&rockchip_i2s_driver); }
static int rockchip_i2s_probe(struct platform_device *pdev) { struct device_node *node = pdev->dev.of_node; struct rk30_i2s_info *i2s; struct resource *mem, *memregion; u32 regs_base; int ret; I2S_DBG("%s()\n", __FUNCTION__); ret = of_property_read_u32(node, "i2s-id", &pdev->id); if (ret < 0) { dev_err(&pdev->dev, "%s() Can not read property: id\n", __FUNCTION__); ret = -ENOMEM; goto err; } if(pdev->id >= MAX_I2S) { dev_err(&pdev->dev, "id %d out of range\n", pdev->id); ret = -ENOMEM; goto err; } i2s = devm_kzalloc(&pdev->dev, sizeof(struct rk30_i2s_info), GFP_KERNEL); if (!i2s) { dev_err(&pdev->dev, "Can't allocate i2s info\n"); ret = -ENOMEM; goto err; } rk30_i2s = i2s; i2s->i2s_hclk = clk_get(&pdev->dev, "i2s_hclk"); if(IS_ERR(i2s->i2s_hclk) ) { dev_err(&pdev->dev, "get i2s_hclk failed.\n"); } else{ clk_prepare_enable(i2s->i2s_hclk); } i2s->i2s_clk= clk_get(&pdev->dev, "i2s_clk"); if (IS_ERR(i2s->i2s_clk)) { dev_err(&pdev->dev, "Can't retrieve i2s clock\n"); ret = PTR_ERR(i2s->i2s_clk); goto err; } #ifdef CLK_SET_lATER INIT_DELAYED_WORK(&i2s->clk_delayed_work, set_clk_later_work); schedule_delayed_work(&i2s->clk_delayed_work, msecs_to_jiffies(10)); #else clk_set_rate(i2s->iis_clk, 11289600); #endif clk_prepare_enable(i2s->i2s_clk); i2s->i2s_mclk= clk_get(&pdev->dev, "i2s_mclk"); if(IS_ERR(i2s->i2s_mclk) ) { printk("This platfrom have not i2s_mclk,no need to set i2s_mclk.\n"); }else{ #ifdef CLK_SET_lATER #else clk_set_rate(i2s->i2s_mclk, 11289600); #endif clk_prepare_enable(i2s->i2s_mclk); } mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!mem) { dev_err(&pdev->dev, "No memory resource\n"); ret = -ENODEV; goto err_clk_put; } memregion = devm_request_mem_region(&pdev->dev, mem->start, resource_size(mem), "rockchip-i2s"); if (!memregion) { dev_err(&pdev->dev, "Memory region already claimed\n"); ret = -EBUSY; goto err_clk_put; } i2s->regs = devm_ioremap(&pdev->dev, mem->start, resource_size(mem)); if (!i2s->regs) { dev_err(&pdev->dev, "ioremap failed\n"); ret = -ENOMEM; goto err_clk_put; } regs_base = mem->start; i2s->playback_dma_data.addr = regs_base + I2S_TXR_BUFF; i2s->playback_dma_data.addr_width = 4; i2s->playback_dma_data.maxburst = 1; i2s->capture_dma_data.addr = regs_base + I2S_RXR_BUFF; i2s->capture_dma_data.addr_width = 4; i2s->capture_dma_data.maxburst = 1; i2s->i2s_tx_status = false; i2s->i2s_rx_status = false; pm_runtime_enable(&pdev->dev); if (!pm_runtime_enabled(&pdev->dev)) { ret = rockchip_i2s_resume_noirq(&pdev->dev); if (ret) goto err_pm_disable; } //set dev name to driver->name.id for sound card register dev_set_name(&pdev->dev, "%s.%d", pdev->dev.driver->name, pdev->id); ret = snd_soc_register_component(&pdev->dev, &rockchip_i2s_component, &rockchip_i2s_dai[pdev->id], 1); if (ret) { dev_err(&pdev->dev, "Could not register DAI: %d\n", ret); ret = -ENOMEM; goto err_suspend; } ret = rockchip_pcm_platform_register(&pdev->dev); if (ret) { dev_err(&pdev->dev, "Could not register PCM: %d\n", ret); goto err_unregister_component; } /* Mark ourselves as in TXRX mode so we can run through our cleanup * process without warnings. */ rockchip_snd_txctrl(i2s, 0); rockchip_snd_rxctrl(i2s, 0); dev_set_drvdata(&pdev->dev, i2s); return 0; err_unregister_component: snd_soc_unregister_component(&pdev->dev); err_suspend: if (!pm_runtime_status_suspended(&pdev->dev)) rockchip_i2s_suspend_noirq(&pdev->dev); err_pm_disable: pm_runtime_disable(&pdev->dev); err_clk_put: clk_put(i2s->i2s_clk); err: return ret; }
static int rockchip_i2s_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) { struct rk30_i2s_info *i2s = to_info(dai); u32 iismod; u32 dmarc; unsigned long flags; struct hdmi_audio hdmi_audio_cfg; I2S_DBG("Enter %s, %d \n", __func__, __LINE__); if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) dai->playback_dma_data = &i2s->playback_dma_data; else dai->capture_dma_data = &i2s->capture_dma_data; spin_lock_irqsave(&lock, flags); /* Working copies of register */ iismod = readl(&(pheadi2s->I2S_TXCR)); iismod &= (~((1<<5)-1)); switch (params_format(params)) { case SNDRV_PCM_FORMAT_S8: iismod |= SAMPLE_DATA_8bit; break; case SNDRV_PCM_FORMAT_S16_LE: iismod |= I2S_DATA_WIDTH(15); break; case SNDRV_PCM_FORMAT_S20_3LE: iismod |= I2S_DATA_WIDTH(19); break; case SNDRV_PCM_FORMAT_S24_LE: case SNDRV_PCM_FORMAT_S24_3LE: iismod |= I2S_DATA_WIDTH(23); break; case SNDRV_PCM_FORMAT_S32_LE: iismod |= I2S_DATA_WIDTH(31); break; } iismod &= ~CHANNLE_4_EN; switch (params_channels(params)) { case 8: iismod |= CHANNLE_4_EN; break; case 6: iismod |= CHANNEL_3_EN; break; case 4: iismod |= CHANNEL_2_EN; break; case 2: iismod |= CHANNEL_1_EN; break; default: I2S_DBG("%d channels not supported\n", params_channels(params)); return -EINVAL; } //set hdmi codec params if(HW_PARAMS_FLAG_NLPCM == params->flags) hdmi_audio_cfg.type = HDMI_AUDIO_NLPCM; else hdmi_audio_cfg.type = HDMI_AUDIO_LPCM; //printk("i2s: hdmi_audio_cfg.type: %d\n", hdmi_audio_cfg.type); hdmi_audio_cfg.channel = params_channels(params); hdmi_audio_cfg.rate = SR2FS(params_rate(params)); hdmi_audio_cfg.word_length = HDMI_AUDIO_WORD_LENGTH_16bit; hdmi_config_audio(&hdmi_audio_cfg); // writel((16<<24) |(16<<18)|(16<<12)|(16<<6)|16, &(pheadi2s->I2S_FIFOLR)); dmarc = readl(&(pheadi2s->I2S_DMACR)); if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) dmarc = ((dmarc & 0xFFFFFE00) | 16); else dmarc = ((dmarc & 0xFE00FFFF) | 16<<16); writel(dmarc, &(pheadi2s->I2S_DMACR)); I2S_DBG("Enter %s, %d I2S_TXCR=0x%08X\n", __func__, __LINE__, iismod); writel(iismod, &(pheadi2s->I2S_TXCR)); iismod = iismod & 0x00007FFF; writel(iismod, &(pheadi2s->I2S_RXCR)); spin_unlock_irqrestore(&lock, flags); return 0; }
/* * Set Rockchip I2S DAI format */ static int rockchip_i2s_set_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt) { struct rk30_i2s_info *i2s = to_info(cpu_dai); u32 tx_ctl,rx_ctl; u32 iis_ckr_value;//clock generation register unsigned long flags; int ret = 0; I2S_DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); spin_lock_irqsave(&lock, flags); tx_ctl = readl(&(pheadi2s->I2S_TXCR)); iis_ckr_value = readl(&(pheadi2s->I2S_CKR)); switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { case SND_SOC_DAIFMT_CBM_CFM: //Codec is master, so set cpu slave. iis_ckr_value &= ~I2S_MODE_MASK; iis_ckr_value |= I2S_SLAVE_MODE; break; case SND_SOC_DAIFMT_CBS_CFS: //Codec is slave, so set cpu master. iis_ckr_value &= ~I2S_MODE_MASK; iis_ckr_value |= I2S_MASTER_MODE; break; default: I2S_DBG("unknwon master/slave format\n"); ret = -EINVAL; goto out_; } writel(iis_ckr_value, &(pheadi2s->I2S_CKR)); switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { case SND_SOC_DAIFMT_RIGHT_J: tx_ctl &= ~I2S_BUS_MODE_MASK; //I2S Bus Mode tx_ctl |= I2S_BUS_MODE_RSJM; break; case SND_SOC_DAIFMT_LEFT_J: tx_ctl &= ~I2S_BUS_MODE_MASK; //I2S Bus Mode tx_ctl |= I2S_BUS_MODE_LSJM; break; case SND_SOC_DAIFMT_I2S: tx_ctl &= ~I2S_BUS_MODE_MASK; //I2S Bus Mode tx_ctl |= I2S_BUS_MODE_NOR; break; default: I2S_DBG("Unknown data format\n"); ret = -EINVAL; goto out_; } I2S_DBG("Enter::%s----%d, I2S_TXCR=0x%X\n",__FUNCTION__,__LINE__,tx_ctl); writel(tx_ctl, &(pheadi2s->I2S_TXCR)); rx_ctl = tx_ctl & 0x00007FFF; writel(rx_ctl, &(pheadi2s->I2S_RXCR)); out_: spin_unlock_irqrestore(&lock, flags); return ret; }