IMX6 audio output on I2S

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

IMX6 audio output on I2S

Jump to solution
4,867 Views
andreaguglielm1
Contributor II

Hi all.

I'm currently working on a board powered by a Freescale iMX 6 processor with kernel 3.0.35 and I'm facing an issue with sound routing. My application is heavily based on Gstreamer. As far as I know, Gstreamer does need a (fake) codec to which forward audio.

My production board does NOT include an hardware codec and I need to forward the sound data directly to I2S. I've developed my application on a demo board with SGTL5000 and on that board the related driver is correctly used. In deploying the final code to the production board I tried to modify the above mentioned driver to fake SGTL5000 presence but with no luck.

The same approach worked well  on kernel  2.6.X (iMX28) where the ALSA subsystem was quite different then subsequent kernel releases.

Is it feasible to adapt SGTL5000 driver to fake codec presence as we have done in kernel 2.6.x? If yes, could someone please give us some hints on how to correctly do that?  By the way, I feel like modifying the driver is not elegant and sane at all. Do you know any standard way to forward sound data to I2S when no codec is available? Is there any specific driver for that?

As we saied we are using kernel 3.0.35 but we have no constraint on using specific version.

Thanks in advance for any clue about my issue.

Andrea Guglielmi

Labels (3)
1 Solution
2,477 Views
andreaguglielm1
Contributor II

I write again here just to say that I found the solution a couple of weeks ago. I hope that will help someone who will have similar troubles.

The big difference between old 2.6.35 and the 3.0.15 kernel is that in the oldest version the sgtl5000 is configured as slave whereas in the newest one it is configured as master.

We focused on I2C and DMA configuration to understand why I2S transfer did not start. We wrongly thought the I2S was set as master (sgtl5000 slave) like the old kernel and we did not check it. When we rechecked the driver source code starting from I2S configuration we found what was wrong. We simply changed I2S configuration and added a divisor calculator. We had to change also the clock source for SSI to PLL4 (best clock source for audio) and set PLL4 frequency to get the best accuracy for the most common sample rates.

I would add that the freescale I2S driver lacks of a lot of features, like a master mode management and a function to set bit clock. Those features are missing in newest kernel too. I can't release a patch cause my code is really bad, but i think freescale should add the above-mentioned features. Al least to deliver to developers a full featured kernel.

Bests,

Andrea Guglielmi

View solution in original post

0 Kudos
7 Replies
2,478 Views
andreaguglielm1
Contributor II

I write again here just to say that I found the solution a couple of weeks ago. I hope that will help someone who will have similar troubles.

The big difference between old 2.6.35 and the 3.0.15 kernel is that in the oldest version the sgtl5000 is configured as slave whereas in the newest one it is configured as master.

We focused on I2C and DMA configuration to understand why I2S transfer did not start. We wrongly thought the I2S was set as master (sgtl5000 slave) like the old kernel and we did not check it. When we rechecked the driver source code starting from I2S configuration we found what was wrong. We simply changed I2S configuration and added a divisor calculator. We had to change also the clock source for SSI to PLL4 (best clock source for audio) and set PLL4 frequency to get the best accuracy for the most common sample rates.

I would add that the freescale I2S driver lacks of a lot of features, like a master mode management and a function to set bit clock. Those features are missing in newest kernel too. I can't release a patch cause my code is really bad, but i think freescale should add the above-mentioned features. Al least to deliver to developers a full featured kernel.

Bests,

Andrea Guglielmi

0 Kudos
2,477 Views
pawelkrzyzanows
Contributor II

Hi,

I see question was answered 3 month ago, but since I am facing similar issue as andreaguglielmi​.

I am trying to get I2S output from i.MX6. As a driver I have decided to use sgtl5000/wm8962 driver.

The major problem I have is how to change imx from slave to master. How You do this?

It would be great if You can help me with this (even if Your code is "messy") I think it is still valuable for me :smileyhappy:

Topic I made is: (follow both so feel free to answer anywhere)

Re: i.MX6 I2S output

0 Kudos
2,477 Views
andreaguglielm1
Contributor II

Hi,

I cannot check code right now, i modified the 3.0.15 kernel.

I am looking at the on-line version of kernel 4.3. In imx_sgtl5000_probe function in /source/sound/soc/fsl/imx-sgtl5000.c file there is the settings for sgtl5000 and I2S.

here: Linux/sound/soc/fsl/imx-sgtl5000.c - Linux Cross Reference - Free Electrons

you have to change SND_SOC_DAIFMT_CBM_CFM with SND_SOC_DAIFMT_CBS_CFS.

It is probable that is not the only change you have to do, i think you have to set by yourself the clock and all settings about it.

I can't help you more now. Next days i should find time to recheck my code.

Regards

2,477 Views
pawelkrzyzanows
Contributor II

Hi Andrea,

on the beginning thank You for any replay Smiley Happy.

The change You said I have done yesterday in meantime between my and Your post, and now driver is able to initiate transmission and stop it. But I am missing LRCK and BCLK. Transmission start and stop I seen because MCLK is stops (without this change it was running whole time) and I see data on SDATA. So I am going in the right direction.

I have sth in codec:

switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {

case SND_SOC_DAIFMT_CBM_CFM:

  pr_err("CBM_CFM\n");

  aif0 |= WM8962_MSTR;

  break;

case SND_SOC_DAIFMT_CBS_CFS:

  pr_err("CBS_CFS\n");

  break;

default:

pr_err("default_3\n");

So If I set codec as a master I get:

#define WM8962_MSTR                             0x0040  /* MSTR */ (from codec.h file)

but If I want to set as a slave I don't get anything? settings 0x0000 are good? becaouse my codec.h file is missing this part. and to update bits I had:

snd_soc_update_bits(codec, WM8962_AUDIO_INTERFACE_0,

WM8962_FMT_MASK | WM8962_BCLK_INV | WM8962_MSTR |

WM8962_LRCLK_INV, aif0);

which looks like mask (3rd parameter) is only for master mode or not.

Will be waiting for response Smiley Happy. Or piece of Your code :smileygrin:

0 Kudos
2,477 Views
pawelkrzyzanows
Contributor II

I have an Idea.

Since I changed slaved <->master, and driver was written as a codec master, all the settings for BCLK/LRCK/MCLK was made in codec register. So even If I switch master<->slave all the clock setting are still done in codec. So I have to change it somehow in i.MX.

Looking forward for any replay

Pawel :smileyhappy:

0 Kudos
2,477 Views
weidong_sun
NXP TechSupport
NXP TechSupport

Hello Andrea,

     In i.MX6, there are SPDIF & HDMI Audio Codec, if you don't need external audio codec, you can choose one of them, In my opinion, SPDIF audio out should be suitable for you.

    Try it , please!

Regards,

Weidong

0 Kudos
2,477 Views
andreaguglielm1
Contributor II

Thanks for you answer.

Sadly I have to interface to an other device that accept audio input only by I2S.

0 Kudos