2 * Copyright 2012 Freescale Semiconductor, Inc.
3 * Copyright 2012 Linaro Ltd.
5 * The code contained herein is licensed under the GNU General Public
6 * License. You may obtain a copy of the GNU General Public License
7 * Version 2 or later at the following locations:
9 * http://www.opensource.org/licenses/gpl-license.html
10 * http://www.gnu.org/copyleft/gpl.html
13 #include <linux/module.h>
15 #include <linux/of_platform.h>
16 #include <sound/soc.h>
18 #include "../codecs/sgtl5000.h"
19 #include "imx-audmux.h"
21 #define DAI_NAME_SIZE 32
23 struct imx_sgtl5000_data
{
24 struct snd_soc_dai_link dai
;
25 struct snd_soc_card card
;
26 char codec_dai_name
[DAI_NAME_SIZE
];
27 char platform_name
[DAI_NAME_SIZE
];
28 unsigned int clk_frequency
;
31 static int imx_sgtl5000_dai_init(struct snd_soc_pcm_runtime
*rtd
)
33 struct imx_sgtl5000_data
*data
= container_of(rtd
->card
,
34 struct imx_sgtl5000_data
, card
);
35 struct device
*dev
= rtd
->card
->dev
;
38 ret
= snd_soc_dai_set_sysclk(rtd
->codec_dai
, SGTL5000_SYSCLK
,
39 data
->clk_frequency
, SND_SOC_CLOCK_IN
);
41 dev_err(dev
, "could not set codec driver clock params\n");
48 static int __devinit
imx_sgtl5000_probe(struct platform_device
*pdev
)
50 struct device_node
*np
= pdev
->dev
.of_node
;
51 struct device_node
*ssi_np
, *codec_np
;
52 struct platform_device
*ssi_pdev
;
53 struct imx_sgtl5000_data
*data
;
54 int int_port
, ext_port
;
57 ret
= of_property_read_u32(np
, "mux-int-port", &int_port
);
59 dev_err(&pdev
->dev
, "mux-int-port missing or invalid\n");
62 ret
= of_property_read_u32(np
, "mux-ext-port", &ext_port
);
64 dev_err(&pdev
->dev
, "mux-ext-port missing or invalid\n");
69 * The port numbering in the hardware manual starts at 1, while
70 * the audmux API expects it starts at 0.
74 ret
= imx_audmux_v2_configure_port(int_port
,
75 IMX_AUDMUX_V2_PTCR_SYN
|
76 IMX_AUDMUX_V2_PTCR_TFSEL(ext_port
) |
77 IMX_AUDMUX_V2_PTCR_TCSEL(ext_port
) |
78 IMX_AUDMUX_V2_PTCR_TFSDIR
|
79 IMX_AUDMUX_V2_PTCR_TCLKDIR
,
80 IMX_AUDMUX_V2_PDCR_RXDSEL(ext_port
));
82 dev_err(&pdev
->dev
, "audmux internal port setup failed\n");
85 imx_audmux_v2_configure_port(ext_port
,
86 IMX_AUDMUX_V2_PTCR_SYN
|
87 IMX_AUDMUX_V2_PTCR_TCSEL(int_port
),
88 IMX_AUDMUX_V2_PDCR_RXDSEL(int_port
));
90 dev_err(&pdev
->dev
, "audmux external port setup failed\n");
94 ssi_np
= of_parse_phandle(pdev
->dev
.of_node
, "ssi-controller", 0);
95 codec_np
= of_parse_phandle(pdev
->dev
.of_node
, "audio-codec", 0);
96 if (!ssi_np
|| !codec_np
) {
97 dev_err(&pdev
->dev
, "phandle missing or invalid\n");
101 ssi_pdev
= of_find_device_by_node(ssi_np
);
103 dev_err(&pdev
->dev
, "failed to find SSI platform device\n");
107 data
= devm_kzalloc(&pdev
->dev
, sizeof(*data
), GFP_KERNEL
);
111 ret
= of_property_read_u32(codec_np
, "clock-frequency",
112 &data
->clk_frequency
);
114 dev_err(&pdev
->dev
, "clock-frequency missing or invalid\n");
118 data
->dai
.name
= "HiFi";
119 data
->dai
.stream_name
= "HiFi";
120 data
->dai
.codec_dai_name
= "sgtl5000";
121 data
->dai
.codec_of_node
= codec_np
;
122 data
->dai
.cpu_dai_name
= dev_name(&ssi_pdev
->dev
);
123 data
->dai
.platform_name
= "imx-pcm-audio";
124 data
->dai
.init
= &imx_sgtl5000_dai_init
;
125 data
->dai
.dai_fmt
= SND_SOC_DAIFMT_I2S
| SND_SOC_DAIFMT_NB_NF
|
126 SND_SOC_DAIFMT_CBM_CFM
;
128 data
->card
.dev
= &pdev
->dev
;
129 ret
= snd_soc_of_parse_card_name(&data
->card
, "model");
132 data
->card
.num_links
= 1;
133 data
->card
.dai_link
= &data
->dai
;
135 ret
= snd_soc_register_card(&data
->card
);
137 dev_err(&pdev
->dev
, "snd_soc_register_card failed (%d)\n", ret
);
141 platform_set_drvdata(pdev
, data
);
143 of_node_put(codec_np
);
148 static int __devexit
imx_sgtl5000_remove(struct platform_device
*pdev
)
150 struct imx_sgtl5000_data
*data
= platform_get_drvdata(pdev
);
152 snd_soc_unregister_card(&data
->card
);
157 static const struct of_device_id imx_sgtl5000_dt_ids
[] = {
158 { .compatible
= "fsl,imx-audio-sgtl5000", },
161 MODULE_DEVICE_TABLE(of
, imx_sgtl5000_dt_ids
);
163 static struct platform_driver imx_sgtl5000_driver
= {
165 .name
= "imx-sgtl5000",
166 .owner
= THIS_MODULE
,
167 .of_match_table
= imx_sgtl5000_dt_ids
,
169 .probe
= imx_sgtl5000_probe
,
170 .remove
= __devexit_p(imx_sgtl5000_remove
),
172 module_platform_driver(imx_sgtl5000_driver
);
174 MODULE_AUTHOR("Shawn Guo <shawn.guo@linaro.org>");
175 MODULE_DESCRIPTION("Freescale i.MX SGTL5000 ASoC machine driver");
176 MODULE_LICENSE("GPL v2");
177 MODULE_ALIAS("platform:imx-sgtl5000");