• TI thinks resolved

Linux/TLV320AIC3106-Q1: How To Configure the 2nd I2S/PCM?

Part Number: TLV320AIC3106-Q1

Tool/software: Linux

Hi All,

I was configuring the 2nd I2S/PCM of TLV320AIC3106-Q1 like below diagram for WL2833Q Bluetooth.

It seemd that I can just add a :ai3x-gpio-func" like

&i2c2 {

        clock-frequency = <400000>;

        pinctrl-names = "default";

        pinctrl-0 = <&pinctrl_i2c2>;

        status = "okay";

 

        codec: tlv320aic3106@18 { ////Audio Codec

                compatible = "ti,tlv320aic3x";

                reg = <0x18>;

                clocks = <&codec_osc>;

                clock-names = "clko_clk";

                AVDD-supply = <&reg_audio>;

                IOVDD-supply = <&reg_audio>;

                DRVDD-supply = <&reg_audio>;

                DVDD-supply = <&reg_audio>;

        gpio-reset = <&gpio4 26 1>;

        ai3x-gpio-func = <11 8>; //<AIC3X_GPIO1_FUNC_AUDIO_WORDCLK, AIC3X_GPIO2_FUNC_AUDIO_BITCLK>

    };

};

But actually, it will crash my 1st I2S (WCLK, BCLK, DIN, DOUT) while playback an audio. So I tried to send the configuration commands through 

I2C like :

i2cset -f -y 1 0x18 98 0xB0

i2cset -f -y 1 0x18 99 0x80

i2cset -f -y 0x18 8 0xD0

I did see the GPIO1 and GPIO2 signals from my scope.

And if I tried to playback an audio from iMX6Q, it will then diable the GPIO1 and GPIO2.

i2cget -f -y 1 0x18 98 showed 0x00

i2cget -f -y 1 0x18 99 showed 0x00

i2cegt -f -y 1 0x18 98 8 showed 0x00

So if there was a good way to configure and enable my Bluetooth?  Thanks for your help.

-Justin

 

  • Hi, Justin,

    My colleague in charge of this device has been notified about your question. As he is out of the office on Holiday, the response could be delayed, so we appreciate your comprehension.

    Best Regards,

      -Diego Meléndez López
       Audio Applications Engineer

  • In reply to Diego Melendez:

    Hi Diego,

    It's all right since it's holiday season. please get back to me once he is back.
    Thank you very much.

    -Justin
  • In reply to Justin Fu:

    Hi Justin,

    Thank you for your patience during the holiday!  

    please see the diagram below.  The MFP3 and GPIOs are muxed, so cannot be concurrently used with signals from your iMX60.  

    This would allow you to continue using a bluetooth device, when the processor is in sleep/low power mode.

    I hope that answers your question,  but if I misunderstood, please let me know.  I'm happy to help!

    best regards, 

    -Steve Wilson

  • In reply to Steve-Wilson:

    Hi Steve,

    So you are saying that (WCLK, BCLK, DIN, DOUT) and (GPIO1, GPIO2, MFP3, DOUT) two channels can only one be activated?

    Then where should I put the this activation code? Does it mean I enable the channel when I want to use it, and disable the channel when I don't want to use it?

    How do I configure/enable/switch to (GPIO1, GPIO2, MFP3, DOUT) this channel, since I can not write the ai3x-gpio-func in device tree?

    -Justin
  • In reply to Justin Fu:

    Hi Justin,

    Correct, only one Audio bus can be active at a time. So if the WL81330 is active, the iMX60 should not be active.

    The GPIO pins become active when you program the registers to be used as I2S audio ports.

    before you switch to the WL81330, you should discontinue the audio from the iMX60, then change audio bus, then start the WL81330 audio.
    it may makes sense to briefly mute the dac too. but see how that goes.

    best regards,
    -Steve Wilson
  • In reply to Justin Fu:

    Justin,

    if you want to have two simultaneous Audio buses the TLV320AIC3262, TLV320AIC3212 and TLV320AIC3268 do have this functionality.

    best regards,
    -Steve
  • In reply to Steve-Wilson:

    Hi Steve,

    Can you provide me some code snippet or sample code of configuration of GPIO1 and GPIO2 to I2S/PCM. I had tried to set up the Register 98 to 0xB0 (as WCLK) and Register 99 to 0x80 (as BCLK), but not worked.

    -Justin
  • In reply to Justin Fu:

    Hi Steve,

    My development environment is Android N7.1.1 (Linux 4.1.15).
    And my current situation is Bluetooth headset can connect
    to my development board, but I can not hear any sound. The Audio codec is capable
    of playback and recording from Android app like Music/SoundRecorder, and from Linux binary
    like tinyplay/tinycap.

    The codes related follows:
    [DeviceTree: imx6q-asurada-pins.dtsi]
    / {
    sound-tlv320aic3106 {
    compatible = "fsl,imx6-asurada-tlv320aic3106",
    "fsl,imx-audio-tlv320aic3x";
    model = "tlv320aic3x-audio";
    audio-codec = <&codec>;
    cpu-dai = <&ssi2>;
    mux-int-port = <2>;
    mux-ext-port = <4>;
    audio-routing =
    "Line Out Jack", "LLOUT",
    "Ext Spk", "MONO_LOUT",
    "Line Out Jack", "RLOUT",
    "LINE1L", "AV Line In Jack",
    "LINE1R", "AV Line In Jack",
    "LINE2L", "Turner Line In",
    "LINE2R", "1388 Line Out",
    "MIC3L", "Aux Line In Jack",
    "MIC3R", "Aux Line In Jack",
    "Playback", "CPU-Playback",
    "CPU-Capture", "Capture";
    };
    };

    &i2c2 {
    clock-frequency = <400000>;
    pinctrl-names = "default";
    pinctrl-0 = <&pinctrl_i2c2>;
    status = "okay";

    codec: tlv320aic3106@18 { ////Audio Codec
    compatible = "ti,tlv320aic3x";
    reg = <0x18>;
    clocks = <&codec_osc>; //original
    //clocks = <&clks IMX6QDL_CLK_CKO>;
    clock-names = "clko_clk";
    AVDD-supply = <&reg_audio>;
    IOVDD-supply = <&reg_audio>;
    DRVDD-supply = <&reg_audio>;
    DVDD-supply = <&reg_audio>;
    gpio-reset = <&gpio4 26 1>;
    #if 0 //justin@20171228
    ai3x-gpio-func = <
    11 //justin@20171219: AIC3X_GPIO1_FUNC_AUDIO_WORDCLK
    8 //justin@20171219: AIC3X_GPIO2_FUNC_AUDIO_BITCLK
    >;
    #endif
    };
    };

    [Codec Driver: kewrnel_imx/sound/soc/codecs/tlv320aic3x.c]
    static const struct snd_kcontrol_new aic3x_mono_controls[] = {

    /* justin@20180103 */
    SOC_SINGLE("GPIO1 Control Switch", AIC3X_GPIO1_REG, 4, 0x0F, 0),
    SOC_SINGLE("GPIO2 Control Switch", AIC3X_GPIO2_REG, 4, 0x0F, 0),
    SOC_SINGLE("Audio Serial Data Interface Mode", AIC3X_ASD_INTF_CTRLB, 6, 0x03, 0),
    };

    [config_tlv320aic3x.h of tinyalsa_hal.c ]
    static struct route_setting mm_bt_mic_input_TLV320AIC3X[] = {
    //R98(AIC3X_GPIO1_REG): WCLK
    {
    .ctl_name = "GPIO1 Control Switch",
    .intval = 11,
    },
    //R99(AIC3X_GPIO2_REG): BCLK
    {
    .ctl_name = "GPIO2 Control Switch",
    .intval = 8,
    },
    //R9(AIC3X_ASD_INTF_CTRLB): DSP mode
    {
    .ctl_name = "Audio Serial Data Interface Transfer Mode",
    .intval = 1,
    },
    //R81(PGAL_2_LLOPM_VOL)
    {
    .ctl_name = "Left Line Mixer PGAL Bypass Switch",
    .intval = 1,
    },
    //R84(PGAR_2_LLOPM_VOL)
    {
    .ctl_name = "Left Line Mixer PGAR Bypass Switch",
    .intval = 1,
    },
    {
    .ctl_name = NULL,
    },
    };

    static struct audio_card tlv320aic3x_card = {
    .name = "tlv320aic3x-audio",
    .driver_name = "tlv320aic3x-aud",
    .supported_out_devices = (
    AUDIO_DEVICE_OUT_WIRED_HEADSET |
    AUDIO_DEVICE_OUT_WIRED_HEADPHONE |
    AUDIO_DEVICE_OUT_SPEAKER |
    AUDIO_DEVICE_OUT_ALL_SCO |
    AUDIO_DEVICE_OUT_DEFAULT ),
    .supported_in_devices = (
    AUDIO_DEVICE_IN_WIRED_HEADSET |
    AUDIO_DEVICE_IN_BUILTIN_MIC |
    AUDIO_DEVICE_IN_ALL_SCO |
    AUDIO_DEVICE_IN_DEFAULT),
    .defaults = defaults_TLV320AIC3X,
    .bt_output = NULL, //bt_output_TLV320AIC3X,
    .speaker_output = NULL, //speaker_output_TLV320AIC3X,
    .hs_output = NULL, //hs_output_TLV320AIC3X,
    .earpiece_output = NULL, //earpiece_output_TLV320AIC3X,
    .vx_hs_mic_input = NULL, //vx_hs_mic_input_TLV320AIC3X,
    .mm_main_mic_input = NULL, //mm_main_mic_input_TLV320AIC3X,
    .vx_main_mic_input = NULL, //vx_main_mic_input_TLV320AIC3X,
    .mm_hs_mic_input = NULL, //mm_hs_mic_input_TLV320AIC3X,
    .vx_bt_mic_input = mm_bt_mic_input_TLV320AIC3X, //vx_bt_mic_input_TLV320AIC3X,
    .mm_bt_mic_input = mm_bt_mic_input_TLV320AIC3X,
    .card = 0,
    .out_rate = 0,
    .out_channels = 0,
    .out_format = 0,
    .in_rate = 0,
    .in_channels = 0,
    .in_format = 0,
    };

    [Board Config: device/fsl/asurada/audio_policy.conf]
    audio_hw_modules {
    primary {
    outputs {
    primary {
    sampling_rates 48000
    channel_masks AUDIO_CHANNEL_OUT_STEREO
    formats AUDIO_FORMAT_PCM_16_BIT
    # justin: devices AUDIO_DEVICE_OUT_SPEAKER|AUDIO_DEVICE_OUT_WIRED_HEADSET|AUDIO_DEVICE_OUT_WIRED_HEADPHONE|AUDIO_DEVICE_OUT_AUX_DIGITAL
    devices AUDIO_DEVICE_OUT_SPEAKER|AUDIO_DEVICE_OUT_WIRED_HEADSET|AUDIO_DEVICE_OUT_WIRED_HEADPHONE|AUDIO_DEVICE_OUT_AUX_DIGITAL|AUDIO_DEVICE_OUT_ALL_SCO
    flags AUDIO_OUTPUT_FLAG_PRIMARY
    }
    hdmi {
    sampling_rates dynamic
    channel_masks dynamic
    formats AUDIO_FORMAT_PCM_16_BIT
    devices AUDIO_DEVICE_OUT_AUX_DIGITAL
    flags AUDIO_OUTPUT_FLAG_DIRECT
    }
    esai {
    sampling_rates 48000
    channel_masks AUDIO_CHANNEL_OUT_5POINT1|AUDIO_CHANNEL_OUT_7POINT1
    formats AUDIO_FORMAT_PCM_16_BIT
    devices AUDIO_DEVICE_OUT_SPEAKER
    flags AUDIO_OUTPUT_FLAG_DIRECT
    }
    }
    inputs {
    primary {
    sampling_rates 8000|11025|16000|22050|24000|32000|44100|48000
    channel_masks AUDIO_CHANNEL_IN_MONO|AUDIO_CHANNEL_IN_STEREO
    formats AUDIO_FORMAT_PCM_16_BIT
    #justin: devices AUDIO_DEVICE_IN_BUILTIN_MIC|AUDIO_DEVICE_IN_WIRED_HEADSET|AUDIO_DEVICE_IN_AUX_DIGITAL
    #justin: |AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET (maybe)
    devices AUDIO_DEVICE_IN_BUILTIN_MIC|AUDIO_DEVICE_IN_WIRED_HEADSET|AUDIO_DEVICE_IN_AUX_DIGITAL|AUDIO_DEVICE_IN_ALL_SCO
    }
    }
    }
    #justin: =====>
    a2dp {
    outputs {
    a2dp {
    sampling_rates 44100
    channel_masks AUDIO_CHANNEL_OUT_STEREO
    formats AUDIO_FORMAT_PCM_16_BIT
    devices AUDIO_DEVICE_OUT_ALL_A2DP
    }
    }
    inputs {
    a2dp {
    sampling_rates 44100|48000
    channel_masks AUDIO_CHANNEL_IN_MONO|AUDIO_CHANNEL_IN_STEREO
    formats AUDIO_FORMAT_PCM_16_BIT
    devices AUDIO_DEVICE_IN_BLUETOOTH_A2DP
    }
    }
    }
    #justin: <=====

    }


    The current problem,my routing path (mm_bt_mic_input_TLV320AIC3X) is not establish from what I have code tracing.
    And I doubt tinyalsa_hal.c has no idea that Bluetooth turns on, and not goes (mm_bt_mic_input_TLV320AIC3X).
    [tinyalsa_hal.c]
    static void select_input_device(struct imx_audio_device *adev)
    {
    int i;
    int headset_on = 0;
    int main_mic_on = 0;
    int sub_mic_on = 0;
    int bt_on = adev->in_device & AUDIO_DEVICE_IN_ALL_SCO;

    if (!bt_on) {
    if ((adev->mode != AUDIO_MODE_IN_CALL) && (adev->active_input != 0)) {
    /* sub mic is used for camcorder or VoIP on speaker phone */
    sub_mic_on = (adev->active_input->source == AUDIO_SOURCE_CAMCORDER) ||
    ((adev->out_device & AUDIO_DEVICE_OUT_SPEAKER) &&
    (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION));
    }

    headset_on = adev->in_device & AUDIO_DEVICE_IN_WIRED_HEADSET;
    main_mic_on = adev->in_device & AUDIO_DEVICE_IN_BUILTIN_MIC;
    }

    ALOGI("justin: %s: bt_on = %d, headset_on = %d, main_mic_on = %d, sub_mic_on = %d\n",
    __func__, bt_on, headset_on, main_mic_on, sub_mic_on);
    /* TODO: check how capture is possible during voice calls or if
    * both use cases are mutually exclusive.
    */
    if (bt_on)
    {
    ALOGI("justin: %s: bt_on\n", __func__);
    for(i = 0; i < MAX_AUDIO_CARD_NUM; i++)
    set_route_by_array(adev->mixer[i], adev->card_list[i]->mm_bt_mic_input, 1);
    }
    else {
    /* Select front end */
    if (headset_on)
    {
    ALOGI("justin: %s: headset_on\n", __func__);
    for(i = 0; i < MAX_AUDIO_CARD_NUM; i++)
    set_route_by_array(adev->mixer[i], adev->card_list[i]->mm_hs_mic_input, 1);
    }
    else if (main_mic_on || sub_mic_on)
    {
    ALOGI("justin: %s: main_mic_on || sub_mic_on\n", __func__);
    for(i = 0; i < MAX_AUDIO_CARD_NUM; i++)
    set_route_by_array(adev->mixer[i], adev->card_list[i]->mm_main_mic_input, 1);
    }
    else
    {
    ALOGI("justin: %s: ELSE\n", __func__);
    for(i = 0; i < MAX_AUDIO_CARD_NUM; i++)
    set_route_by_array(adev->mixer[i], adev->card_list[i]->mm_main_mic_input, 0);
    }
    }
    }

    Please help. Thank you very much.

    -Justin
  • In reply to Justin Fu:

    Justin,

    I haven't forgotten about you. I will try to set up the secondary I2S this afternoon and get back to you with the results.

    best regards
    -STeve Wilson
  • In reply to Steve-Wilson:

    Hi Steve,

    Thank you for your help. I am expecting your result.

    -Justin