diff options
author | Manuel Lauss <manuel.lauss@googlemail.com> | 2010-08-26 08:53:51 -0400 |
---|---|---|
committer | Mark Brown <broonie@opensource.wolfsonmicro.com> | 2010-08-31 08:06:31 -0400 |
commit | ffc4fdbbe1b4be79e98340ebcd5a0ade6f5de318 (patch) | |
tree | e4f16ef2561497482df5ac9039ba7bdb21212b2d | |
parent | 0bb5f267af41c39af895faee3abe2d9ab8c562e0 (diff) |
ASoC: fix au1x platform
This patch fixes up the au1x audio platform after the multi-component
merge:
- compile fixes and updates to get DB1200 platform audio working again,
- removal of global variables in AC97/I2S/DMA(PCM) modules.
The AC97 part is limited to one instance only for now due to issues
with getting at driver data in the soc_ac97_ops.
Signed-off-by: Manuel Lauss <manuel.lauss@googlemail.com>
Acked-by: Liam Girdwood <lrg@slimlogic.co.uk>
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
-rw-r--r-- | arch/mips/alchemy/devboards/db1200/platform.c | 6 | ||||
-rw-r--r-- | sound/soc/au1x/db1200.c | 16 | ||||
-rw-r--r-- | sound/soc/au1x/dbdma2.c | 82 | ||||
-rw-r--r-- | sound/soc/au1x/psc-ac97.c | 59 | ||||
-rw-r--r-- | sound/soc/au1x/psc-i2s.c | 42 | ||||
-rw-r--r-- | sound/soc/au1x/psc.h | 7 |
6 files changed, 91 insertions, 121 deletions
diff --git a/arch/mips/alchemy/devboards/db1200/platform.c b/arch/mips/alchemy/devboards/db1200/platform.c index 3fa34c3abc04..fbb55935b99e 100644 --- a/arch/mips/alchemy/devboards/db1200/platform.c +++ b/arch/mips/alchemy/devboards/db1200/platform.c | |||
@@ -429,6 +429,11 @@ static struct platform_device db1200_audio_dev = { | |||
429 | .resource = au1200_psc1_res, | 429 | .resource = au1200_psc1_res, |
430 | }; | 430 | }; |
431 | 431 | ||
432 | static struct platform_device db1200_stac_dev = { | ||
433 | .name = "ac97-codec", | ||
434 | .id = 1, /* on PSC1 */ | ||
435 | }; | ||
436 | |||
432 | static struct platform_device *db1200_devs[] __initdata = { | 437 | static struct platform_device *db1200_devs[] __initdata = { |
433 | NULL, /* PSC0, selected by S6.8 */ | 438 | NULL, /* PSC0, selected by S6.8 */ |
434 | &db1200_ide_dev, | 439 | &db1200_ide_dev, |
@@ -436,6 +441,7 @@ static struct platform_device *db1200_devs[] __initdata = { | |||
436 | &db1200_rtc_dev, | 441 | &db1200_rtc_dev, |
437 | &db1200_nand_dev, | 442 | &db1200_nand_dev, |
438 | &db1200_audio_dev, | 443 | &db1200_audio_dev, |
444 | &db1200_stac_dev, | ||
439 | }; | 445 | }; |
440 | 446 | ||
441 | static int __init db1200_dev_init(void) | 447 | static int __init db1200_dev_init(void) |
diff --git a/sound/soc/au1x/db1200.c b/sound/soc/au1x/db1200.c index d8dc8225576a..b62fcd33e586 100644 --- a/sound/soc/au1x/db1200.c +++ b/sound/soc/au1x/db1200.c | |||
@@ -27,10 +27,10 @@ | |||
27 | static struct snd_soc_dai_link db1200_ac97_dai = { | 27 | static struct snd_soc_dai_link db1200_ac97_dai = { |
28 | .name = "AC97", | 28 | .name = "AC97", |
29 | .stream_name = "AC97 HiFi", | 29 | .stream_name = "AC97 HiFi", |
30 | .cpu_dai_name = "au1xpsc-ac97", | ||
31 | .codec_dai_name = "ac97-hifi", | 30 | .codec_dai_name = "ac97-hifi", |
32 | .platform_name = "au1xpsc-pcm-audio", | 31 | .cpu_dai_name = "au1xpsc_ac97.1", |
33 | .codec_name = "ac97-codec", | 32 | .platform_name = "au1xpsc-pcm.1", |
33 | .codec_name = "ac97-codec.1", | ||
34 | }; | 34 | }; |
35 | 35 | ||
36 | static struct snd_soc_card db1200_ac97_machine = { | 36 | static struct snd_soc_card db1200_ac97_machine = { |
@@ -75,10 +75,10 @@ static struct snd_soc_ops db1200_i2s_wm8731_ops = { | |||
75 | static struct snd_soc_dai_link db1200_i2s_dai = { | 75 | static struct snd_soc_dai_link db1200_i2s_dai = { |
76 | .name = "WM8731", | 76 | .name = "WM8731", |
77 | .stream_name = "WM8731 PCM", | 77 | .stream_name = "WM8731 PCM", |
78 | .cpu_dai_name = "au1xpsc", | 78 | .codec_dai_name = "wm8731-hifi", |
79 | .codec_dai_name = "wm8731-hifi" | 79 | .cpu_dai_name = "au1xpsc_i2s.1", |
80 | .platform_name = "au1xpsc-pcm-audio", | 80 | .platform_name = "au1xpsc-pcm.1", |
81 | .codec_name = "wm8731-codec.0-001a", | 81 | .codec_name = "wm8731-codec.0-001b", |
82 | .ops = &db1200_i2s_wm8731_ops, | 82 | .ops = &db1200_i2s_wm8731_ops, |
83 | }; | 83 | }; |
84 | 84 | ||
@@ -97,7 +97,7 @@ static int __init db1200_audio_load(void) | |||
97 | int ret; | 97 | int ret; |
98 | 98 | ||
99 | ret = -ENOMEM; | 99 | ret = -ENOMEM; |
100 | db1200_asoc_dev = platform_device_alloc("soc-audio", -1); | 100 | db1200_asoc_dev = platform_device_alloc("soc-audio", 1); /* PSC1 */ |
101 | if (!db1200_asoc_dev) | 101 | if (!db1200_asoc_dev) |
102 | goto out; | 102 | goto out; |
103 | 103 | ||
diff --git a/sound/soc/au1x/dbdma2.c b/sound/soc/au1x/dbdma2.c index 00fdb9cbfc2d..10fdd2854e58 100644 --- a/sound/soc/au1x/dbdma2.c +++ b/sound/soc/au1x/dbdma2.c | |||
@@ -10,9 +10,6 @@ | |||
10 | * | 10 | * |
11 | * DMA glue for Au1x-PSC audio. | 11 | * DMA glue for Au1x-PSC audio. |
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 | */ | 13 | */ |
17 | 14 | ||
18 | 15 | ||
@@ -61,9 +58,6 @@ struct au1xpsc_audio_dmadata { | |||
61 | int msbits; | 58 | int msbits; |
62 | }; | 59 | }; |
63 | 60 | ||
64 | /* instance data. There can be only one, MacLeod!!!! */ | ||
65 | static struct au1xpsc_audio_dmadata *au1xpsc_audio_pcmdma[2]; | ||
66 | |||
67 | /* | 61 | /* |
68 | * These settings are somewhat okay, at least on my machine audio plays | 62 | * These settings are somewhat okay, at least on my machine audio plays |
69 | * almost skip-free. Especially the 64kB buffer seems to help a LOT. | 63 | * almost skip-free. Especially the 64kB buffer seems to help a LOT. |
@@ -199,6 +193,14 @@ out: | |||
199 | return 0; | 193 | return 0; |
200 | } | 194 | } |
201 | 195 | ||
196 | static inline struct au1xpsc_audio_dmadata *to_dmadata(struct snd_pcm_substream *ss) | ||
197 | { | ||
198 | struct snd_soc_pcm_runtime *rtd = ss->private_data; | ||
199 | struct au1xpsc_audio_dmadata *pcd = | ||
200 | snd_soc_platform_get_drvdata(rtd->platform); | ||
201 | return &pcd[SUBSTREAM_TYPE(ss)]; | ||
202 | } | ||
203 | |||
202 | static int au1xpsc_pcm_hw_params(struct snd_pcm_substream *substream, | 204 | static int au1xpsc_pcm_hw_params(struct snd_pcm_substream *substream, |
203 | struct snd_pcm_hw_params *params) | 205 | struct snd_pcm_hw_params *params) |
204 | { | 206 | { |
@@ -211,7 +213,7 @@ static int au1xpsc_pcm_hw_params(struct snd_pcm_substream *substream, | |||
211 | goto out; | 213 | goto out; |
212 | 214 | ||
213 | stype = SUBSTREAM_TYPE(substream); | 215 | stype = SUBSTREAM_TYPE(substream); |
214 | pcd = au1xpsc_audio_pcmdma[stype]; | 216 | pcd = to_dmadata(substream); |
215 | 217 | ||
216 | DBG("runtime->dma_area = 0x%08lx dma_addr_t = 0x%08lx dma_size = %d " | 218 | DBG("runtime->dma_area = 0x%08lx dma_addr_t = 0x%08lx dma_size = %d " |
217 | "runtime->min_align %d\n", | 219 | "runtime->min_align %d\n", |
@@ -249,8 +251,7 @@ static int au1xpsc_pcm_hw_free(struct snd_pcm_substream *substream) | |||
249 | 251 | ||
250 | static int au1xpsc_pcm_prepare(struct snd_pcm_substream *substream) | 252 | static int au1xpsc_pcm_prepare(struct snd_pcm_substream *substream) |
251 | { | 253 | { |
252 | struct au1xpsc_audio_dmadata *pcd = | 254 | struct au1xpsc_audio_dmadata *pcd = to_dmadata(substream); |
253 | au1xpsc_audio_pcmdma[SUBSTREAM_TYPE(substream)]; | ||
254 | 255 | ||
255 | au1xxx_dbdma_reset(pcd->ddma_chan); | 256 | au1xxx_dbdma_reset(pcd->ddma_chan); |
256 | 257 | ||
@@ -267,7 +268,7 @@ static int au1xpsc_pcm_prepare(struct snd_pcm_substream *substream) | |||
267 | 268 | ||
268 | static int au1xpsc_pcm_trigger(struct snd_pcm_substream *substream, int cmd) | 269 | static int au1xpsc_pcm_trigger(struct snd_pcm_substream *substream, int cmd) |
269 | { | 270 | { |
270 | u32 c = au1xpsc_audio_pcmdma[SUBSTREAM_TYPE(substream)]->ddma_chan; | 271 | u32 c = to_dmadata(substream)->ddma_chan; |
271 | 272 | ||
272 | switch (cmd) { | 273 | switch (cmd) { |
273 | case SNDRV_PCM_TRIGGER_START: | 274 | case SNDRV_PCM_TRIGGER_START: |
@@ -287,8 +288,7 @@ static int au1xpsc_pcm_trigger(struct snd_pcm_substream *substream, int cmd) | |||
287 | static snd_pcm_uframes_t | 288 | static snd_pcm_uframes_t |
288 | au1xpsc_pcm_pointer(struct snd_pcm_substream *substream) | 289 | au1xpsc_pcm_pointer(struct snd_pcm_substream *substream) |
289 | { | 290 | { |
290 | return bytes_to_frames(substream->runtime, | 291 | return bytes_to_frames(substream->runtime, to_dmadata(substream)->pos); |
291 | au1xpsc_audio_pcmdma[SUBSTREAM_TYPE(substream)]->pos); | ||
292 | } | 292 | } |
293 | 293 | ||
294 | static int au1xpsc_pcm_open(struct snd_pcm_substream *substream) | 294 | static int au1xpsc_pcm_open(struct snd_pcm_substream *substream) |
@@ -299,7 +299,7 @@ static int au1xpsc_pcm_open(struct snd_pcm_substream *substream) | |||
299 | 299 | ||
300 | static int au1xpsc_pcm_close(struct snd_pcm_substream *substream) | 300 | static int au1xpsc_pcm_close(struct snd_pcm_substream *substream) |
301 | { | 301 | { |
302 | au1x_pcm_dbdma_free(au1xpsc_audio_pcmdma[SUBSTREAM_TYPE(substream)]); | 302 | au1x_pcm_dbdma_free(to_dmadata(substream)); |
303 | return 0; | 303 | return 0; |
304 | } | 304 | } |
305 | 305 | ||
@@ -329,35 +329,21 @@ static int au1xpsc_pcm_new(struct snd_card *card, | |||
329 | return 0; | 329 | return 0; |
330 | } | 330 | } |
331 | 331 | ||
332 | static int au1xpsc_pcm_probe(struct snd_soc_platform *platform) | ||
333 | { | ||
334 | if (!au1xpsc_audio_pcmdma[PCM_TX] || !au1xpsc_audio_pcmdma[PCM_RX]) | ||
335 | return -ENODEV; | ||
336 | |||
337 | return 0; | ||
338 | } | ||
339 | |||
340 | /* au1xpsc audio platform */ | 332 | /* au1xpsc audio platform */ |
341 | struct snd_soc_platform_driver au1xpsc_soc_platform = { | 333 | struct snd_soc_platform_driver au1xpsc_soc_platform = { |
342 | .probe = au1xpsc_pcm_probe, | ||
343 | .ops = &au1xpsc_pcm_ops, | 334 | .ops = &au1xpsc_pcm_ops, |
344 | .pcm_new = au1xpsc_pcm_new, | 335 | .pcm_new = au1xpsc_pcm_new, |
345 | .pcm_free = au1xpsc_pcm_free_dma_buffers, | 336 | .pcm_free = au1xpsc_pcm_free_dma_buffers, |
346 | }; | 337 | }; |
347 | EXPORT_SYMBOL_GPL(au1xpsc_soc_platform); | ||
348 | 338 | ||
349 | static int __devinit au1xpsc_pcm_drvprobe(struct platform_device *pdev) | 339 | static int __devinit au1xpsc_pcm_drvprobe(struct platform_device *pdev) |
350 | { | 340 | { |
341 | struct au1xpsc_audio_dmadata *dmadata; | ||
351 | struct resource *r; | 342 | struct resource *r; |
352 | int ret; | 343 | int ret; |
353 | 344 | ||
354 | if (au1xpsc_audio_pcmdma[PCM_TX] || au1xpsc_audio_pcmdma[PCM_RX]) | 345 | dmadata = kzalloc(2 * sizeof(struct au1xpsc_audio_dmadata), GFP_KERNEL); |
355 | return -EBUSY; | 346 | if (!dmadata) |
356 | |||
357 | /* TX DMA */ | ||
358 | au1xpsc_audio_pcmdma[PCM_TX] | ||
359 | = kzalloc(sizeof(struct au1xpsc_audio_dmadata), GFP_KERNEL); | ||
360 | if (!au1xpsc_audio_pcmdma[PCM_TX]) | ||
361 | return -ENOMEM; | 347 | return -ENOMEM; |
362 | 348 | ||
363 | r = platform_get_resource(pdev, IORESOURCE_DMA, 0); | 349 | r = platform_get_resource(pdev, IORESOURCE_DMA, 0); |
@@ -365,54 +351,40 @@ static int __devinit au1xpsc_pcm_drvprobe(struct platform_device *pdev) | |||
365 | ret = -ENODEV; | 351 | ret = -ENODEV; |
366 | goto out1; | 352 | goto out1; |
367 | } | 353 | } |
368 | (au1xpsc_audio_pcmdma[PCM_TX])->ddma_id = r->start; | 354 | dmadata[PCM_TX].ddma_id = r->start; |
369 | 355 | ||
370 | /* RX DMA */ | 356 | /* RX DMA */ |
371 | au1xpsc_audio_pcmdma[PCM_RX] | ||
372 | = kzalloc(sizeof(struct au1xpsc_audio_dmadata), GFP_KERNEL); | ||
373 | if (!au1xpsc_audio_pcmdma[PCM_RX]) | ||
374 | return -ENOMEM; | ||
375 | |||
376 | r = platform_get_resource(pdev, IORESOURCE_DMA, 1); | 357 | r = platform_get_resource(pdev, IORESOURCE_DMA, 1); |
377 | if (!r) { | 358 | if (!r) { |
378 | ret = -ENODEV; | 359 | ret = -ENODEV; |
379 | goto out2; | 360 | goto out1; |
380 | } | 361 | } |
381 | (au1xpsc_audio_pcmdma[PCM_RX])->ddma_id = r->start; | 362 | dmadata[PCM_RX].ddma_id = r->start; |
363 | |||
364 | platform_set_drvdata(pdev, dmadata); | ||
382 | 365 | ||
383 | ret = snd_soc_register_platform(&pdev->dev, &au1xpsc_soc_platform); | 366 | ret = snd_soc_register_platform(&pdev->dev, &au1xpsc_soc_platform); |
384 | if (!ret) | 367 | if (!ret) |
385 | return ret; | 368 | return ret; |
386 | 369 | ||
387 | out2: | ||
388 | kfree(au1xpsc_audio_pcmdma[PCM_RX]); | ||
389 | au1xpsc_audio_pcmdma[PCM_RX] = NULL; | ||
390 | out1: | 370 | out1: |
391 | kfree(au1xpsc_audio_pcmdma[PCM_TX]); | 371 | kfree(dmadata); |
392 | au1xpsc_audio_pcmdma[PCM_TX] = NULL; | ||
393 | return ret; | 372 | return ret; |
394 | } | 373 | } |
395 | 374 | ||
396 | static int __devexit au1xpsc_pcm_drvremove(struct platform_device *pdev) | 375 | static int __devexit au1xpsc_pcm_drvremove(struct platform_device *pdev) |
397 | { | 376 | { |
398 | int i; | 377 | struct au1xpsc_audio_dmadata *dmadata = platform_get_drvdata(pdev); |
399 | 378 | ||
400 | snd_soc_unregister_platform(&pdev->dev); | 379 | snd_soc_unregister_platform(&pdev->dev); |
401 | 380 | kfree(dmadata); | |
402 | for (i = 0; i < 2; i++) { | ||
403 | if (au1xpsc_audio_pcmdma[i]) { | ||
404 | au1x_pcm_dbdma_free(au1xpsc_audio_pcmdma[i]); | ||
405 | kfree(au1xpsc_audio_pcmdma[i]); | ||
406 | au1xpsc_audio_pcmdma[i] = NULL; | ||
407 | } | ||
408 | } | ||
409 | 381 | ||
410 | return 0; | 382 | return 0; |
411 | } | 383 | } |
412 | 384 | ||
413 | static struct platform_driver au1xpsc_pcm_driver = { | 385 | static struct platform_driver au1xpsc_pcm_driver = { |
414 | .driver = { | 386 | .driver = { |
415 | .name = "au1xpsc-pcm-audio", | 387 | .name = "au1xpsc-pcm", |
416 | .owner = THIS_MODULE, | 388 | .owner = THIS_MODULE, |
417 | }, | 389 | }, |
418 | .probe = au1xpsc_pcm_drvprobe, | 390 | .probe = au1xpsc_pcm_drvprobe, |
@@ -421,8 +393,6 @@ static struct platform_driver au1xpsc_pcm_driver = { | |||
421 | 393 | ||
422 | static int __init au1xpsc_audio_dbdma_load(void) | 394 | static int __init au1xpsc_audio_dbdma_load(void) |
423 | { | 395 | { |
424 | au1xpsc_audio_pcmdma[PCM_TX] = NULL; | ||
425 | au1xpsc_audio_pcmdma[PCM_RX] = NULL; | ||
426 | return platform_driver_register(&au1xpsc_pcm_driver); | 396 | return platform_driver_register(&au1xpsc_pcm_driver); |
427 | } | 397 | } |
428 | 398 | ||
@@ -460,7 +430,7 @@ struct platform_device *au1xpsc_pcm_add(struct platform_device *pdev) | |||
460 | res[1].start = res[1].end = id[1]; | 430 | res[1].start = res[1].end = id[1]; |
461 | res[0].flags = res[1].flags = IORESOURCE_DMA; | 431 | res[0].flags = res[1].flags = IORESOURCE_DMA; |
462 | 432 | ||
463 | pd = platform_device_alloc("au1xpsc-pcm", -1); | 433 | pd = platform_device_alloc("au1xpsc-pcm", pdev->id); |
464 | if (!pd) | 434 | if (!pd) |
465 | goto out; | 435 | goto out; |
466 | 436 | ||
diff --git a/sound/soc/au1x/psc-ac97.c b/sound/soc/au1x/psc-ac97.c index 6a9516cbe424..d0db66f24a00 100644 --- a/sound/soc/au1x/psc-ac97.c +++ b/sound/soc/au1x/psc-ac97.c | |||
@@ -10,9 +10,6 @@ | |||
10 | * | 10 | * |
11 | * Au1xxx-PSC AC97 glue. | 11 | * Au1xxx-PSC AC97 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 | */ | 13 | */ |
17 | 14 | ||
18 | #include <linux/init.h> | 15 | #include <linux/init.h> |
@@ -56,12 +53,29 @@ | |||
56 | /* instance data. There can be only one, MacLeod!!!! */ | 53 | /* instance data. There can be only one, MacLeod!!!! */ |
57 | static struct au1xpsc_audio_data *au1xpsc_ac97_workdata; | 54 | static struct au1xpsc_audio_data *au1xpsc_ac97_workdata; |
58 | 55 | ||
56 | #if 0 | ||
57 | |||
58 | /* this could theoretically work, but ac97->bus->card->private_data can be NULL | ||
59 | * when snd_ac97_mixer() is called; I don't know if the rest further down the | ||
60 | * chain are always valid either. | ||
61 | */ | ||
62 | static inline struct au1xpsc_audio_data *ac97_to_pscdata(struct snd_ac97 *x) | ||
63 | { | ||
64 | struct snd_soc_card *c = x->bus->card->private_data; | ||
65 | return snd_soc_dai_get_drvdata(c->rtd->cpu_dai); | ||
66 | } | ||
67 | |||
68 | #else | ||
69 | |||
70 | #define ac97_to_pscdata(x) au1xpsc_ac97_workdata | ||
71 | |||
72 | #endif | ||
73 | |||
59 | /* AC97 controller reads codec register */ | 74 | /* AC97 controller reads codec register */ |
60 | static unsigned short au1xpsc_ac97_read(struct snd_ac97 *ac97, | 75 | static unsigned short au1xpsc_ac97_read(struct snd_ac97 *ac97, |
61 | unsigned short reg) | 76 | unsigned short reg) |
62 | { | 77 | { |
63 | /* FIXME */ | 78 | struct au1xpsc_audio_data *pscdata = ac97_to_pscdata(ac97); |
64 | struct au1xpsc_audio_data *pscdata = au1xpsc_ac97_workdata; | ||
65 | unsigned short retry, tmo; | 79 | unsigned short retry, tmo; |
66 | unsigned long data; | 80 | unsigned long data; |
67 | 81 | ||
@@ -102,8 +116,7 @@ static unsigned short au1xpsc_ac97_read(struct snd_ac97 *ac97, | |||
102 | static void au1xpsc_ac97_write(struct snd_ac97 *ac97, unsigned short reg, | 116 | static void au1xpsc_ac97_write(struct snd_ac97 *ac97, unsigned short reg, |
103 | unsigned short val) | 117 | unsigned short val) |
104 | { | 118 | { |
105 | /* FIXME */ | 119 | struct au1xpsc_audio_data *pscdata = ac97_to_pscdata(ac97); |
106 | struct au1xpsc_audio_data *pscdata = au1xpsc_ac97_workdata; | ||
107 | unsigned int tmo, retry; | 120 | unsigned int tmo, retry; |
108 | 121 | ||
109 | au_writel(PSC_AC97EVNT_CD, AC97_EVNT(pscdata)); | 122 | au_writel(PSC_AC97EVNT_CD, AC97_EVNT(pscdata)); |
@@ -134,8 +147,7 @@ static void au1xpsc_ac97_write(struct snd_ac97 *ac97, unsigned short reg, | |||
134 | /* AC97 controller asserts a warm reset */ | 147 | /* AC97 controller asserts a warm reset */ |
135 | static void au1xpsc_ac97_warm_reset(struct snd_ac97 *ac97) | 148 | static void au1xpsc_ac97_warm_reset(struct snd_ac97 *ac97) |
136 | { | 149 | { |
137 | /* FIXME */ | 150 | struct au1xpsc_audio_data *pscdata = ac97_to_pscdata(ac97); |
138 | struct au1xpsc_audio_data *pscdata = au1xpsc_ac97_workdata; | ||
139 | 151 | ||
140 | au_writel(PSC_AC97RST_SNC, AC97_RST(pscdata)); | 152 | au_writel(PSC_AC97RST_SNC, AC97_RST(pscdata)); |
141 | au_sync(); | 153 | au_sync(); |
@@ -146,8 +158,7 @@ static void au1xpsc_ac97_warm_reset(struct snd_ac97 *ac97) | |||
146 | 158 | ||
147 | static void au1xpsc_ac97_cold_reset(struct snd_ac97 *ac97) | 159 | static void au1xpsc_ac97_cold_reset(struct snd_ac97 *ac97) |
148 | { | 160 | { |
149 | /* FIXME */ | 161 | struct au1xpsc_audio_data *pscdata = ac97_to_pscdata(ac97); |
150 | struct au1xpsc_audio_data *pscdata = au1xpsc_ac97_workdata; | ||
151 | int i; | 162 | int i; |
152 | 163 | ||
153 | /* disable PSC during cold reset */ | 164 | /* disable PSC during cold reset */ |
@@ -202,8 +213,7 @@ static int au1xpsc_ac97_hw_params(struct snd_pcm_substream *substream, | |||
202 | struct snd_pcm_hw_params *params, | 213 | struct snd_pcm_hw_params *params, |
203 | struct snd_soc_dai *dai) | 214 | struct snd_soc_dai *dai) |
204 | { | 215 | { |
205 | /* FIXME */ | 216 | struct au1xpsc_audio_data *pscdata = snd_soc_dai_get_drvdata(dai); |
206 | struct au1xpsc_audio_data *pscdata = au1xpsc_ac97_workdata; | ||
207 | unsigned long r, ro, stat; | 217 | unsigned long r, ro, stat; |
208 | int chans, t, stype = SUBSTREAM_TYPE(substream); | 218 | int chans, t, stype = SUBSTREAM_TYPE(substream); |
209 | 219 | ||
@@ -283,8 +293,7 @@ out: | |||
283 | static int au1xpsc_ac97_trigger(struct snd_pcm_substream *substream, | 293 | static int au1xpsc_ac97_trigger(struct snd_pcm_substream *substream, |
284 | int cmd, struct snd_soc_dai *dai) | 294 | int cmd, struct snd_soc_dai *dai) |
285 | { | 295 | { |
286 | /* FIXME */ | 296 | struct au1xpsc_audio_data *pscdata = snd_soc_dai_get_drvdata(dai); |
287 | struct au1xpsc_audio_data *pscdata = au1xpsc_ac97_workdata; | ||
288 | int ret, stype = SUBSTREAM_TYPE(substream); | 297 | int ret, stype = SUBSTREAM_TYPE(substream); |
289 | 298 | ||
290 | ret = 0; | 299 | ret = 0; |
@@ -325,7 +334,7 @@ static struct snd_soc_dai_ops au1xpsc_ac97_dai_ops = { | |||
325 | .hw_params = au1xpsc_ac97_hw_params, | 334 | .hw_params = au1xpsc_ac97_hw_params, |
326 | }; | 335 | }; |
327 | 336 | ||
328 | struct snd_soc_dai_driver au1xpsc_ac97_dai = { | 337 | static const struct snd_soc_dai_driver au1xpsc_ac97_dai_template = { |
329 | .ac97_control = 1, | 338 | .ac97_control = 1, |
330 | .probe = au1xpsc_ac97_probe, | 339 | .probe = au1xpsc_ac97_probe, |
331 | .playback = { | 340 | .playback = { |
@@ -342,7 +351,6 @@ struct snd_soc_dai_driver au1xpsc_ac97_dai = { | |||
342 | }, | 351 | }, |
343 | .ops = &au1xpsc_ac97_dai_ops, | 352 | .ops = &au1xpsc_ac97_dai_ops, |
344 | }; | 353 | }; |
345 | EXPORT_SYMBOL_GPL(au1xpsc_ac97_dai); | ||
346 | 354 | ||
347 | static int __devinit au1xpsc_ac97_drvprobe(struct platform_device *pdev) | 355 | static int __devinit au1xpsc_ac97_drvprobe(struct platform_device *pdev) |
348 | { | 356 | { |
@@ -351,9 +359,6 @@ static int __devinit au1xpsc_ac97_drvprobe(struct platform_device *pdev) | |||
351 | unsigned long sel; | 359 | unsigned long sel; |
352 | struct au1xpsc_audio_data *wd; | 360 | struct au1xpsc_audio_data *wd; |
353 | 361 | ||
354 | if (au1xpsc_ac97_workdata) | ||
355 | return -EBUSY; | ||
356 | |||
357 | wd = kzalloc(sizeof(struct au1xpsc_audio_data), GFP_KERNEL); | 362 | wd = kzalloc(sizeof(struct au1xpsc_audio_data), GFP_KERNEL); |
358 | if (!wd) | 363 | if (!wd) |
359 | return -ENOMEM; | 364 | return -ENOMEM; |
@@ -387,14 +392,20 @@ static int __devinit au1xpsc_ac97_drvprobe(struct platform_device *pdev) | |||
387 | au_writel(PSC_SEL_PS_AC97MODE | sel, PSC_SEL(wd)); | 392 | au_writel(PSC_SEL_PS_AC97MODE | sel, PSC_SEL(wd)); |
388 | au_sync(); | 393 | au_sync(); |
389 | 394 | ||
390 | ret = snd_soc_register_dai(&pdev->dev, &au1xpsc_ac97_dai); | 395 | /* name the DAI like this device instance ("au1xpsc-ac97.PSCINDEX") */ |
396 | memcpy(&wd->dai_drv, &au1xpsc_ac97_dai_template, | ||
397 | sizeof(struct snd_soc_dai_driver)); | ||
398 | wd->dai_drv.name = dev_name(&pdev->dev); | ||
399 | |||
400 | platform_set_drvdata(pdev, wd); | ||
401 | |||
402 | ret = snd_soc_register_dai(&pdev->dev, &wd->dai_drv); | ||
391 | if (ret) | 403 | if (ret) |
392 | goto out1; | 404 | goto out1; |
393 | 405 | ||
394 | wd->dmapd = au1xpsc_pcm_add(pdev); | 406 | wd->dmapd = au1xpsc_pcm_add(pdev); |
395 | if (wd->dmapd) { | 407 | if (wd->dmapd) { |
396 | platform_set_drvdata(pdev, wd); | 408 | au1xpsc_ac97_workdata = wd; |
397 | au1xpsc_ac97_workdata = wd; /* MDEV */ | ||
398 | return 0; | 409 | return 0; |
399 | } | 410 | } |
400 | 411 | ||
@@ -477,7 +488,7 @@ static struct dev_pm_ops au1xpscac97_pmops = { | |||
477 | 488 | ||
478 | static struct platform_driver au1xpsc_ac97_driver = { | 489 | static struct platform_driver au1xpsc_ac97_driver = { |
479 | .driver = { | 490 | .driver = { |
480 | .name = "au1xpsc-ac97", | 491 | .name = "au1xpsc_ac97", |
481 | .owner = THIS_MODULE, | 492 | .owner = THIS_MODULE, |
482 | .pm = AU1XPSCAC97_PMOPS, | 493 | .pm = AU1XPSCAC97_PMOPS, |
483 | }, | 494 | }, |
diff --git a/sound/soc/au1x/psc-i2s.c b/sound/soc/au1x/psc-i2s.c index 94e560a8756d..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,19 +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 snd_soc_dai *dai) | ||
267 | { | ||
268 | return au1xpsc_i2s_workdata ? 0 : -ENODEV; | ||
269 | } | ||
270 | |||
271 | static struct snd_soc_dai_ops au1xpsc_i2s_dai_ops = { | 260 | static struct snd_soc_dai_ops au1xpsc_i2s_dai_ops = { |
272 | .trigger = au1xpsc_i2s_trigger, | 261 | .trigger = au1xpsc_i2s_trigger, |
273 | .hw_params = au1xpsc_i2s_hw_params, | 262 | .hw_params = au1xpsc_i2s_hw_params, |
274 | .set_fmt = au1xpsc_i2s_set_fmt, | 263 | .set_fmt = au1xpsc_i2s_set_fmt, |
275 | }; | 264 | }; |
276 | 265 | ||
277 | static struct snd_soc_dai_driver au1xpsc_i2s_dai = { | 266 | static const struct snd_soc_dai_driver au1xpsc_i2s_dai_template = { |
278 | .probe = au1xpsc_i2s_probe, | ||
279 | .playback = { | 267 | .playback = { |
280 | .rates = AU1XPSC_I2S_RATES, | 268 | .rates = AU1XPSC_I2S_RATES, |
281 | .formats = AU1XPSC_I2S_FMTS, | 269 | .formats = AU1XPSC_I2S_FMTS, |
@@ -298,9 +286,6 @@ static int __devinit au1xpsc_i2s_drvprobe(struct platform_device *pdev) | |||
298 | int ret; | 286 | int ret; |
299 | struct au1xpsc_audio_data *wd; | 287 | struct au1xpsc_audio_data *wd; |
300 | 288 | ||
301 | if (au1xpsc_i2s_workdata) | ||
302 | return -EBUSY; | ||
303 | |||
304 | wd = kzalloc(sizeof(struct au1xpsc_audio_data), GFP_KERNEL); | 289 | wd = kzalloc(sizeof(struct au1xpsc_audio_data), GFP_KERNEL); |
305 | if (!wd) | 290 | if (!wd) |
306 | return -ENOMEM; | 291 | return -ENOMEM; |
@@ -337,17 +322,21 @@ static int __devinit au1xpsc_i2s_drvprobe(struct platform_device *pdev) | |||
337 | * time out. | 322 | * time out. |
338 | */ | 323 | */ |
339 | 324 | ||
340 | ret = snd_soc_register_dai(&pdev->dev, &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); | ||
341 | if (ret) | 333 | if (ret) |
342 | goto out1; | 334 | goto out1; |
343 | 335 | ||
344 | /* finally add the DMA device for this PSC */ | 336 | /* finally add the DMA device for this PSC */ |
345 | wd->dmapd = au1xpsc_pcm_add(pdev); | 337 | wd->dmapd = au1xpsc_pcm_add(pdev); |
346 | if (wd->dmapd) { | 338 | if (wd->dmapd) |
347 | platform_set_drvdata(pdev, wd); | ||
348 | au1xpsc_i2s_workdata = wd; | ||
349 | return 0; | 339 | return 0; |
350 | } | ||
351 | 340 | ||
352 | snd_soc_unregister_dai(&pdev->dev); | 341 | snd_soc_unregister_dai(&pdev->dev); |
353 | out1: | 342 | out1: |
@@ -376,8 +365,6 @@ static int __devexit au1xpsc_i2s_drvremove(struct platform_device *pdev) | |||
376 | release_mem_region(r->start, resource_size(r)); | 365 | release_mem_region(r->start, resource_size(r)); |
377 | kfree(wd); | 366 | kfree(wd); |
378 | 367 | ||
379 | au1xpsc_i2s_workdata = NULL; /* MDEV */ | ||
380 | |||
381 | return 0; | 368 | return 0; |
382 | } | 369 | } |
383 | 370 | ||
@@ -427,7 +414,7 @@ static struct dev_pm_ops au1xpsci2s_pmops = { | |||
427 | 414 | ||
428 | static struct platform_driver au1xpsc_i2s_driver = { | 415 | static struct platform_driver au1xpsc_i2s_driver = { |
429 | .driver = { | 416 | .driver = { |
430 | .name = "au1xpsc", | 417 | .name = "au1xpsc_i2s", |
431 | .owner = THIS_MODULE, | 418 | .owner = THIS_MODULE, |
432 | .pm = AU1XPSCI2S_PMOPS, | 419 | .pm = AU1XPSCI2S_PMOPS, |
433 | }, | 420 | }, |
@@ -437,7 +424,6 @@ static struct platform_driver au1xpsc_i2s_driver = { | |||
437 | 424 | ||
438 | static int __init au1xpsc_i2s_load(void) | 425 | static int __init au1xpsc_i2s_load(void) |
439 | { | 426 | { |
440 | au1xpsc_i2s_workdata = NULL; | ||
441 | return platform_driver_register(&au1xpsc_i2s_driver); | 427 | return platform_driver_register(&au1xpsc_i2s_driver); |
442 | } | 428 | } |
443 | 429 | ||
diff --git a/sound/soc/au1x/psc.h b/sound/soc/au1x/psc.h index f281443fd52f..b30eadd422a7 100644 --- a/sound/soc/au1x/psc.h +++ b/sound/soc/au1x/psc.h | |||
@@ -8,16 +8,11 @@ | |||
8 | * it under the terms of the GNU General Public License version 2 as | 8 | * it under the terms of the GNU General Public License version 2 as |
9 | * published by the Free Software Foundation. | 9 | * published by the Free Software Foundation. |
10 | * | 10 | * |
11 | * NOTE: all of these drivers can only work with a SINGLE instance | ||
12 | * of a PSC. Multiple independent audio devices are impossible | ||
13 | * with ASoC v1. | ||
14 | */ | 11 | */ |
15 | 12 | ||
16 | #ifndef _AU1X_PCM_H | 13 | #ifndef _AU1X_PCM_H |
17 | #define _AU1X_PCM_H | 14 | #define _AU1X_PCM_H |
18 | 15 | ||
19 | extern struct snd_ac97_bus_ops soc_ac97_ops; | ||
20 | |||
21 | /* DBDMA helpers */ | 16 | /* DBDMA helpers */ |
22 | extern struct platform_device *au1xpsc_pcm_add(struct platform_device *pdev); | 17 | extern struct platform_device *au1xpsc_pcm_add(struct platform_device *pdev); |
23 | extern void au1xpsc_pcm_destroy(struct platform_device *dmapd); | 18 | extern void au1xpsc_pcm_destroy(struct platform_device *dmapd); |
@@ -28,6 +23,8 @@ struct au1xpsc_audio_data { | |||
28 | unsigned long cfg; | 23 | unsigned long cfg; |
29 | unsigned long rate; | 24 | unsigned long rate; |
30 | 25 | ||
26 | struct snd_soc_dai_driver dai_drv; | ||
27 | |||
31 | unsigned long pm[2]; | 28 | unsigned long pm[2]; |
32 | struct mutex lock; | 29 | struct mutex lock; |
33 | struct platform_device *dmapd; | 30 | struct platform_device *dmapd; |