Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/sound/pci/emu10k1/p16v.c
10820 views
1
/*
2
* Copyright (c) by James Courtier-Dutton <[email protected]>
3
* Driver p16v chips
4
* Version: 0.25
5
*
6
* FEATURES currently supported:
7
* Output fixed at S32_LE, 2 channel to hw:0,0
8
* Rates: 44.1, 48, 96, 192.
9
*
10
* Changelog:
11
* 0.8
12
* Use separate card based buffer for periods table.
13
* 0.9
14
* Use 2 channel output streams instead of 8 channel.
15
* (8 channel output streams might be good for ASIO type output)
16
* Corrected speaker output, so Front -> Front etc.
17
* 0.10
18
* Fixed missed interrupts.
19
* 0.11
20
* Add Sound card model number and names.
21
* Add Analog volume controls.
22
* 0.12
23
* Corrected playback interrupts. Now interrupt per period, instead of half period.
24
* 0.13
25
* Use single trigger for multichannel.
26
* 0.14
27
* Mic capture now works at fixed: S32_LE, 96000Hz, Stereo.
28
* 0.15
29
* Force buffer_size / period_size == INTEGER.
30
* 0.16
31
* Update p16v.c to work with changed alsa api.
32
* 0.17
33
* Update p16v.c to work with changed alsa api. Removed boot_devs.
34
* 0.18
35
* Merging with snd-emu10k1 driver.
36
* 0.19
37
* One stereo channel at 24bit now works.
38
* 0.20
39
* Added better register defines.
40
* 0.21
41
* Integrated with snd-emu10k1 driver.
42
* 0.22
43
* Removed #if 0 ... #endif
44
* 0.23
45
* Implement different capture rates.
46
* 0.24
47
* Implement different capture source channels.
48
* e.g. When HD Capture source is set to SPDIF,
49
* setting HD Capture channel to 0 captures from CDROM digital input.
50
* setting HD Capture channel to 1 captures from SPDIF in.
51
* 0.25
52
* Include capture buffer sizes.
53
*
54
* BUGS:
55
* Some stability problems when unloading the snd-p16v kernel module.
56
* --
57
*
58
* TODO:
59
* SPDIF out.
60
* Find out how to change capture sample rates. E.g. To record SPDIF at 48000Hz.
61
* Currently capture fixed at 48000Hz.
62
*
63
* --
64
* GENERAL INFO:
65
* Model: SB0240
66
* P16V Chip: CA0151-DBS
67
* Audigy 2 Chip: CA0102-IAT
68
* AC97 Codec: STAC 9721
69
* ADC: Philips 1361T (Stereo 24bit)
70
* DAC: CS4382-K (8-channel, 24bit, 192Khz)
71
*
72
* This code was initially based on code from ALSA's emu10k1x.c which is:
73
* Copyright (c) by Francisco Moraes <[email protected]>
74
*
75
* This program is free software; you can redistribute it and/or modify
76
* it under the terms of the GNU General Public License as published by
77
* the Free Software Foundation; either version 2 of the License, or
78
* (at your option) any later version.
79
*
80
* This program is distributed in the hope that it will be useful,
81
* but WITHOUT ANY WARRANTY; without even the implied warranty of
82
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
83
* GNU General Public License for more details.
84
*
85
* You should have received a copy of the GNU General Public License
86
* along with this program; if not, write to the Free Software
87
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
88
*
89
*/
90
#include <linux/delay.h>
91
#include <linux/init.h>
92
#include <linux/interrupt.h>
93
#include <linux/pci.h>
94
#include <linux/slab.h>
95
#include <linux/vmalloc.h>
96
#include <linux/moduleparam.h>
97
#include <sound/core.h>
98
#include <sound/initval.h>
99
#include <sound/pcm.h>
100
#include <sound/ac97_codec.h>
101
#include <sound/info.h>
102
#include <sound/tlv.h>
103
#include <sound/emu10k1.h>
104
#include "p16v.h"
105
106
#define SET_CHANNEL 0 /* Testing channel outputs 0=Front, 1=Center/LFE, 2=Unknown, 3=Rear */
107
#define PCM_FRONT_CHANNEL 0
108
#define PCM_REAR_CHANNEL 1
109
#define PCM_CENTER_LFE_CHANNEL 2
110
#define PCM_SIDE_CHANNEL 3
111
#define CONTROL_FRONT_CHANNEL 0
112
#define CONTROL_REAR_CHANNEL 3
113
#define CONTROL_CENTER_LFE_CHANNEL 1
114
#define CONTROL_SIDE_CHANNEL 2
115
116
/* Card IDs:
117
* Class 0401: 1102:0004 (rev 04) Subsystem: 1102:2002 -> Audigy2 ZS 7.1 Model:SB0350
118
* Class 0401: 1102:0004 (rev 04) Subsystem: 1102:1007 -> Audigy2 6.1 Model:SB0240
119
* Class 0401: 1102:0004 (rev 04) Subsystem: 1102:1002 -> Audigy2 Platinum Model:SB msb0240230009266
120
* Class 0401: 1102:0004 (rev 04) Subsystem: 1102:2007 -> Audigy4 Pro Model:SB0380 M1SB0380472001901E
121
*
122
*/
123
124
/* hardware definition */
125
static struct snd_pcm_hardware snd_p16v_playback_hw = {
126
.info = SNDRV_PCM_INFO_MMAP |
127
SNDRV_PCM_INFO_INTERLEAVED |
128
SNDRV_PCM_INFO_BLOCK_TRANSFER |
129
SNDRV_PCM_INFO_RESUME |
130
SNDRV_PCM_INFO_MMAP_VALID |
131
SNDRV_PCM_INFO_SYNC_START,
132
.formats = SNDRV_PCM_FMTBIT_S32_LE, /* Only supports 24-bit samples padded to 32 bits. */
133
.rates = SNDRV_PCM_RATE_192000 | SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_44100,
134
.rate_min = 44100,
135
.rate_max = 192000,
136
.channels_min = 8,
137
.channels_max = 8,
138
.buffer_bytes_max = ((65536 - 64) * 8),
139
.period_bytes_min = 64,
140
.period_bytes_max = (65536 - 64),
141
.periods_min = 2,
142
.periods_max = 8,
143
.fifo_size = 0,
144
};
145
146
static struct snd_pcm_hardware snd_p16v_capture_hw = {
147
.info = (SNDRV_PCM_INFO_MMAP |
148
SNDRV_PCM_INFO_INTERLEAVED |
149
SNDRV_PCM_INFO_BLOCK_TRANSFER |
150
SNDRV_PCM_INFO_RESUME |
151
SNDRV_PCM_INFO_MMAP_VALID),
152
.formats = SNDRV_PCM_FMTBIT_S32_LE,
153
.rates = SNDRV_PCM_RATE_192000 | SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_44100,
154
.rate_min = 44100,
155
.rate_max = 192000,
156
.channels_min = 2,
157
.channels_max = 2,
158
.buffer_bytes_max = (65536 - 64),
159
.period_bytes_min = 64,
160
.period_bytes_max = (65536 - 128) >> 1, /* size has to be N*64 bytes */
161
.periods_min = 2,
162
.periods_max = 2,
163
.fifo_size = 0,
164
};
165
166
static void snd_p16v_pcm_free_substream(struct snd_pcm_runtime *runtime)
167
{
168
struct snd_emu10k1_pcm *epcm = runtime->private_data;
169
170
if (epcm) {
171
/* snd_printk(KERN_DEBUG "epcm free: %p\n", epcm); */
172
kfree(epcm);
173
}
174
}
175
176
/* open_playback callback */
177
static int snd_p16v_pcm_open_playback_channel(struct snd_pcm_substream *substream, int channel_id)
178
{
179
struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream);
180
struct snd_emu10k1_voice *channel = &(emu->p16v_voices[channel_id]);
181
struct snd_emu10k1_pcm *epcm;
182
struct snd_pcm_runtime *runtime = substream->runtime;
183
int err;
184
185
epcm = kzalloc(sizeof(*epcm), GFP_KERNEL);
186
/* snd_printk(KERN_DEBUG "epcm kcalloc: %p\n", epcm); */
187
188
if (epcm == NULL)
189
return -ENOMEM;
190
epcm->emu = emu;
191
epcm->substream = substream;
192
/*
193
snd_printk(KERN_DEBUG "epcm device=%d, channel_id=%d\n",
194
substream->pcm->device, channel_id);
195
*/
196
runtime->private_data = epcm;
197
runtime->private_free = snd_p16v_pcm_free_substream;
198
199
runtime->hw = snd_p16v_playback_hw;
200
201
channel->emu = emu;
202
channel->number = channel_id;
203
204
channel->use=1;
205
#if 0 /* debug */
206
snd_printk(KERN_DEBUG
207
"p16v: open channel_id=%d, channel=%p, use=0x%x\n",
208
channel_id, channel, channel->use);
209
printk(KERN_DEBUG "open:channel_id=%d, chip=%p, channel=%p\n",
210
channel_id, chip, channel);
211
#endif /* debug */
212
/* channel->interrupt = snd_p16v_pcm_channel_interrupt; */
213
channel->epcm = epcm;
214
if ((err = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS)) < 0)
215
return err;
216
217
runtime->sync.id32[0] = substream->pcm->card->number;
218
runtime->sync.id32[1] = 'P';
219
runtime->sync.id32[2] = 16;
220
runtime->sync.id32[3] = 'V';
221
222
return 0;
223
}
224
/* open_capture callback */
225
static int snd_p16v_pcm_open_capture_channel(struct snd_pcm_substream *substream, int channel_id)
226
{
227
struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream);
228
struct snd_emu10k1_voice *channel = &(emu->p16v_capture_voice);
229
struct snd_emu10k1_pcm *epcm;
230
struct snd_pcm_runtime *runtime = substream->runtime;
231
int err;
232
233
epcm = kzalloc(sizeof(*epcm), GFP_KERNEL);
234
/* snd_printk(KERN_DEBUG "epcm kcalloc: %p\n", epcm); */
235
236
if (epcm == NULL)
237
return -ENOMEM;
238
epcm->emu = emu;
239
epcm->substream = substream;
240
/*
241
snd_printk(KERN_DEBUG "epcm device=%d, channel_id=%d\n",
242
substream->pcm->device, channel_id);
243
*/
244
runtime->private_data = epcm;
245
runtime->private_free = snd_p16v_pcm_free_substream;
246
247
runtime->hw = snd_p16v_capture_hw;
248
249
channel->emu = emu;
250
channel->number = channel_id;
251
252
channel->use=1;
253
#if 0 /* debug */
254
snd_printk(KERN_DEBUG
255
"p16v: open channel_id=%d, channel=%p, use=0x%x\n",
256
channel_id, channel, channel->use);
257
printk(KERN_DEBUG "open:channel_id=%d, chip=%p, channel=%p\n",
258
channel_id, chip, channel);
259
#endif /* debug */
260
/* channel->interrupt = snd_p16v_pcm_channel_interrupt; */
261
channel->epcm = epcm;
262
if ((err = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS)) < 0)
263
return err;
264
265
return 0;
266
}
267
268
269
/* close callback */
270
static int snd_p16v_pcm_close_playback(struct snd_pcm_substream *substream)
271
{
272
struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream);
273
//struct snd_pcm_runtime *runtime = substream->runtime;
274
//struct snd_emu10k1_pcm *epcm = runtime->private_data;
275
emu->p16v_voices[substream->pcm->device - emu->p16v_device_offset].use = 0;
276
/* FIXME: maybe zero others */
277
return 0;
278
}
279
280
/* close callback */
281
static int snd_p16v_pcm_close_capture(struct snd_pcm_substream *substream)
282
{
283
struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream);
284
//struct snd_pcm_runtime *runtime = substream->runtime;
285
//struct snd_emu10k1_pcm *epcm = runtime->private_data;
286
emu->p16v_capture_voice.use = 0;
287
/* FIXME: maybe zero others */
288
return 0;
289
}
290
291
static int snd_p16v_pcm_open_playback_front(struct snd_pcm_substream *substream)
292
{
293
return snd_p16v_pcm_open_playback_channel(substream, PCM_FRONT_CHANNEL);
294
}
295
296
static int snd_p16v_pcm_open_capture(struct snd_pcm_substream *substream)
297
{
298
// Only using channel 0 for now, but the card has 2 channels.
299
return snd_p16v_pcm_open_capture_channel(substream, 0);
300
}
301
302
/* hw_params callback */
303
static int snd_p16v_pcm_hw_params_playback(struct snd_pcm_substream *substream,
304
struct snd_pcm_hw_params *hw_params)
305
{
306
int result;
307
result = snd_pcm_lib_malloc_pages(substream,
308
params_buffer_bytes(hw_params));
309
return result;
310
}
311
312
/* hw_params callback */
313
static int snd_p16v_pcm_hw_params_capture(struct snd_pcm_substream *substream,
314
struct snd_pcm_hw_params *hw_params)
315
{
316
int result;
317
result = snd_pcm_lib_malloc_pages(substream,
318
params_buffer_bytes(hw_params));
319
return result;
320
}
321
322
323
/* hw_free callback */
324
static int snd_p16v_pcm_hw_free_playback(struct snd_pcm_substream *substream)
325
{
326
int result;
327
result = snd_pcm_lib_free_pages(substream);
328
return result;
329
}
330
331
/* hw_free callback */
332
static int snd_p16v_pcm_hw_free_capture(struct snd_pcm_substream *substream)
333
{
334
int result;
335
result = snd_pcm_lib_free_pages(substream);
336
return result;
337
}
338
339
340
/* prepare playback callback */
341
static int snd_p16v_pcm_prepare_playback(struct snd_pcm_substream *substream)
342
{
343
struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream);
344
struct snd_pcm_runtime *runtime = substream->runtime;
345
int channel = substream->pcm->device - emu->p16v_device_offset;
346
u32 *table_base = (u32 *)(emu->p16v_buffer.area+(8*16*channel));
347
u32 period_size_bytes = frames_to_bytes(runtime, runtime->period_size);
348
int i;
349
u32 tmp;
350
351
#if 0 /* debug */
352
snd_printk(KERN_DEBUG "prepare:channel_number=%d, rate=%d, "
353
"format=0x%x, channels=%d, buffer_size=%ld, "
354
"period_size=%ld, periods=%u, frames_to_bytes=%d\n",
355
channel, runtime->rate, runtime->format, runtime->channels,
356
runtime->buffer_size, runtime->period_size,
357
runtime->periods, frames_to_bytes(runtime, 1));
358
snd_printk(KERN_DEBUG "dma_addr=%x, dma_area=%p, table_base=%p\n",
359
runtime->dma_addr, runtime->dma_area, table_base);
360
snd_printk(KERN_DEBUG "dma_addr=%x, dma_area=%p, dma_bytes(size)=%x\n",
361
emu->p16v_buffer.addr, emu->p16v_buffer.area,
362
emu->p16v_buffer.bytes);
363
#endif /* debug */
364
tmp = snd_emu10k1_ptr_read(emu, A_SPDIF_SAMPLERATE, channel);
365
switch (runtime->rate) {
366
case 44100:
367
snd_emu10k1_ptr_write(emu, A_SPDIF_SAMPLERATE, channel, (tmp & ~0xe0e0) | 0x8080);
368
break;
369
case 96000:
370
snd_emu10k1_ptr_write(emu, A_SPDIF_SAMPLERATE, channel, (tmp & ~0xe0e0) | 0x4040);
371
break;
372
case 192000:
373
snd_emu10k1_ptr_write(emu, A_SPDIF_SAMPLERATE, channel, (tmp & ~0xe0e0) | 0x2020);
374
break;
375
case 48000:
376
default:
377
snd_emu10k1_ptr_write(emu, A_SPDIF_SAMPLERATE, channel, (tmp & ~0xe0e0) | 0x0000);
378
break;
379
}
380
/* FIXME: Check emu->buffer.size before actually writing to it. */
381
for(i = 0; i < runtime->periods; i++) {
382
table_base[i*2]=runtime->dma_addr+(i*period_size_bytes);
383
table_base[(i*2)+1]=period_size_bytes<<16;
384
}
385
386
snd_emu10k1_ptr20_write(emu, PLAYBACK_LIST_ADDR, channel, emu->p16v_buffer.addr+(8*16*channel));
387
snd_emu10k1_ptr20_write(emu, PLAYBACK_LIST_SIZE, channel, (runtime->periods - 1) << 19);
388
snd_emu10k1_ptr20_write(emu, PLAYBACK_LIST_PTR, channel, 0);
389
snd_emu10k1_ptr20_write(emu, PLAYBACK_DMA_ADDR, channel, runtime->dma_addr);
390
//snd_emu10k1_ptr20_write(emu, PLAYBACK_PERIOD_SIZE, channel, frames_to_bytes(runtime, runtime->period_size)<<16); // buffer size in bytes
391
snd_emu10k1_ptr20_write(emu, PLAYBACK_PERIOD_SIZE, channel, 0); // buffer size in bytes
392
snd_emu10k1_ptr20_write(emu, PLAYBACK_POINTER, channel, 0);
393
snd_emu10k1_ptr20_write(emu, 0x07, channel, 0x0);
394
snd_emu10k1_ptr20_write(emu, 0x08, channel, 0);
395
396
return 0;
397
}
398
399
/* prepare capture callback */
400
static int snd_p16v_pcm_prepare_capture(struct snd_pcm_substream *substream)
401
{
402
struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream);
403
struct snd_pcm_runtime *runtime = substream->runtime;
404
int channel = substream->pcm->device - emu->p16v_device_offset;
405
u32 tmp;
406
407
/*
408
printk(KERN_DEBUG "prepare capture:channel_number=%d, rate=%d, "
409
"format=0x%x, channels=%d, buffer_size=%ld, period_size=%ld, "
410
"frames_to_bytes=%d\n",
411
channel, runtime->rate, runtime->format, runtime->channels,
412
runtime->buffer_size, runtime->period_size,
413
frames_to_bytes(runtime, 1));
414
*/
415
tmp = snd_emu10k1_ptr_read(emu, A_SPDIF_SAMPLERATE, channel);
416
switch (runtime->rate) {
417
case 44100:
418
snd_emu10k1_ptr_write(emu, A_SPDIF_SAMPLERATE, channel, (tmp & ~0x0e00) | 0x0800);
419
break;
420
case 96000:
421
snd_emu10k1_ptr_write(emu, A_SPDIF_SAMPLERATE, channel, (tmp & ~0x0e00) | 0x0400);
422
break;
423
case 192000:
424
snd_emu10k1_ptr_write(emu, A_SPDIF_SAMPLERATE, channel, (tmp & ~0x0e00) | 0x0200);
425
break;
426
case 48000:
427
default:
428
snd_emu10k1_ptr_write(emu, A_SPDIF_SAMPLERATE, channel, (tmp & ~0x0e00) | 0x0000);
429
break;
430
}
431
/* FIXME: Check emu->buffer.size before actually writing to it. */
432
snd_emu10k1_ptr20_write(emu, 0x13, channel, 0);
433
snd_emu10k1_ptr20_write(emu, CAPTURE_DMA_ADDR, channel, runtime->dma_addr);
434
snd_emu10k1_ptr20_write(emu, CAPTURE_BUFFER_SIZE, channel, frames_to_bytes(runtime, runtime->buffer_size) << 16); // buffer size in bytes
435
snd_emu10k1_ptr20_write(emu, CAPTURE_POINTER, channel, 0);
436
//snd_emu10k1_ptr20_write(emu, CAPTURE_SOURCE, 0x0, 0x333300e4); /* Select MIC or Line in */
437
//snd_emu10k1_ptr20_write(emu, EXTENDED_INT_MASK, 0, snd_emu10k1_ptr20_read(emu, EXTENDED_INT_MASK, 0) | (0x110000<<channel));
438
439
return 0;
440
}
441
442
static void snd_p16v_intr_enable(struct snd_emu10k1 *emu, unsigned int intrenb)
443
{
444
unsigned long flags;
445
unsigned int enable;
446
447
spin_lock_irqsave(&emu->emu_lock, flags);
448
enable = inl(emu->port + INTE2) | intrenb;
449
outl(enable, emu->port + INTE2);
450
spin_unlock_irqrestore(&emu->emu_lock, flags);
451
}
452
453
static void snd_p16v_intr_disable(struct snd_emu10k1 *emu, unsigned int intrenb)
454
{
455
unsigned long flags;
456
unsigned int disable;
457
458
spin_lock_irqsave(&emu->emu_lock, flags);
459
disable = inl(emu->port + INTE2) & (~intrenb);
460
outl(disable, emu->port + INTE2);
461
spin_unlock_irqrestore(&emu->emu_lock, flags);
462
}
463
464
/* trigger_playback callback */
465
static int snd_p16v_pcm_trigger_playback(struct snd_pcm_substream *substream,
466
int cmd)
467
{
468
struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream);
469
struct snd_pcm_runtime *runtime;
470
struct snd_emu10k1_pcm *epcm;
471
int channel;
472
int result = 0;
473
struct snd_pcm_substream *s;
474
u32 basic = 0;
475
u32 inte = 0;
476
int running = 0;
477
478
switch (cmd) {
479
case SNDRV_PCM_TRIGGER_START:
480
running=1;
481
break;
482
case SNDRV_PCM_TRIGGER_STOP:
483
default:
484
running = 0;
485
break;
486
}
487
snd_pcm_group_for_each_entry(s, substream) {
488
if (snd_pcm_substream_chip(s) != emu ||
489
s->stream != SNDRV_PCM_STREAM_PLAYBACK)
490
continue;
491
runtime = s->runtime;
492
epcm = runtime->private_data;
493
channel = substream->pcm->device-emu->p16v_device_offset;
494
/* snd_printk(KERN_DEBUG "p16v channel=%d\n", channel); */
495
epcm->running = running;
496
basic |= (0x1<<channel);
497
inte |= (INTE2_PLAYBACK_CH_0_LOOP<<channel);
498
snd_pcm_trigger_done(s, substream);
499
}
500
/* snd_printk(KERN_DEBUG "basic=0x%x, inte=0x%x\n", basic, inte); */
501
502
switch (cmd) {
503
case SNDRV_PCM_TRIGGER_START:
504
snd_p16v_intr_enable(emu, inte);
505
snd_emu10k1_ptr20_write(emu, BASIC_INTERRUPT, 0, snd_emu10k1_ptr20_read(emu, BASIC_INTERRUPT, 0)| (basic));
506
break;
507
case SNDRV_PCM_TRIGGER_STOP:
508
snd_emu10k1_ptr20_write(emu, BASIC_INTERRUPT, 0, snd_emu10k1_ptr20_read(emu, BASIC_INTERRUPT, 0) & ~(basic));
509
snd_p16v_intr_disable(emu, inte);
510
break;
511
default:
512
result = -EINVAL;
513
break;
514
}
515
return result;
516
}
517
518
/* trigger_capture callback */
519
static int snd_p16v_pcm_trigger_capture(struct snd_pcm_substream *substream,
520
int cmd)
521
{
522
struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream);
523
struct snd_pcm_runtime *runtime = substream->runtime;
524
struct snd_emu10k1_pcm *epcm = runtime->private_data;
525
int channel = 0;
526
int result = 0;
527
u32 inte = INTE2_CAPTURE_CH_0_LOOP | INTE2_CAPTURE_CH_0_HALF_LOOP;
528
529
switch (cmd) {
530
case SNDRV_PCM_TRIGGER_START:
531
snd_p16v_intr_enable(emu, inte);
532
snd_emu10k1_ptr20_write(emu, BASIC_INTERRUPT, 0, snd_emu10k1_ptr20_read(emu, BASIC_INTERRUPT, 0)|(0x100<<channel));
533
epcm->running = 1;
534
break;
535
case SNDRV_PCM_TRIGGER_STOP:
536
snd_emu10k1_ptr20_write(emu, BASIC_INTERRUPT, 0, snd_emu10k1_ptr20_read(emu, BASIC_INTERRUPT, 0) & ~(0x100<<channel));
537
snd_p16v_intr_disable(emu, inte);
538
//snd_emu10k1_ptr20_write(emu, EXTENDED_INT_MASK, 0, snd_emu10k1_ptr20_read(emu, EXTENDED_INT_MASK, 0) & ~(0x110000<<channel));
539
epcm->running = 0;
540
break;
541
default:
542
result = -EINVAL;
543
break;
544
}
545
return result;
546
}
547
548
/* pointer_playback callback */
549
static snd_pcm_uframes_t
550
snd_p16v_pcm_pointer_playback(struct snd_pcm_substream *substream)
551
{
552
struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream);
553
struct snd_pcm_runtime *runtime = substream->runtime;
554
struct snd_emu10k1_pcm *epcm = runtime->private_data;
555
snd_pcm_uframes_t ptr, ptr1, ptr2,ptr3,ptr4 = 0;
556
int channel = substream->pcm->device - emu->p16v_device_offset;
557
if (!epcm->running)
558
return 0;
559
560
ptr3 = snd_emu10k1_ptr20_read(emu, PLAYBACK_LIST_PTR, channel);
561
ptr1 = snd_emu10k1_ptr20_read(emu, PLAYBACK_POINTER, channel);
562
ptr4 = snd_emu10k1_ptr20_read(emu, PLAYBACK_LIST_PTR, channel);
563
if (ptr3 != ptr4) ptr1 = snd_emu10k1_ptr20_read(emu, PLAYBACK_POINTER, channel);
564
ptr2 = bytes_to_frames(runtime, ptr1);
565
ptr2+= (ptr4 >> 3) * runtime->period_size;
566
ptr=ptr2;
567
if (ptr >= runtime->buffer_size)
568
ptr -= runtime->buffer_size;
569
570
return ptr;
571
}
572
573
/* pointer_capture callback */
574
static snd_pcm_uframes_t
575
snd_p16v_pcm_pointer_capture(struct snd_pcm_substream *substream)
576
{
577
struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream);
578
struct snd_pcm_runtime *runtime = substream->runtime;
579
struct snd_emu10k1_pcm *epcm = runtime->private_data;
580
snd_pcm_uframes_t ptr, ptr1, ptr2 = 0;
581
int channel = 0;
582
583
if (!epcm->running)
584
return 0;
585
586
ptr1 = snd_emu10k1_ptr20_read(emu, CAPTURE_POINTER, channel);
587
ptr2 = bytes_to_frames(runtime, ptr1);
588
ptr=ptr2;
589
if (ptr >= runtime->buffer_size) {
590
ptr -= runtime->buffer_size;
591
printk(KERN_WARNING "buffer capture limited!\n");
592
}
593
/*
594
printk(KERN_DEBUG "ptr1 = 0x%lx, ptr2=0x%lx, ptr=0x%lx, "
595
"buffer_size = 0x%x, period_size = 0x%x, bits=%d, rate=%d\n",
596
ptr1, ptr2, ptr, (int)runtime->buffer_size,
597
(int)runtime->period_size, (int)runtime->frame_bits,
598
(int)runtime->rate);
599
*/
600
return ptr;
601
}
602
603
/* operators */
604
static struct snd_pcm_ops snd_p16v_playback_front_ops = {
605
.open = snd_p16v_pcm_open_playback_front,
606
.close = snd_p16v_pcm_close_playback,
607
.ioctl = snd_pcm_lib_ioctl,
608
.hw_params = snd_p16v_pcm_hw_params_playback,
609
.hw_free = snd_p16v_pcm_hw_free_playback,
610
.prepare = snd_p16v_pcm_prepare_playback,
611
.trigger = snd_p16v_pcm_trigger_playback,
612
.pointer = snd_p16v_pcm_pointer_playback,
613
};
614
615
static struct snd_pcm_ops snd_p16v_capture_ops = {
616
.open = snd_p16v_pcm_open_capture,
617
.close = snd_p16v_pcm_close_capture,
618
.ioctl = snd_pcm_lib_ioctl,
619
.hw_params = snd_p16v_pcm_hw_params_capture,
620
.hw_free = snd_p16v_pcm_hw_free_capture,
621
.prepare = snd_p16v_pcm_prepare_capture,
622
.trigger = snd_p16v_pcm_trigger_capture,
623
.pointer = snd_p16v_pcm_pointer_capture,
624
};
625
626
627
int snd_p16v_free(struct snd_emu10k1 *chip)
628
{
629
// release the data
630
if (chip->p16v_buffer.area) {
631
snd_dma_free_pages(&chip->p16v_buffer);
632
/*
633
snd_printk(KERN_DEBUG "period lables free: %p\n",
634
&chip->p16v_buffer);
635
*/
636
}
637
return 0;
638
}
639
640
int __devinit snd_p16v_pcm(struct snd_emu10k1 *emu, int device, struct snd_pcm **rpcm)
641
{
642
struct snd_pcm *pcm;
643
struct snd_pcm_substream *substream;
644
int err;
645
int capture=1;
646
647
/* snd_printk(KERN_DEBUG "snd_p16v_pcm called. device=%d\n", device); */
648
emu->p16v_device_offset = device;
649
if (rpcm)
650
*rpcm = NULL;
651
652
if ((err = snd_pcm_new(emu->card, "p16v", device, 1, capture, &pcm)) < 0)
653
return err;
654
655
pcm->private_data = emu;
656
// Single playback 8 channel device.
657
// Single capture 2 channel device.
658
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_p16v_playback_front_ops);
659
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_p16v_capture_ops);
660
661
pcm->info_flags = 0;
662
pcm->dev_subclass = SNDRV_PCM_SUBCLASS_GENERIC_MIX;
663
strcpy(pcm->name, "p16v");
664
emu->pcm_p16v = pcm;
665
666
for(substream = pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream;
667
substream;
668
substream = substream->next) {
669
if ((err = snd_pcm_lib_preallocate_pages(substream,
670
SNDRV_DMA_TYPE_DEV,
671
snd_dma_pci_data(emu->pci),
672
((65536 - 64) * 8), ((65536 - 64) * 8))) < 0)
673
return err;
674
/*
675
snd_printk(KERN_DEBUG
676
"preallocate playback substream: err=%d\n", err);
677
*/
678
}
679
680
for (substream = pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream;
681
substream;
682
substream = substream->next) {
683
if ((err = snd_pcm_lib_preallocate_pages(substream,
684
SNDRV_DMA_TYPE_DEV,
685
snd_dma_pci_data(emu->pci),
686
65536 - 64, 65536 - 64)) < 0)
687
return err;
688
/*
689
snd_printk(KERN_DEBUG
690
"preallocate capture substream: err=%d\n", err);
691
*/
692
}
693
694
if (rpcm)
695
*rpcm = pcm;
696
697
return 0;
698
}
699
700
static int snd_p16v_volume_info(struct snd_kcontrol *kcontrol,
701
struct snd_ctl_elem_info *uinfo)
702
{
703
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
704
uinfo->count = 2;
705
uinfo->value.integer.min = 0;
706
uinfo->value.integer.max = 255;
707
return 0;
708
}
709
710
static int snd_p16v_volume_get(struct snd_kcontrol *kcontrol,
711
struct snd_ctl_elem_value *ucontrol)
712
{
713
struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
714
int high_low = (kcontrol->private_value >> 8) & 0xff;
715
int reg = kcontrol->private_value & 0xff;
716
u32 value;
717
718
value = snd_emu10k1_ptr20_read(emu, reg, high_low);
719
if (high_low) {
720
ucontrol->value.integer.value[0] = 0xff - ((value >> 24) & 0xff); /* Left */
721
ucontrol->value.integer.value[1] = 0xff - ((value >> 16) & 0xff); /* Right */
722
} else {
723
ucontrol->value.integer.value[0] = 0xff - ((value >> 8) & 0xff); /* Left */
724
ucontrol->value.integer.value[1] = 0xff - ((value >> 0) & 0xff); /* Right */
725
}
726
return 0;
727
}
728
729
static int snd_p16v_volume_put(struct snd_kcontrol *kcontrol,
730
struct snd_ctl_elem_value *ucontrol)
731
{
732
struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
733
int high_low = (kcontrol->private_value >> 8) & 0xff;
734
int reg = kcontrol->private_value & 0xff;
735
u32 value, oval;
736
737
oval = value = snd_emu10k1_ptr20_read(emu, reg, 0);
738
if (high_low == 1) {
739
value &= 0xffff;
740
value |= ((0xff - ucontrol->value.integer.value[0]) << 24) |
741
((0xff - ucontrol->value.integer.value[1]) << 16);
742
} else {
743
value &= 0xffff0000;
744
value |= ((0xff - ucontrol->value.integer.value[0]) << 8) |
745
((0xff - ucontrol->value.integer.value[1]) );
746
}
747
if (value != oval) {
748
snd_emu10k1_ptr20_write(emu, reg, 0, value);
749
return 1;
750
}
751
return 0;
752
}
753
754
static int snd_p16v_capture_source_info(struct snd_kcontrol *kcontrol,
755
struct snd_ctl_elem_info *uinfo)
756
{
757
static char *texts[8] = {
758
"SPDIF", "I2S", "SRC48", "SRCMulti_SPDIF", "SRCMulti_I2S",
759
"CDIF", "FX", "AC97"
760
};
761
762
uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
763
uinfo->count = 1;
764
uinfo->value.enumerated.items = 8;
765
if (uinfo->value.enumerated.item > 7)
766
uinfo->value.enumerated.item = 7;
767
strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
768
return 0;
769
}
770
771
static int snd_p16v_capture_source_get(struct snd_kcontrol *kcontrol,
772
struct snd_ctl_elem_value *ucontrol)
773
{
774
struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
775
776
ucontrol->value.enumerated.item[0] = emu->p16v_capture_source;
777
return 0;
778
}
779
780
static int snd_p16v_capture_source_put(struct snd_kcontrol *kcontrol,
781
struct snd_ctl_elem_value *ucontrol)
782
{
783
struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
784
unsigned int val;
785
int change = 0;
786
u32 mask;
787
u32 source;
788
789
val = ucontrol->value.enumerated.item[0] ;
790
if (val > 7)
791
return -EINVAL;
792
change = (emu->p16v_capture_source != val);
793
if (change) {
794
emu->p16v_capture_source = val;
795
source = (val << 28) | (val << 24) | (val << 20) | (val << 16);
796
mask = snd_emu10k1_ptr20_read(emu, BASIC_INTERRUPT, 0) & 0xffff;
797
snd_emu10k1_ptr20_write(emu, BASIC_INTERRUPT, 0, source | mask);
798
}
799
return change;
800
}
801
802
static int snd_p16v_capture_channel_info(struct snd_kcontrol *kcontrol,
803
struct snd_ctl_elem_info *uinfo)
804
{
805
static char *texts[4] = { "0", "1", "2", "3", };
806
807
uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
808
uinfo->count = 1;
809
uinfo->value.enumerated.items = 4;
810
if (uinfo->value.enumerated.item > 3)
811
uinfo->value.enumerated.item = 3;
812
strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
813
return 0;
814
}
815
816
static int snd_p16v_capture_channel_get(struct snd_kcontrol *kcontrol,
817
struct snd_ctl_elem_value *ucontrol)
818
{
819
struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
820
821
ucontrol->value.enumerated.item[0] = emu->p16v_capture_channel;
822
return 0;
823
}
824
825
static int snd_p16v_capture_channel_put(struct snd_kcontrol *kcontrol,
826
struct snd_ctl_elem_value *ucontrol)
827
{
828
struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
829
unsigned int val;
830
int change = 0;
831
u32 tmp;
832
833
val = ucontrol->value.enumerated.item[0] ;
834
if (val > 3)
835
return -EINVAL;
836
change = (emu->p16v_capture_channel != val);
837
if (change) {
838
emu->p16v_capture_channel = val;
839
tmp = snd_emu10k1_ptr20_read(emu, CAPTURE_P16V_SOURCE, 0) & 0xfffc;
840
snd_emu10k1_ptr20_write(emu, CAPTURE_P16V_SOURCE, 0, tmp | val);
841
}
842
return change;
843
}
844
static const DECLARE_TLV_DB_SCALE(snd_p16v_db_scale1, -5175, 25, 1);
845
846
#define P16V_VOL(xname,xreg,xhl) { \
847
.iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
848
.access = SNDRV_CTL_ELEM_ACCESS_READWRITE | \
849
SNDRV_CTL_ELEM_ACCESS_TLV_READ, \
850
.info = snd_p16v_volume_info, \
851
.get = snd_p16v_volume_get, \
852
.put = snd_p16v_volume_put, \
853
.tlv = { .p = snd_p16v_db_scale1 }, \
854
.private_value = ((xreg) | ((xhl) << 8)) \
855
}
856
857
static struct snd_kcontrol_new p16v_mixer_controls[] __devinitdata = {
858
P16V_VOL("HD Analog Front Playback Volume", PLAYBACK_VOLUME_MIXER9, 0),
859
P16V_VOL("HD Analog Rear Playback Volume", PLAYBACK_VOLUME_MIXER10, 1),
860
P16V_VOL("HD Analog Center/LFE Playback Volume", PLAYBACK_VOLUME_MIXER9, 1),
861
P16V_VOL("HD Analog Side Playback Volume", PLAYBACK_VOLUME_MIXER10, 0),
862
P16V_VOL("HD SPDIF Front Playback Volume", PLAYBACK_VOLUME_MIXER7, 0),
863
P16V_VOL("HD SPDIF Rear Playback Volume", PLAYBACK_VOLUME_MIXER8, 1),
864
P16V_VOL("HD SPDIF Center/LFE Playback Volume", PLAYBACK_VOLUME_MIXER7, 1),
865
P16V_VOL("HD SPDIF Side Playback Volume", PLAYBACK_VOLUME_MIXER8, 0),
866
{
867
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
868
.name = "HD source Capture",
869
.info = snd_p16v_capture_source_info,
870
.get = snd_p16v_capture_source_get,
871
.put = snd_p16v_capture_source_put
872
},
873
{
874
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
875
.name = "HD channel Capture",
876
.info = snd_p16v_capture_channel_info,
877
.get = snd_p16v_capture_channel_get,
878
.put = snd_p16v_capture_channel_put
879
},
880
};
881
882
883
int __devinit snd_p16v_mixer(struct snd_emu10k1 *emu)
884
{
885
int i, err;
886
struct snd_card *card = emu->card;
887
888
for (i = 0; i < ARRAY_SIZE(p16v_mixer_controls); i++) {
889
if ((err = snd_ctl_add(card, snd_ctl_new1(&p16v_mixer_controls[i],
890
emu))) < 0)
891
return err;
892
}
893
return 0;
894
}
895
896
#ifdef CONFIG_PM
897
898
#define NUM_CHS 1 /* up to 4, but only first channel is used */
899
900
int __devinit snd_p16v_alloc_pm_buffer(struct snd_emu10k1 *emu)
901
{
902
emu->p16v_saved = vmalloc(NUM_CHS * 4 * 0x80);
903
if (! emu->p16v_saved)
904
return -ENOMEM;
905
return 0;
906
}
907
908
void snd_p16v_free_pm_buffer(struct snd_emu10k1 *emu)
909
{
910
vfree(emu->p16v_saved);
911
}
912
913
void snd_p16v_suspend(struct snd_emu10k1 *emu)
914
{
915
int i, ch;
916
unsigned int *val;
917
918
val = emu->p16v_saved;
919
for (ch = 0; ch < NUM_CHS; ch++)
920
for (i = 0; i < 0x80; i++, val++)
921
*val = snd_emu10k1_ptr20_read(emu, i, ch);
922
}
923
924
void snd_p16v_resume(struct snd_emu10k1 *emu)
925
{
926
int i, ch;
927
unsigned int *val;
928
929
val = emu->p16v_saved;
930
for (ch = 0; ch < NUM_CHS; ch++)
931
for (i = 0; i < 0x80; i++, val++)
932
snd_emu10k1_ptr20_write(emu, i, ch, *val);
933
}
934
#endif
935
936