diff options
Diffstat (limited to 'sound/soc/au1x/psc-ac97.c')
-rw-r--r-- | sound/soc/au1x/psc-ac97.c | 71 |
1 files changed, 37 insertions, 34 deletions
diff --git a/sound/soc/au1x/psc-ac97.c b/sound/soc/au1x/psc-ac97.c index d14a5a91a465..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; |
@@ -315,27 +324,19 @@ static int au1xpsc_ac97_trigger(struct snd_pcm_substream *substream, | |||
315 | return ret; | 324 | return ret; |
316 | } | 325 | } |
317 | 326 | ||
318 | static int au1xpsc_ac97_probe(struct platform_device *pdev, | 327 | static int au1xpsc_ac97_probe(struct snd_soc_dai *dai) |
319 | struct snd_soc_dai *dai) | ||
320 | { | 328 | { |
321 | return au1xpsc_ac97_workdata ? 0 : -ENODEV; | 329 | return au1xpsc_ac97_workdata ? 0 : -ENODEV; |
322 | } | 330 | } |
323 | 331 | ||
324 | static void au1xpsc_ac97_remove(struct platform_device *pdev, | ||
325 | struct snd_soc_dai *dai) | ||
326 | { | ||
327 | } | ||
328 | |||
329 | static struct snd_soc_dai_ops au1xpsc_ac97_dai_ops = { | 332 | static struct snd_soc_dai_ops au1xpsc_ac97_dai_ops = { |
330 | .trigger = au1xpsc_ac97_trigger, | 333 | .trigger = au1xpsc_ac97_trigger, |
331 | .hw_params = au1xpsc_ac97_hw_params, | 334 | .hw_params = au1xpsc_ac97_hw_params, |
332 | }; | 335 | }; |
333 | 336 | ||
334 | struct snd_soc_dai au1xpsc_ac97_dai = { | 337 | static const struct snd_soc_dai_driver au1xpsc_ac97_dai_template = { |
335 | .name = "au1xpsc_ac97", | ||
336 | .ac97_control = 1, | 338 | .ac97_control = 1, |
337 | .probe = au1xpsc_ac97_probe, | 339 | .probe = au1xpsc_ac97_probe, |
338 | .remove = au1xpsc_ac97_remove, | ||
339 | .playback = { | 340 | .playback = { |
340 | .rates = AC97_RATES, | 341 | .rates = AC97_RATES, |
341 | .formats = AC97_FMTS, | 342 | .formats = AC97_FMTS, |
@@ -350,7 +351,6 @@ struct snd_soc_dai au1xpsc_ac97_dai = { | |||
350 | }, | 351 | }, |
351 | .ops = &au1xpsc_ac97_dai_ops, | 352 | .ops = &au1xpsc_ac97_dai_ops, |
352 | }; | 353 | }; |
353 | EXPORT_SYMBOL_GPL(au1xpsc_ac97_dai); | ||
354 | 354 | ||
355 | static int __devinit au1xpsc_ac97_drvprobe(struct platform_device *pdev) | 355 | static int __devinit au1xpsc_ac97_drvprobe(struct platform_device *pdev) |
356 | { | 356 | { |
@@ -359,9 +359,6 @@ static int __devinit au1xpsc_ac97_drvprobe(struct platform_device *pdev) | |||
359 | unsigned long sel; | 359 | unsigned long sel; |
360 | struct au1xpsc_audio_data *wd; | 360 | struct au1xpsc_audio_data *wd; |
361 | 361 | ||
362 | if (au1xpsc_ac97_workdata) | ||
363 | return -EBUSY; | ||
364 | |||
365 | wd = kzalloc(sizeof(struct au1xpsc_audio_data), GFP_KERNEL); | 362 | wd = kzalloc(sizeof(struct au1xpsc_audio_data), GFP_KERNEL); |
366 | if (!wd) | 363 | if (!wd) |
367 | return -ENOMEM; | 364 | return -ENOMEM; |
@@ -395,18 +392,24 @@ static int __devinit au1xpsc_ac97_drvprobe(struct platform_device *pdev) | |||
395 | au_writel(PSC_SEL_PS_AC97MODE | sel, PSC_SEL(wd)); | 392 | au_writel(PSC_SEL_PS_AC97MODE | sel, PSC_SEL(wd)); |
396 | au_sync(); | 393 | au_sync(); |
397 | 394 | ||
398 | ret = snd_soc_register_dai(&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); | ||
399 | if (ret) | 403 | if (ret) |
400 | goto out1; | 404 | goto out1; |
401 | 405 | ||
402 | wd->dmapd = au1xpsc_pcm_add(pdev); | 406 | wd->dmapd = au1xpsc_pcm_add(pdev); |
403 | if (wd->dmapd) { | 407 | if (wd->dmapd) { |
404 | platform_set_drvdata(pdev, wd); | 408 | au1xpsc_ac97_workdata = wd; |
405 | au1xpsc_ac97_workdata = wd; /* MDEV */ | ||
406 | return 0; | 409 | return 0; |
407 | } | 410 | } |
408 | 411 | ||
409 | snd_soc_unregister_dai(&au1xpsc_ac97_dai); | 412 | snd_soc_unregister_dai(&pdev->dev); |
410 | out1: | 413 | out1: |
411 | release_mem_region(r->start, resource_size(r)); | 414 | release_mem_region(r->start, resource_size(r)); |
412 | out0: | 415 | out0: |
@@ -422,7 +425,7 @@ static int __devexit au1xpsc_ac97_drvremove(struct platform_device *pdev) | |||
422 | if (wd->dmapd) | 425 | if (wd->dmapd) |
423 | au1xpsc_pcm_destroy(wd->dmapd); | 426 | au1xpsc_pcm_destroy(wd->dmapd); |
424 | 427 | ||
425 | snd_soc_unregister_dai(&au1xpsc_ac97_dai); | 428 | snd_soc_unregister_dai(&pdev->dev); |
426 | 429 | ||
427 | /* disable PSC completely */ | 430 | /* disable PSC completely */ |
428 | au_writel(0, AC97_CFG(wd)); | 431 | au_writel(0, AC97_CFG(wd)); |