]>
Commit | Line | Data |
---|---|---|
fff8491c PU |
1 | /* |
2 | * omap-twl4030.c -- SoC audio for TI SoC based boards with twl4030 codec | |
3 | * | |
4 | * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com | |
5 | * All rights reserved. | |
6 | * | |
7 | * Author: Peter Ujfalusi <peter.ujfalusi@ti.com> | |
8 | * | |
9 | * This driver replaces the following machine drivers: | |
10 | * omap3beagle (Author: Steve Sakoman <steve@sakoman.com>) | |
11 | * omap3evm (Author: Anuj Aggarwal <anuj.aggarwal@ti.com>) | |
12 | * overo (Author: Steve Sakoman <steve@sakoman.com>) | |
13 | * igep0020 (Author: Enric Balletbo i Serra <eballetbo@iseebcn.com>) | |
14 | * | |
15 | * This program is free software; you can redistribute it and/or | |
16 | * modify it under the terms of the GNU General Public License | |
17 | * version 2 as published by the Free Software Foundation. | |
18 | * | |
19 | * This program is distributed in the hope that it will be useful, but | |
20 | * WITHOUT ANY WARRANTY; without even the implied warranty of | |
21 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
22 | * General Public License for more details. | |
23 | * | |
24 | * You should have received a copy of the GNU General Public License | |
25 | * along with this program; if not, write to the Free Software | |
26 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA | |
27 | * 02110-1301 USA | |
28 | * | |
29 | */ | |
30 | ||
31 | #include <linux/platform_device.h> | |
32 | #include <linux/platform_data/omap-twl4030.h> | |
33 | #include <linux/module.h> | |
34 | #include <linux/of.h> | |
35 | ||
36 | #include <sound/core.h> | |
37 | #include <sound/pcm.h> | |
38 | #include <sound/soc.h> | |
39 | ||
40 | #include "omap-mcbsp.h" | |
41 | #include "omap-pcm.h" | |
42 | ||
43 | static int omap_twl4030_hw_params(struct snd_pcm_substream *substream, | |
44 | struct snd_pcm_hw_params *params) | |
45 | { | |
46 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | |
47 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | |
48 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | |
49 | struct snd_soc_codec *codec = rtd->codec; | |
50 | struct snd_soc_card *card = codec->card; | |
51 | unsigned int fmt; | |
52 | int ret; | |
53 | ||
54 | switch (params_channels(params)) { | |
55 | case 2: /* Stereo I2S mode */ | |
56 | fmt = SND_SOC_DAIFMT_I2S | | |
57 | SND_SOC_DAIFMT_NB_NF | | |
58 | SND_SOC_DAIFMT_CBM_CFM; | |
59 | break; | |
60 | case 4: /* Four channel TDM mode */ | |
61 | fmt = SND_SOC_DAIFMT_DSP_A | | |
62 | SND_SOC_DAIFMT_IB_NF | | |
63 | SND_SOC_DAIFMT_CBM_CFM; | |
64 | break; | |
65 | default: | |
66 | return -EINVAL; | |
67 | } | |
68 | ||
69 | /* Set codec DAI configuration */ | |
70 | ret = snd_soc_dai_set_fmt(codec_dai, fmt); | |
71 | if (ret < 0) { | |
72 | dev_err(card->dev, "can't set codec DAI configuration\n"); | |
73 | return ret; | |
74 | } | |
75 | ||
76 | /* Set cpu DAI configuration */ | |
77 | ret = snd_soc_dai_set_fmt(cpu_dai, fmt); | |
78 | if (ret < 0) { | |
79 | dev_err(card->dev, "can't set cpu DAI configuration\n"); | |
80 | return ret; | |
81 | } | |
82 | ||
83 | return 0; | |
84 | } | |
85 | ||
86 | static struct snd_soc_ops omap_twl4030_ops = { | |
87 | .hw_params = omap_twl4030_hw_params, | |
88 | }; | |
89 | ||
90 | /* Digital audio interface glue - connects codec <--> CPU */ | |
91 | static struct snd_soc_dai_link omap_twl4030_dai_links[] = { | |
92 | { | |
93 | .name = "TWL4030", | |
94 | .stream_name = "TWL4030", | |
95 | .cpu_dai_name = "omap-mcbsp.2", | |
96 | .codec_dai_name = "twl4030-hifi", | |
97 | .platform_name = "omap-pcm-audio", | |
98 | .codec_name = "twl4030-codec", | |
99 | .ops = &omap_twl4030_ops, | |
100 | }, | |
101 | }; | |
102 | ||
103 | /* Audio machine driver */ | |
104 | static struct snd_soc_card omap_twl4030_card = { | |
105 | .owner = THIS_MODULE, | |
106 | .dai_link = omap_twl4030_dai_links, | |
107 | .num_links = ARRAY_SIZE(omap_twl4030_dai_links), | |
108 | }; | |
109 | ||
7ff60006 | 110 | static int omap_twl4030_probe(struct platform_device *pdev) |
fff8491c PU |
111 | { |
112 | struct omap_tw4030_pdata *pdata = dev_get_platdata(&pdev->dev); | |
113 | struct device_node *node = pdev->dev.of_node; | |
114 | struct snd_soc_card *card = &omap_twl4030_card; | |
115 | int ret = 0; | |
116 | ||
117 | card->dev = &pdev->dev; | |
118 | ||
119 | if (node) { | |
120 | struct device_node *dai_node; | |
121 | ||
122 | if (snd_soc_of_parse_card_name(card, "ti,model")) { | |
123 | dev_err(&pdev->dev, "Card name is not provided\n"); | |
124 | return -ENODEV; | |
125 | } | |
126 | ||
127 | dai_node = of_parse_phandle(node, "ti,mcbsp", 0); | |
128 | if (!dai_node) { | |
129 | dev_err(&pdev->dev, "McBSP node is not provided\n"); | |
130 | return -EINVAL; | |
131 | } | |
132 | omap_twl4030_dai_links[0].cpu_dai_name = NULL; | |
133 | omap_twl4030_dai_links[0].cpu_of_node = dai_node; | |
134 | ||
135 | } else if (pdata) { | |
136 | if (pdata->card_name) { | |
137 | card->name = pdata->card_name; | |
138 | } else { | |
139 | dev_err(&pdev->dev, "Card name is not provided\n"); | |
140 | return -ENODEV; | |
141 | } | |
142 | } else { | |
143 | dev_err(&pdev->dev, "Missing pdata\n"); | |
144 | return -ENODEV; | |
145 | } | |
146 | ||
147 | ret = snd_soc_register_card(card); | |
148 | if (ret) { | |
149 | dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n", | |
150 | ret); | |
151 | return ret; | |
152 | } | |
153 | ||
154 | return 0; | |
155 | } | |
156 | ||
7ff60006 | 157 | static int omap_twl4030_remove(struct platform_device *pdev) |
fff8491c PU |
158 | { |
159 | struct snd_soc_card *card = platform_get_drvdata(pdev); | |
160 | ||
161 | snd_soc_unregister_card(card); | |
162 | ||
163 | return 0; | |
164 | } | |
165 | ||
166 | static const struct of_device_id omap_twl4030_of_match[] = { | |
167 | {.compatible = "ti,omap-twl4030", }, | |
168 | { }, | |
169 | }; | |
170 | MODULE_DEVICE_TABLE(of, omap_twl4030_of_match); | |
171 | ||
172 | static struct platform_driver omap_twl4030_driver = { | |
173 | .driver = { | |
174 | .name = "omap-twl4030", | |
175 | .owner = THIS_MODULE, | |
176 | .pm = &snd_soc_pm_ops, | |
177 | .of_match_table = omap_twl4030_of_match, | |
178 | }, | |
179 | .probe = omap_twl4030_probe, | |
7ff60006 | 180 | .remove = omap_twl4030_remove, |
fff8491c PU |
181 | }; |
182 | ||
183 | module_platform_driver(omap_twl4030_driver); | |
184 | ||
185 | MODULE_AUTHOR("Peter Ujfalusi <peter.ujfalusi@ti.com>"); | |
186 | MODULE_DESCRIPTION("ALSA SoC for TI SoC based boards with twl4030 codec"); | |
187 | MODULE_LICENSE("GPL"); | |
188 | MODULE_ALIAS("platform:omap-twl4030"); |