Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/sound/soc/au1x/psc-ac97.c
26444 views
1
// SPDX-License-Identifier: GPL-2.0-only
2
/*
3
* Au12x0/Au1550 PSC ALSA ASoC audio support.
4
*
5
* (c) 2007-2009 MSC Vertriebsges.m.b.H.,
6
* Manuel Lauss <[email protected]>
7
*
8
* Au1xxx-PSC AC97 glue.
9
*/
10
11
#include <linux/init.h>
12
#include <linux/module.h>
13
#include <linux/slab.h>
14
#include <linux/device.h>
15
#include <linux/delay.h>
16
#include <linux/mutex.h>
17
#include <linux/suspend.h>
18
#include <sound/core.h>
19
#include <sound/pcm.h>
20
#include <sound/initval.h>
21
#include <sound/soc.h>
22
#include <asm/mach-au1x00/au1000.h>
23
#include <asm/mach-au1x00/au1xxx_psc.h>
24
25
#include "psc.h"
26
27
/* how often to retry failed codec register reads/writes */
28
#define AC97_RW_RETRIES 5
29
30
#define AC97_DIR \
31
(SND_SOC_DAIDIR_PLAYBACK | SND_SOC_DAIDIR_CAPTURE)
32
33
#define AC97_RATES \
34
SNDRV_PCM_RATE_8000_48000
35
36
#define AC97_FMTS \
37
(SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3BE)
38
39
#define AC97PCR_START(stype) \
40
((stype) == SNDRV_PCM_STREAM_PLAYBACK ? PSC_AC97PCR_TS : PSC_AC97PCR_RS)
41
#define AC97PCR_STOP(stype) \
42
((stype) == SNDRV_PCM_STREAM_PLAYBACK ? PSC_AC97PCR_TP : PSC_AC97PCR_RP)
43
#define AC97PCR_CLRFIFO(stype) \
44
((stype) == SNDRV_PCM_STREAM_PLAYBACK ? PSC_AC97PCR_TC : PSC_AC97PCR_RC)
45
46
#define AC97STAT_BUSY(stype) \
47
((stype) == SNDRV_PCM_STREAM_PLAYBACK ? PSC_AC97STAT_TB : PSC_AC97STAT_RB)
48
49
/* instance data. There can be only one, MacLeod!!!! */
50
static struct au1xpsc_audio_data *au1xpsc_ac97_workdata;
51
52
#if 0
53
54
/* this could theoretically work, but ac97->bus->card->private_data can be NULL
55
* when snd_ac97_mixer() is called; I don't know if the rest further down the
56
* chain are always valid either.
57
*/
58
static inline struct au1xpsc_audio_data *ac97_to_pscdata(struct snd_ac97 *x)
59
{
60
struct snd_soc_card *c = x->bus->card->private_data;
61
return snd_soc_dai_get_drvdata(c->snd_soc_rtd_to_cpu(rtd, 0));
62
}
63
64
#else
65
66
#define ac97_to_pscdata(x) au1xpsc_ac97_workdata
67
68
#endif
69
70
/* AC97 controller reads codec register */
71
static unsigned short au1xpsc_ac97_read(struct snd_ac97 *ac97,
72
unsigned short reg)
73
{
74
struct au1xpsc_audio_data *pscdata = ac97_to_pscdata(ac97);
75
unsigned short retry, tmo;
76
unsigned long data;
77
78
__raw_writel(PSC_AC97EVNT_CD, AC97_EVNT(pscdata));
79
wmb(); /* drain writebuffer */
80
81
retry = AC97_RW_RETRIES;
82
do {
83
mutex_lock(&pscdata->lock);
84
85
__raw_writel(PSC_AC97CDC_RD | PSC_AC97CDC_INDX(reg),
86
AC97_CDC(pscdata));
87
wmb(); /* drain writebuffer */
88
89
tmo = 20;
90
do {
91
udelay(21);
92
if (__raw_readl(AC97_EVNT(pscdata)) & PSC_AC97EVNT_CD)
93
break;
94
} while (--tmo);
95
96
data = __raw_readl(AC97_CDC(pscdata));
97
98
__raw_writel(PSC_AC97EVNT_CD, AC97_EVNT(pscdata));
99
wmb(); /* drain writebuffer */
100
101
mutex_unlock(&pscdata->lock);
102
103
if (reg != ((data >> 16) & 0x7f))
104
tmo = 1; /* wrong register, try again */
105
106
} while (--retry && !tmo);
107
108
return retry ? data & 0xffff : 0xffff;
109
}
110
111
/* AC97 controller writes to codec register */
112
static void au1xpsc_ac97_write(struct snd_ac97 *ac97, unsigned short reg,
113
unsigned short val)
114
{
115
struct au1xpsc_audio_data *pscdata = ac97_to_pscdata(ac97);
116
unsigned int tmo, retry;
117
118
__raw_writel(PSC_AC97EVNT_CD, AC97_EVNT(pscdata));
119
wmb(); /* drain writebuffer */
120
121
retry = AC97_RW_RETRIES;
122
do {
123
mutex_lock(&pscdata->lock);
124
125
__raw_writel(PSC_AC97CDC_INDX(reg) | (val & 0xffff),
126
AC97_CDC(pscdata));
127
wmb(); /* drain writebuffer */
128
129
tmo = 20;
130
do {
131
udelay(21);
132
if (__raw_readl(AC97_EVNT(pscdata)) & PSC_AC97EVNT_CD)
133
break;
134
} while (--tmo);
135
136
__raw_writel(PSC_AC97EVNT_CD, AC97_EVNT(pscdata));
137
wmb(); /* drain writebuffer */
138
139
mutex_unlock(&pscdata->lock);
140
} while (--retry && !tmo);
141
}
142
143
/* AC97 controller asserts a warm reset */
144
static void au1xpsc_ac97_warm_reset(struct snd_ac97 *ac97)
145
{
146
struct au1xpsc_audio_data *pscdata = ac97_to_pscdata(ac97);
147
148
__raw_writel(PSC_AC97RST_SNC, AC97_RST(pscdata));
149
wmb(); /* drain writebuffer */
150
msleep(10);
151
__raw_writel(0, AC97_RST(pscdata));
152
wmb(); /* drain writebuffer */
153
}
154
155
static void au1xpsc_ac97_cold_reset(struct snd_ac97 *ac97)
156
{
157
struct au1xpsc_audio_data *pscdata = ac97_to_pscdata(ac97);
158
int i;
159
160
/* disable PSC during cold reset */
161
__raw_writel(0, AC97_CFG(au1xpsc_ac97_workdata));
162
wmb(); /* drain writebuffer */
163
__raw_writel(PSC_CTRL_DISABLE, PSC_CTRL(pscdata));
164
wmb(); /* drain writebuffer */
165
166
/* issue cold reset */
167
__raw_writel(PSC_AC97RST_RST, AC97_RST(pscdata));
168
wmb(); /* drain writebuffer */
169
msleep(500);
170
__raw_writel(0, AC97_RST(pscdata));
171
wmb(); /* drain writebuffer */
172
173
/* enable PSC */
174
__raw_writel(PSC_CTRL_ENABLE, PSC_CTRL(pscdata));
175
wmb(); /* drain writebuffer */
176
177
/* wait for PSC to indicate it's ready */
178
i = 1000;
179
while (!((__raw_readl(AC97_STAT(pscdata)) & PSC_AC97STAT_SR)) && (--i))
180
msleep(1);
181
182
if (i == 0) {
183
printk(KERN_ERR "au1xpsc-ac97: PSC not ready!\n");
184
return;
185
}
186
187
/* enable the ac97 function */
188
__raw_writel(pscdata->cfg | PSC_AC97CFG_DE_ENABLE, AC97_CFG(pscdata));
189
wmb(); /* drain writebuffer */
190
191
/* wait for AC97 core to become ready */
192
i = 1000;
193
while (!((__raw_readl(AC97_STAT(pscdata)) & PSC_AC97STAT_DR)) && (--i))
194
msleep(1);
195
if (i == 0)
196
printk(KERN_ERR "au1xpsc-ac97: AC97 ctrl not ready\n");
197
}
198
199
/* AC97 controller operations */
200
static struct snd_ac97_bus_ops psc_ac97_ops = {
201
.read = au1xpsc_ac97_read,
202
.write = au1xpsc_ac97_write,
203
.reset = au1xpsc_ac97_cold_reset,
204
.warm_reset = au1xpsc_ac97_warm_reset,
205
};
206
207
static int au1xpsc_ac97_hw_params(struct snd_pcm_substream *substream,
208
struct snd_pcm_hw_params *params,
209
struct snd_soc_dai *dai)
210
{
211
struct au1xpsc_audio_data *pscdata = snd_soc_dai_get_drvdata(dai);
212
unsigned long r, ro, stat;
213
int chans, t, stype = substream->stream;
214
215
chans = params_channels(params);
216
217
r = ro = __raw_readl(AC97_CFG(pscdata));
218
stat = __raw_readl(AC97_STAT(pscdata));
219
220
/* already active? */
221
if (stat & (PSC_AC97STAT_TB | PSC_AC97STAT_RB)) {
222
/* reject parameters not currently set up */
223
if ((PSC_AC97CFG_GET_LEN(r) != params->msbits) ||
224
(pscdata->rate != params_rate(params)))
225
return -EINVAL;
226
} else {
227
228
/* set sample bitdepth: REG[24:21]=(BITS-2)/2 */
229
r &= ~PSC_AC97CFG_LEN_MASK;
230
r |= PSC_AC97CFG_SET_LEN(params->msbits);
231
232
/* channels: enable slots for front L/R channel */
233
if (stype == SNDRV_PCM_STREAM_PLAYBACK) {
234
r &= ~PSC_AC97CFG_TXSLOT_MASK;
235
r |= PSC_AC97CFG_TXSLOT_ENA(3);
236
r |= PSC_AC97CFG_TXSLOT_ENA(4);
237
} else {
238
r &= ~PSC_AC97CFG_RXSLOT_MASK;
239
r |= PSC_AC97CFG_RXSLOT_ENA(3);
240
r |= PSC_AC97CFG_RXSLOT_ENA(4);
241
}
242
243
/* do we need to poke the hardware? */
244
if (!(r ^ ro))
245
goto out;
246
247
/* ac97 engine is about to be disabled */
248
mutex_lock(&pscdata->lock);
249
250
/* disable AC97 device controller first... */
251
__raw_writel(r & ~PSC_AC97CFG_DE_ENABLE, AC97_CFG(pscdata));
252
wmb(); /* drain writebuffer */
253
254
/* ...wait for it... */
255
t = 100;
256
while ((__raw_readl(AC97_STAT(pscdata)) & PSC_AC97STAT_DR) && --t)
257
msleep(1);
258
259
if (!t)
260
printk(KERN_ERR "PSC-AC97: can't disable!\n");
261
262
/* ...write config... */
263
__raw_writel(r, AC97_CFG(pscdata));
264
wmb(); /* drain writebuffer */
265
266
/* ...enable the AC97 controller again... */
267
__raw_writel(r | PSC_AC97CFG_DE_ENABLE, AC97_CFG(pscdata));
268
wmb(); /* drain writebuffer */
269
270
/* ...and wait for ready bit */
271
t = 100;
272
while ((!(__raw_readl(AC97_STAT(pscdata)) & PSC_AC97STAT_DR)) && --t)
273
msleep(1);
274
275
if (!t)
276
printk(KERN_ERR "PSC-AC97: can't enable!\n");
277
278
mutex_unlock(&pscdata->lock);
279
280
pscdata->cfg = r;
281
pscdata->rate = params_rate(params);
282
}
283
284
out:
285
return 0;
286
}
287
288
static int au1xpsc_ac97_trigger(struct snd_pcm_substream *substream,
289
int cmd, struct snd_soc_dai *dai)
290
{
291
struct au1xpsc_audio_data *pscdata = snd_soc_dai_get_drvdata(dai);
292
int ret, stype = substream->stream;
293
294
ret = 0;
295
296
switch (cmd) {
297
case SNDRV_PCM_TRIGGER_START:
298
case SNDRV_PCM_TRIGGER_RESUME:
299
__raw_writel(AC97PCR_CLRFIFO(stype), AC97_PCR(pscdata));
300
wmb(); /* drain writebuffer */
301
__raw_writel(AC97PCR_START(stype), AC97_PCR(pscdata));
302
wmb(); /* drain writebuffer */
303
break;
304
case SNDRV_PCM_TRIGGER_STOP:
305
case SNDRV_PCM_TRIGGER_SUSPEND:
306
__raw_writel(AC97PCR_STOP(stype), AC97_PCR(pscdata));
307
wmb(); /* drain writebuffer */
308
309
while (__raw_readl(AC97_STAT(pscdata)) & AC97STAT_BUSY(stype))
310
asm volatile ("nop");
311
312
__raw_writel(AC97PCR_CLRFIFO(stype), AC97_PCR(pscdata));
313
wmb(); /* drain writebuffer */
314
315
break;
316
default:
317
ret = -EINVAL;
318
}
319
return ret;
320
}
321
322
static int au1xpsc_ac97_startup(struct snd_pcm_substream *substream,
323
struct snd_soc_dai *dai)
324
{
325
struct au1xpsc_audio_data *pscdata = snd_soc_dai_get_drvdata(dai);
326
snd_soc_dai_set_dma_data(dai, substream, &pscdata->dmaids[0]);
327
return 0;
328
}
329
330
static int au1xpsc_ac97_probe(struct snd_soc_dai *dai)
331
{
332
return au1xpsc_ac97_workdata ? 0 : -ENODEV;
333
}
334
335
static const struct snd_soc_dai_ops au1xpsc_ac97_dai_ops = {
336
.probe = au1xpsc_ac97_probe,
337
.startup = au1xpsc_ac97_startup,
338
.trigger = au1xpsc_ac97_trigger,
339
.hw_params = au1xpsc_ac97_hw_params,
340
};
341
342
static const struct snd_soc_dai_driver au1xpsc_ac97_dai_template = {
343
.playback = {
344
.rates = AC97_RATES,
345
.formats = AC97_FMTS,
346
.channels_min = 2,
347
.channels_max = 2,
348
},
349
.capture = {
350
.rates = AC97_RATES,
351
.formats = AC97_FMTS,
352
.channels_min = 2,
353
.channels_max = 2,
354
},
355
.ops = &au1xpsc_ac97_dai_ops,
356
};
357
358
static const struct snd_soc_component_driver au1xpsc_ac97_component = {
359
.name = "au1xpsc-ac97",
360
.legacy_dai_naming = 1,
361
};
362
363
static int au1xpsc_ac97_drvprobe(struct platform_device *pdev)
364
{
365
int ret;
366
struct resource *dmares;
367
unsigned long sel;
368
struct au1xpsc_audio_data *wd;
369
370
wd = devm_kzalloc(&pdev->dev, sizeof(struct au1xpsc_audio_data),
371
GFP_KERNEL);
372
if (!wd)
373
return -ENOMEM;
374
375
mutex_init(&wd->lock);
376
377
wd->mmio = devm_platform_ioremap_resource(pdev, 0);
378
if (IS_ERR(wd->mmio))
379
return PTR_ERR(wd->mmio);
380
381
dmares = platform_get_resource(pdev, IORESOURCE_DMA, 0);
382
if (!dmares)
383
return -EBUSY;
384
wd->dmaids[SNDRV_PCM_STREAM_PLAYBACK] = dmares->start;
385
386
dmares = platform_get_resource(pdev, IORESOURCE_DMA, 1);
387
if (!dmares)
388
return -EBUSY;
389
wd->dmaids[SNDRV_PCM_STREAM_CAPTURE] = dmares->start;
390
391
/* configuration: max dma trigger threshold, enable ac97 */
392
wd->cfg = PSC_AC97CFG_RT_FIFO8 | PSC_AC97CFG_TT_FIFO8 |
393
PSC_AC97CFG_DE_ENABLE;
394
395
/* preserve PSC clock source set up by platform */
396
sel = __raw_readl(PSC_SEL(wd)) & PSC_SEL_CLK_MASK;
397
__raw_writel(PSC_CTRL_DISABLE, PSC_CTRL(wd));
398
wmb(); /* drain writebuffer */
399
__raw_writel(0, PSC_SEL(wd));
400
wmb(); /* drain writebuffer */
401
__raw_writel(PSC_SEL_PS_AC97MODE | sel, PSC_SEL(wd));
402
wmb(); /* drain writebuffer */
403
404
/* name the DAI like this device instance ("au1xpsc-ac97.PSCINDEX") */
405
memcpy(&wd->dai_drv, &au1xpsc_ac97_dai_template,
406
sizeof(struct snd_soc_dai_driver));
407
wd->dai_drv.name = dev_name(&pdev->dev);
408
409
platform_set_drvdata(pdev, wd);
410
411
ret = snd_soc_set_ac97_ops(&psc_ac97_ops);
412
if (ret)
413
return ret;
414
415
ret = snd_soc_register_component(&pdev->dev, &au1xpsc_ac97_component,
416
&wd->dai_drv, 1);
417
if (ret)
418
return ret;
419
420
au1xpsc_ac97_workdata = wd;
421
return 0;
422
}
423
424
static void au1xpsc_ac97_drvremove(struct platform_device *pdev)
425
{
426
struct au1xpsc_audio_data *wd = platform_get_drvdata(pdev);
427
428
snd_soc_unregister_component(&pdev->dev);
429
430
/* disable PSC completely */
431
__raw_writel(0, AC97_CFG(wd));
432
wmb(); /* drain writebuffer */
433
__raw_writel(PSC_CTRL_DISABLE, PSC_CTRL(wd));
434
wmb(); /* drain writebuffer */
435
436
au1xpsc_ac97_workdata = NULL; /* MDEV */
437
}
438
439
static int au1xpsc_ac97_drvsuspend(struct device *dev)
440
{
441
struct au1xpsc_audio_data *wd = dev_get_drvdata(dev);
442
443
/* save interesting registers and disable PSC */
444
wd->pm[0] = __raw_readl(PSC_SEL(wd));
445
446
__raw_writel(0, AC97_CFG(wd));
447
wmb(); /* drain writebuffer */
448
__raw_writel(PSC_CTRL_DISABLE, PSC_CTRL(wd));
449
wmb(); /* drain writebuffer */
450
451
return 0;
452
}
453
454
static int au1xpsc_ac97_drvresume(struct device *dev)
455
{
456
struct au1xpsc_audio_data *wd = dev_get_drvdata(dev);
457
458
/* restore PSC clock config */
459
__raw_writel(wd->pm[0] | PSC_SEL_PS_AC97MODE, PSC_SEL(wd));
460
wmb(); /* drain writebuffer */
461
462
/* after this point the ac97 core will cold-reset the codec.
463
* During cold-reset the PSC is reinitialized and the last
464
* configuration set up in hw_params() is restored.
465
*/
466
return 0;
467
}
468
469
static DEFINE_SIMPLE_DEV_PM_OPS(au1xpscac97_pmops, au1xpsc_ac97_drvsuspend,
470
au1xpsc_ac97_drvresume);
471
472
static struct platform_driver au1xpsc_ac97_driver = {
473
.driver = {
474
.name = "au1xpsc_ac97",
475
.pm = pm_ptr(&au1xpscac97_pmops),
476
},
477
.probe = au1xpsc_ac97_drvprobe,
478
.remove = au1xpsc_ac97_drvremove,
479
};
480
481
module_platform_driver(au1xpsc_ac97_driver);
482
483
MODULE_LICENSE("GPL");
484
MODULE_DESCRIPTION("Au12x0/Au1550 PSC AC97 ALSA ASoC audio driver");
485
MODULE_AUTHOR("Manuel Lauss");
486
487
488