Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/sound/pci/au88x0/au88x0_pcm.c
10817 views
1
/*
2
* This program is free software; you can redistribute it and/or modify
3
* it under the terms of the GNU General Public License as published by
4
* the Free Software Foundation; either version 2 of the License, or
5
* (at your option) any later version.
6
*
7
* This program is distributed in the hope that it will be useful,
8
* but WITHOUT ANY WARRANTY; without even the implied warranty of
9
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10
* GNU Library General Public License for more details.
11
*
12
* You should have received a copy of the GNU General Public License
13
* along with this program; if not, write to the Free Software
14
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
15
*/
16
17
/*
18
* Vortex PCM ALSA driver.
19
*
20
* Supports ADB and WT DMA. Unfortunately, WT channels do not run yet.
21
* It remains stuck,and DMA transfers do not happen.
22
*/
23
#include <sound/asoundef.h>
24
#include <linux/time.h>
25
#include <sound/core.h>
26
#include <sound/pcm.h>
27
#include <sound/pcm_params.h>
28
#include "au88x0.h"
29
30
#define VORTEX_PCM_TYPE(x) (x->name[40])
31
32
/* hardware definition */
33
static struct snd_pcm_hardware snd_vortex_playback_hw_adb = {
34
.info =
35
(SNDRV_PCM_INFO_MMAP | /* SNDRV_PCM_INFO_RESUME | */
36
SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_INTERLEAVED |
37
SNDRV_PCM_INFO_MMAP_VALID),
38
.formats =
39
SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_U8 |
40
SNDRV_PCM_FMTBIT_MU_LAW | SNDRV_PCM_FMTBIT_A_LAW,
41
.rates = SNDRV_PCM_RATE_CONTINUOUS,
42
.rate_min = 5000,
43
.rate_max = 48000,
44
.channels_min = 1,
45
.channels_max = 2,
46
.buffer_bytes_max = 0x10000,
47
.period_bytes_min = 0x20,
48
.period_bytes_max = 0x1000,
49
.periods_min = 2,
50
.periods_max = 1024,
51
};
52
53
#ifndef CHIP_AU8820
54
static struct snd_pcm_hardware snd_vortex_playback_hw_a3d = {
55
.info =
56
(SNDRV_PCM_INFO_MMAP | /* SNDRV_PCM_INFO_RESUME | */
57
SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_INTERLEAVED |
58
SNDRV_PCM_INFO_MMAP_VALID),
59
.formats =
60
SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_U8 |
61
SNDRV_PCM_FMTBIT_MU_LAW | SNDRV_PCM_FMTBIT_A_LAW,
62
.rates = SNDRV_PCM_RATE_CONTINUOUS,
63
.rate_min = 5000,
64
.rate_max = 48000,
65
.channels_min = 1,
66
.channels_max = 1,
67
.buffer_bytes_max = 0x10000,
68
.period_bytes_min = 0x100,
69
.period_bytes_max = 0x1000,
70
.periods_min = 2,
71
.periods_max = 64,
72
};
73
#endif
74
static struct snd_pcm_hardware snd_vortex_playback_hw_spdif = {
75
.info =
76
(SNDRV_PCM_INFO_MMAP | /* SNDRV_PCM_INFO_RESUME | */
77
SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_INTERLEAVED |
78
SNDRV_PCM_INFO_MMAP_VALID),
79
.formats =
80
SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_U8 |
81
SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_LE | SNDRV_PCM_FMTBIT_MU_LAW |
82
SNDRV_PCM_FMTBIT_A_LAW,
83
.rates =
84
SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000,
85
.rate_min = 32000,
86
.rate_max = 48000,
87
.channels_min = 1,
88
.channels_max = 2,
89
.buffer_bytes_max = 0x10000,
90
.period_bytes_min = 0x100,
91
.period_bytes_max = 0x1000,
92
.periods_min = 2,
93
.periods_max = 64,
94
};
95
96
#ifndef CHIP_AU8810
97
static struct snd_pcm_hardware snd_vortex_playback_hw_wt = {
98
.info = (SNDRV_PCM_INFO_MMAP |
99
SNDRV_PCM_INFO_INTERLEAVED |
100
SNDRV_PCM_INFO_BLOCK_TRANSFER | SNDRV_PCM_INFO_MMAP_VALID),
101
.formats = SNDRV_PCM_FMTBIT_S16_LE,
102
.rates = SNDRV_PCM_RATE_8000_48000 | SNDRV_PCM_RATE_CONTINUOUS, // SNDRV_PCM_RATE_48000,
103
.rate_min = 8000,
104
.rate_max = 48000,
105
.channels_min = 1,
106
.channels_max = 2,
107
.buffer_bytes_max = 0x10000,
108
.period_bytes_min = 0x0400,
109
.period_bytes_max = 0x1000,
110
.periods_min = 2,
111
.periods_max = 64,
112
};
113
#endif
114
#ifdef CHIP_AU8830
115
static unsigned int au8830_channels[3] = {
116
1, 2, 4,
117
};
118
119
static struct snd_pcm_hw_constraint_list hw_constraints_au8830_channels = {
120
.count = ARRAY_SIZE(au8830_channels),
121
.list = au8830_channels,
122
.mask = 0,
123
};
124
#endif
125
/* open callback */
126
static int snd_vortex_pcm_open(struct snd_pcm_substream *substream)
127
{
128
vortex_t *vortex = snd_pcm_substream_chip(substream);
129
struct snd_pcm_runtime *runtime = substream->runtime;
130
int err;
131
132
/* Force equal size periods */
133
if ((err =
134
snd_pcm_hw_constraint_integer(runtime,
135
SNDRV_PCM_HW_PARAM_PERIODS)) < 0)
136
return err;
137
/* Avoid PAGE_SIZE boundary to fall inside of a period. */
138
if ((err =
139
snd_pcm_hw_constraint_pow2(runtime, 0,
140
SNDRV_PCM_HW_PARAM_PERIOD_BYTES)) < 0)
141
return err;
142
143
snd_pcm_hw_constraint_step(runtime, 0,
144
SNDRV_PCM_HW_PARAM_BUFFER_BYTES, 64);
145
146
if (VORTEX_PCM_TYPE(substream->pcm) != VORTEX_PCM_WT) {
147
#ifndef CHIP_AU8820
148
if (VORTEX_PCM_TYPE(substream->pcm) == VORTEX_PCM_A3D) {
149
runtime->hw = snd_vortex_playback_hw_a3d;
150
}
151
#endif
152
if (VORTEX_PCM_TYPE(substream->pcm) == VORTEX_PCM_SPDIF) {
153
runtime->hw = snd_vortex_playback_hw_spdif;
154
switch (vortex->spdif_sr) {
155
case 32000:
156
runtime->hw.rates = SNDRV_PCM_RATE_32000;
157
break;
158
case 44100:
159
runtime->hw.rates = SNDRV_PCM_RATE_44100;
160
break;
161
case 48000:
162
runtime->hw.rates = SNDRV_PCM_RATE_48000;
163
break;
164
}
165
}
166
if (VORTEX_PCM_TYPE(substream->pcm) == VORTEX_PCM_ADB
167
|| VORTEX_PCM_TYPE(substream->pcm) == VORTEX_PCM_I2S)
168
runtime->hw = snd_vortex_playback_hw_adb;
169
#ifdef CHIP_AU8830
170
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK &&
171
VORTEX_PCM_TYPE(substream->pcm) == VORTEX_PCM_ADB) {
172
runtime->hw.channels_max = 4;
173
snd_pcm_hw_constraint_list(runtime, 0,
174
SNDRV_PCM_HW_PARAM_CHANNELS,
175
&hw_constraints_au8830_channels);
176
}
177
#endif
178
substream->runtime->private_data = NULL;
179
}
180
#ifndef CHIP_AU8810
181
else {
182
runtime->hw = snd_vortex_playback_hw_wt;
183
substream->runtime->private_data = NULL;
184
}
185
#endif
186
return 0;
187
}
188
189
/* close callback */
190
static int snd_vortex_pcm_close(struct snd_pcm_substream *substream)
191
{
192
//vortex_t *chip = snd_pcm_substream_chip(substream);
193
stream_t *stream = (stream_t *) substream->runtime->private_data;
194
195
// the hardware-specific codes will be here
196
if (stream != NULL) {
197
stream->substream = NULL;
198
stream->nr_ch = 0;
199
}
200
substream->runtime->private_data = NULL;
201
return 0;
202
}
203
204
/* hw_params callback */
205
static int
206
snd_vortex_pcm_hw_params(struct snd_pcm_substream *substream,
207
struct snd_pcm_hw_params *hw_params)
208
{
209
vortex_t *chip = snd_pcm_substream_chip(substream);
210
stream_t *stream = (stream_t *) (substream->runtime->private_data);
211
int err;
212
213
// Alloc buffer memory.
214
err =
215
snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params));
216
if (err < 0) {
217
printk(KERN_ERR "Vortex: pcm page alloc failed!\n");
218
return err;
219
}
220
/*
221
printk(KERN_INFO "Vortex: periods %d, period_bytes %d, channels = %d\n", params_periods(hw_params),
222
params_period_bytes(hw_params), params_channels(hw_params));
223
*/
224
spin_lock_irq(&chip->lock);
225
// Make audio routes and config buffer DMA.
226
if (VORTEX_PCM_TYPE(substream->pcm) != VORTEX_PCM_WT) {
227
int dma, type = VORTEX_PCM_TYPE(substream->pcm);
228
/* Dealloc any routes. */
229
if (stream != NULL)
230
vortex_adb_allocroute(chip, stream->dma,
231
stream->nr_ch, stream->dir,
232
stream->type);
233
/* Alloc routes. */
234
dma =
235
vortex_adb_allocroute(chip, -1,
236
params_channels(hw_params),
237
substream->stream, type);
238
if (dma < 0) {
239
spin_unlock_irq(&chip->lock);
240
return dma;
241
}
242
stream = substream->runtime->private_data = &chip->dma_adb[dma];
243
stream->substream = substream;
244
/* Setup Buffers. */
245
vortex_adbdma_setbuffers(chip, dma,
246
params_period_bytes(hw_params),
247
params_periods(hw_params));
248
}
249
#ifndef CHIP_AU8810
250
else {
251
/* if (stream != NULL)
252
vortex_wt_allocroute(chip, substream->number, 0); */
253
vortex_wt_allocroute(chip, substream->number,
254
params_channels(hw_params));
255
stream = substream->runtime->private_data =
256
&chip->dma_wt[substream->number];
257
stream->dma = substream->number;
258
stream->substream = substream;
259
vortex_wtdma_setbuffers(chip, substream->number,
260
params_period_bytes(hw_params),
261
params_periods(hw_params));
262
}
263
#endif
264
spin_unlock_irq(&chip->lock);
265
return 0;
266
}
267
268
/* hw_free callback */
269
static int snd_vortex_pcm_hw_free(struct snd_pcm_substream *substream)
270
{
271
vortex_t *chip = snd_pcm_substream_chip(substream);
272
stream_t *stream = (stream_t *) (substream->runtime->private_data);
273
274
spin_lock_irq(&chip->lock);
275
// Delete audio routes.
276
if (VORTEX_PCM_TYPE(substream->pcm) != VORTEX_PCM_WT) {
277
if (stream != NULL)
278
vortex_adb_allocroute(chip, stream->dma,
279
stream->nr_ch, stream->dir,
280
stream->type);
281
}
282
#ifndef CHIP_AU8810
283
else {
284
if (stream != NULL)
285
vortex_wt_allocroute(chip, stream->dma, 0);
286
}
287
#endif
288
substream->runtime->private_data = NULL;
289
spin_unlock_irq(&chip->lock);
290
291
return snd_pcm_lib_free_pages(substream);
292
}
293
294
/* prepare callback */
295
static int snd_vortex_pcm_prepare(struct snd_pcm_substream *substream)
296
{
297
vortex_t *chip = snd_pcm_substream_chip(substream);
298
struct snd_pcm_runtime *runtime = substream->runtime;
299
stream_t *stream = (stream_t *) substream->runtime->private_data;
300
int dma = stream->dma, fmt, dir;
301
302
// set up the hardware with the current configuration.
303
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
304
dir = 1;
305
else
306
dir = 0;
307
fmt = vortex_alsafmt_aspfmt(runtime->format);
308
spin_lock_irq(&chip->lock);
309
if (VORTEX_PCM_TYPE(substream->pcm) != VORTEX_PCM_WT) {
310
vortex_adbdma_setmode(chip, dma, 1, dir, fmt, 0 /*? */ ,
311
0);
312
vortex_adbdma_setstartbuffer(chip, dma, 0);
313
if (VORTEX_PCM_TYPE(substream->pcm) != VORTEX_PCM_SPDIF)
314
vortex_adb_setsrc(chip, dma, runtime->rate, dir);
315
}
316
#ifndef CHIP_AU8810
317
else {
318
vortex_wtdma_setmode(chip, dma, 1, fmt, 0, 0);
319
// FIXME: Set rate (i guess using vortex_wt_writereg() somehow).
320
vortex_wtdma_setstartbuffer(chip, dma, 0);
321
}
322
#endif
323
spin_unlock_irq(&chip->lock);
324
return 0;
325
}
326
327
/* trigger callback */
328
static int snd_vortex_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
329
{
330
vortex_t *chip = snd_pcm_substream_chip(substream);
331
stream_t *stream = (stream_t *) substream->runtime->private_data;
332
int dma = stream->dma;
333
334
spin_lock(&chip->lock);
335
switch (cmd) {
336
case SNDRV_PCM_TRIGGER_START:
337
// do something to start the PCM engine
338
//printk(KERN_INFO "vortex: start %d\n", dma);
339
stream->fifo_enabled = 1;
340
if (VORTEX_PCM_TYPE(substream->pcm) != VORTEX_PCM_WT) {
341
vortex_adbdma_resetup(chip, dma);
342
vortex_adbdma_startfifo(chip, dma);
343
}
344
#ifndef CHIP_AU8810
345
else {
346
printk(KERN_INFO "vortex: wt start %d\n", dma);
347
vortex_wtdma_startfifo(chip, dma);
348
}
349
#endif
350
break;
351
case SNDRV_PCM_TRIGGER_STOP:
352
// do something to stop the PCM engine
353
//printk(KERN_INFO "vortex: stop %d\n", dma);
354
stream->fifo_enabled = 0;
355
if (VORTEX_PCM_TYPE(substream->pcm) != VORTEX_PCM_WT)
356
vortex_adbdma_pausefifo(chip, dma);
357
//vortex_adbdma_stopfifo(chip, dma);
358
#ifndef CHIP_AU8810
359
else {
360
printk(KERN_INFO "vortex: wt stop %d\n", dma);
361
vortex_wtdma_stopfifo(chip, dma);
362
}
363
#endif
364
break;
365
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
366
//printk(KERN_INFO "vortex: pause %d\n", dma);
367
if (VORTEX_PCM_TYPE(substream->pcm) != VORTEX_PCM_WT)
368
vortex_adbdma_pausefifo(chip, dma);
369
#ifndef CHIP_AU8810
370
else
371
vortex_wtdma_pausefifo(chip, dma);
372
#endif
373
break;
374
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
375
//printk(KERN_INFO "vortex: resume %d\n", dma);
376
if (VORTEX_PCM_TYPE(substream->pcm) != VORTEX_PCM_WT)
377
vortex_adbdma_resumefifo(chip, dma);
378
#ifndef CHIP_AU8810
379
else
380
vortex_wtdma_resumefifo(chip, dma);
381
#endif
382
break;
383
default:
384
spin_unlock(&chip->lock);
385
return -EINVAL;
386
}
387
spin_unlock(&chip->lock);
388
return 0;
389
}
390
391
/* pointer callback */
392
static snd_pcm_uframes_t snd_vortex_pcm_pointer(struct snd_pcm_substream *substream)
393
{
394
vortex_t *chip = snd_pcm_substream_chip(substream);
395
stream_t *stream = (stream_t *) substream->runtime->private_data;
396
int dma = stream->dma;
397
snd_pcm_uframes_t current_ptr = 0;
398
399
spin_lock(&chip->lock);
400
if (VORTEX_PCM_TYPE(substream->pcm) != VORTEX_PCM_WT)
401
current_ptr = vortex_adbdma_getlinearpos(chip, dma);
402
#ifndef CHIP_AU8810
403
else
404
current_ptr = vortex_wtdma_getlinearpos(chip, dma);
405
#endif
406
//printk(KERN_INFO "vortex: pointer = 0x%x\n", current_ptr);
407
spin_unlock(&chip->lock);
408
return (bytes_to_frames(substream->runtime, current_ptr));
409
}
410
411
/* operators */
412
static struct snd_pcm_ops snd_vortex_playback_ops = {
413
.open = snd_vortex_pcm_open,
414
.close = snd_vortex_pcm_close,
415
.ioctl = snd_pcm_lib_ioctl,
416
.hw_params = snd_vortex_pcm_hw_params,
417
.hw_free = snd_vortex_pcm_hw_free,
418
.prepare = snd_vortex_pcm_prepare,
419
.trigger = snd_vortex_pcm_trigger,
420
.pointer = snd_vortex_pcm_pointer,
421
.page = snd_pcm_sgbuf_ops_page,
422
};
423
424
/*
425
* definitions of capture are omitted here...
426
*/
427
428
static char *vortex_pcm_prettyname[VORTEX_PCM_LAST] = {
429
CARD_NAME " ADB",
430
CARD_NAME " SPDIF",
431
CARD_NAME " A3D",
432
CARD_NAME " WT",
433
CARD_NAME " I2S",
434
};
435
static char *vortex_pcm_name[VORTEX_PCM_LAST] = {
436
"adb",
437
"spdif",
438
"a3d",
439
"wt",
440
"i2s",
441
};
442
443
/* SPDIF kcontrol */
444
445
static int snd_vortex_spdif_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
446
{
447
uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
448
uinfo->count = 1;
449
return 0;
450
}
451
452
static int snd_vortex_spdif_mask_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
453
{
454
ucontrol->value.iec958.status[0] = 0xff;
455
ucontrol->value.iec958.status[1] = 0xff;
456
ucontrol->value.iec958.status[2] = 0xff;
457
ucontrol->value.iec958.status[3] = IEC958_AES3_CON_FS;
458
return 0;
459
}
460
461
static int snd_vortex_spdif_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
462
{
463
vortex_t *vortex = snd_kcontrol_chip(kcontrol);
464
ucontrol->value.iec958.status[0] = 0x00;
465
ucontrol->value.iec958.status[1] = IEC958_AES1_CON_ORIGINAL|IEC958_AES1_CON_DIGDIGCONV_ID;
466
ucontrol->value.iec958.status[2] = 0x00;
467
switch (vortex->spdif_sr) {
468
case 32000: ucontrol->value.iec958.status[3] = IEC958_AES3_CON_FS_32000; break;
469
case 44100: ucontrol->value.iec958.status[3] = IEC958_AES3_CON_FS_44100; break;
470
case 48000: ucontrol->value.iec958.status[3] = IEC958_AES3_CON_FS_48000; break;
471
}
472
return 0;
473
}
474
475
static int snd_vortex_spdif_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
476
{
477
vortex_t *vortex = snd_kcontrol_chip(kcontrol);
478
int spdif_sr = 48000;
479
switch (ucontrol->value.iec958.status[3] & IEC958_AES3_CON_FS) {
480
case IEC958_AES3_CON_FS_32000: spdif_sr = 32000; break;
481
case IEC958_AES3_CON_FS_44100: spdif_sr = 44100; break;
482
case IEC958_AES3_CON_FS_48000: spdif_sr = 48000; break;
483
}
484
if (spdif_sr == vortex->spdif_sr)
485
return 0;
486
vortex->spdif_sr = spdif_sr;
487
vortex_spdif_init(vortex, vortex->spdif_sr, 1);
488
return 1;
489
}
490
491
/* spdif controls */
492
static struct snd_kcontrol_new snd_vortex_mixer_spdif[] __devinitdata = {
493
{
494
.iface = SNDRV_CTL_ELEM_IFACE_PCM,
495
.name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT),
496
.info = snd_vortex_spdif_info,
497
.get = snd_vortex_spdif_get,
498
.put = snd_vortex_spdif_put,
499
},
500
{
501
.access = SNDRV_CTL_ELEM_ACCESS_READ,
502
.iface = SNDRV_CTL_ELEM_IFACE_PCM,
503
.name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,CON_MASK),
504
.info = snd_vortex_spdif_info,
505
.get = snd_vortex_spdif_mask_get
506
},
507
};
508
509
/* create a pcm device */
510
static int __devinit snd_vortex_new_pcm(vortex_t *chip, int idx, int nr)
511
{
512
struct snd_pcm *pcm;
513
struct snd_kcontrol *kctl;
514
int i;
515
int err, nr_capt;
516
517
if (!chip || idx < 0 || idx >= VORTEX_PCM_LAST)
518
return -ENODEV;
519
520
/* idx indicates which kind of PCM device. ADB, SPDIF, I2S and A3D share the
521
* same dma engine. WT uses it own separate dma engine which can't capture. */
522
if (idx == VORTEX_PCM_ADB)
523
nr_capt = nr;
524
else
525
nr_capt = 0;
526
err = snd_pcm_new(chip->card, vortex_pcm_prettyname[idx], idx, nr,
527
nr_capt, &pcm);
528
if (err < 0)
529
return err;
530
snprintf(pcm->name, sizeof(pcm->name),
531
"%s %s", CARD_NAME_SHORT, vortex_pcm_name[idx]);
532
chip->pcm[idx] = pcm;
533
// This is an evil hack, but it saves a lot of duplicated code.
534
VORTEX_PCM_TYPE(pcm) = idx;
535
pcm->private_data = chip;
536
/* set operators */
537
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK,
538
&snd_vortex_playback_ops);
539
if (idx == VORTEX_PCM_ADB)
540
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE,
541
&snd_vortex_playback_ops);
542
543
/* pre-allocation of Scatter-Gather buffers */
544
545
snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV_SG,
546
snd_dma_pci_data(chip->pci_dev),
547
0x10000, 0x10000);
548
549
if (VORTEX_PCM_TYPE(pcm) == VORTEX_PCM_SPDIF) {
550
for (i = 0; i < ARRAY_SIZE(snd_vortex_mixer_spdif); i++) {
551
kctl = snd_ctl_new1(&snd_vortex_mixer_spdif[i], chip);
552
if (!kctl)
553
return -ENOMEM;
554
if ((err = snd_ctl_add(chip->card, kctl)) < 0)
555
return err;
556
}
557
}
558
return 0;
559
}
560
561