diff options
Diffstat (limited to 'sound/soc/au1x/psc-i2s.c')
-rw-r--r-- | sound/soc/au1x/psc-i2s.c | 53 |
1 files changed, 15 insertions, 38 deletions
diff --git a/sound/soc/au1x/psc-i2s.c b/sound/soc/au1x/psc-i2s.c index 6083fe7799fa..fca091276320 100644 --- a/sound/soc/au1x/psc-i2s.c +++ b/sound/soc/au1x/psc-i2s.c | |||
@@ -10,9 +10,6 @@ | |||
10 | * | 10 | * |
11 | * Au1xxx-PSC I2S glue. | 11 | * Au1xxx-PSC I2S glue. |
12 | * | 12 | * |
13 | * NOTE: all of these drivers can only work with a SINGLE instance | ||
14 | * of a PSC. Multiple independent audio devices are impossible | ||
15 | * with ASoC v1. | ||
16 | * NOTE: so far only PSC slave mode (bit- and frameclock) is supported. | 13 | * NOTE: so far only PSC slave mode (bit- and frameclock) is supported. |
17 | */ | 14 | */ |
18 | 15 | ||
@@ -54,13 +51,10 @@ | |||
54 | ((stype) == PCM_TX ? PSC_I2SPCR_TC : PSC_I2SPCR_RC) | 51 | ((stype) == PCM_TX ? PSC_I2SPCR_TC : PSC_I2SPCR_RC) |
55 | 52 | ||
56 | 53 | ||
57 | /* instance data. There can be only one, MacLeod!!!! */ | ||
58 | static struct au1xpsc_audio_data *au1xpsc_i2s_workdata; | ||
59 | |||
60 | static int au1xpsc_i2s_set_fmt(struct snd_soc_dai *cpu_dai, | 54 | static int au1xpsc_i2s_set_fmt(struct snd_soc_dai *cpu_dai, |
61 | unsigned int fmt) | 55 | unsigned int fmt) |
62 | { | 56 | { |
63 | struct au1xpsc_audio_data *pscdata = au1xpsc_i2s_workdata; | 57 | struct au1xpsc_audio_data *pscdata = snd_soc_dai_get_drvdata(cpu_dai); |
64 | unsigned long ct; | 58 | unsigned long ct; |
65 | int ret; | 59 | int ret; |
66 | 60 | ||
@@ -120,7 +114,7 @@ static int au1xpsc_i2s_hw_params(struct snd_pcm_substream *substream, | |||
120 | struct snd_pcm_hw_params *params, | 114 | struct snd_pcm_hw_params *params, |
121 | struct snd_soc_dai *dai) | 115 | struct snd_soc_dai *dai) |
122 | { | 116 | { |
123 | struct au1xpsc_audio_data *pscdata = au1xpsc_i2s_workdata; | 117 | struct au1xpsc_audio_data *pscdata = snd_soc_dai_get_drvdata(dai); |
124 | 118 | ||
125 | int cfgbits; | 119 | int cfgbits; |
126 | unsigned long stat; | 120 | unsigned long stat; |
@@ -245,7 +239,7 @@ static int au1xpsc_i2s_stop(struct au1xpsc_audio_data *pscdata, int stype) | |||
245 | static int au1xpsc_i2s_trigger(struct snd_pcm_substream *substream, int cmd, | 239 | static int au1xpsc_i2s_trigger(struct snd_pcm_substream *substream, int cmd, |
246 | struct snd_soc_dai *dai) | 240 | struct snd_soc_dai *dai) |
247 | { | 241 | { |
248 | struct au1xpsc_audio_data *pscdata = au1xpsc_i2s_workdata; | 242 | struct au1xpsc_audio_data *pscdata = snd_soc_dai_get_drvdata(dai); |
249 | int ret, stype = SUBSTREAM_TYPE(substream); | 243 | int ret, stype = SUBSTREAM_TYPE(substream); |
250 | 244 | ||
251 | switch (cmd) { | 245 | switch (cmd) { |
@@ -263,27 +257,13 @@ static int au1xpsc_i2s_trigger(struct snd_pcm_substream *substream, int cmd, | |||
263 | return ret; | 257 | return ret; |
264 | } | 258 | } |
265 | 259 | ||
266 | static int au1xpsc_i2s_probe(struct platform_device *pdev, | ||
267 | struct snd_soc_dai *dai) | ||
268 | { | ||
269 | return au1xpsc_i2s_workdata ? 0 : -ENODEV; | ||
270 | } | ||
271 | |||
272 | static void au1xpsc_i2s_remove(struct platform_device *pdev, | ||
273 | struct snd_soc_dai *dai) | ||
274 | { | ||
275 | } | ||
276 | |||
277 | static struct snd_soc_dai_ops au1xpsc_i2s_dai_ops = { | 260 | static struct snd_soc_dai_ops au1xpsc_i2s_dai_ops = { |
278 | .trigger = au1xpsc_i2s_trigger, | 261 | .trigger = au1xpsc_i2s_trigger, |
279 | .hw_params = au1xpsc_i2s_hw_params, | 262 | .hw_params = au1xpsc_i2s_hw_params, |
280 | .set_fmt = au1xpsc_i2s_set_fmt, | 263 | .set_fmt = au1xpsc_i2s_set_fmt, |
281 | }; | 264 | }; |
282 | 265 | ||
283 | struct snd_soc_dai au1xpsc_i2s_dai = { | 266 | static const struct snd_soc_dai_driver au1xpsc_i2s_dai_template = { |
284 | .name = "au1xpsc_i2s", | ||
285 | .probe = au1xpsc_i2s_probe, | ||
286 | .remove = au1xpsc_i2s_remove, | ||
287 | .playback = { | 267 | .playback = { |
288 | .rates = AU1XPSC_I2S_RATES, | 268 | .rates = AU1XPSC_I2S_RATES, |
289 | .formats = AU1XPSC_I2S_FMTS, | 269 | .formats = AU1XPSC_I2S_FMTS, |
@@ -298,7 +278,6 @@ struct snd_soc_dai au1xpsc_i2s_dai = { | |||
298 | }, | 278 | }, |
299 | .ops = &au1xpsc_i2s_dai_ops, | 279 | .ops = &au1xpsc_i2s_dai_ops, |
300 | }; | 280 | }; |
301 | EXPORT_SYMBOL(au1xpsc_i2s_dai); | ||
302 | 281 | ||
303 | static int __devinit au1xpsc_i2s_drvprobe(struct platform_device *pdev) | 282 | static int __devinit au1xpsc_i2s_drvprobe(struct platform_device *pdev) |
304 | { | 283 | { |
@@ -307,9 +286,6 @@ static int __devinit au1xpsc_i2s_drvprobe(struct platform_device *pdev) | |||
307 | int ret; | 286 | int ret; |
308 | struct au1xpsc_audio_data *wd; | 287 | struct au1xpsc_audio_data *wd; |
309 | 288 | ||
310 | if (au1xpsc_i2s_workdata) | ||
311 | return -EBUSY; | ||
312 | |||
313 | wd = kzalloc(sizeof(struct au1xpsc_audio_data), GFP_KERNEL); | 289 | wd = kzalloc(sizeof(struct au1xpsc_audio_data), GFP_KERNEL); |
314 | if (!wd) | 290 | if (!wd) |
315 | return -ENOMEM; | 291 | return -ENOMEM; |
@@ -346,19 +322,23 @@ static int __devinit au1xpsc_i2s_drvprobe(struct platform_device *pdev) | |||
346 | * time out. | 322 | * time out. |
347 | */ | 323 | */ |
348 | 324 | ||
349 | ret = snd_soc_register_dai(&au1xpsc_i2s_dai); | 325 | /* name the DAI like this device instance ("au1xpsc-i2s.PSCINDEX") */ |
326 | memcpy(&wd->dai_drv, &au1xpsc_i2s_dai_template, | ||
327 | sizeof(struct snd_soc_dai_driver)); | ||
328 | wd->dai_drv.name = dev_name(&pdev->dev); | ||
329 | |||
330 | platform_set_drvdata(pdev, wd); | ||
331 | |||
332 | ret = snd_soc_register_dai(&pdev->dev, &wd->dai_drv); | ||
350 | if (ret) | 333 | if (ret) |
351 | goto out1; | 334 | goto out1; |
352 | 335 | ||
353 | /* finally add the DMA device for this PSC */ | 336 | /* finally add the DMA device for this PSC */ |
354 | wd->dmapd = au1xpsc_pcm_add(pdev); | 337 | wd->dmapd = au1xpsc_pcm_add(pdev); |
355 | if (wd->dmapd) { | 338 | if (wd->dmapd) |
356 | platform_set_drvdata(pdev, wd); | ||
357 | au1xpsc_i2s_workdata = wd; | ||
358 | return 0; | 339 | return 0; |
359 | } | ||
360 | 340 | ||
361 | snd_soc_unregister_dai(&au1xpsc_i2s_dai); | 341 | snd_soc_unregister_dai(&pdev->dev); |
362 | out1: | 342 | out1: |
363 | release_mem_region(r->start, resource_size(r)); | 343 | release_mem_region(r->start, resource_size(r)); |
364 | out0: | 344 | out0: |
@@ -374,7 +354,7 @@ static int __devexit au1xpsc_i2s_drvremove(struct platform_device *pdev) | |||
374 | if (wd->dmapd) | 354 | if (wd->dmapd) |
375 | au1xpsc_pcm_destroy(wd->dmapd); | 355 | au1xpsc_pcm_destroy(wd->dmapd); |
376 | 356 | ||
377 | snd_soc_unregister_dai(&au1xpsc_i2s_dai); | 357 | snd_soc_unregister_dai(&pdev->dev); |
378 | 358 | ||
379 | au_writel(0, I2S_CFG(wd)); | 359 | au_writel(0, I2S_CFG(wd)); |
380 | au_sync(); | 360 | au_sync(); |
@@ -385,8 +365,6 @@ static int __devexit au1xpsc_i2s_drvremove(struct platform_device *pdev) | |||
385 | release_mem_region(r->start, resource_size(r)); | 365 | release_mem_region(r->start, resource_size(r)); |
386 | kfree(wd); | 366 | kfree(wd); |
387 | 367 | ||
388 | au1xpsc_i2s_workdata = NULL; /* MDEV */ | ||
389 | |||
390 | return 0; | 368 | return 0; |
391 | } | 369 | } |
392 | 370 | ||
@@ -446,7 +424,6 @@ static struct platform_driver au1xpsc_i2s_driver = { | |||
446 | 424 | ||
447 | static int __init au1xpsc_i2s_load(void) | 425 | static int __init au1xpsc_i2s_load(void) |
448 | { | 426 | { |
449 | au1xpsc_i2s_workdata = NULL; | ||
450 | return platform_driver_register(&au1xpsc_i2s_driver); | 427 | return platform_driver_register(&au1xpsc_i2s_driver); |
451 | } | 428 | } |
452 | 429 | ||