aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/au1x/psc-ac97.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/soc/au1x/psc-ac97.c')
-rw-r--r--sound/soc/au1x/psc-ac97.c71
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!!!! */
57static struct au1xpsc_audio_data *au1xpsc_ac97_workdata; 54static 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 */
62static 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 */
60static unsigned short au1xpsc_ac97_read(struct snd_ac97 *ac97, 75static 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,
102static void au1xpsc_ac97_write(struct snd_ac97 *ac97, unsigned short reg, 116static 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 */
135static void au1xpsc_ac97_warm_reset(struct snd_ac97 *ac97) 148static 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
147static void au1xpsc_ac97_cold_reset(struct snd_ac97 *ac97) 159static 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:
283static int au1xpsc_ac97_trigger(struct snd_pcm_substream *substream, 293static 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
318static int au1xpsc_ac97_probe(struct platform_device *pdev, 327static 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
324static void au1xpsc_ac97_remove(struct platform_device *pdev,
325 struct snd_soc_dai *dai)
326{
327}
328
329static struct snd_soc_dai_ops au1xpsc_ac97_dai_ops = { 332static 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
334struct snd_soc_dai au1xpsc_ac97_dai = { 337static 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};
353EXPORT_SYMBOL_GPL(au1xpsc_ac97_dai);
354 354
355static int __devinit au1xpsc_ac97_drvprobe(struct platform_device *pdev) 355static 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);
410out1: 413out1:
411 release_mem_region(r->start, resource_size(r)); 414 release_mem_region(r->start, resource_size(r));
412out0: 415out0:
@@ -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));