aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/codecs/ad1980.c
diff options
context:
space:
mode:
authorLiam Girdwood <lrg@slimlogic.co.uk>2010-03-17 16:15:21 -0400
committerLiam Girdwood <lrg@slimlogic.co.uk>2010-08-12 09:00:00 -0400
commitf0fba2ad1b6b53d5360125c41953b7afcd6deff0 (patch)
treef6ad50905f8daa616593c978d7ae992e73241180 /sound/soc/codecs/ad1980.c
parentbda7d2a862e6b788bca2d02d38a07966a9c92e48 (diff)
ASoC: multi-component - ASoC Multi-Component Support
This patch extends the ASoC API to allow sound cards to have more than one CODEC and more than one platform DMA controller. This is achieved by dividing some current ASoC structures that contain both driver data and device data into structures that only either contain device data or driver data. i.e. struct snd_soc_codec ---> struct snd_soc_codec (device data) +-> struct snd_soc_codec_driver (driver data) struct snd_soc_platform ---> struct snd_soc_platform (device data) +-> struct snd_soc_platform_driver (driver data) struct snd_soc_dai ---> struct snd_soc_dai (device data) +-> struct snd_soc_dai_driver (driver data) struct snd_soc_device ---> deleted This now allows ASoC to be more tightly aligned with the Linux driver model and also means that every ASoC codec, platform and (platform) DAI is a kernel device. ASoC component private data is now stored as device private data. The ASoC sound card struct snd_soc_card has also been updated to store lists of it's components rather than a pointer to a codec and platform. The PCM runtime struct soc_pcm_runtime now has pointers to all its components. This patch adds DAPM support for ASoC multi-component and removes struct snd_soc_socdev from DAPM core. All DAPM calls are now made on a card, codec or runtime PCM level basis rather than using snd_soc_socdev. Other notable multi-component changes:- * Stream operations now de-reference less structures. * close_delayed work() now runs on a DAI basis rather than looping all DAIs in a card. * PM suspend()/resume() operations can now handle N CODECs and Platforms per sound card. * Added soc_bind_dai_link() to bind the component devices to the sound card. * Added soc_dai_link_probe() and soc_dai_link_remove() to probe and remove DAI link components. * sysfs entries can now be registered per component per card. * snd_soc_new_pcms() functionailty rolled into dai_link_probe(). * snd_soc_register_codec() now does all the codec list and mutex init. This patch changes the probe() and remove() of the CODEC drivers as follows:- o Make CODEC driver a platform driver o Moved all struct snd_soc_codec list, mutex, etc initialiasation to core. o Removed all static codec pointers (drivers now support > 1 codec dev) o snd_soc_register_pcms() now done by core. o snd_soc_register_dai() folded into snd_soc_register_codec(). CS4270 portions: Acked-by: Timur Tabi <timur@freescale.com> Some TLV320aic23 and Cirrus platform fixes. Signed-off-by: Ryan Mallon <ryan@bluewatersys.com> TI CODEC and OMAP fixes Signed-off-by: Peter Ujfalusi <peter.ujfalusi@nokia.com> Signed-off-by: Janusz Krzysztofik <jkrzyszt@tis.icnet.pl> Signed-off-by: Jarkko Nikula <jhnikula@gmail.com> Samsung platform and misc fixes :- Signed-off-by: Chanwoo Choi <cw00.choi@samsung.com> Signed-off-by: Joonyoung Shim <jy0922.shim@samsung.com> Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com> Reviewed-by: Jassi Brar <jassi.brar@samsung.com> Signed-off-by: Seungwhan Youn <sw.youn@samsung.com> MPC8610 and PPC fixes. Signed-off-by: Timur Tabi <timur@freescale.com> i.MX fixes and some core fixes. Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de> J4740 platform fixes:- Signed-off-by: Lars-Peter Clausen <lars@metafoo.de> CC: Tony Lindgren <tony@atomide.com> CC: Nicolas Ferre <nicolas.ferre@atmel.com> CC: Kevin Hilman <khilman@deeprootsystems.com> CC: Sascha Hauer <s.hauer@pengutronix.de> CC: Atsushi Nemoto <anemo@mba.ocn.ne.jp> CC: Kuninori Morimoto <morimoto.kuninori@renesas.com> CC: Daniel Gloeckner <dg@emlix.com> CC: Manuel Lauss <mano@roarinelk.homelinux.net> CC: Mike Frysinger <vapier.adi@gmail.com> CC: Arnaud Patard <apatard@mandriva.com> CC: Wan ZongShun <mcuos.com@gmail.com> Acked-by: Mark Brown <broonie@opensource.wolfsonmicro.com> Signed-off-by: Liam Girdwood <lrg@slimlogic.co.uk>
Diffstat (limited to 'sound/soc/codecs/ad1980.c')
-rw-r--r--sound/soc/codecs/ad1980.c107
1 files changed, 46 insertions, 61 deletions
diff --git a/sound/soc/codecs/ad1980.c b/sound/soc/codecs/ad1980.c
index 042072738cd..1371afac657 100644
--- a/sound/soc/codecs/ad1980.c
+++ b/sound/soc/codecs/ad1980.c
@@ -130,8 +130,8 @@ static int ac97_write(struct snd_soc_codec *codec, unsigned int reg,
130 return 0; 130 return 0;
131} 131}
132 132
133struct snd_soc_dai ad1980_dai = { 133struct snd_soc_dai_driver ad1980_dai = {
134 .name = "AC97", 134 .name = "ad1980-hifi",
135 .ac97_control = 1, 135 .ac97_control = 1,
136 .playback = { 136 .playback = {
137 .stream_name = "Playback", 137 .stream_name = "Playback",
@@ -177,53 +177,20 @@ err:
177 return -EIO; 177 return -EIO;
178} 178}
179 179
180static int ad1980_soc_probe(struct platform_device *pdev) 180static int ad1980_soc_probe(struct snd_soc_codec *codec)
181{ 181{
182 struct snd_soc_device *socdev = platform_get_drvdata(pdev); 182 int ret;
183 struct snd_soc_codec *codec;
184 int ret = 0;
185 u16 vendor_id2; 183 u16 vendor_id2;
186 u16 ext_status; 184 u16 ext_status;
187 185
188 printk(KERN_INFO "AD1980 SoC Audio Codec\n"); 186 printk(KERN_INFO "AD1980 SoC Audio Codec\n");
189 187
190 socdev->card->codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL);
191 if (socdev->card->codec == NULL)
192 return -ENOMEM;
193 codec = socdev->card->codec;
194 mutex_init(&codec->mutex);
195
196 codec->reg_cache =
197 kzalloc(sizeof(u16) * ARRAY_SIZE(ad1980_reg), GFP_KERNEL);
198 if (codec->reg_cache == NULL) {
199 ret = -ENOMEM;
200 goto cache_err;
201 }
202 memcpy(codec->reg_cache, ad1980_reg, sizeof(u16) * \
203 ARRAY_SIZE(ad1980_reg));
204 codec->reg_cache_size = sizeof(u16) * ARRAY_SIZE(ad1980_reg);
205 codec->reg_cache_step = 2;
206 codec->name = "AD1980";
207 codec->owner = THIS_MODULE;
208 codec->dai = &ad1980_dai;
209 codec->num_dai = 1;
210 codec->write = ac97_write;
211 codec->read = ac97_read;
212 INIT_LIST_HEAD(&codec->dapm_widgets);
213 INIT_LIST_HEAD(&codec->dapm_paths);
214
215 ret = snd_soc_new_ac97_codec(codec, &soc_ac97_ops, 0); 188 ret = snd_soc_new_ac97_codec(codec, &soc_ac97_ops, 0);
216 if (ret < 0) { 189 if (ret < 0) {
217 printk(KERN_ERR "ad1980: failed to register AC97 codec\n"); 190 printk(KERN_ERR "ad1980: failed to register AC97 codec\n");
218 goto codec_err; 191 return ret;
219 } 192 }
220 193
221 /* register pcms */
222 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
223 if (ret < 0)
224 goto pcm_err;
225
226
227 ret = ad1980_reset(codec, 0); 194 ret = ad1980_reset(codec, 0);
228 if (ret < 0) { 195 if (ret < 0) {
229 printk(KERN_ERR "Failed to reset AD1980: AC97 link error\n"); 196 printk(KERN_ERR "Failed to reset AD1980: AC97 link error\n");
@@ -262,41 +229,59 @@ static int ad1980_soc_probe(struct platform_device *pdev)
262 return 0; 229 return 0;
263 230
264reset_err: 231reset_err:
265 snd_soc_free_pcms(socdev);
266
267pcm_err:
268 snd_soc_free_ac97_codec(codec); 232 snd_soc_free_ac97_codec(codec);
269
270codec_err:
271 kfree(codec->reg_cache);
272
273cache_err:
274 kfree(socdev->card->codec);
275 socdev->card->codec = NULL;
276 return ret; 233 return ret;
277} 234}
278 235
279static int ad1980_soc_remove(struct platform_device *pdev) 236static int ad1980_soc_remove(struct snd_soc_codec *codec)
280{ 237{
281 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
282 struct snd_soc_codec *codec = socdev->card->codec;
283
284 if (codec == NULL)
285 return 0;
286
287 snd_soc_dapm_free(socdev);
288 snd_soc_free_pcms(socdev);
289 snd_soc_free_ac97_codec(codec); 238 snd_soc_free_ac97_codec(codec);
290 kfree(codec->reg_cache);
291 kfree(codec);
292 return 0; 239 return 0;
293} 240}
294 241
295struct snd_soc_codec_device soc_codec_dev_ad1980 = { 242static struct snd_soc_codec_driver soc_codec_dev_ad1980 = {
296 .probe = ad1980_soc_probe, 243 .probe = ad1980_soc_probe,
297 .remove = ad1980_soc_remove, 244 .remove = ad1980_soc_remove,
245 .reg_cache_size = ARRAY_SIZE(ad1980_reg),
246 .reg_word_size = sizeof(u16),
247 .reg_cache_step = 2,
248 .write = ac97_write,
249 .read = ac97_read,
298}; 250};
299EXPORT_SYMBOL_GPL(soc_codec_dev_ad1980); 251
252static __devinit int ad1980_probe(struct platform_device *pdev)
253{
254 return snd_soc_register_codec(&pdev->dev,
255 &soc_codec_dev_ad1980, &ad1980_dai, 1);
256}
257
258static int __devexit ad1980_remove(struct platform_device *pdev)
259{
260 snd_soc_unregister_codec(&pdev->dev);
261 return 0;
262}
263
264static struct platform_driver ad1980_codec_driver = {
265 .driver = {
266 .name = "ad1980-codec",
267 .owner = THIS_MODULE,
268 },
269
270 .probe = ad1980_probe,
271 .remove = __devexit_p(ad1980_remove),
272};
273
274static int __init ad1980_init(void)
275{
276 return platform_driver_register(&ad1980_codec_driver);
277}
278module_init(ad1980_init);
279
280static void __exit ad1980_exit(void)
281{
282 platform_driver_unregister(&ad1980_codec_driver);
283}
284module_exit(ad1980_exit);
300 285
301MODULE_DESCRIPTION("ASoC ad1980 driver"); 286MODULE_DESCRIPTION("ASoC ad1980 driver");
302MODULE_AUTHOR("Roy Huang, Cliff Cai"); 287MODULE_AUTHOR("Roy Huang, Cliff Cai");