diff options
author | Nicolin Chen <b42378@freescale.com> | 2013-08-28 00:04:46 -0400 |
---|---|---|
committer | Mark Brown <broonie@linaro.org> | 2013-08-29 08:15:26 -0400 |
commit | 2a956ec04b3703809b6cf500dbee450e44f3a70c (patch) | |
tree | 33507aab00af2b415db30533f056973f6b277b57 /sound | |
parent | f61df384282dfd1ca845e73ca8b8a187b87eb38a (diff) |
ASoC: fsl: Add S/PDIF machine driver
This patch implements a device-tree-only machine driver for Freescale
i.MX series Soc. It works with spdif_transmitter/spdif_receiver and
fsl_spdif.c drivers.
Signed-off-by: Nicolin Chen <b42378@freescale.com>
Acked-by: Stephen Warren <swarren@nvidia.com>
Signed-off-by: Mark Brown <broonie@linaro.org>
Diffstat (limited to 'sound')
-rw-r--r-- | sound/soc/fsl/Kconfig | 11 | ||||
-rw-r--r-- | sound/soc/fsl/Makefile | 2 | ||||
-rw-r--r-- | sound/soc/fsl/imx-spdif.c | 148 |
3 files changed, 161 insertions, 0 deletions
diff --git a/sound/soc/fsl/Kconfig b/sound/soc/fsl/Kconfig index cd088cc8c866..a70838034600 100644 --- a/sound/soc/fsl/Kconfig +++ b/sound/soc/fsl/Kconfig | |||
@@ -193,6 +193,17 @@ config SND_SOC_IMX_SGTL5000 | |||
193 | Say Y if you want to add support for SoC audio on an i.MX board with | 193 | Say Y if you want to add support for SoC audio on an i.MX board with |
194 | a sgtl5000 codec. | 194 | a sgtl5000 codec. |
195 | 195 | ||
196 | config SND_SOC_IMX_SPDIF | ||
197 | tristate "SoC Audio support for i.MX boards with S/PDIF" | ||
198 | select SND_SOC_IMX_PCM_DMA | ||
199 | select SND_SOC_FSL_SPDIF | ||
200 | select SND_SOC_FSL_UTILS | ||
201 | select SND_SOC_SPDIF | ||
202 | help | ||
203 | SoC Audio support for i.MX boards with S/PDIF | ||
204 | Say Y if you want to add support for SoC audio on an i.MX board with | ||
205 | a S/DPDIF. | ||
206 | |||
196 | config SND_SOC_IMX_MC13783 | 207 | config SND_SOC_IMX_MC13783 |
197 | tristate "SoC Audio support for I.MX boards with mc13783" | 208 | tristate "SoC Audio support for I.MX boards with mc13783" |
198 | depends on MFD_MC13783 && ARM | 209 | depends on MFD_MC13783 && ARM |
diff --git a/sound/soc/fsl/Makefile b/sound/soc/fsl/Makefile index 4b5970e014dd..e2aaff717f8a 100644 --- a/sound/soc/fsl/Makefile +++ b/sound/soc/fsl/Makefile | |||
@@ -45,6 +45,7 @@ snd-soc-mx27vis-aic32x4-objs := mx27vis-aic32x4.o | |||
45 | snd-soc-wm1133-ev1-objs := wm1133-ev1.o | 45 | snd-soc-wm1133-ev1-objs := wm1133-ev1.o |
46 | snd-soc-imx-sgtl5000-objs := imx-sgtl5000.o | 46 | snd-soc-imx-sgtl5000-objs := imx-sgtl5000.o |
47 | snd-soc-imx-wm8962-objs := imx-wm8962.o | 47 | snd-soc-imx-wm8962-objs := imx-wm8962.o |
48 | snd-soc-imx-spdif-objs :=imx-spdif.o | ||
48 | snd-soc-imx-mc13783-objs := imx-mc13783.o | 49 | snd-soc-imx-mc13783-objs := imx-mc13783.o |
49 | 50 | ||
50 | obj-$(CONFIG_SND_SOC_EUKREA_TLV320) += snd-soc-eukrea-tlv320.o | 51 | obj-$(CONFIG_SND_SOC_EUKREA_TLV320) += snd-soc-eukrea-tlv320.o |
@@ -53,4 +54,5 @@ obj-$(CONFIG_SND_SOC_MX27VIS_AIC32X4) += snd-soc-mx27vis-aic32x4.o | |||
53 | obj-$(CONFIG_SND_MXC_SOC_WM1133_EV1) += snd-soc-wm1133-ev1.o | 54 | obj-$(CONFIG_SND_MXC_SOC_WM1133_EV1) += snd-soc-wm1133-ev1.o |
54 | obj-$(CONFIG_SND_SOC_IMX_SGTL5000) += snd-soc-imx-sgtl5000.o | 55 | obj-$(CONFIG_SND_SOC_IMX_SGTL5000) += snd-soc-imx-sgtl5000.o |
55 | obj-$(CONFIG_SND_SOC_IMX_WM8962) += snd-soc-imx-wm8962.o | 56 | obj-$(CONFIG_SND_SOC_IMX_WM8962) += snd-soc-imx-wm8962.o |
57 | obj-$(CONFIG_SND_SOC_IMX_SPDIF) += snd-soc-imx-spdif.o | ||
56 | obj-$(CONFIG_SND_SOC_IMX_MC13783) += snd-soc-imx-mc13783.o | 58 | obj-$(CONFIG_SND_SOC_IMX_MC13783) += snd-soc-imx-mc13783.o |
diff --git a/sound/soc/fsl/imx-spdif.c b/sound/soc/fsl/imx-spdif.c new file mode 100644 index 000000000000..816013b0ebba --- /dev/null +++ b/sound/soc/fsl/imx-spdif.c | |||
@@ -0,0 +1,148 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2013 Freescale Semiconductor, Inc. | ||
3 | * | ||
4 | * The code contained herein is licensed under the GNU General Public | ||
5 | * License. You may obtain a copy of the GNU General Public License | ||
6 | * Version 2 or later at the following locations: | ||
7 | * | ||
8 | * http://www.opensource.org/licenses/gpl-license.html | ||
9 | * http://www.gnu.org/copyleft/gpl.html | ||
10 | */ | ||
11 | |||
12 | #include <linux/module.h> | ||
13 | #include <linux/of_platform.h> | ||
14 | #include <sound/soc.h> | ||
15 | |||
16 | struct imx_spdif_data { | ||
17 | struct snd_soc_dai_link dai[2]; | ||
18 | struct snd_soc_card card; | ||
19 | struct platform_device *txdev; | ||
20 | struct platform_device *rxdev; | ||
21 | }; | ||
22 | |||
23 | static int imx_spdif_audio_probe(struct platform_device *pdev) | ||
24 | { | ||
25 | struct device_node *spdif_np, *np = pdev->dev.of_node; | ||
26 | struct imx_spdif_data *data; | ||
27 | int ret = 0, num_links = 0; | ||
28 | |||
29 | spdif_np = of_parse_phandle(np, "spdif-controller", 0); | ||
30 | if (!spdif_np) { | ||
31 | dev_err(&pdev->dev, "failed to find spdif-controller\n"); | ||
32 | ret = -EINVAL; | ||
33 | goto end; | ||
34 | } | ||
35 | |||
36 | data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL); | ||
37 | if (!data) { | ||
38 | dev_err(&pdev->dev, "failed to allocate memory\n"); | ||
39 | ret = -ENOMEM; | ||
40 | goto end; | ||
41 | } | ||
42 | |||
43 | if (of_property_read_bool(np, "spdif-out")) { | ||
44 | data->dai[num_links].name = "S/PDIF TX"; | ||
45 | data->dai[num_links].stream_name = "S/PDIF PCM Playback"; | ||
46 | data->dai[num_links].codec_dai_name = "dit-hifi"; | ||
47 | data->dai[num_links].codec_name = "spdif-dit"; | ||
48 | data->dai[num_links].cpu_of_node = spdif_np; | ||
49 | data->dai[num_links].platform_of_node = spdif_np; | ||
50 | num_links++; | ||
51 | |||
52 | data->txdev = platform_device_register_simple("spdif-dit", -1, NULL, 0); | ||
53 | if (IS_ERR(data->txdev)) { | ||
54 | ret = PTR_ERR(data->txdev); | ||
55 | dev_err(&pdev->dev, "register dit failed: %d\n", ret); | ||
56 | goto end; | ||
57 | } | ||
58 | } | ||
59 | |||
60 | if (of_property_read_bool(np, "spdif-in")) { | ||
61 | data->dai[num_links].name = "S/PDIF RX"; | ||
62 | data->dai[num_links].stream_name = "S/PDIF PCM Capture"; | ||
63 | data->dai[num_links].codec_dai_name = "dir-hifi"; | ||
64 | data->dai[num_links].codec_name = "spdif-dir"; | ||
65 | data->dai[num_links].cpu_of_node = spdif_np; | ||
66 | data->dai[num_links].platform_of_node = spdif_np; | ||
67 | num_links++; | ||
68 | |||
69 | data->rxdev = platform_device_register_simple("spdif-dir", -1, NULL, 0); | ||
70 | if (IS_ERR(data->rxdev)) { | ||
71 | ret = PTR_ERR(data->rxdev); | ||
72 | dev_err(&pdev->dev, "register dir failed: %d\n", ret); | ||
73 | goto error_dit; | ||
74 | } | ||
75 | } | ||
76 | |||
77 | if (!num_links) { | ||
78 | dev_err(&pdev->dev, "no enabled S/PDIF DAI link\n"); | ||
79 | goto error_dir; | ||
80 | } | ||
81 | |||
82 | data->card.dev = &pdev->dev; | ||
83 | data->card.num_links = num_links; | ||
84 | data->card.dai_link = data->dai; | ||
85 | |||
86 | ret = snd_soc_of_parse_card_name(&data->card, "model"); | ||
87 | if (ret) | ||
88 | goto error_dir; | ||
89 | |||
90 | ret = snd_soc_register_card(&data->card); | ||
91 | if (ret) { | ||
92 | dev_err(&pdev->dev, "snd_soc_register_card failed: %d\n", ret); | ||
93 | goto error_dir; | ||
94 | } | ||
95 | |||
96 | platform_set_drvdata(pdev, data); | ||
97 | |||
98 | goto end; | ||
99 | |||
100 | error_dir: | ||
101 | if (data->rxdev) | ||
102 | platform_device_unregister(data->rxdev); | ||
103 | error_dit: | ||
104 | if (data->txdev) | ||
105 | platform_device_unregister(data->txdev); | ||
106 | end: | ||
107 | if (spdif_np) | ||
108 | of_node_put(spdif_np); | ||
109 | |||
110 | return ret; | ||
111 | } | ||
112 | |||
113 | static int imx_spdif_audio_remove(struct platform_device *pdev) | ||
114 | { | ||
115 | struct imx_spdif_data *data = platform_get_drvdata(pdev); | ||
116 | |||
117 | if (data->rxdev) | ||
118 | platform_device_unregister(data->rxdev); | ||
119 | if (data->txdev) | ||
120 | platform_device_unregister(data->txdev); | ||
121 | |||
122 | snd_soc_unregister_card(&data->card); | ||
123 | |||
124 | return 0; | ||
125 | } | ||
126 | |||
127 | static const struct of_device_id imx_spdif_dt_ids[] = { | ||
128 | { .compatible = "fsl,imx-audio-spdif", }, | ||
129 | { /* sentinel */ } | ||
130 | }; | ||
131 | MODULE_DEVICE_TABLE(of, imx_spdif_dt_ids); | ||
132 | |||
133 | static struct platform_driver imx_spdif_driver = { | ||
134 | .driver = { | ||
135 | .name = "imx-spdif", | ||
136 | .owner = THIS_MODULE, | ||
137 | .of_match_table = imx_spdif_dt_ids, | ||
138 | }, | ||
139 | .probe = imx_spdif_audio_probe, | ||
140 | .remove = imx_spdif_audio_remove, | ||
141 | }; | ||
142 | |||
143 | module_platform_driver(imx_spdif_driver); | ||
144 | |||
145 | MODULE_AUTHOR("Freescale Semiconductor, Inc."); | ||
146 | MODULE_DESCRIPTION("Freescale i.MX S/PDIF machine driver"); | ||
147 | MODULE_LICENSE("GPL v2"); | ||
148 | MODULE_ALIAS("platform:imx-spdif"); | ||