aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/fsl
diff options
context:
space:
mode:
authorShawn Guo <shawn.guo@linaro.org>2012-03-16 04:56:44 -0400
committerMark Brown <broonie@opensource.wolfsonmicro.com>2012-04-01 06:28:27 -0400
commitc448303e86c970cca4833bd9480c08f09b948b40 (patch)
treecfa6b74ffad848b97d8d19be6a04bd279bcb5591 /sound/soc/fsl
parent09ce1111f3893106463559ed62f27fe999ace5d6 (diff)
ASoC: fsl: add imx-sgtl5000 machine driver
This is the initial imx-sgtl5000 machine driver support with only playback dai link implemented. More features can be added on top of it later. It's a device tree only machine driver working with fsl_ssi driver. Signed-off-by: Shawn Guo <shawn.guo@linaro.org> Acked-by: Sascha Hauer <s.hauer@pengutronix.de> Acked-by: Timur Tabi <timur@freescale.com> Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Diffstat (limited to 'sound/soc/fsl')
-rw-r--r--sound/soc/fsl/Kconfig12
-rw-r--r--sound/soc/fsl/Makefile2
-rw-r--r--sound/soc/fsl/imx-sgtl5000.c177
3 files changed, 191 insertions, 0 deletions
diff --git a/sound/soc/fsl/Kconfig b/sound/soc/fsl/Kconfig
index 535ee73ecf15..aa14fc9744cc 100644
--- a/sound/soc/fsl/Kconfig
+++ b/sound/soc/fsl/Kconfig
@@ -164,4 +164,16 @@ config SND_SOC_EUKREA_TLV320
164 Enable I2S based access to the TLV320AIC23B codec attached 164 Enable I2S based access to the TLV320AIC23B codec attached
165 to the SSI interface 165 to the SSI interface
166 166
167config SND_SOC_IMX_SGTL5000
168 tristate "SoC Audio support for i.MX boards with sgtl5000"
169 depends on OF && I2C
170 select SND_SOC_SGTL5000
171 select SND_SOC_IMX_PCM_DMA
172 select SND_SOC_IMX_AUDMUX
173 select SND_SOC_FSL_SSI
174 select SND_SOC_FSL_UTILS
175 help
176 Say Y if you want to add support for SoC audio on an i.MX board with
177 a sgtl5000 codec.
178
167endif # SND_IMX_SOC 179endif # SND_IMX_SOC
diff --git a/sound/soc/fsl/Makefile b/sound/soc/fsl/Makefile
index fbdbed0af909..638d3852601a 100644
--- a/sound/soc/fsl/Makefile
+++ b/sound/soc/fsl/Makefile
@@ -40,8 +40,10 @@ snd-soc-eukrea-tlv320-objs := eukrea-tlv320.o
40snd-soc-phycore-ac97-objs := phycore-ac97.o 40snd-soc-phycore-ac97-objs := phycore-ac97.o
41snd-soc-mx27vis-aic32x4-objs := mx27vis-aic32x4.o 41snd-soc-mx27vis-aic32x4-objs := mx27vis-aic32x4.o
42snd-soc-wm1133-ev1-objs := wm1133-ev1.o 42snd-soc-wm1133-ev1-objs := wm1133-ev1.o
43snd-soc-imx-sgtl5000-objs := imx-sgtl5000.o
43 44
44obj-$(CONFIG_SND_SOC_EUKREA_TLV320) += snd-soc-eukrea-tlv320.o 45obj-$(CONFIG_SND_SOC_EUKREA_TLV320) += snd-soc-eukrea-tlv320.o
45obj-$(CONFIG_SND_SOC_PHYCORE_AC97) += snd-soc-phycore-ac97.o 46obj-$(CONFIG_SND_SOC_PHYCORE_AC97) += snd-soc-phycore-ac97.o
46obj-$(CONFIG_SND_SOC_MX27VIS_AIC32X4) += snd-soc-mx27vis-aic32x4.o 47obj-$(CONFIG_SND_SOC_MX27VIS_AIC32X4) += snd-soc-mx27vis-aic32x4.o
47obj-$(CONFIG_SND_MXC_SOC_WM1133_EV1) += snd-soc-wm1133-ev1.o 48obj-$(CONFIG_SND_MXC_SOC_WM1133_EV1) += snd-soc-wm1133-ev1.o
49obj-$(CONFIG_SND_SOC_IMX_SGTL5000) += snd-soc-imx-sgtl5000.o
diff --git a/sound/soc/fsl/imx-sgtl5000.c b/sound/soc/fsl/imx-sgtl5000.c
new file mode 100644
index 000000000000..3786b61b4fea
--- /dev/null
+++ b/sound/soc/fsl/imx-sgtl5000.c
@@ -0,0 +1,177 @@
1/*
2 * Copyright 2012 Freescale Semiconductor, Inc.
3 * Copyright 2012 Linaro Ltd.
4 *
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:
8 *
9 * http://www.opensource.org/licenses/gpl-license.html
10 * http://www.gnu.org/copyleft/gpl.html
11 */
12
13#include <linux/module.h>
14#include <linux/of.h>
15#include <linux/of_platform.h>
16#include <sound/soc.h>
17
18#include "../codecs/sgtl5000.h"
19#include "imx-audmux.h"
20
21#define DAI_NAME_SIZE 32
22
23struct 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;
29};
30
31static int imx_sgtl5000_dai_init(struct snd_soc_pcm_runtime *rtd)
32{
33 struct imx_sgtl5000_data *data = container_of(rtd->card,
34 struct imx_sgtl5000_data, card);
35 struct device *dev = rtd->card->dev;
36 int ret;
37
38 ret = snd_soc_dai_set_sysclk(rtd->codec_dai, SGTL5000_SYSCLK,
39 data->clk_frequency, SND_SOC_CLOCK_IN);
40 if (ret) {
41 dev_err(dev, "could not set codec driver clock params\n");
42 return ret;
43 }
44
45 return 0;
46}
47
48static int __devinit imx_sgtl5000_probe(struct platform_device *pdev)
49{
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;
55 int ret;
56
57 ret = of_property_read_u32(np, "mux-int-port", &int_port);
58 if (ret) {
59 dev_err(&pdev->dev, "mux-int-port missing or invalid\n");
60 return ret;
61 }
62 ret = of_property_read_u32(np, "mux-ext-port", &ext_port);
63 if (ret) {
64 dev_err(&pdev->dev, "mux-ext-port missing or invalid\n");
65 return ret;
66 }
67
68 /*
69 * The port numbering in the hardware manual starts at 1, while
70 * the audmux API expects it starts at 0.
71 */
72 int_port--;
73 ext_port--;
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));
81 if (ret) {
82 dev_err(&pdev->dev, "audmux internal port setup failed\n");
83 return ret;
84 }
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));
89 if (ret) {
90 dev_err(&pdev->dev, "audmux external port setup failed\n");
91 return ret;
92 }
93
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");
98 return -EINVAL;
99 }
100
101 ssi_pdev = of_find_device_by_node(ssi_np);
102 if (!ssi_pdev) {
103 dev_err(&pdev->dev, "failed to find SSI platform device\n");
104 return -EINVAL;
105 }
106
107 data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
108 if (!data)
109 return -ENOMEM;
110
111 ret = of_property_read_u32(codec_np, "clock-frequency",
112 &data->clk_frequency);
113 if (ret) {
114 dev_err(&pdev->dev, "clock-frequency missing or invalid\n");
115 return ret;
116 }
117
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;
127
128 data->card.dev = &pdev->dev;
129 ret = snd_soc_of_parse_card_name(&data->card, "model");
130 if (ret)
131 return ret;
132 data->card.num_links = 1;
133 data->card.dai_link = &data->dai;
134
135 ret = snd_soc_register_card(&data->card);
136 if (ret) {
137 dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n", ret);
138 return ret;
139 }
140
141 platform_set_drvdata(pdev, data);
142 of_node_put(ssi_np);
143 of_node_put(codec_np);
144
145 return 0;
146}
147
148static int __devexit imx_sgtl5000_remove(struct platform_device *pdev)
149{
150 struct imx_sgtl5000_data *data = platform_get_drvdata(pdev);
151
152 snd_soc_unregister_card(&data->card);
153
154 return 0;
155}
156
157static const struct of_device_id imx_sgtl5000_dt_ids[] = {
158 { .compatible = "fsl,imx-audio-sgtl5000", },
159 { /* sentinel */ }
160};
161MODULE_DEVICE_TABLE(of, imx_sgtl5000_dt_ids);
162
163static struct platform_driver imx_sgtl5000_driver = {
164 .driver = {
165 .name = "imx-sgtl5000",
166 .owner = THIS_MODULE,
167 .of_match_table = imx_sgtl5000_dt_ids,
168 },
169 .probe = imx_sgtl5000_probe,
170 .remove = __devexit_p(imx_sgtl5000_remove),
171};
172module_platform_driver(imx_sgtl5000_driver);
173
174MODULE_AUTHOR("Shawn Guo <shawn.guo@linaro.org>");
175MODULE_DESCRIPTION("Freescale i.MX SGTL5000 ASoC machine driver");
176MODULE_LICENSE("GPL v2");
177MODULE_ALIAS("platform:imx-sgtl5000");