Mono audio input did not work on Jetson TK1

Hello,

If I change the audio input mode to “Analog Mono input” in sound setting, it did not have any input from microphone on TK1.

I set the below setting that I found on the forums of TK1:

amixer cset name=“Stereo ADC MIXL ADC2 Switch” 0
amixer cset name=“Stereo ADC MIXR ADC2 Switch” 0
amixer cset name=“Int Mic Switch” 0
amixer cset name=“ADC Capture Switch” 1
amixer cset name=“RECMIXL BST1 Switch” 0
amixer cset name=“RECMIXR BST1 Switch” 0
amixer cset name=“RECMIXL BST2 Switch” 1
amixer cset name=“RECMIXR BST2 Switch” 1
amixer cset name=“Stereo ADC L1 Mux” “ADC”
amixer cset name=“Stereo ADC R1 Mux” “ADC”
amixer cset name=“Stereo ADC MIXL ADC1 Switch” 1
amixer cset name=“Stereo ADC MIXR ADC1 Switch” 1
amixer cset name=“Stereo ADC MIXL ADC2 Switch” 0
amixer cset name=“Stereo ADC MIXR ADC2 Switch” 0
amixer cset name=“IN1 Mode Control” “Single ended”
amixer cset name=“IN2 Mode Control” “Single ended”
amixer cset name=“Mic Jack Switch” 1

It only worked normally in stereo mode, but it did not work in mono mode.

How can I fix it?

Best Regards,
Michael

Hi Michael,

I will check on this and get back to you. For newer devices (TX1, TX2, etc) we can convert the stereo stream at the I2S level from stereo to mono. However, the TK1 uses and older kernel and drivers and so I need to see if there is a easy way to convert the stereo I2S stream to mono, or if we can do this via the codec.

Regards,
Jon

Hi Michael,

I had a quick look at this and verified your findings above. I also found that using the above mixer settings, if I leave the mode as ‘Analog stereo input’ and then …

arecord -v -d 10 cap.wav

By default the above captures only a single channel and so the file generated is mono. So pulseaudio is converting the stereo input to mono. You would need to pass ‘-c 2’ to capture stereo in the above.

One thing that is a bit tricky with mono, is that the default configuration for the I2S interface between Tegra and the codec, is I2S, which implies there are always 2 channels received from and transmitted to the codec. Simply because standard I2S signaling always has a left and right channel. To capture true mono from the codec, we would need to either configure the I2S interface for dsp-a/b mode and then we could just have 1 channel or on newer kernels (for newer Tegra devices) we have a mixer control for the I2S driver to convert the stereo to mono in the Tegra audio subsystem.

Is your goal just to generate a mono output WAV file?

Regards,
Jon

Hi Jon,

Thanks for your reply.

Because I hope that it can work normally after I change the mode to mono on GUI. It would be more convenient.

Best Regards,
Michael

Hi Jon,

If I understand it correctly, the first step is that set the codec audio path to mono, the second step is that implement your suggestion that configure the I2S interface for dsp-a/b mode to just have 1 channel.

Is my understanding correct? Please correct me if I am wrong.

So, I tried to set the codec to mono as below :

Step 1 : Changed the input mode to “Analog Mono input” in sound setting.

Step 2 : Try to set the codec audio path to mono :

amixer cset name="Int Mic Switch" 0 
amixer cset name="IN Capture Volume" 31
amixer cset name="IN1 Mode Control" "Single ended"
amixer cset name="IN2 Mode Control" "Single ended"
amixer cset name="RECMIXL BST2 Switch" 1
amixer cset name="RECMIXR BST2 Switch" 1
amixer cset name="RECMIXL INL Switch" 0
amixer cset name="RECMIXR INL Switch" 0
amixer cset name="RECMIXL BST1 Switch" 0
amixer cset name="RECMIXR BST1 Switch" 0
amixer cset name="RECMIXL HPOL Switch" 0
amixer cset name="RECMIXR HPOR Switch" 0
amixer cset name="Mono ADC L1 Mux" "ADCL"
amixer cset name="Mono ADC R1 Mux" "ADCR"
amixer cset name="Mono ADC MIXL ADC1 Switch" 1  
amixer cset name="Mono ADC MIXR ADC1 Switch" 1  
amixer cset name="Mono ADC MIXL ADC2 Switch" 0  
amixer cset name="Mono ADC MIXR ADC2 Switch" 0 
amixer cset name="Mono ADC Capture Volume" 127
amixer cset name="IF2 ADC L Mux" 1
amixer cset name="IF2 ADC R Mux" 1
amixer cset name="DAI select" 0
amixer cset name="SDI select" 1
amixer cset name="Mic Jack Switch" 1

It was not worked…

So maybe I need to do second step to configure the I2S interface for dsp-a/b mode to just have 1 channel.
But I do not know how to do it, please give me some suggestion on this. Thanks.

Best Regards,
Michael

Hi Michael,

I have been looking at this a bit closer and found a bug in the Tegra I2S driver. Basically, when selecting the mono mode, the number of bits per sample is incorrectly set in the I2S driver. For example, if you were using 16-bit per sample, then the I2S interface was being configured for 8-bits if mono mode is used. I was able to fix the I2S driver by making the following change and verified that it worked with the settings you have in comment #1 above.

diff --git a/sound/soc/tegra/tegra30_i2s.c b/sound/soc/tegra/tegra30_i2s.c
index 4ad48e040654..12602fcaca12 100644
--- a/sound/soc/tegra/tegra30_i2s.c
+++ b/sound/soc/tegra/tegra30_i2s.c
@@ -560,11 +560,13 @@ static int tegra30_i2s_hw_params(struct snd_pcm_substream *substream,
        srate = params_rate(params);
 
        if (reg_ctrl & TEGRA30_I2S_CTRL_MASTER_ENABLE) {
-               i2sclock = srate * params_channels(params) * sample_size;
+               i2sclock = srate * sample_size;
 
                /* Additional "* 4" is needed for FSYNC mode */
                if (reg_ctrl & TEGRA30_I2S_CTRL_FRAME_FORMAT_FSYNC)
-                       i2sclock *= 4;
+                       i2sclock *= params_channels(params) * 4;
+               else
+                       i2sclock *= 2;
 
                if (i2s->i2s_bit_clk != 0)
                        i2sclock = i2s->i2s_bit_clk;

Let me know if this helps.

Regards,
Jon

Hi Jon,

It works! Thanks for your help.

Best Regards,
Michael