diff --git a/sound/soc/sunxi/i2s/sndi2s.c b/sound/soc/sunxi/i2s/sndi2s.c index a9dd8c4e6df8e7..65be48f621b123 100644 --- a/sound/soc/sunxi/i2s/sndi2s.c +++ b/sound/soc/sunxi/i2s/sndi2s.c @@ -144,7 +144,7 @@ struct snd_soc_dai_driver sndi2s_dai = { .playback = { .stream_name = "Playback", .channels_min = 1, - .channels_max = 2, + .channels_max = 8, .rates = sndi2s_RATES_MASTER, .formats = sndi2s_FORMATS, }, diff --git a/sound/soc/sunxi/i2s/sunxi-i2s.c b/sound/soc/sunxi/i2s/sunxi-i2s.c index 530b2b7feb5e1e..accac5ce16a274 100644 --- a/sound/soc/sunxi/i2s/sunxi-i2s.c +++ b/sound/soc/sunxi/i2s/sunxi-i2s.c @@ -353,25 +353,34 @@ void sunxi_snd_rxctrl_i2s(int on) /* * TODO: Function Description -* Saved in snd_soc_dai_ops sunxi_iis_dai_ops. -* Function called internally. The Machine Driver doesn't need to call this function because it is called whenever sunxi_i2s_set_clkdiv is called. -* The master clock in Allwinner SoM depends on the sampling frequency. +* Saved in snd_soc_dai_ops sunxi_iis_dai_ops. Function called +* internally. The Machine Driver doesn't need to call this function +* because it is called whenever sunxi_i2s_set_clkdiv is called. The +* master clock in Allwinner SoM depends on the sampling frequency. */ static int sunxi_i2s_set_sysclk(struct snd_soc_dai *cpu_dai, int clk_id, unsigned int freq, int dir) { u32 reg_val; - printk("[I2S]Entered %s\n", __func__); + printk("[I2S]Entered %s (clk_id %i, freq %i, dir %i, slave %i)\n", __func__, clk_id, freq , dir, sunxi_iis.slave); if(!sunxi_iis.slave) { switch(clk_id) { case SUNXI_SET_MCLK: // Set the master clock frequency. - // TODO - Check if the master clock is needed when slave mode is selected. + // Two different pll clocks + if (freq == 0) + { + freq = 24576000; // 8k, 12k, 16k, 24k, 32k, 48k, 64k, 96k, 128k, 192k + } else if (freq == 1) + { + freq = 22579200; // 11.025k, 22.05k, 44.1k, 88.2k, 176.4k + } if (clk_set_rate(i2s_pll2clk, freq)) { pr_err("Try to set the i2s_pll2clk failed!\n"); return -EINVAL; } + printk("[I2S]Entered %s set pll to: %i\n", __func__, freq); break; case SUNXI_MCLKO_EN: // Enables the master clock output reg_val = readl(sunxi_iis.regs + SUNXI_IISCLKD); @@ -380,7 +389,8 @@ static int sunxi_i2s_set_sysclk(struct snd_soc_dai *cpu_dai, int clk_id, unsigne if(dir == 0) // Disable reg_val &= ~(0x1<<7); writel(reg_val, sunxi_iis.regs + SUNXI_IISCLKD); - break; + printk("[I2S]Entered %s Master Clock output set to %i (0=disabled, 1=enabled)\n", __func__, dir); + break; } } return 0; @@ -399,21 +409,47 @@ static int sunxi_i2s_set_clkdiv(struct snd_soc_dai *cpu_dai, int div_id, int val // Here i should know the sample rate and the FS multiple. - printk("[I2S]Entered %s\n", __func__); + printk("[I2S]Entered %s (div_id: %i, slave %i, value %i)\n", __func__, div_id, sunxi_iis.slave, value); switch (div_id) { case SUNXI_DIV_MCLK: // Sets MCLKDIV - reg_val = readl(sunxi_iis.regs + SUNXI_IISCLKD); - reg_val &= ~(0xf<<0); - reg_val |= ((value & 0xf)<<0); - writel(reg_val, sunxi_iis.regs + SUNXI_IISCLKD); - break; + if(value <= 8) + value = (value >>1); + else if(value == 12) + value = 0x5; + else if(value == 16) + value = 0x6; + else if(value == 24) + value = 0x7; + else if(value == 32) + value = 0x8; + else if(value == 48) + value = 0x9; + else if(value == 64) + value = 0xa; + + reg_val = readl(sunxi_iis.regs + SUNXI_IISCLKD); + reg_val &= ~(0xf<<0); + reg_val |= (value<<0); + writel(reg_val, sunxi_iis.regs + SUNXI_IISCLKD); + break; case SUNXI_DIV_BCLK: // Sets BCLKDIV - reg_val = readl(sunxi_iis.regs + SUNXI_IISCLKD); - reg_val &= ~(0x7<<4); - reg_val |= ((value & 0x7)<<4); - writel(reg_val, sunxi_iis.regs + SUNXI_IISCLKD); - break; + if(value <= 8) + value = (value>>1) - 1; + else if(value == 12) + value = 0x4; + else if(value == 16) + value = 0x5; + else if(value == 32) + value = 0x6; + else if(value == 64) + value = 0x7; + + reg_val = readl(sunxi_iis.regs + SUNXI_IISCLKD); + reg_val &= ~(0x7<<4); + reg_val |= (value<<4); + writel(reg_val, sunxi_iis.regs + SUNXI_IISCLKD); + break; case SUNXI_SAMPLING_FREQ: if(!sunxi_iis.slave) { @@ -429,11 +465,12 @@ static int sunxi_i2s_set_clkdiv(struct snd_soc_dai *cpu_dai, int div_id, int val else { sunxi_iis.samp_fs = (u32)value; - sunxi_i2s_set_sysclk(cpu_dai, SUNXI_SET_MCLK, mclk, 0); // Set the master clock. - reg_val = readl(sunxi_iis.regs + SUNXI_IISCLKD); - reg_val &= ~(0x7f<<0); // Clear MCLK and BCLK - reg_val |= (((mclk_div & 0xf)<<0) | ((bclk_div & 0x7)<<4)); - writel(reg_val, sunxi_iis.regs + SUNXI_IISCLKD); + sunxi_i2s_set_sysclk(cpu_dai, SUNXI_SET_MCLK, mclk, 0); // Set the master clock (PLL). + sunxi_i2s_set_sysclk(cpu_dai, SUNXI_MCLKO_EN, mclk, 1); // Enable master clock output + /* reg_val = readl(sunxi_iis.regs + SUNXI_IISCLKD); */ + /* reg_val &= ~(0x7f<<0); // Clear MCLK and BCLK */ + /* reg_val |= (((mclk_div & 0xf)<<0) | ((bclk_div & 0x7)<<4)); */ + /* writel(reg_val, sunxi_iis.regs + SUNXI_IISCLKD); */ } } else @@ -924,11 +961,9 @@ static int sunxi_i2s_hw_params(struct snd_pcm_substream *substream, sunxi_iis.samp_res = 24; if(sunxi_iis.ws_size != 32) // If the Word Size is not equal to 32, sets word size to 32. { - reg_val1 = readl(sunxi_iis.regs + SUNXI_IISFAT0); - reg_val1 |= SUNXI_IISFAT0_WSS_32BCLK; - writel(reg_val1, sunxi_iis.regs + SUNXI_IISFAT0); - sunxi_iis.ws_size = 32; - printk("[I2S] sunxi_i2s_hw_params: Changing word slect size to 32bit.\n"); + reg_val1 |= SUNXI_IISFAT0_WSS_32BCLK; // + sunxi_iis.ws_size = 32; + printk("[I2S] sunxi_i2s_hw_params: Changing word slect size to 32bit.\n"); } printk("[I2S] sunxi_i2s_hw_params: format 24 bit\n"); break; @@ -938,11 +973,9 @@ static int sunxi_i2s_hw_params(struct snd_pcm_substream *substream, sunxi_iis.samp_res = 24; if(sunxi_iis.ws_size < 24) // If the Word Size is lower tehen 24bits, sets the default Word Size (32bits). { - reg_val1 = readl(sunxi_iis.regs + SUNXI_IISFAT0); - reg_val1 |= SUNXI_IISFAT0_WSS_32BCLK; - writel(reg_val1, sunxi_iis.regs + SUNXI_IISFAT0); - sunxi_iis.ws_size = 32; - printk("[I2S] sunxi_i2s_hw_params: Changing word slect size to 32bit.\n"); + reg_val1 |= SUNXI_IISFAT0_WSS_32BCLK; + sunxi_iis.ws_size = 32; + printk("[I2S] sunxi_i2s_hw_params: Changing word slect size to 32bit.\n"); } break; } @@ -1019,7 +1052,7 @@ static int sunxi_i2s_dai_probe(struct snd_soc_dai *cpu_dai) printk("[I2S]Entered %s\n", __func__); // I2S Default Register Configuration - sunxi_iis.slave = 1, + // sunxi_iis.slave = 1, // already set in sunxi_i2s_dai_probe sunxi_iis.samp_fs = 48000, sunxi_iis.samp_res = 24, sunxi_iis.samp_format = SND_SOC_DAIFMT_I2S, @@ -1164,7 +1197,7 @@ static struct snd_soc_dai_driver sunxi_iis_dai = { .rate_min = SNDRV_PCM_RATE_8000, .rate_max = SNDRV_PCM_RATE_192000, .channels_min = 1, - .channels_max = 2, + .channels_max = 8, }, .symmetric_rates = 1, }; diff --git a/sound/soc/sunxi/i2s/sunxi-i2sdma.c b/sound/soc/sunxi/i2s/sunxi-i2sdma.c index 02819069fb312d..8ab971e365071a 100644 --- a/sound/soc/sunxi/i2s/sunxi-i2sdma.c +++ b/sound/soc/sunxi/i2s/sunxi-i2sdma.c @@ -50,7 +50,7 @@ static const struct snd_pcm_hardware sunxi_pcm_play_hardware = { .rate_min = 8000, .rate_max = 192000, .channels_min = 1, - .channels_max = 2, + .channels_max = 8, .buffer_bytes_max = 128*1024, /* value must be (2^n)Kbyte size */ // .period_bytes_min = 1024*4,//1024*4, .period_bytes_min = 16*2, diff --git a/sound/soc/sunxi/i2s/sunxi-sndi2s.c b/sound/soc/sunxi/i2s/sunxi-sndi2s.c index ff518dad79b1ae..66c533e70606b2 100644 --- a/sound/soc/sunxi/i2s/sunxi-sndi2s.c +++ b/sound/soc/sunxi/i2s/sunxi-sndi2s.c @@ -278,13 +278,13 @@ static int sunxi_sndi2s_hw_params(struct snd_pcm_substream *substream, //call sunxi_iis_set_fmt ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | - SND_SOC_DAIFMT_NB_NF/* | SND_SOC_DAIFMT_CBM_CFM*/); + SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM); if (ret < 0) return ret; //call sunxi_iis_set_fmt ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S | - SND_SOC_DAIFMT_NB_NF/* | SND_SOC_DAIFMT_CBM_CFM*/); + SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM); if (ret < 0) return ret;