How to enable TLV320 on IMX6Q?

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

How to enable TLV320 on IMX6Q?

13,282 Views
ct3paul
Contributor II

Hi everybody! I want use audio chip TLV320AIC23BPW.My CPU is IMX6Q.How can i do?

Labels (1)
Tags (2)
0 Kudos
Reply
11 Replies

4,552 Views
Sasamy
Contributor IV

Hi

We use i.mx6q sabrelite board as an example, main changes in Linux kernel (rel_imx_3.0.35_4.1.0):

arch/arm/mach-mx6board-mx6q_sabrelite.c

static iomux_v3_cfg_t mx6q_sabrelite_pads[] = {

....

        /* AUDMUX */

        MX6Q_PAD_KEY_COL1__AUDMUX_AUD5_TXFS,

        MX6Q_PAD_KEY_ROW0__AUDMUX_AUD5_TXD,

        MX6Q_PAD_KEY_ROW1__AUDMUX_AUD5_RXD,

        MX6Q_PAD_KEY_COL0__AUDMUX_AUD5_TXC,

        MX6Q_PAD_NANDF_CS2__CCM_CLKO2,          /* --> TLV320AIC23B MCLK */

        /* I2C1, TLV320AIC23B */

        MX6Q_PAD_CSI0_DAT8__I2C1_SDA,

        MX6Q_PAD_CSI0_DAT9__I2C1_SCL,

....

}

....

static struct mxc_audio_platform_data mx6_sabrelite_audio_data;

static int mx6_sabrelite_sgtl5000_init(void)

{    

        struct clk *clko2;

        struct clk *new_parent;

        int rate;

        clko2 = clk_get(NULL, "clko2_clk");

        if (IS_ERR(clko2)) {

                pr_err("can't get CLKO2 clock.\n");

                return PTR_ERR(clko2);

        }

        new_parent = clk_get(NULL, "osc_clk");

        if (!IS_ERR(new_parent)) {

                clk_set_parent(clko2, new_parent);

                clk_put(new_parent);

        }

        /* MCLK = 12 MHz */

        rate = clk_round_rate(clko2, 12000000);

        mx6_sabrelite_audio_data.sysclk = rate;

        clk_set_rate(clko2, rate);

        clk_enable(clko2);

        return 0;

}

static struct imx_ssi_platform_data mx6_sabrelite_ssi_pdata = {

        .flags = IMX_SSI_DMA | IMX_SSI_SYN,

};

static struct imx_ssi_platform_data mx6_sabrelite_ssi_pdata = {

        .flags = IMX_SSI_DMA | IMX_SSI_SYN,

};

static struct mxc_audio_platform_data mx6_sabrelite_audio_data = {

        .ssi_num = 1,

        .src_port = 2,

        .ext_port = 5,

        .init = mx6_sabrelite_sgtl5000_init,

        .hp_gpio = -1,

};

static struct platform_device mx6_sabrelite_audio_device = {

        .name = "imx-sgtl5000",

};

static struct i2c_board_info mxc_i2c0_board_info[] __initdata = {

        {

                I2C_BOARD_INFO("tlv320aic23", 0x1a),

        },

};

------------------------------------------------------------------------

sound/soc/imx/Kconfig

config SND_SOC_IMX_SGTL5000

        tristate "SoC Audio support for i.MX boards with sgtl5000"

        depends on I2C && (MACH_MX35_3DS || MACH_MX51_BABBAGE \

                        || MACH_MX6Q_SABRELITE || MACH_MX6Q_ARM2)

        select SND_SOC_TLV320AIC23

        select SND_MXC_SOC_MX2

        help

          Say Y if you want to add support for SoC audio on an i.MX board with

          a sgtl5000 codec.

------------------------------------------------------------------------

sound/soc/imx/imx-sgtl5000.c

see attachment for machine layer code

------------------------------------------------------------------------

connection of the codec:

i.mx6q  <-->  tlv320aic23b(pin)

AUD5_TXFS    LRCIN(5), LRCOUT(7)

AUD5_TXD    DIN(4)

AUD5_RXD    DOUT(6)

AUD5_TXC    BCLK(3)

CCM_CLKO2    XTI(25)

I2C1_SDA    SDIN(23)

I2C1_SCL    SCLK(24)

Alexander

4,552 Views
ct3paul
Contributor II

Hi,Alexander.Thank you very much!

But my problem is I don't have audio chip SGTL5000.I just use TLV320AIC23BPW. And my English is poor because I from China.I feel sorry.

I want to know can my TLV320AIC23BPW  work well if I do like your say?


Thanks!

Chen

0 Kudos
Reply

4,552 Views
Sasamy
Contributor IV

Hi  tao chen

We very small company and doesn't do big changes in a kernel - simply replacement of a reference code, my example - sgtl5000 replacement by other codec - tlv320aic23b in our board, it works.

http://www.starterkit.ru/html/images/products/sk_imx6q.png

0 Kudos
Reply

4,552 Views
ct3paul
Contributor II

Hi,Alexander.

So,I just change my kernel like you and insmod imx-sgtl5000.c,my tlv320aic23b will woork?


Thanks!

Chen

0 Kudos
Reply

4,552 Views
Sasamy
Contributor IV

Hi Chen,

please see the introduction of ASoC http://www.alsa-project.org/main/index.php/ASoC

To achieve all this, ASoC basically splits an embedded audio system into 3 components:

  • Codec driver: The codec driver is platform independent and contains audio controls, audio interface capabilities, codec dapm definition and codec IO functions.

already in the Linux kernel, selected by "select SND_SOC_TLV320AIC23" in sound/soc/imx/Kconfig

http://git.freescale.com/git/cgit.cgi/imx/linux-2.6-imx.git/tree/sound/soc/codecs/tlv320aic23.c?h=im...

  • Platform driver: The platform driver contains the audio dma engine and audio interface drivers (e.g. I2S, AC97, PCM) for that platform.

already in the Linux kernel, selected by "select SND_MXC_SOC_MX2" in sound/soc/imx/Kconfig

  • Machine driver: The machine driver handles any machine specific controls and audio events. i.e. turing on an amp at start of playback.

finally, we need a small portion of the initialization (arch/arm/mach-mx6/board-mx6q_xxx.c) and the "glue" (sound/soc/imx/imx-xxx.c), I gave an example of how we did it

Alexander

0 Kudos
Reply

4,552 Views
ct3paul
Contributor II

Hi,Alexander.


Thank you very much!My board can find audio device now.And I can hear voice when I aplay audio file.Now,the audio has a little BUG and I will solve it.Thank for your answer!


Thanks!

Chen

0 Kudos
Reply

4,552 Views
Sasamy
Contributor IV

Update for kernel 3.10.xx

in attachment ready to use machine layer driver

example description in device tree

+    sound {

+        compatible = "fsl,imx-audio-tlv320";

+        model = "imx-tlv320";

+        ssi-controller = <&ssi2>;

+        audio-codec = <&codec>;

+        audio-routing =

+            "MICIN", "Mic Jack",

+            "Headphone Jack", "LHPOUT",

+            "Headphone Jack", "RHPOUT";

+        mux-int-port = <2>;

+        mux-ext-port = <5>;

+    };

    sound-hdmi {

        compatible = "fsl,imx6q-audio-hdmi",

                 "fsl,imx-audio-hdmi";

....

+&audmux {

+    status = "okay";

+    pinctrl-names = "default";

+    pinctrl-0 = <&pinctrl_audmux_sk>;

+};

&i2c1 {

    status = "okay";

    clock-frequency = <100000>;

    pinctrl-names = "default";

    pinctrl-0 = <&pinctrl_i2c1_sk>;

+    codec: tlv320aic23@1a {

+        compatible = "ti,tlv320aic23";

+        reg = <0x1a>;

+        clocks = <&clks 200>;

+        clock-frequency = <12000000>;

+    };

about clock

+        clocks = <&clks 200>;

according to the documentation

http://git.freescale.com/git/cgit.cgi/imx/linux-2.6-imx.git/tree/Documentation/devicetree/bindings/c...

cko2              200

and clock set 24 MHz in startup code

http://git.freescale.com/git/cgit.cgi/imx/linux-2.6-imx.git/tree/arch/arm/mach-imx/clk-imx6q.c?h=imx...

it allows you to set 12 MHz without additional code, just describe the value, the driver switches the frequency

+        clock-frequency = <12000000>;

....

&iomuxc {

    pinctrl-names = "default";

    pinctrl-0 = <&pinctrl_hog>;

    hog {

        pinctrl_hog: hoggrp {

            fsl,pins = <

                /* SD1_DET */

                MX6QDL_PAD_SD4_DAT1__GPIO2_IO09             0x80000000

+                /* AUDIO_MCLK */

+                MX6QDL_PAD_NANDF_CS2__CCM_CLKO2             0x80000000             

....

+    audmux {

+        pinctrl_audmux_sk: audmux-sk {

+            fsl,pins = <

+                MX6QDL_PAD_KEY_COL0__AUD5_TXC               0x130b0

+                MX6QDL_PAD_KEY_ROW0__AUD5_TXD               0x130b0

+                MX6QDL_PAD_KEY_COL1__AUD5_TXFS              0x130b0

+                MX6QDL_PAD_KEY_ROW1__AUD5_RXD               0x130b0

+            >;

+        };

+    };

....

+&ssi2 {

+    fsl,mode = "i2s-slave";

+    status = "okay";

+};

....

0 Kudos
Reply

4,552 Views
anilghadiya
Contributor II

Hi Alexander,

I want to insert the adau1701 codec driver and machine driver for the same as dynamic modules(.ko). So, i took the adau1701.c/h and sigmadsp.c/h and built the module.Then i took the machine driver for sgtl5000 codec and modified for adau1701 and i am able to build it. But when i insert both the modules, none of the drivers probe is getting called.

Attached is the machine driver and device tree file. I am using imx6qdl-sabrelite board with 3.10.17_1.0.0 SD card image.

Thanks in advance,

Anil Ghadiya

0 Kudos
Reply

4,552 Views
Sasamy
Contributor IV

Hi Anil Ghadiya,

unfortunately I have not worked with this codec, adau1701 codec supports the device tree from version 3.11, you can try to copy it from there

Linux/sound/soc/codecs/adau1701.c - Linux Cross Reference - Free Electrons

You can also check the I2C address (i2cdetect)

http://lxr.free-electrons.com/source/Documentation/devicetree/bindings/sound/adi,adau1701.txt?v=3.11

> The i2c address. Value depends on the state of ADDR0 and ADDR1, as wired in hardware.

Alexander.

0 Kudos
Reply

4,552 Views
anilghadiya
Contributor II

Hi Alexander,

Thanks for your reply.

I have changed the device tree and tried to insert the machine driver but still the probe function is not getting called.

Below is my device tree changes... could you please take a look...

sound {

        /*"fsl,imx6q-sabrelite-adau1701",*/

       compatible = "adi,imx-audio-adau1701";

       model = "imx-adau1701";

       ssi-controller = <&ssi1>;

       audio-codec = <&codec>;

       audio-routing =

                 "MIC_IN", "Mic Jack",

                 "Mic Jack", "Mic Bias",

                 "Headphone Jack", "HP_OUT";

       mux-int-port = <1>;

       mux-ext-port = <4>;

  };

.....

&i2c3 {

        clock-frequency = <100000>;

        pinctrl-names = "default";

        pinctrl-0 = <&pinctrl_i2c3_3>;

        status = "okay";

  codec: adau1701@34 {

                 compatible = "adi,adau1701";

                 reg = <0x34>;

  };

Machine driver contains.....

static const struct of_device_id imx_adau1701_dt_ids[] = {

  { .compatible = "adi,imx-audio-adau1701", },

};

MODULE_DEVICE_TABLE(of, imx_adau1701_dt_ids);

static struct platform_driver imx_adau1701_driver = {

  .driver = {

            .name = "imx-adau1701",

            .owner = THIS_MODULE,

            .of_match_table = imx_adau1701_dt_ids,

       },

  .probe = imx_adau1701_probe,

  .remove = imx_adau1701_remove,

};

module_platform_driver(imx_adau1701_driver);

I am connecting the device(adau1701) via i2c to the iMX6-sabrelite board.

Thanks in advance,

Anil Ghadiya

0 Kudos
Reply

4,552 Views
anilghadiya
Contributor II

Hi Alexander,

I am able to create the device and probe of machine driver is getting invoked now. But probe fails when i try to register the sound card. It giving error because of the cpu_dai_name is not given correctly. Could you help in figuring out the value for the .cpu_dai_name for iMX6-sabrelite board.

Thanks and Regards,

Anil Ghadiya

0 Kudos
Reply