From 39cb3fce0efdab540e2dcd247acfc6e60a04b47b Mon Sep 17 00:00:00 2001 From: fkwp Date: Fri, 24 Oct 2014 15:31:33 +0200 Subject: [PATCH 1/6] set soc dai fmt to SND_SOC_DAIFMT_CBM_CFM --- sound/soc/sunxi/i2s/sunxi-sndi2s.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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; From 920c40ca51fec9044cfa7ea40a27f7ecc3e514c6 Mon Sep 17 00:00:00 2001 From: fkwp Date: Fri, 24 Oct 2014 19:23:58 +0200 Subject: [PATCH 2/6] removed sunxi_iis.slave setting _dai_probe since it is set before in _dai_probe --- sound/soc/sunxi/i2s/sunxi-i2s.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/sunxi/i2s/sunxi-i2s.c b/sound/soc/sunxi/i2s/sunxi-i2s.c index 530b2b7feb5e1e..aec68f0d38901e 100644 --- a/sound/soc/sunxi/i2s/sunxi-i2s.c +++ b/sound/soc/sunxi/i2s/sunxi-i2s.c @@ -1019,7 +1019,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, From ad0d993a22875ffc29a6e344fc53a3709faf6974 Mon Sep 17 00:00:00 2001 From: fkwp Date: Fri, 24 Oct 2014 20:06:02 +0200 Subject: [PATCH 3/6] fixed Master Clock: _set_sysctl sets now the correct PLL. Corrected in _set_clkdiv the values of the dividers MCLKDIV and BCLKDIV. In addition SUNXI_SAMPLING_FREQ now enables the Master Clock output and prevents to clear/reset MCLK and BCLK --- sound/soc/sunxi/i2s/sunxi-i2s.c | 81 ++++++++++++++++++++++++--------- 1 file changed, 59 insertions(+), 22 deletions(-) diff --git a/sound/soc/sunxi/i2s/sunxi-i2s.c b/sound/soc/sunxi/i2s/sunxi-i2s.c index aec68f0d38901e..20c1c86bd4f67a 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 + { + 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 From 15d5b5177344bcfa685b6deb2658593a5e1027fb Mon Sep 17 00:00:00 2001 From: fkwp Date: Fri, 24 Oct 2014 20:16:48 +0200 Subject: [PATCH 4/6] fixed Word Size Setting in case of samp_res > ws_size --- sound/soc/sunxi/i2s/sunxi-i2s.c | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/sound/soc/sunxi/i2s/sunxi-i2s.c b/sound/soc/sunxi/i2s/sunxi-i2s.c index 20c1c86bd4f67a..4e1a7a96e94422 100644 --- a/sound/soc/sunxi/i2s/sunxi-i2s.c +++ b/sound/soc/sunxi/i2s/sunxi-i2s.c @@ -961,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; @@ -975,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; } From 2b6ebc98fc9a9fc0ed949c16fe20341e215e94ab Mon Sep 17 00:00:00 2001 From: fkwp Date: Fri, 24 Oct 2014 20:25:20 +0200 Subject: [PATCH 5/6] Enabled 8ch output --- sound/soc/sunxi/i2s/sndi2s.c | 2 +- sound/soc/sunxi/i2s/sunxi-i2s.c | 2 +- sound/soc/sunxi/i2s/sunxi-i2sdma.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) 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 4e1a7a96e94422..4859d73368b920 100644 --- a/sound/soc/sunxi/i2s/sunxi-i2s.c +++ b/sound/soc/sunxi/i2s/sunxi-i2s.c @@ -1197,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, From 26bbf749ebf4037b79bfd32878928faab8e1dd32 Mon Sep 17 00:00:00 2001 From: fkwp Date: Sat, 25 Oct 2014 11:12:39 +0200 Subject: [PATCH 6/6] fix _set_sysclk (PLL) --- sound/soc/sunxi/i2s/sunxi-i2s.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/sunxi/i2s/sunxi-i2s.c b/sound/soc/sunxi/i2s/sunxi-i2s.c index 4859d73368b920..accac5ce16a274 100644 --- a/sound/soc/sunxi/i2s/sunxi-i2s.c +++ b/sound/soc/sunxi/i2s/sunxi-i2s.c @@ -371,7 +371,7 @@ static int sunxi_i2s_set_sysclk(struct snd_soc_dai *cpu_dai, int clk_id, unsigne if (freq == 0) { freq = 24576000; // 8k, 12k, 16k, 24k, 32k, 48k, 64k, 96k, 128k, 192k - } else + } else if (freq == 1) { freq = 22579200; // 11.025k, 22.05k, 44.1k, 88.2k, 176.4k }