Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion sound/soc/sunxi/i2s/sndi2s.c
Original file line number Diff line number Diff line change
Expand Up @@ -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,
},
Expand Down
101 changes: 67 additions & 34 deletions sound/soc/sunxi/i2s/sunxi-i2s.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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;
Expand All @@ -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)
{
Expand All @@ -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
Expand Down Expand Up @@ -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;
Expand All @@ -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;
}
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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,
};
Expand Down
2 changes: 1 addition & 1 deletion sound/soc/sunxi/i2s/sunxi-i2sdma.c
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
4 changes: 2 additions & 2 deletions sound/soc/sunxi/i2s/sunxi-sndi2s.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down