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
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
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.
Hi,Alexander.
So,I just change my kernel like you and insmod imx-sgtl5000.c,my tlv320aic23b will woork?
Thanks!
Chen
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:
already in the Linux kernel, selected by "select SND_SOC_TLV320AIC23" in sound/soc/imx/Kconfig
already in the Linux kernel, selected by "select SND_MXC_SOC_MX2" in sound/soc/imx/Kconfig
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
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
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
cko2 200
and clock set 24 MHz in startup code
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";
+};
....
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
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.
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
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