[alsa-devel] Output frequency configuration for I2S in beagleboard? (underrun problem)
Hi,
I would like to know the actual configuration for the output of the Beagle Board I2S, from the OMAP35x Reference Manual, on page 2887:
• Enable the Sample Rate Generator (take it out of reset). Set McBSPi.MCBSPLP_SPCR2_REG[6] GRSTbit to1 to enable the Sample Rate Generator. After the Sample Rate Generator is enabled, wait for 2 CLKG cycles for the Sample Rate Generator logic to stabilize. * On the next rising edge of CLKSRG, the CLKG signal transitions to '1' and starts clocking with a frequency equal to (input clock frequency)/(CLKGDV + 1).* • If necessary, enable the receiver and/or the transmitter.
It says the clocking will start with the frequency of input clock (I thougth it is 26Mhz but i've been told is 96Khz, not quite sure) and CLKGDV is a variable number to get a desired frequency.
from omap-mcbsp.c:
*static int omap_mcbsp_dai_set_clkdiv(struct snd_soc_dai *cpu_dai, int div_id, int div) { struct omap_mcbsp_data *mcbsp_data = to_mcbsp(cpu_dai->private_data); struct omap_mcbsp_reg_cfg *regs = &mcbsp_data->regs; dbg("omap_mcbsp_dai_set_clkdiv START"); if (div_id != OMAP_MCBSP_CLKGDV) return -ENODEV; dbg("div: %d",div); regs->srgr1 |= CLKGDV(div - 1); dbg("omap_mcbsp_dai_set_clkdiv END"); return 0; }*
Here, the value is asigned to srgr1. I capture all actions from startup and from aplay but this function is never called. Do you know when it should be called or where we can find the div value?
I'm having trouble adapting an external codec from the beagle, and I think it may be because of the output frequency from the beagle. I'm getting some underruns during playback(with aplay) and I don't know exactly where to begin. Suggestions are welcome.
Thanks for your help
Best regards, Ernesto
On Tue, May 12, 2009 at 06:28:58PM -0500, Ernesto Torres wrote:
*static int omap_mcbsp_dai_set_clkdiv(struct snd_soc_dai *cpu_dai, int div_id, int div)
Here, the value is asigned to srgr1. I capture all actions from startup and from aplay but this function is never called. Do you know when it should be called or where we can find the div value?
The beagle is configured to clock the I2S bus from the TWL4030 rather than from the OMAP.
On Wednesday 13 May 2009 02:28:58 ext Ernesto Torres wrote:
Hi,
I would like to know the actual configuration for the output of the Beagle Board I2S, from the OMAP35x Reference Manual, on page 2887:
Is you external codec supports master mode (provides the needed clocks on the I2S bus)? I would suggest to use it in that way, since configuring OMAP to provide close enough frequency can be tricky. I have did this for experimenting on our custom board, just to see how it works. This is the code is taken from the soc board file's hw_params function:
div = clk_id = freq = 0; switch (params_rate(params)) { case 44100: /* 44.117 */ div = 68; clk_id = OMAP_MCBSP_SYSCLK_CLKS_FCLK; freq = 96000000; break; case 48000: /* 48.032 */ div = 54; clk_id = OMAP_MCBSP_SYSCLK_CLK; freq = 83000000; break; default: printk(KERN_ERR "hw params: unknown rate %d\n", params_rate(params)); return -EINVAL; }
ret = snd_soc_dai_set_sysclk(cpu_dai, clk_id, freq, SND_SOC_CLOCK_IN); if (ret < 0) { printk(KERN_ERR "can't set cpu system clock\n"); return ret; }
ret = cpu_dai->dai_ops.set_clkdiv(cpu_dai, OMAP_MCBSP_CLKGDV, div); if (ret < 0) { printk(KERN_ERR "can't set cpu clock divider\n"); }
As you can see I needed to select different clock source for 44.1 and 48 KHz sample rate for OMAP to use as a base for the dividing...
So: try to use the OMAP as slave, if it is possible.
Hi, thanks for your replies, unfortunately, the codec has to be slave, it doesn't support yet to send clock via i2s. I have another question, it migh= t be seem simple but it will clarify some of my thoughts.
_From omap3beagle.c hw_params:
* /* Set the codec system clock for DAC and ADC */ ret =3D snd_soc_dai_set_sysclk(codec_dai, 0, 26000000, SND_SOC_CLOCK_IN);*
The sysclk is set to 26Mhz and it is coming from the TWL which acts as master.
I had it configured to 12288000(info from datasheet) which was suppose to work until I knew the codec I'm using can't be master. (It is still is on 12288000)
How should it be configured to make the OMAP Master? Should I leave it as 26Mhz and do manually all the divisions? I'm using SND_SOC_DAIFMT_CBS_CFS for the Beagle.
Thank you for your help
BR, Ernesto
On Wed, May 13, 2009 at 5:41 AM, Peter Ujfalusi peter.ujfalusi@nokia.comw= rote:
On Wednesday 13 May 2009 02:28:58 ext Ernesto Torres wrote:
Hi,
I would like to know the actual configuration for the output of the
Beagle
Board I2S, from the OMAP35x Reference Manual, on page 2887:
Is you external codec supports master mode (provides the needed clocks on the I2S bus)? I would suggest to use it in that way, since configuring OMAP to provide close enough frequency can be tricky. I have did this for experimenting on our custom board, just to see how it works. This is the code is taken from the soc board file's hw_params function:
div =3D clk_id =3D freq =3D 0; switch (params_rate(params)) { case 44100: /* 44.117 */ div =3D 68; clk_id =3D OMAP_MCBSP_SYSCLK_CLKS_FCLK; freq =3D 96000000; break; case 48000: /* 48.032 */ div =3D 54; clk_id =3D OMAP_MCBSP_SYSCLK_CLK; freq =3D 83000000; break; default: printk(KERN_ERR "hw params: unknown rate %d\n", params_rate(params)); return -EINVAL; }
ret =3D snd_soc_dai_set_sysclk(cpu_dai, clk_id, freq, SND_SOC_CLOCK_IN); if (ret < 0) { printk(KERN_ERR "can't set cpu system clock\n"); return ret; }
ret =3D cpu_dai->dai_ops.set_clkdiv(cpu_dai, OMAP_MCBSP_CLKGDV, div); if (ret < 0) { printk(KERN_ERR "can't set cpu clock divider\n"); }
As you can see I needed to select different clock source for 44.1 and 48 KHz sample rate for OMAP to use as a base for the dividing...
So: try to use the OMAP as slave, if it is possible.
-- P=E9ter
--=20 ___________ EhTd
On Wednesday 13 May 2009 21:08:20 ext Ernesto Torres wrote:
Hi, thanks for your replies, unfortunately, the codec has to be slave, it doesn't support yet to send clock via i2s.
Too bad.
I have another question, it might be seem simple but it will clarify some of my thoughts.
From omap3beagle.c hw_params:
/* Set the codec system clock for DAC and ADC */ ret = snd_soc_dai_set_sysclk(codec_dai, 0, 26000000, SND_SOC_CLOCK_IN);
The sysclk is set to 26Mhz and it is coming from the TWL which acts as master.
26MHz is the MCLK, which is used by the TWL4030 codec's APLL as a master clock.
I had it configured to 12288000(info from datasheet) which was suppose to work until I knew the codec I'm using can't be master. (It is still is on 12288000)
So you modified the omap3beagle.c file to use your codec, which is not the TWL4030, and it is not on the McBSP2 bus, right? Or have you written a new board file for your codec and removed the twl4030 codec from the kernel?
How should it be configured to make the OMAP Master? Should I leave it as 26Mhz and do manually all the divisions? I'm using SND_SOC_DAIFMT_CBS_CFS for the Beagle.
You seams to be confusing things here...
In order to use the OMAP as master: In the hw_param function (on my custom board with twl4030 codec as slave):
/* codec is slave */ ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS); /* OMAP is master */ ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS); /* codec MCLK is 19.2MHz in my board, 26 MHz on beagle */ ret = snd_soc_dai_set_sysclk(codec_dai, 0, 19200000, SND_SOC_CLOCK_IN); /* McBSP clock settings for my custom board. * Note that the freq is there for reference, it is not * used by the McBSP code. Only the divider is used. * You need to figure out the correct frequencies and dividers * for beagle. You can try these also values, but I would not * count on that these are correct for beagle... * * The important things in here: * div: divider * clk_id: Master clock used for the divider */ div = clk_id = freq = 0; switch (params_rate(params)) { case 44100: /* 44.117 */ div = 68; clk_id = OMAP_MCBSP_SYSCLK_CLKS_FCLK; freq = 96000000; break; case 48000: /* 48.032 */ div = 54; clk_id = OMAP_MCBSP_SYSCLK_CLK; freq = 83000000; break; default: printk(KERN_ERR "hw params: unknown rate %d\n", params_rate(params)); return -EINVAL; }
ret = snd_soc_dai_set_sysclk(cpu_dai, clk_id, freq, SND_SOC_CLOCK_IN); ret = cpu_dai->dai_ops.set_clkdiv(cpu_dai, OMAP_MCBSP_CLKGDV, div);
Since you want OMAP as master you need to configure the cpu_dai correctly to provide the clocks for the codec.
Does this clear things for you?
Hi,
The external codec is connected to McBSP3, it has been pinmuxed to use the pins on the expansion.
The code from the TWL4030 has been erased and replaced by the code for the external codec. The files remain the same for now. Board still believes is twl4030 but sends info via other addresses.(I2C2 & McBSP3)
External codec has 12.288 Mhz clock Beagle has 26Mhz
_From your code: case 48000: /* 48.032 */ div =3D 54; clk_id =3D OMAP_MCBSP_SYSCLK_CLK; freq =3D 83000000; break;
If I understand correctly, 48.032 will be the result of the mclk division. * (input clock frequency)/(CLKGDV + 1)*=3D 48.032
*input clock frequency*=3DOMAP_MCBSP_SYSCLK_CLK *CLKGDV*=3Ddiv=3D53(according to : * regs->srgr1 |=3D CLKGDV(div - 1);)*
Doing some math: CLKGDV=3Ddiv-1=3D54-1=3D53 48032*54=3Dinput clock frequency=3D2593728?
What should be the value for OMAP_MCBSP_SYSCLK_CLK?
BR, Ernesto
On Thu, May 14, 2009 at 1:16 AM, Peter Ujfalusi peter.ujfalusi@nokia.comw= rote:
On Wednesday 13 May 2009 21:08:20 ext Ernesto Torres wrote:
Hi, thanks for your replies, unfortunately, the codec has to be slave, it doesn't support yet to send clock via i2s.
Too bad.
I have another question, it might be seem simple but it will clarify some of my thoughts.
From omap3beagle.c hw_params:
/* Set the codec system clock for DAC and ADC */ ret =3D snd_soc_dai_set_sysclk(codec_dai, 0, 26000000, SND_SOC_CLOCK_IN);
The sysclk is set to 26Mhz and it is coming from the TWL which acts as master.
26MHz is the MCLK, which is used by the TWL4030 codec's APLL as a master clock.
I had it configured to 12288000(info from datasheet) which was suppose =
to
work until I knew the codec I'm using can't be master. (It is still is =
on
So you modified the omap3beagle.c file to use your codec, which is not th=
e
TWL4030, and it is not on the McBSP2 bus, right? Or have you written a ne=
w
board file for your codec and removed the twl4030 codec from the kernel?
How should it be configured to make the OMAP Master? Should I leave it =
as
26Mhz and do manually all the divisions? I'm using SND_SOC_DAIFMT_CBS_C=
FS
for the Beagle.
You seams to be confusing things here...
In order to use the OMAP as master: In the hw_param function (on my custom board with twl4030 codec as slave)=
:
/* codec is slave */ ret =3D snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS); /* OMAP is master */ ret =3D snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS); /* codec MCLK is 19.2MHz in my board, 26 MHz on beagle */ ret =3D snd_soc_dai_set_sysclk(codec_dai, 0, 19200000, SND_SOC_CLOCK_IN); /* McBSP clock settings for my custom board.
- Note that the freq is there for reference, it is not
- used by the McBSP code. Only the divider is used.
- You need to figure out the correct frequencies and dividers
- for beagle. You can try these also values, but I would not
- count on that these are correct for beagle...
- The important things in here:
- div: divider
- clk_id: Master clock used for the divider */
div =3D clk_id =3D freq =3D 0; switch (params_rate(params)) { case 44100: /* 44.117 */ div =3D 68; clk_id =3D OMAP_MCBSP_SYSCLK_CLKS_FCLK; freq =3D 96000000; break; case 48000: /* 48.032 */ div =3D 54; clk_id =3D OMAP_MCBSP_SYSCLK_CLK; freq =3D 83000000; break; default: printk(KERN_ERR "hw params: unknown rate %d\n", params_rate(params)); return -EINVAL; }
ret =3D snd_soc_dai_set_sysclk(cpu_dai, clk_id, freq, SND_SOC_CLOCK_IN); ret =3D cpu_dai->dai_ops.set_clkdiv(cpu_dai, OMAP_MCBSP_CLKGDV, div);
Since you want OMAP as master you need to configure the cpu_dai correctly to provide the clocks for the codec.
Does this clear things for you?
P=E9ter
--=20 ___________ EhTd
On Thursday 14 May 2009 18:12:54 ext Ernesto Torres wrote:
Hi,
The external codec is connected to McBSP3, it has been pinmuxed to use the pins on the expansion.
The code from the TWL4030 has been erased and replaced by the code for the external codec. The files remain the same for now. Board still believes is twl4030 but sends info via other addresses.(I2C2 & McBSP3)
External codec has 12.288 Mhz clock Beagle has 26Mhz
To be precise: TWL4030 codec on Beagle board has 26MHz MCLK. This has nothing to do with the McBSP clocking at all.
From your code: case 48000: /* 48.032 */ div = 54; clk_id = OMAP_MCBSP_SYSCLK_CLK; freq = 83000000; break;
If I understand correctly, 48.032 will be the result of the mclk division.
(input clock frequency)/(CLKGDV + 1)*= 48.032
Not really, with the clkdiv you get the bitclock.
*input clock frequency*=OMAP_MCBSP_SYSCLK_CLK *CLKGDV*=div=53(according to : * regs->srgr1 |= CLKGDV(div - 1);)*
Doing some math: CLKGDV=div-1=54-1=53 48032*54=input clock frequency=2593728?
This is how you are calculating it: 48032*16*2*54=82999296
If we want to have the clocks for 48KHz 16bit stereo playback, and we going to use OMAP as master: Select the clock source for McBSP as OMAP_MCBSP_SYSCLK_CLK, which means that we are using McBSPi_ICLK for the SRG divider source In my HW the McBSPi_ICLK is 83MHz Than: 83000000 / 16 / 2 / div = 48000 div = 83000000 / 16 / 2 / 48000 div = 54.0364 ~= 54
Thanks for the information, I'll try this approach and see how it goes
BR, Ernesto
On Fri, May 15, 2009 at 1:23 AM, Peter Ujfalusi peter.ujfalusi@nokia.comwrote:
On Thursday 14 May 2009 18:12:54 ext Ernesto Torres wrote:
Hi,
The external codec is connected to McBSP3, it has been pinmuxed to use
the
pins on the expansion.
The code from the TWL4030 has been erased and replaced by the code for
the
external codec. The files remain the same for now. Board still believes
is
twl4030 but sends info via other addresses.(I2C2 & McBSP3)
External codec has 12.288 Mhz clock Beagle has 26Mhz
To be precise: TWL4030 codec on Beagle board has 26MHz MCLK. This has nothing to do with the McBSP clocking at all.
From your code: case 48000: /* 48.032 */ div = 54; clk_id = OMAP_MCBSP_SYSCLK_CLK; freq = 83000000; break;
If I understand correctly, 48.032 will be the result of the mclk
division.
(input clock frequency)/(CLKGDV + 1)*= 48.032
Not really, with the clkdiv you get the bitclock.
*input clock frequency*=OMAP_MCBSP_SYSCLK_CLK *CLKGDV*=div=53(according to : * regs->srgr1 |= CLKGDV(div - 1);)*
Doing some math: CLKGDV=div-1=54-1=53 48032*54=input clock frequency=2593728?
This is how you are calculating it: 48032*16*2*54=82999296
If we want to have the clocks for 48KHz 16bit stereo playback, and we going to use OMAP as master: Select the clock source for McBSP as OMAP_MCBSP_SYSCLK_CLK, which means that we are using McBSPi_ICLK for the SRG divider source In my HW the McBSPi_ICLK is 83MHz Than: 83000000 / 16 / 2 / div = 48000 div = 83000000 / 16 / 2 / 48000 div = 54.0364 ~= 54
-- Péter
Finally, we got it working, properly configuring with the clock divide was the solution. Thanks for your help.
BR, Ernesto
participants (3)
-
Ernesto Torres
-
Mark Brown
-
Peter Ujfalusi