From: 黄涛 Date: Tue, 28 Feb 2012 11:55:29 +0000 (+0800) Subject: rk: i2s: fix compile error X-Git-Tag: firefly_0821_release~9595^2~109 X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=f64ec89d3f5d85dd56eb199c0e55ae502bedebdb;p=firefly-linux-kernel-4.4.55.git rk: i2s: fix compile error --- diff --git a/sound/soc/rk29/Kconfig b/sound/soc/rk29/Kconfig index 2cd8bfb71aad..e58d9f09d4ab 100755 --- a/sound/soc/rk29/Kconfig +++ b/sound/soc/rk29/Kconfig @@ -1,6 +1,6 @@ config SND_RK29_SOC tristate "SoC Audio for the rockchip RK29/RK30 System-on-Chip" - depends on (ARCH_RK29 || ARCH_RK30)&& SND_SOC + depends on PLAT_RK && SND_SOC help Say Y or M if you want to add support for codecs attached to the ROCKCHIP IIS interface. You will also need @@ -44,7 +44,7 @@ endif config SND_RK29_SOC_WM8988 tristate "SoC I2S Audio support for rockchip - WM8988" - depends on SND_RK29_SOC && (I2C_RK29 || I2C_RK30) + depends on SND_RK29_SOC select SND_RK29_SOC_I2S select SND_SOC_WM8988 help @@ -53,7 +53,7 @@ config SND_RK29_SOC_WM8988 config SND_RK29_SOC_WM8900 tristate "SoC I2S Audio support for rockchip - WM8900" - depends on SND_RK29_SOC && (I2C_RK29 || I2C_RK30) + depends on SND_RK29_SOC select SND_RK29_SOC_I2S select SND_SOC_WM8900 help @@ -61,7 +61,7 @@ config SND_RK29_SOC_WM8900 with the WM8900. config SND_RK29_SOC_RT5621 tristate "SoC I2S Audio support for rockchip - rt5621" - depends on SND_RK29_SOC && (I2C_RK29 || I2C_RK30) + depends on SND_RK29_SOC select SND_RK29_SOC_I2S select SND_SOC_RT5621 help @@ -69,7 +69,7 @@ config SND_RK29_SOC_RT5621 with the rt5621. config SND_RK29_SOC_RT5631 tristate "SoC I2S Audio support for rockchip - RT5631" - depends on SND_RK29_SOC && (I2C_RK29 || I2C_RK30) + depends on SND_RK29_SOC select SND_RK29_SOC_I2S select SND_SOC_RT5631 help @@ -78,7 +78,7 @@ config SND_RK29_SOC_RT5631 config SND_RK29_SOC_RT5625 tristate "SoC I2S Audio support for rockchip - RT5625" - depends on SND_RK29_SOC && (I2C_RK29 || I2C_RK30) + depends on SND_RK29_SOC select SND_RK29_SOC_I2S select SND_SOC_RT5625 help @@ -87,7 +87,7 @@ config SND_RK29_SOC_RT5625 config SND_RK29_SOC_WM8994 tristate "SoC I2S Audio support for rockchip - WM8994" - depends on SND_RK29_SOC && (I2C_RK29 || I2C_RK30) + depends on SND_RK29_SOC select SND_RK29_SOC_I2S select SND_SOC_WM8994 help @@ -96,7 +96,7 @@ config SND_RK29_SOC_WM8994 config SND_RK29_SOC_CS42L52 tristate "SoC I2S Audio support for rockchip - CS42L52" - depends on SND_RK29_SOC && (I2C_RK29 || I2C_RK30) + depends on SND_RK29_SOC select SND_RK29_SOC_I2S select SND_SOC_CS42L52 help @@ -105,7 +105,7 @@ config SND_RK29_SOC_CS42L52 config SND_RK29_SOC_AIC3111 tristate "SoC I2S Audio support for rockchip - AIC3111" - depends on SND_RK29_SOC && (I2C_RK29 || I2C_RK30) + depends on SND_RK29_SOC select SND_RK29_SOC_I2S select SND_SOC_TLV320AIC3111 help @@ -114,7 +114,7 @@ config SND_RK29_SOC_AIC3111 config SND_RK29_SOC_RK1000 tristate "SoC I2S Audio support for rockchip - RK1000" - depends on SND_RK29_SOC && (I2C_RK29 || I2C_RK30) + depends on SND_RK29_SOC select SND_RK29_SOC_I2S select SND_SOC_RK1000 help diff --git a/sound/soc/rk29/Makefile b/sound/soc/rk29/Makefile index 3092da30c1e5..06bed425d071 100644 --- a/sound/soc/rk29/Makefile +++ b/sound/soc/rk29/Makefile @@ -1,6 +1,11 @@ # ROCKCHIP Platform Support snd-soc-rockchip-objs := rk29_pcm.o +ifdef CONFIG_ARCH_RK29 snd-soc-rockchip-i2s-objs := rk29_i2s.o +endif +ifdef CONFIG_ARCH_RK30 +snd-soc-rockchip-i2s-objs := rk30_i2s.o +endif obj-$(CONFIG_SND_RK29_SOC) += snd-soc-rockchip.o obj-$(CONFIG_SND_RK29_SOC_I2S) += snd-soc-rockchip-i2s.o diff --git a/sound/soc/rk29/rk29_i2s.c b/sound/soc/rk29/rk29_i2s.c index 9275e958f43b..3c129885ba73 100755 --- a/sound/soc/rk29/rk29_i2s.c +++ b/sound/soc/rk29/rk29_i2s.c @@ -27,21 +27,13 @@ #include #include -#ifdef ARCH_RK29 #include #include #include #include #include #include -#else -#include -#include -#include -#include -#include -#include -#endif + #include "rk29_pcm.h" #include "rk29_i2s.h" @@ -60,15 +52,15 @@ struct rk29_i2s_info { struct device *dev; void __iomem *regs; - u32 feature; + u32 feature; struct clk *iis_clk; struct clk *iis_pclk; - unsigned char master; + unsigned char master; - struct rockchip_pcm_dma_params *dma_playback; - struct rockchip_pcm_dma_params *dma_capture; + struct rockchip_pcm_dma_params *dma_playback; + struct rockchip_pcm_dma_params *dma_capture; u32 suspend_iismod; u32 suspend_iiscon; @@ -135,7 +127,7 @@ static struct rockchip_pcm_dma_params rockchip_i2s_pcm_stereo_in[MAX_I2S] = { }; */ -#ifdef ARCH_RK29 +#if 1 static u32 i2s0_clk_enter(void) { u32 clk = cru_readl(CRU_CLKSEL3_CON); @@ -151,7 +143,7 @@ static void i2s0_clk_exit(u32 clk) mdelay(1); } #else -static u32 i2s0_clk_enter(void) +static u32 i2s0_clk_enter() { return 0; } @@ -296,11 +288,11 @@ static void rockchip_snd_rxctrl(struct rk29_i2s_info *i2s, int on, bool stopI2S) * Set Rockchip I2S DAI format */ static int rockchip_i2s_set_fmt(struct snd_soc_dai *cpu_dai, - unsigned int fmt) + unsigned int fmt) { - struct rk29_i2s_info *i2s = to_info(cpu_dai); - u32 tx_ctl,rx_ctl; -#ifdef ARCH_RK29 + struct rk29_i2s_info *i2s = to_info(cpu_dai); + u32 tx_ctl,rx_ctl; + I2S_DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); tx_ctl = readl(&(pheadi2s->I2S_TXCR)); @@ -317,48 +309,26 @@ static int rockchip_i2s_set_fmt(struct snd_soc_dai *cpu_dai, default: I2S_DBG("unknwon master/slave format\n"); return -EINVAL; - } -#else - u32 iis_ckr_value;//clock generation register - - I2S_DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); + } - 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: - iis_ckr_value &= ~I2S_MODE_MASK; - iis_ckr_value |= I2S_MASTER_MODE; - break; - case SND_SOC_DAIFMT_CBS_CFS: - iis_ckr_value &= ~I2S_MODE_MASK; - iis_ckr_value |= I2S_SLAVE_MODE; - break; - default: - I2S_DBG("unknwon master/slave format\n"); - return -EINVAL; - } - writel(iis_ckr_value, &(pheadi2s->I2S_CKR)); -#endif - 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"); - return -EINVAL; - } - I2S_DBG("Enter::%s----%d, I2S_TXCR=0x%X\n",__FUNCTION__,__LINE__,tx_ctl); + 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"); + return -EINVAL; + } + I2S_DBG("Enter::%s----%d, I2S_TXCR=0x%X\n",__FUNCTION__,__LINE__,tx_ctl); #if 0//defined(CONFIG_SND_RK29_SOC_alc5631) || defined(CONFIG_SND_RK29_SOC_alc5621) rx_ctl = tx_ctl; rx_ctl &= ~I2S_MODE_MASK; @@ -367,9 +337,9 @@ static int rockchip_i2s_set_fmt(struct snd_soc_dai *cpu_dai, #else writel(tx_ctl, &(pheadi2s->I2S_TXCR)); #endif - rx_ctl = tx_ctl & 0x00007FFF; - writel(rx_ctl, &(pheadi2s->I2S_RXCR)); - return 0; + rx_ctl = tx_ctl & 0x00007FFF; + writel(rx_ctl, &(pheadi2s->I2S_RXCR)); + return 0; } static int rockchip_i2s_hw_params(struct snd_pcm_substream *substream, @@ -384,9 +354,15 @@ static int rockchip_i2s_hw_params(struct snd_pcm_substream *substream, #endif u32 iismod; u32 dmarc; - u32 iis_ckr_value;//clock generation register - - I2S_DBG("Enter %s, %d >>>>>>>>>>>\n", __func__, __LINE__); + + I2S_DBG("Enter %s, %d >>>>>>>>>>>\n", __func__, __LINE__); + /*by Vincent Hsiung for EQ Vol Change*/ + #define HW_PARAMS_FLAG_EQVOL_ON 0x21 + #define HW_PARAMS_FLAG_EQVOL_OFF 0x22 + if ((params->flags == HW_PARAMS_FLAG_EQVOL_ON)||(params->flags == HW_PARAMS_FLAG_EQVOL_OFF)) + { + return 0; + } #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)) if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) @@ -407,8 +383,7 @@ static int rockchip_i2s_hw_params(struct snd_pcm_substream *substream, /* Working copies of register */ iismod = readl(&(pheadi2s->I2S_TXCR)); - -// iismod &= (~((1<<5)-1)); + //iismod &= (~((1<<5)-1)); switch (params_format(params)) { case SNDRV_PCM_FORMAT_S8: iismod |= SAMPLE_DATA_8bit; @@ -417,43 +392,33 @@ static int rockchip_i2s_hw_params(struct snd_pcm_substream *substream, iismod |= I2S_DATA_WIDTH(15); break; case SNDRV_PCM_FORMAT_S20_3LE: - iismod |= I2S_DATA_WIDTH(19); - break; + iismod |= I2S_DATA_WIDTH(19); + break; case SNDRV_PCM_FORMAT_S24_LE: - iismod |= I2S_DATA_WIDTH(23); - break; + iismod |= I2S_DATA_WIDTH(23); + break; case SNDRV_PCM_FORMAT_S32_LE: - iismod |= I2S_DATA_WIDTH(31); - break; - } -#ifdef ARCH29 - #if defined (CONFIG_SND_RK29_CODEC_SOC_SLAVE) - iismod &= ~I2S_SLAVE_MODE; - #endif - - #if defined (CONFIG_SND_RK29_CODEC_SOC_MASTER) - iismod |= I2S_SLAVE_MODE; - #endif -#else - iis_ckr_value = readl(&(pheadi2s->I2S_CKR)); - #if defined (CONFIG_SND_RK29_CODEC_SOC_SLAVE) - iis_ckr_value &= ~I2S_SLAVE_MODE; - #endif - #if defined (CONFIG_SND_RK29_CODEC_SOC_MASTER) - iis_ckr_value |= I2S_SLAVE_MODE; - #endif - writel(iis_ckr_value, &(pheadi2s->I2S_CKR)); -#endif -// writel((16<<24) |(16<<18)|(16<<12)|(16<<6)|16, &(pheadi2s->I2S_FIFOLR)); - dmarc = readl(&(pheadi2s->I2S_DMACR)); + iismod |= I2S_DATA_WIDTH(31); + break; + } + #if defined (CONFIG_SND_RK29_CODEC_SOC_SLAVE) + iismod &= ~I2S_SLAVE_MODE; + #endif - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) - dmarc = ((dmarc & 0xFFFFFE00) | 16); - else - dmarc = ((dmarc & 0xFE00FFFF) | 16<<16); + #if defined (CONFIG_SND_RK29_CODEC_SOC_MASTER) + iismod |= I2S_SLAVE_MODE; + #endif + + //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(dmarc, &(pheadi2s->I2S_DMACR)); + I2S_DBG("Enter %s, %d I2S_TXCR=0x%08X\n", __func__, __LINE__, iismod); #if 0//defined(CONFIG_SND_RK29_SOC_alc5631) || defined(CONFIG_SND_RK29_SOC_alc5621) dmarc = iismod; dmarc &= ~I2S_MODE_MASK; @@ -462,24 +427,25 @@ static int rockchip_i2s_hw_params(struct snd_pcm_substream *substream, #else writel(iismod, &(pheadi2s->I2S_TXCR)); #endif - iismod = iismod & 0x00007FFF; - writel(iismod, &(pheadi2s->I2S_RXCR)); - return 0; + iismod = iismod & 0x00007FFF; + writel(iismod, &(pheadi2s->I2S_RXCR)); + return 0; } + static int rockchip_i2s_trigger(struct snd_pcm_substream *substream, int cmd, struct snd_soc_dai *dai) { - int ret = 0; - struct snd_soc_pcm_runtime *rtd = substream->private_data; + int ret = 0; + struct snd_soc_pcm_runtime *rtd = substream->private_data; #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)) struct rk29_i2s_info *i2s = to_info(rtd->cpu_dai); #else struct rk29_i2s_info *i2s = to_info(rtd->dai->cpu_dai); #endif - bool stopI2S = false; + bool stopI2S = false; - I2S_DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); - switch (cmd) { + 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: @@ -501,9 +467,9 @@ static int rockchip_i2s_trigger(struct snd_pcm_substream *substream, int cmd, st default: ret = -EINVAL; break; - } + } - return ret; + return ret; } /* * Set Rockchip Clock source @@ -511,14 +477,14 @@ static int rockchip_i2s_trigger(struct snd_pcm_substream *substream, int cmd, st static int rockchip_i2s_set_sysclk(struct snd_soc_dai *cpu_dai, int clk_id, unsigned int freq, int dir) { - struct rk29_i2s_info *i2s; + struct rk29_i2s_info *i2s; - i2s = to_info(cpu_dai); + i2s = to_info(cpu_dai); - I2S_DBG("Enter:%s, %d, i2s=0x%p, freq=%d\n", __FUNCTION__, __LINE__, i2s, freq); + 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->iis_clk, freq); - return 0; + clk_set_rate(i2s->iis_clk, freq); + return 0; } /* @@ -527,20 +493,19 @@ static int rockchip_i2s_set_sysclk(struct snd_soc_dai *cpu_dai, static int rockchip_i2s_set_clkdiv(struct snd_soc_dai *cpu_dai, int div_id, int div) { -/* - struct rk29_i2s_info *i2s; - u32 reg; + struct rk29_i2s_info *i2s; + u32 reg; - i2s = to_info(cpu_dai); + i2s = to_info(cpu_dai); - //stereo mode MCLK/SCK=4 + /*stereo mode MCLK/SCK=4*/ - reg = readl(&(pheadi2s->I2S_TXCKR)); + reg = readl(&(pheadi2s->I2S_TXCKR)); - I2S_DBG("Enter:%s, %d, div_id=0x%08X, div=0x%08X\n", __FUNCTION__, __LINE__, div_id, div); + 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) { + /*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); @@ -554,26 +519,36 @@ static int rockchip_i2s_set_clkdiv(struct snd_soc_dai *cpu_dai, break; default: return -EINVAL; - } - writel(reg, &(pheadi2s->I2S_TXCKR)); - writel(reg, &(pheadi2s->I2S_RXCKR)); -*/ - return 0; + } + writel(reg, &(pheadi2s->I2S_TXCKR)); + writel(reg, &(pheadi2s->I2S_RXCKR)); + return 0; +} + +/* + * To avoid duplicating clock code, allow machine driver to + * get the clockrate from here. + */ +u32 rockchip_i2s_get_clockrate(void) +{ + I2S_DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); + return 0; ///clk_get_rate(s3c24xx_i2s.iis_clk); } +EXPORT_SYMBOL_GPL(rockchip_i2s_get_clockrate); #ifdef CONFIG_PM int rockchip_i2s_suspend(struct snd_soc_dai *cpu_dai) { - I2S_DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); -// clk_disable(clk); - return 0; + I2S_DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); + //clk_disable(clk); + return 0; } int rockchip_i2s_resume(struct snd_soc_dai *cpu_dai) { - I2S_DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); -// clk_enable(clk); - return 0; + I2S_DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); + //clk_enable(clk); + return 0; } #else #define rockchip_i2s_suspend NULL @@ -603,7 +578,7 @@ static int rockchip_i2s_dai_probe(struct platform_device *pdev, struct snd_soc_d #endif { I2S_DBG("Enter %s, %d >>>>>>>>>>>\n", __func__, __LINE__); -#ifdef ARCH_RK29 + switch(dai->id) { case 0: rk29_mux_api_set(GPIO2D0_I2S0CLK_MIIRXCLKIN_NAME, GPIO2H_I2S0_CLK); @@ -630,40 +605,6 @@ static int rockchip_i2s_dai_probe(struct platform_device *pdev, struct snd_soc_d I2S_DBG("Enter:%s, %d, Error For DevId!!!", __FUNCTION__, __LINE__); return -EINVAL; } -#else - switch(dai->id) { - case 0: - rk30_mux_api_set(GPIO0A7_I2S8CHSDI_NAME, GPIO0A_I2S_8CH_SDI); - rk30_mux_api_set(GPIO0B0_I2S8CHCLK_NAME, GPIO0B_I2S_8CH_CLK); - rk30_mux_api_set(GPIO0B1_I2S8CHSCLK_NAME, GPIO0B_I2S_8CH_SCLK); - rk30_mux_api_set(GPIO0B2_I2S8CHLRCKRX_NAME, GPIO0B_I2S_8CH_LRCK_RX); - rk30_mux_api_set(GPIO0B3_I2S8CHLRCKTX_NAME, GPIO0B_I2S_8CH_LRCK_TX); - rk30_mux_api_set(GPIO0B4_I2S8CHSDO0_NAME, GPIO0B_I2S_8CH_SDO0); - rk30_mux_api_set(GPIO0B5_I2S8CHSDO1_NAME, GPIO0B_I2S_8CH_SDO1); - rk30_mux_api_set(GPIO0B6_I2S8CHSDO2_NAME, GPIO0B_I2S_8CH_SDO2); - rk30_mux_api_set(GPIO0B7_I2S8CHSDO3_NAME, GPIO0B_I2S_8CH_SDO3); - break; - case 1: - rk30_mux_api_set(GPIO0C0_I2S12CHCLK_NAME, GPIO0C_I2S1_2CH_CLK); - rk30_mux_api_set(GPIO0C1_I2S12CHSCLK_NAME, GPIO0C_I2S1_2CH_SCLK); - rk30_mux_api_set(GPIO0C2_I2S12CHLRCKRX_NAME, GPIO0C_I2S1_2CH_LRCK_RX); - rk30_mux_api_set(GPIO0C3_I2S12CHLRCKTX_NAME, GPIO0C_I2S1_2CH_LRCK_TX); - rk30_mux_api_set(GPIO0C4_I2S12CHSDI_NAME, GPIO0C_I2S1_2CH_SDI); - rk30_mux_api_set(GPIO0C5_I2S12CHSDO_NAME, GPIO0C_I2S1_2CH_SDO); - break; - case 2: - rk30_mux_api_set(GPIO0D0_I2S22CHCLK_SMCCSN0_NAME, GPIO0D_I2S2_2CH_CLK); - rk30_mux_api_set(GPIO0D1_I2S22CHSCLK_SMCWEN_NAME, GPIO0D_I2S2_2CH_SCLK); - rk30_mux_api_set(GPIO0D2_I2S22CHLRCKRX_SMCOEN_NAME, GPIO0D_I2S2_2CH_LRCK_RX); - rk30_mux_api_set(GPIO0D3_I2S22CHLRCKTX_SMCADVN_NAME, GPIO0D_I2S2_2CH_LRCK_TX); - rk30_mux_api_set(GPIO0D4_I2S22CHSDI_SMCADDR0_NAME, GPIO0D_I2S2_2CH_SDI); - rk30_mux_api_set(GPIO0D5_I2S22CHSDO_SMCADDR1_NAME, GPIO0D_I2S2_2CH_SDO); - break; - default: - I2S_DBG("Enter:%s, %d, Error For DevId!!!", __FUNCTION__, __LINE__); - return -EINVAL; - } -#endif return 0; } @@ -673,13 +614,13 @@ static int rk29_i2s_probe(struct platform_device *pdev, #else struct snd_soc_dai *dai, #endif - struct rk29_i2s_info *i2s, - unsigned long base) + struct rk29_i2s_info *i2s, + unsigned long base) { struct device *dev = &pdev->dev; - struct resource *res; + struct resource *res; - I2S_DBG("Enter %s, %d >>>>>>>>>>>\n", __func__, __LINE__); + I2S_DBG("Enter %s, %d >>>>>>>>>>>\n", __func__, __LINE__); i2s->dev = dev; @@ -733,30 +674,28 @@ static int rk29_i2s_probe(struct platform_device *pdev, static int __devinit rockchip_i2s_probe(struct platform_device *pdev) { - struct rk29_i2s_info *i2s; + struct rk29_i2s_info *i2s; #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)) struct snd_soc_dai_driver *dai; #else struct snd_soc_dai *dai; #endif - int ret; + int ret; - I2S_DBG("Enter %s, %d pdev->id = %d >>>>>>>>>>>\n", __func__, __LINE__, pdev->id); + I2S_DBG("Enter %s, %d pdev->id = %d >>>>>>>>>>>\n", __func__, __LINE__, pdev->id); - if(pdev->id >= MAX_I2S) { - dev_err(&pdev->dev, "id %d out of range\n", pdev->id); - return -EINVAL; - } + if(pdev->id >= MAX_I2S) { + dev_err(&pdev->dev, "id %d out of range\n", pdev->id); + return -EINVAL; + } - i2s = &rk29_i2s[pdev->id]; - dai = &rk29_i2s_dai[pdev->id]; + i2s = &rk29_i2s[pdev->id]; + dai = &rk29_i2s_dai[pdev->id]; #if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 37)) dai->dev = &pdev->dev; #endif dai->id = pdev->id; dai->symmetric_rates = 1; - -#ifdef ARCH_RK29 if(pdev->id == 0) { dai->name = "rk29_i2s.0"; dai->playback.channels_min = 2; @@ -766,26 +705,6 @@ static int __devinit rockchip_i2s_probe(struct platform_device *pdev) dai->playback.channels_min = 2; dai->playback.channels_max = 2; } -#else - switch(pdev->id) - { - case 0: - dai->name = "rk29_i2s.0"; - dai->playback.channels_min = 2; - dai->playback.channels_max = 8; - break; - case 1: - dai->name = "rk29_i2s.1"; - dai->playback.channels_min = 2; - dai->playback.channels_max = 2; - break; - case 2: - dai->name = "rk29_i2s.2"; - dai->playback.channels_min = 2; - dai->playback.channels_max = 2; - break; - } -#endif dai->playback.rates = ROCKCHIP_I2S_RATES; dai->playback.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S24_LE; dai->capture.channels_min = 2; @@ -797,10 +716,11 @@ static int __devinit rockchip_i2s_probe(struct platform_device *pdev) dai->suspend = rockchip_i2s_suspend; dai->resume = rockchip_i2s_resume; + //i2s->feature |= S3C_FEATURE_CDCLKCON; + i2s->dma_capture = &rk29_i2s_pcm_stereo_in[pdev->id]; i2s->dma_playback = &rk29_i2s_pcm_stereo_out[pdev->id]; - -#ifdef ARCH_RK29 + if (pdev->id == 1) { i2s->dma_capture->channel = DMACH_I2S_2CH_RX; i2s->dma_capture->dma_addr = RK29_I2S_2CH_PHYS + I2S_RXR_BUFF; @@ -812,29 +732,7 @@ static int __devinit rockchip_i2s_probe(struct platform_device *pdev) i2s->dma_playback->channel = DMACH_I2S_8CH_TX; i2s->dma_playback->dma_addr = RK29_I2S_8CH_PHYS + I2S_TXR_BUFF; } -#else - switch(pdev->id) - { - case 0: - i2s->dma_capture->channel = DMACH_I2S0_8CH_RX; - i2s->dma_capture->dma_addr = RK30_I2S0_8CH_PHYS + I2S_RXR_BUFF; - i2s->dma_playback->channel = DMACH_I2S0_8CH_TX; - i2s->dma_playback->dma_addr = RK30_I2S0_8CH_PHYS + I2S_TXR_BUFF; - break; - case 1: - i2s->dma_capture->channel = DMACH_I2S1_2CH_RX; - i2s->dma_capture->dma_addr = RK30_I2S1_2CH_PHYS + I2S_RXR_BUFF; - i2s->dma_playback->channel = DMACH_I2S1_2CH_TX; - i2s->dma_playback->dma_addr = RK30_I2S1_2CH_PHYS + I2S_TXR_BUFF; - break; - case 2: - i2s->dma_capture->channel = DMACH_I2S2_2CH_RX; - i2s->dma_capture->dma_addr = RK30_I2S2_2CH_PHYS + I2S_RXR_BUFF; - i2s->dma_playback->channel = DMACH_I2S2_2CH_TX; - i2s->dma_playback->dma_addr = RK30_I2S2_2CH_PHYS + I2S_TXR_BUFF; - break; - } -#endif + i2s->dma_capture->client = &rk29_dma_client_in; i2s->dma_capture->dma_size = 4; i2s->dma_capture->flag = 0; //add by sxj, used for burst change @@ -854,7 +752,7 @@ static int __devinit rockchip_i2s_probe(struct platform_device *pdev) } clk_enable(i2s->iis_clk); -// clk_set_rate(i2s->iis_clk, 11289600); + clk_set_rate(i2s->iis_clk, 11289600); ret = rk29_i2s_probe(pdev, dai, i2s, 0); if (ret) goto err_clk; @@ -873,6 +771,7 @@ err: return ret; } + static int __devexit rockchip_i2s_remove(struct platform_device *pdev) { #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)) @@ -880,6 +779,7 @@ static int __devexit rockchip_i2s_remove(struct platform_device *pdev) #else snd_soc_unregister_dai(&rk29_i2s_dai); #endif + return 0; } @@ -894,8 +794,8 @@ static struct platform_driver rockchip_i2s_driver = { static int __init rockchip_i2s_init(void) { - I2S_DBG("Enter %s, %d >>>>>>>>>>>\n", __func__, __LINE__); - + I2S_DBG("Enter %s, %d >>>>>>>>>>>\n", __func__, __LINE__); + return platform_driver_register(&rockchip_i2s_driver); } module_init(rockchip_i2s_init); @@ -915,7 +815,6 @@ MODULE_LICENSE("GPL"); #ifdef CONFIG_PROC_FS #include #include -#ifdef ARCK_RK29 static int proc_i2s_show(struct seq_file *s, void *v) { struct rk29_i2s_info *i2s=&rk29_i2s[0]; @@ -935,24 +834,6 @@ static int proc_i2s_show(struct seq_file *s, void *v) return 0; } -#else -static int proc_i2s_show(struct seq_file *s, void *v) -{ - struct rk29_i2s_info *i2s=&rk29_i2s[1]; - printk("========Show I2S reg========\n"); - - printk("I2S_TXCR = 0x%08X\n", readl(&(pheadi2s->I2S_TXCR))); - printk("I2S_RXCR = 0x%08X\n", readl(&(pheadi2s->I2S_RXCR))); - printk("I2S_CKR = 0x%08X\n", readl(&(pheadi2s->I2S_CKR))); - printk("I2S_DMACR = 0x%08X\n", readl(&(pheadi2s->I2S_DMACR))); - printk("I2S_INTCR = 0x%08X\n", readl(&(pheadi2s->I2S_INTCR))); - printk("I2S_INTSR = 0x%08X\n", readl(&(pheadi2s->I2S_INTSR))); - printk("I2S_XFER = 0x%08X\n", readl(&(pheadi2s->I2S_XFER))); - - printk("========Show I2S reg========\n"); - return 0; -} -#endif static int proc_i2s_open(struct inode *inode, struct file *file) { return single_open(file, proc_i2s_show, NULL); @@ -969,6 +850,7 @@ static int __init i2s_proc_init(void) { proc_create("i2s_reg", 0, NULL, &proc_i2s_fops); return 0; + } late_initcall(i2s_proc_init); #endif /* CONFIG_PROC_FS */ diff --git a/sound/soc/rk29/rk29_i2s.h b/sound/soc/rk29/rk29_i2s.h index 47273b75c141..291bf9ef7a5a 100755 --- a/sound/soc/rk29/rk29_i2s.h +++ b/sound/soc/rk29/rk29_i2s.h @@ -23,7 +23,7 @@ #define CHANNEL_2_EN (1<<15) #define CHANNEL_3_EN (2<<15) #define CHANNLE_4_EN (3<<15) -#ifdef ARCH_RK29 +#ifdef CONFIG_ARCH_RK29 #define TX_MODE_MASTER (0<<13) #define TX_MODE_SLAVE (1<<13) #else @@ -98,7 +98,7 @@ #define I2S_HWT_16BIT (0<<14) #define I2S_HWT_32BIT (1<<14) -#ifdef ARCH_RK29 +#ifdef CONFIG_ARCH_RK29 #define I2S_MASTER_MODE (0<<13) #define I2S_SLAVE_MODE (1<<13) #define I2S_MODE_MASK (1<<13) @@ -187,7 +187,7 @@ #define I2S_TXR_BUFF 0x20 #define I2S_RXR_BUFF 0x24 -#ifdef ARCH_RK29 +#ifdef CONFIG_ARCH_RK29 //I2S Registers typedef volatile struct tagIIS_STRUCT { diff --git a/sound/soc/rk29/rk29_pcm.c b/sound/soc/rk29/rk29_pcm.c index 8cbc3de72ab4..c015652d6a2d 100755 --- a/sound/soc/rk29/rk29_pcm.c +++ b/sound/soc/rk29/rk29_pcm.c @@ -16,7 +16,6 @@ #include #include #include -#include #include #include @@ -25,14 +24,9 @@ #include #include -#ifdef ARCH_RK29 -#include -#else -#include -#endif -#include "rk29_pcm.h" +#include -#include +#include "rk29_pcm.h" #if 0 #define DBG(x...) printk(KERN_INFO x) @@ -179,7 +173,7 @@ static int rockchip_pcm_hw_params(struct snd_pcm_substream *substream, struct rockchip_pcm_dma_params *dma = rtd->dai->cpu_dai->dma_data; #endif unsigned long totbytes = params_buffer_bytes(params); -// int ret = 0; + int ret = 0; DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); /*by Vincent Hsiung for EQ Vol Change*/ @@ -285,6 +279,7 @@ static int rockchip_pcm_prepare(struct snd_pcm_substream *substream) DBG("Enter::%s, %d, ret=%d, Channel=%d, Addr=0x%X\n", __FUNCTION__, __LINE__, ret, prtd->params->channel, prtd->params->dma_addr); ret = rk29_dma_config(prtd->params->channel, prtd->params->dma_size, 1); + prtd->params->flag = 1; DBG("Enter:%s, %d, ret = %d, Channel=%d, Size=%d\n", __FUNCTION__, __LINE__, ret, prtd->params->channel, @@ -515,8 +510,9 @@ static int rockchip_pcm_new(struct snd_card *card, struct snd_soc_dai *dai, struct snd_pcm *pcm) { int ret = 0; + DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); - + if (!card->dev->dma_mask) card->dev->dma_mask = &rockchip_pcm_dmamask; if (!card->dev->coherent_dma_mask) @@ -556,7 +552,7 @@ static struct snd_soc_platform_driver rockchip_pcm_platform = { static int __devinit rockchip_pcm_platform_probe(struct platform_device *pdev) { - DBG("Enter::%s, %d\n", __FUNCTION__, __LINE__); + DBG("Enter::%s, %d\n", __FUNCTION__, __LINE__); return snd_soc_register_platform(&pdev->dev, &rockchip_pcm_platform); } @@ -577,7 +573,7 @@ static struct platform_driver rockchip_pcm_driver = { static int __init snd_rockchip_pcm_init(void) { - DBG("Enter::%s, %d\n", __FUNCTION__, __LINE__); + DBG("Enter::%s, %d\n", __FUNCTION__, __LINE__); return platform_driver_register(&rockchip_pcm_driver); } module_init(snd_rockchip_pcm_init); @@ -598,7 +594,7 @@ EXPORT_SYMBOL_GPL(rk29_soc_platform); static int __init rockchip_soc_platform_init(void) { - DBG("Enter::%s, %d\n", __FUNCTION__, __LINE__); + DBG("Enter::%s, %d\n", __FUNCTION__, __LINE__); return snd_soc_register_platform(&rk29_soc_platform); } module_init(rockchip_soc_platform_init); @@ -615,4 +611,3 @@ MODULE_AUTHOR("rockchip"); MODULE_DESCRIPTION("ROCKCHIP PCM ASoC Interface"); MODULE_LICENSE("GPL"); - diff --git a/sound/soc/rk29/rk30_i2s.c b/sound/soc/rk29/rk30_i2s.c new file mode 100755 index 000000000000..9d46dfd9a4fd --- /dev/null +++ b/sound/soc/rk29/rk30_i2s.c @@ -0,0 +1,761 @@ +/* + * rk29_i2s.c -- ALSA SoC ROCKCHIP IIS Audio Layer Platform driver + * + * Driver for rockchip iis audio + * + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "rk29_pcm.h" +#include "rk29_i2s.h" + + +#if 0 +#define I2S_DBG(x...) printk(KERN_INFO x) +#else +#define I2S_DBG(x...) do { } while (0) +#endif + +#define pheadi2s ((pI2S_REG)(i2s->regs)) + +#define MAX_I2S 2 + +struct rk29_i2s_info { + struct device *dev; + void __iomem *regs; + + u32 feature; + + struct clk *iis_clk; + struct clk *iis_pclk; + + unsigned char master; + + struct rockchip_pcm_dma_params *dma_playback; + struct rockchip_pcm_dma_params *dma_capture; + + u32 suspend_iismod; + u32 suspend_iiscon; + u32 suspend_iispsr; +}; + +static struct rk29_dma_client rk29_dma_client_out = { + .name = "I2S PCM Stereo Out" +}; + +static struct rk29_dma_client rk29_dma_client_in = { + .name = "I2S PCM Stereo In" +}; + +static inline struct rk29_i2s_info *to_info(struct snd_soc_dai *cpu_dai) +{ + return snd_soc_dai_get_drvdata(cpu_dai); +} + +static struct rockchip_pcm_dma_params rk29_i2s_pcm_stereo_out[MAX_I2S]; +static struct rockchip_pcm_dma_params rk29_i2s_pcm_stereo_in[MAX_I2S]; +static struct rk29_i2s_info rk29_i2s[MAX_I2S]; + +struct snd_soc_dai_driver rk29_i2s_dai[MAX_I2S]; +EXPORT_SYMBOL_GPL(rk29_i2s_dai); + +static u32 i2s0_clk_enter(void) +{ + return 0; +} + +static void i2s0_clk_exit(u32 clk) +{ +} + +/* + *Turn on or off the transmission path. + */ + +static int flag_i2s_tx = 0; +static int flag_i2s_rx = 0; +static void rockchip_snd_txctrl(struct rk29_i2s_info *i2s, int on, bool stopI2S) +{ + u32 opr,xfer; + u32 clk; + + opr = readl(&(pheadi2s->I2S_DMACR)); + xfer = readl(&(pheadi2s->I2S_XFER)); + + if (on) + { + I2S_DBG("rockchip_snd_txctrl: on\n"); + + //start tx + //if ((flag_i2s_tx == 0) && (flag_i2s_rx == 0)) + if ((xfer&I2S_TX_TRAN_START)==0 || (xfer&I2S_RX_TRAN_START)==0) + { + clk = i2s0_clk_enter(); + + //if start tx & rx clk, need reset i2s + xfer |= I2S_TX_TRAN_START; + xfer |= I2S_RX_TRAN_START; + writel(xfer, &(pheadi2s->I2S_XFER)); + + i2s0_clk_exit(clk); + } + + if ((opr & I2S_TRAN_DMA_ENABLE) == 0) + { + opr |= I2S_TRAN_DMA_ENABLE; + writel(opr, &(pheadi2s->I2S_DMACR)); + } + + flag_i2s_tx = 1; + } + else + { + //stop tx + + flag_i2s_tx = 0; + if ((flag_i2s_rx == 0) && (flag_i2s_tx == 0)) + { + opr &= ~I2S_TRAN_DMA_ENABLE; + writel(opr, &(pheadi2s->I2S_DMACR)); + if(stopI2S) + { + clk = i2s0_clk_enter(); + + xfer &= ~I2S_RX_TRAN_START; + xfer &= ~I2S_TX_TRAN_START; + writel(xfer, &(pheadi2s->I2S_XFER)); + + i2s0_clk_exit(clk); + } + + //after stop rx & tx clk, reset i2s + //writel(0x001,&(pheadi2s->I2S_TXRST)); + //writel(0x001,&(pheadi2s->I2S_RXRST)); + } + + I2S_DBG("rockchip_snd_txctrl: off\n"); + } +} + +static void rockchip_snd_rxctrl(struct rk29_i2s_info *i2s, int on, bool stopI2S) +{ + u32 opr,xfer; + u32 clk; + + opr = readl(&(pheadi2s->I2S_DMACR)); + xfer = readl(&(pheadi2s->I2S_XFER)); + + if (on) + { + I2S_DBG("rockchip_snd_rxctrl: on\n"); + + //start rx + //if ((flag_i2s_tx == 0) && (flag_i2s_rx == 0)) + if ((xfer&I2S_TX_TRAN_START)==0 || (xfer&I2S_RX_TRAN_START)==0) + { + clk = i2s0_clk_enter(); + + xfer |= I2S_TX_TRAN_START; + xfer |= I2S_RX_TRAN_START; + writel(xfer, &(pheadi2s->I2S_XFER)); + + i2s0_clk_exit(clk); + } + + if ((opr & I2S_RECE_DMA_ENABLE) == 0) + { + opr |= I2S_RECE_DMA_ENABLE; + writel(opr, &(pheadi2s->I2S_DMACR)); + } + + flag_i2s_rx = 1; + } + else + { + //stop rx + flag_i2s_rx = 0; + if ((flag_i2s_rx == 0) && (flag_i2s_tx == 0)) + { + opr &= ~I2S_RECE_DMA_ENABLE; + writel(opr, &(pheadi2s->I2S_DMACR)); + + if(stopI2S) + { + clk = i2s0_clk_enter(); + + xfer &= ~I2S_RX_TRAN_START; + xfer &= ~I2S_TX_TRAN_START; + writel(xfer, &(pheadi2s->I2S_XFER)); + + i2s0_clk_exit(clk); + } + + //after stop rx & tx clk, reset i2s + //writel(0x001,&(pheadi2s->I2S_TXRST)); + //writel(0x001,&(pheadi2s->I2S_RXRST)); + } + + I2S_DBG("rockchip_snd_rxctrl: off\n"); + } +} + +/* + * Set Rockchip I2S DAI format + */ +static int rockchip_i2s_set_fmt(struct snd_soc_dai *cpu_dai, + unsigned int fmt) +{ + struct rk29_i2s_info *i2s = to_info(cpu_dai); + u32 tx_ctl,rx_ctl; + u32 iis_ckr_value;//clock generation register + + I2S_DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); + + 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: + iis_ckr_value &= ~I2S_MODE_MASK; + iis_ckr_value |= I2S_MASTER_MODE; + break; + case SND_SOC_DAIFMT_CBS_CFS: + iis_ckr_value &= ~I2S_MODE_MASK; + iis_ckr_value |= I2S_SLAVE_MODE; + break; + default: + I2S_DBG("unknwon master/slave format\n"); + return -EINVAL; + } + 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"); + return -EINVAL; + } + I2S_DBG("Enter::%s----%d, I2S_TXCR=0x%X\n",__FUNCTION__,__LINE__,tx_ctl); +#if 0//defined(CONFIG_SND_RK29_SOC_alc5631) || defined(CONFIG_SND_RK29_SOC_alc5621) + rx_ctl = tx_ctl; + rx_ctl &= ~I2S_MODE_MASK; + rx_ctl |= I2S_SLAVE_MODE; // set tx slave, rx master + writel(rx_ctl, &(pheadi2s->I2S_TXCR)); +#else + writel(tx_ctl, &(pheadi2s->I2S_TXCR)); +#endif + rx_ctl = tx_ctl & 0x00007FFF; + writel(rx_ctl, &(pheadi2s->I2S_RXCR)); + return 0; +} + +static int rockchip_i2s_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, struct snd_soc_dai *socdai) +{ + struct rk29_i2s_info *i2s = to_info(socdai); + u32 iismod; + u32 dmarc; + u32 iis_ckr_value;//clock generation register + + I2S_DBG("Enter %s, %d >>>>>>>>>>>\n", __func__, __LINE__); + + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) + snd_soc_dai_set_dma_data(socdai, substream, i2s->dma_playback); + else + snd_soc_dai_set_dma_data(socdai, substream, i2s->dma_capture); + + /* 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: + iismod |= I2S_DATA_WIDTH(23); + break; + case SNDRV_PCM_FORMAT_S32_LE: + iismod |= I2S_DATA_WIDTH(31); + break; + } + iis_ckr_value = readl(&(pheadi2s->I2S_CKR)); + #if defined (CONFIG_SND_RK29_CODEC_SOC_SLAVE) + iis_ckr_value &= ~I2S_SLAVE_MODE; + #endif + #if defined (CONFIG_SND_RK29_CODEC_SOC_MASTER) + iis_ckr_value |= I2S_SLAVE_MODE; + #endif + writel(iis_ckr_value, &(pheadi2s->I2S_CKR)); +// 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); +#if 0//defined(CONFIG_SND_RK29_SOC_alc5631) || defined(CONFIG_SND_RK29_SOC_alc5621) + dmarc = iismod; + dmarc &= ~I2S_MODE_MASK; + dmarc |= I2S_SLAVE_MODE; // set tx slave, rx master + writel(dmarc, &(pheadi2s->I2S_TXCR)); +#else + writel(iismod, &(pheadi2s->I2S_TXCR)); +#endif + iismod = iismod & 0x00007FFF; + writel(iismod, &(pheadi2s->I2S_RXCR)); + return 0; +} + +static int rockchip_i2s_trigger(struct snd_pcm_substream *substream, int cmd, struct snd_soc_dai *dai) +{ + int ret = 0; + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct rk29_i2s_info *i2s = to_info(rtd->cpu_dai); + bool stopI2S = false; + + 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, stopI2S); + else + rockchip_snd_txctrl(i2s, 1, stopI2S); + break; + + case SNDRV_PCM_TRIGGER_SUSPEND: + stopI2S = true; + case SNDRV_PCM_TRIGGER_STOP: + case SNDRV_PCM_TRIGGER_PAUSE_PUSH: + if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) + rockchip_snd_rxctrl(i2s, 0, stopI2S); + else + rockchip_snd_txctrl(i2s, 0, stopI2S); + break; + default: + ret = -EINVAL; + break; + } + + return ret; +} +/* + * Set Rockchip Clock source + */ +static int rockchip_i2s_set_sysclk(struct snd_soc_dai *cpu_dai, + int clk_id, unsigned int freq, int dir) +{ + struct rk29_i2s_info *i2s; + + 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->iis_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 rk29_i2s_info *i2s; + u32 reg; + + i2s = to_info(cpu_dai); + + //stereo mode MCLK/SCK=4 + + reg = readl(&(pheadi2s->I2S_TXCKR)); + + 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); + break; + case ROCKCHIP_DIV_MCLK: + reg &= ~I2S_MCLK_DIV_MASK; + reg |= I2S_MCLK_DIV(div); + break; + case ROCKCHIP_DIV_PRESCALER: + + break; + default: + return -EINVAL; + } + writel(reg, &(pheadi2s->I2S_TXCKR)); + writel(reg, &(pheadi2s->I2S_RXCKR)); +*/ + return 0; +} + +#ifdef CONFIG_PM +int rockchip_i2s_suspend(struct snd_soc_dai *cpu_dai) +{ + I2S_DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); +// clk_disable(clk); + return 0; +} + +int rockchip_i2s_resume(struct snd_soc_dai *cpu_dai) +{ + I2S_DBG("Enter::%s----%d\n",__FUNCTION__,__LINE__); +// clk_enable(clk); + return 0; +} +#else +#define rockchip_i2s_suspend NULL +#define rockchip_i2s_resume NULL +#endif + +#if defined(CONFIG_SND_RK29_SOC_alc5631) || defined(CONFIG_SND_RK29_SOC_alc5621) +#define ROCKCHIP_I2S_RATES (SNDRV_PCM_RATE_44100) //zyy 20110704, playback and record use same sample rate +#else +#define ROCKCHIP_I2S_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |\ + SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 |\ + SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000) +#endif + +static struct snd_soc_dai_ops rockchip_i2s_dai_ops = { + .trigger = rockchip_i2s_trigger, + .hw_params = rockchip_i2s_hw_params, + .set_fmt = rockchip_i2s_set_fmt, + .set_clkdiv = rockchip_i2s_set_clkdiv, + .set_sysclk = rockchip_i2s_set_sysclk, +}; + +static int rockchip_i2s_dai_probe(struct snd_soc_dai *dai) +{ + I2S_DBG("Enter %s, %d >>>>>>>>>>>\n", __func__, __LINE__); + switch(dai->id) { + case 0: + rk30_mux_api_set(GPIO0A7_I2S8CHSDI_NAME, GPIO0A_I2S_8CH_SDI); + rk30_mux_api_set(GPIO0B0_I2S8CHCLK_NAME, GPIO0B_I2S_8CH_CLK); + rk30_mux_api_set(GPIO0B1_I2S8CHSCLK_NAME, GPIO0B_I2S_8CH_SCLK); + rk30_mux_api_set(GPIO0B2_I2S8CHLRCKRX_NAME, GPIO0B_I2S_8CH_LRCK_RX); + rk30_mux_api_set(GPIO0B3_I2S8CHLRCKTX_NAME, GPIO0B_I2S_8CH_LRCK_TX); + rk30_mux_api_set(GPIO0B4_I2S8CHSDO0_NAME, GPIO0B_I2S_8CH_SDO0); + rk30_mux_api_set(GPIO0B5_I2S8CHSDO1_NAME, GPIO0B_I2S_8CH_SDO1); + rk30_mux_api_set(GPIO0B6_I2S8CHSDO2_NAME, GPIO0B_I2S_8CH_SDO2); + rk30_mux_api_set(GPIO0B7_I2S8CHSDO3_NAME, GPIO0B_I2S_8CH_SDO3); + break; + case 1: + rk30_mux_api_set(GPIO0C0_I2S12CHCLK_NAME, GPIO0C_I2S1_2CH_CLK); + rk30_mux_api_set(GPIO0C1_I2S12CHSCLK_NAME, GPIO0C_I2S1_2CH_SCLK); + rk30_mux_api_set(GPIO0C2_I2S12CHLRCKRX_NAME, GPIO0C_I2S1_2CH_LRCK_RX); + rk30_mux_api_set(GPIO0C3_I2S12CHLRCKTX_NAME, GPIO0C_I2S1_2CH_LRCK_TX); + rk30_mux_api_set(GPIO0C4_I2S12CHSDI_NAME, GPIO0C_I2S1_2CH_SDI); + rk30_mux_api_set(GPIO0C5_I2S12CHSDO_NAME, GPIO0C_I2S1_2CH_SDO); + break; + case 2: + rk30_mux_api_set(GPIO0D0_I2S22CHCLK_SMCCSN0_NAME, GPIO0D_I2S2_2CH_CLK); + rk30_mux_api_set(GPIO0D1_I2S22CHSCLK_SMCWEN_NAME, GPIO0D_I2S2_2CH_SCLK); + rk30_mux_api_set(GPIO0D2_I2S22CHLRCKRX_SMCOEN_NAME, GPIO0D_I2S2_2CH_LRCK_RX); + rk30_mux_api_set(GPIO0D3_I2S22CHLRCKTX_SMCADVN_NAME, GPIO0D_I2S2_2CH_LRCK_TX); + rk30_mux_api_set(GPIO0D4_I2S22CHSDI_SMCADDR0_NAME, GPIO0D_I2S2_2CH_SDI); + rk30_mux_api_set(GPIO0D5_I2S22CHSDO_SMCADDR1_NAME, GPIO0D_I2S2_2CH_SDO); + break; + default: + I2S_DBG("Enter:%s, %d, Error For DevId!!!", __FUNCTION__, __LINE__); + return -EINVAL; + } + return 0; +} + +static int rk29_i2s_probe(struct platform_device *pdev, + struct snd_soc_dai_driver *dai, + struct rk29_i2s_info *i2s, + unsigned long base) +{ + struct device *dev = &pdev->dev; + struct resource *res; + + I2S_DBG("Enter %s, %d >>>>>>>>>>>\n", __func__, __LINE__); + + i2s->dev = dev; + + /* record our i2s structure for later use in the callbacks */ + dev_set_drvdata(&pdev->dev, i2s); + + if (!base) { + res = platform_get_resource(pdev, + IORESOURCE_MEM, + 0); + if (!res) { + dev_err(dev, "Unable to get register resource\n"); + return -ENXIO; + } + + if (!request_mem_region(res->start, resource_size(res), + "rk29_i2s")) { + dev_err(dev, "Unable to request register region\n"); + return -EBUSY; + } + + base = res->start; + } + + i2s->regs = ioremap(base, (res->end - res->start) + 1); ////res)); + if (i2s->regs == NULL) { + dev_err(dev, "cannot ioremap registers\n"); + return -ENXIO; + } + + i2s->iis_pclk = clk_get(dev, "i2s"); + if (IS_ERR(i2s->iis_pclk)) { + dev_err(dev, "failed to get iis_clock\n"); + iounmap(i2s->regs); + return -ENOENT; + } + + clk_enable(i2s->iis_pclk); + + /* Mark ourselves as in TXRX mode so we can run through our cleanup + * process without warnings. */ + rockchip_snd_txctrl(i2s, 0, true); + rockchip_snd_rxctrl(i2s, 0, true); + + return 0; +} + +static int __devinit rockchip_i2s_probe(struct platform_device *pdev) +{ + struct rk29_i2s_info *i2s; + struct snd_soc_dai_driver *dai; + int ret; + + I2S_DBG("Enter %s, %d pdev->id = %d >>>>>>>>>>>\n", __func__, __LINE__, pdev->id); + + if(pdev->id >= MAX_I2S) { + dev_err(&pdev->dev, "id %d out of range\n", pdev->id); + return -EINVAL; + } + + i2s = &rk29_i2s[pdev->id]; + dai = &rk29_i2s_dai[pdev->id]; + dai->id = pdev->id; + dai->symmetric_rates = 1; + + switch(pdev->id) + { + case 0: + dai->name = "rk29_i2s.0"; + dai->playback.channels_min = 2; + dai->playback.channels_max = 8; + break; + case 1: + dai->name = "rk29_i2s.1"; + dai->playback.channels_min = 2; + dai->playback.channels_max = 2; + break; + case 2: + dai->name = "rk29_i2s.2"; + dai->playback.channels_min = 2; + dai->playback.channels_max = 2; + break; + } + + dai->playback.rates = ROCKCHIP_I2S_RATES; + dai->playback.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S24_LE; + dai->capture.channels_min = 2; + dai->capture.channels_max = 2; + dai->capture.rates = ROCKCHIP_I2S_RATES;//;SNDRV_PCM_RATE_44100 + dai->capture.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S24_LE; + dai->probe = rockchip_i2s_dai_probe; + dai->ops = &rockchip_i2s_dai_ops; + dai->suspend = rockchip_i2s_suspend; + dai->resume = rockchip_i2s_resume; + + i2s->dma_capture = &rk29_i2s_pcm_stereo_in[pdev->id]; + i2s->dma_playback = &rk29_i2s_pcm_stereo_out[pdev->id]; + + switch(pdev->id) + { + case 0: + i2s->dma_capture->channel = DMACH_I2S0_8CH_RX; + i2s->dma_capture->dma_addr = RK30_I2S0_8CH_PHYS + I2S_RXR_BUFF; + i2s->dma_playback->channel = DMACH_I2S0_8CH_TX; + i2s->dma_playback->dma_addr = RK30_I2S0_8CH_PHYS + I2S_TXR_BUFF; + break; + case 1: + i2s->dma_capture->channel = DMACH_I2S1_2CH_RX; + i2s->dma_capture->dma_addr = RK30_I2S1_2CH_PHYS + I2S_RXR_BUFF; + i2s->dma_playback->channel = DMACH_I2S1_2CH_TX; + i2s->dma_playback->dma_addr = RK30_I2S1_2CH_PHYS + I2S_TXR_BUFF; + break; + case 2: + i2s->dma_capture->channel = DMACH_I2S2_2CH_RX; + i2s->dma_capture->dma_addr = RK30_I2S2_2CH_PHYS + I2S_RXR_BUFF; + i2s->dma_playback->channel = DMACH_I2S2_2CH_TX; + i2s->dma_playback->dma_addr = RK30_I2S2_2CH_PHYS + I2S_TXR_BUFF; + break; + } + + i2s->dma_capture->client = &rk29_dma_client_in; + i2s->dma_capture->dma_size = 4; + i2s->dma_capture->flag = 0; //add by sxj, used for burst change + i2s->dma_playback->client = &rk29_dma_client_out; + i2s->dma_playback->dma_size = 4; + i2s->dma_playback->flag = 0; //add by sxj, used for burst change +#ifdef CONFIG_SND_I2S_DMA_EVENT_STATIC + WARN_ON(rk29_dma_request(i2s->dma_playback->channel, i2s->dma_playback->client, NULL)); + WARN_ON(rk29_dma_request(i2s->dma_capture->channel, i2s->dma_capture->client, NULL)); +#endif + i2s->iis_clk = clk_get(&pdev->dev, "i2s"); + I2S_DBG("Enter:%s, %d, iis_clk=%p\n", __FUNCTION__, __LINE__, i2s->iis_clk); + if (IS_ERR(i2s->iis_clk)) { + dev_err(&pdev->dev, "failed to get i2s clk\n"); + ret = PTR_ERR(i2s->iis_clk); + goto err; + } + + clk_enable(i2s->iis_clk); + clk_set_rate(i2s->iis_clk, 11289600); + ret = rk29_i2s_probe(pdev, dai, i2s, 0); + if (ret) + goto err_clk; + + ret = snd_soc_register_dai(&pdev->dev, dai); + if (ret != 0) + goto err_i2sv2; + + return 0; + +err_i2sv2: + /* Not implemented for I2Sv2 core yet */ +err_clk: + clk_put(i2s->iis_clk); +err: + return ret; +} + +static int __devexit rockchip_i2s_remove(struct platform_device *pdev) +{ + snd_soc_unregister_dai(&pdev->dev); + return 0; +} + +static struct platform_driver rockchip_i2s_driver = { + .probe = rockchip_i2s_probe, + .remove = __devexit_p(rockchip_i2s_remove), + .driver = { + .name = "rk29_i2s", + .owner = THIS_MODULE, + }, +}; + +static int __init rockchip_i2s_init(void) +{ + I2S_DBG("Enter %s, %d >>>>>>>>>>>\n", __func__, __LINE__); + + return platform_driver_register(&rockchip_i2s_driver); +} +module_init(rockchip_i2s_init); + +static void __exit rockchip_i2s_exit(void) +{ + platform_driver_unregister(&rockchip_i2s_driver); +} +module_exit(rockchip_i2s_exit); + +/* Module information */ +MODULE_AUTHOR("rockchip"); +MODULE_DESCRIPTION("ROCKCHIP IIS ASoC Interface"); +MODULE_LICENSE("GPL"); + + +#ifdef CONFIG_PROC_FS +#include +#include +static int proc_i2s_show(struct seq_file *s, void *v) +{ + struct rk29_i2s_info *i2s=&rk29_i2s[1]; + printk("========Show I2S reg========\n"); + + printk("I2S_TXCR = 0x%08X\n", readl(&(pheadi2s->I2S_TXCR))); + printk("I2S_RXCR = 0x%08X\n", readl(&(pheadi2s->I2S_RXCR))); + printk("I2S_CKR = 0x%08X\n", readl(&(pheadi2s->I2S_CKR))); + printk("I2S_DMACR = 0x%08X\n", readl(&(pheadi2s->I2S_DMACR))); + printk("I2S_INTCR = 0x%08X\n", readl(&(pheadi2s->I2S_INTCR))); + printk("I2S_INTSR = 0x%08X\n", readl(&(pheadi2s->I2S_INTSR))); + printk("I2S_XFER = 0x%08X\n", readl(&(pheadi2s->I2S_XFER))); + + printk("========Show I2S reg========\n"); + return 0; +} + +static int proc_i2s_open(struct inode *inode, struct file *file) +{ + return single_open(file, proc_i2s_show, NULL); +} + +static const struct file_operations proc_i2s_fops = { + .open = proc_i2s_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +static int __init i2s_proc_init(void) +{ + proc_create("i2s_reg", 0, NULL, &proc_i2s_fops); + return 0; +} +late_initcall(i2s_proc_init); +#endif /* CONFIG_PROC_FS */ +