Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/sound/isa/msnd/msnd.c
26424 views
1
// SPDX-License-Identifier: GPL-2.0-or-later
2
/*********************************************************************
3
*
4
* 2002/06/30 Karsten Wiese:
5
* removed kernel-version dependencies.
6
* ripped from linux kernel 2.4.18 (OSS Implementation) by me.
7
* In the OSS Version, this file is compiled to a separate MODULE,
8
* that is used by the pinnacle and the classic driver.
9
* since there is no classic driver for alsa yet (i dont have a classic
10
* & writing one blindfold is difficult) this file's object is statically
11
* linked into the pinnacle-driver-module for now. look for the string
12
* "uncomment this to make this a module again"
13
* to do guess what.
14
*
15
* the following is a copy of the 2.4.18 OSS FREE file-heading comment:
16
*
17
* msnd.c - Driver Base
18
*
19
* Turtle Beach MultiSound Sound Card Driver for Linux
20
*
21
* Copyright (C) 1998 Andrew Veliath
22
*
23
********************************************************************/
24
25
#include <linux/kernel.h>
26
#include <linux/sched/signal.h>
27
#include <linux/types.h>
28
#include <linux/interrupt.h>
29
#include <linux/io.h>
30
#include <linux/fs.h>
31
#include <linux/delay.h>
32
#include <linux/module.h>
33
34
#include <sound/core.h>
35
#include <sound/initval.h>
36
#include <sound/pcm.h>
37
#include <sound/pcm_params.h>
38
39
#include "msnd.h"
40
41
#define LOGNAME "msnd"
42
43
44
void snd_msnd_init_queue(void __iomem *base, int start, int size)
45
{
46
writew(PCTODSP_BASED(start), base + JQS_wStart);
47
writew(PCTODSP_OFFSET(size) - 1, base + JQS_wSize);
48
writew(0, base + JQS_wHead);
49
writew(0, base + JQS_wTail);
50
}
51
EXPORT_SYMBOL(snd_msnd_init_queue);
52
53
static int snd_msnd_wait_TXDE(struct snd_msnd *dev)
54
{
55
unsigned int io = dev->io;
56
int timeout = 1000;
57
58
while (timeout-- > 0)
59
if (inb(io + HP_ISR) & HPISR_TXDE)
60
return 0;
61
62
return -EIO;
63
}
64
65
static int snd_msnd_wait_HC0(struct snd_msnd *dev)
66
{
67
unsigned int io = dev->io;
68
int timeout = 1000;
69
70
while (timeout-- > 0)
71
if (!(inb(io + HP_CVR) & HPCVR_HC))
72
return 0;
73
74
return -EIO;
75
}
76
77
int snd_msnd_send_dsp_cmd(struct snd_msnd *dev, u8 cmd)
78
{
79
unsigned long flags;
80
81
spin_lock_irqsave(&dev->lock, flags);
82
if (snd_msnd_wait_HC0(dev) == 0) {
83
outb(cmd, dev->io + HP_CVR);
84
spin_unlock_irqrestore(&dev->lock, flags);
85
return 0;
86
}
87
spin_unlock_irqrestore(&dev->lock, flags);
88
89
dev_dbg(dev->card->dev, LOGNAME ": Send DSP command timeout\n");
90
91
return -EIO;
92
}
93
EXPORT_SYMBOL(snd_msnd_send_dsp_cmd);
94
95
int snd_msnd_send_word(struct snd_msnd *dev, unsigned char high,
96
unsigned char mid, unsigned char low)
97
{
98
unsigned int io = dev->io;
99
100
if (snd_msnd_wait_TXDE(dev) == 0) {
101
outb(high, io + HP_TXH);
102
outb(mid, io + HP_TXM);
103
outb(low, io + HP_TXL);
104
return 0;
105
}
106
107
dev_dbg(dev->card->dev, LOGNAME ": Send host word timeout\n");
108
109
return -EIO;
110
}
111
EXPORT_SYMBOL(snd_msnd_send_word);
112
113
int snd_msnd_upload_host(struct snd_msnd *dev, const u8 *bin, int len)
114
{
115
int i;
116
117
if (len % 3 != 0) {
118
dev_err(dev->card->dev, LOGNAME
119
": Upload host data not multiple of 3!\n");
120
return -EINVAL;
121
}
122
123
for (i = 0; i < len; i += 3)
124
if (snd_msnd_send_word(dev, bin[i], bin[i + 1], bin[i + 2]))
125
return -EIO;
126
127
inb(dev->io + HP_RXL);
128
inb(dev->io + HP_CVR);
129
130
return 0;
131
}
132
EXPORT_SYMBOL(snd_msnd_upload_host);
133
134
int snd_msnd_enable_irq(struct snd_msnd *dev)
135
{
136
unsigned long flags;
137
138
if (dev->irq_ref++)
139
return 0;
140
141
dev_dbg(dev->card->dev, LOGNAME ": Enabling IRQ\n");
142
143
spin_lock_irqsave(&dev->lock, flags);
144
if (snd_msnd_wait_TXDE(dev) == 0) {
145
outb(inb(dev->io + HP_ICR) | HPICR_TREQ, dev->io + HP_ICR);
146
if (dev->type == msndClassic)
147
outb(dev->irqid, dev->io + HP_IRQM);
148
149
outb(inb(dev->io + HP_ICR) & ~HPICR_TREQ, dev->io + HP_ICR);
150
outb(inb(dev->io + HP_ICR) | HPICR_RREQ, dev->io + HP_ICR);
151
enable_irq(dev->irq);
152
snd_msnd_init_queue(dev->DSPQ, dev->dspq_data_buff,
153
dev->dspq_buff_size);
154
spin_unlock_irqrestore(&dev->lock, flags);
155
return 0;
156
}
157
spin_unlock_irqrestore(&dev->lock, flags);
158
159
dev_dbg(dev->card->dev, LOGNAME ": Enable IRQ failed\n");
160
161
return -EIO;
162
}
163
EXPORT_SYMBOL(snd_msnd_enable_irq);
164
165
int snd_msnd_disable_irq(struct snd_msnd *dev)
166
{
167
unsigned long flags;
168
169
if (--dev->irq_ref > 0)
170
return 0;
171
172
if (dev->irq_ref < 0)
173
dev_dbg(dev->card->dev, LOGNAME ": IRQ ref count is %d\n",
174
dev->irq_ref);
175
176
dev_dbg(dev->card->dev, LOGNAME ": Disabling IRQ\n");
177
178
spin_lock_irqsave(&dev->lock, flags);
179
if (snd_msnd_wait_TXDE(dev) == 0) {
180
outb(inb(dev->io + HP_ICR) & ~HPICR_RREQ, dev->io + HP_ICR);
181
if (dev->type == msndClassic)
182
outb(HPIRQ_NONE, dev->io + HP_IRQM);
183
disable_irq(dev->irq);
184
spin_unlock_irqrestore(&dev->lock, flags);
185
return 0;
186
}
187
spin_unlock_irqrestore(&dev->lock, flags);
188
189
dev_dbg(dev->card->dev, LOGNAME ": Disable IRQ failed\n");
190
191
return -EIO;
192
}
193
EXPORT_SYMBOL(snd_msnd_disable_irq);
194
195
static inline long get_play_delay_jiffies(struct snd_msnd *chip, long size)
196
{
197
long tmp = (size * HZ * chip->play_sample_size) / 8;
198
return tmp / (chip->play_sample_rate * chip->play_channels);
199
}
200
201
static void snd_msnd_dsp_write_flush(struct snd_msnd *chip)
202
{
203
if (!(chip->mode & FMODE_WRITE) || !test_bit(F_WRITING, &chip->flags))
204
return;
205
set_bit(F_WRITEFLUSH, &chip->flags);
206
/* interruptible_sleep_on_timeout(
207
&chip->writeflush,
208
get_play_delay_jiffies(&chip, chip->DAPF.len));*/
209
clear_bit(F_WRITEFLUSH, &chip->flags);
210
if (!signal_pending(current))
211
schedule_timeout_interruptible(
212
get_play_delay_jiffies(chip, chip->play_period_bytes));
213
clear_bit(F_WRITING, &chip->flags);
214
}
215
216
void snd_msnd_dsp_halt(struct snd_msnd *chip, struct file *file)
217
{
218
if ((file ? file->f_mode : chip->mode) & FMODE_READ) {
219
clear_bit(F_READING, &chip->flags);
220
snd_msnd_send_dsp_cmd(chip, HDEX_RECORD_STOP);
221
snd_msnd_disable_irq(chip);
222
if (file) {
223
dev_dbg(chip->card->dev, LOGNAME
224
": Stopping read for %p\n", file);
225
chip->mode &= ~FMODE_READ;
226
}
227
clear_bit(F_AUDIO_READ_INUSE, &chip->flags);
228
}
229
if ((file ? file->f_mode : chip->mode) & FMODE_WRITE) {
230
if (test_bit(F_WRITING, &chip->flags)) {
231
snd_msnd_dsp_write_flush(chip);
232
snd_msnd_send_dsp_cmd(chip, HDEX_PLAY_STOP);
233
}
234
snd_msnd_disable_irq(chip);
235
if (file) {
236
dev_dbg(chip->card->dev,
237
LOGNAME ": Stopping write for %p\n", file);
238
chip->mode &= ~FMODE_WRITE;
239
}
240
clear_bit(F_AUDIO_WRITE_INUSE, &chip->flags);
241
}
242
}
243
EXPORT_SYMBOL(snd_msnd_dsp_halt);
244
245
246
int snd_msnd_DARQ(struct snd_msnd *chip, int bank)
247
{
248
int /*size, n,*/ timeout = 3;
249
u16 wTmp;
250
/* void *DAQD; */
251
252
/* Increment the tail and check for queue wrap */
253
wTmp = readw(chip->DARQ + JQS_wTail) + PCTODSP_OFFSET(DAQDS__size);
254
if (wTmp > readw(chip->DARQ + JQS_wSize))
255
wTmp = 0;
256
while (wTmp == readw(chip->DARQ + JQS_wHead) && timeout--)
257
udelay(1);
258
259
if (chip->capturePeriods == 2) {
260
void __iomem *pDAQ = chip->mappedbase + DARQ_DATA_BUFF +
261
bank * DAQDS__size + DAQDS_wStart;
262
unsigned short offset = 0x3000 + chip->capturePeriodBytes;
263
264
if (readw(pDAQ) != PCTODSP_BASED(0x3000))
265
offset = 0x3000;
266
writew(PCTODSP_BASED(offset), pDAQ);
267
}
268
269
writew(wTmp, chip->DARQ + JQS_wTail);
270
271
#if 0
272
/* Get our digital audio queue struct */
273
DAQD = bank * DAQDS__size + chip->mappedbase + DARQ_DATA_BUFF;
274
275
/* Get length of data */
276
size = readw(DAQD + DAQDS_wSize);
277
278
/* Read data from the head (unprotected bank 1 access okay
279
since this is only called inside an interrupt) */
280
outb(HPBLKSEL_1, chip->io + HP_BLKS);
281
n = msnd_fifo_write(&chip->DARF,
282
(char *)(chip->base + bank * DAR_BUFF_SIZE),
283
size, 0);
284
if (n <= 0) {
285
outb(HPBLKSEL_0, chip->io + HP_BLKS);
286
return n;
287
}
288
outb(HPBLKSEL_0, chip->io + HP_BLKS);
289
#endif
290
291
return 1;
292
}
293
EXPORT_SYMBOL(snd_msnd_DARQ);
294
295
int snd_msnd_DAPQ(struct snd_msnd *chip, int start)
296
{
297
u16 DAPQ_tail;
298
int protect = start, nbanks = 0;
299
void __iomem *DAQD;
300
static int play_banks_submitted;
301
/* unsigned long flags;
302
spin_lock_irqsave(&chip->lock, flags); not necessary */
303
304
DAPQ_tail = readw(chip->DAPQ + JQS_wTail);
305
while (DAPQ_tail != readw(chip->DAPQ + JQS_wHead) || start) {
306
int bank_num = DAPQ_tail / PCTODSP_OFFSET(DAQDS__size);
307
308
if (start) {
309
start = 0;
310
play_banks_submitted = 0;
311
}
312
313
/* Get our digital audio queue struct */
314
DAQD = bank_num * DAQDS__size + chip->mappedbase +
315
DAPQ_DATA_BUFF;
316
317
/* Write size of this bank */
318
writew(chip->play_period_bytes, DAQD + DAQDS_wSize);
319
if (play_banks_submitted < 3)
320
++play_banks_submitted;
321
else if (chip->playPeriods == 2) {
322
unsigned short offset = chip->play_period_bytes;
323
324
if (readw(DAQD + DAQDS_wStart) != PCTODSP_BASED(0x0))
325
offset = 0;
326
327
writew(PCTODSP_BASED(offset), DAQD + DAQDS_wStart);
328
}
329
++nbanks;
330
331
/* Then advance the tail */
332
DAPQ_tail = (++bank_num % 3) * PCTODSP_OFFSET(DAQDS__size);
333
writew(DAPQ_tail, chip->DAPQ + JQS_wTail);
334
/* Tell the DSP to play the bank */
335
snd_msnd_send_dsp_cmd(chip, HDEX_PLAY_START);
336
if (protect)
337
if (2 == bank_num)
338
break;
339
}
340
/* spin_unlock_irqrestore(&chip->lock, flags); not necessary */
341
return nbanks;
342
}
343
EXPORT_SYMBOL(snd_msnd_DAPQ);
344
345
static void snd_msnd_play_reset_queue(struct snd_msnd *chip,
346
unsigned int pcm_periods,
347
unsigned int pcm_count)
348
{
349
int n;
350
void __iomem *pDAQ = chip->mappedbase + DAPQ_DATA_BUFF;
351
352
chip->last_playbank = -1;
353
chip->playLimit = pcm_count * (pcm_periods - 1);
354
chip->playPeriods = pcm_periods;
355
writew(PCTODSP_OFFSET(0 * DAQDS__size), chip->DAPQ + JQS_wHead);
356
writew(PCTODSP_OFFSET(0 * DAQDS__size), chip->DAPQ + JQS_wTail);
357
358
chip->play_period_bytes = pcm_count;
359
360
for (n = 0; n < pcm_periods; ++n, pDAQ += DAQDS__size) {
361
writew(PCTODSP_BASED((u32)(pcm_count * n)),
362
pDAQ + DAQDS_wStart);
363
writew(0, pDAQ + DAQDS_wSize);
364
writew(1, pDAQ + DAQDS_wFormat);
365
writew(chip->play_sample_size, pDAQ + DAQDS_wSampleSize);
366
writew(chip->play_channels, pDAQ + DAQDS_wChannels);
367
writew(chip->play_sample_rate, pDAQ + DAQDS_wSampleRate);
368
writew(HIMT_PLAY_DONE * 0x100 + n, pDAQ + DAQDS_wIntMsg);
369
writew(n, pDAQ + DAQDS_wFlags);
370
}
371
}
372
373
static void snd_msnd_capture_reset_queue(struct snd_msnd *chip,
374
unsigned int pcm_periods,
375
unsigned int pcm_count)
376
{
377
int n;
378
void __iomem *pDAQ;
379
/* unsigned long flags; */
380
381
/* snd_msnd_init_queue(chip->DARQ, DARQ_DATA_BUFF, DARQ_BUFF_SIZE); */
382
383
chip->last_recbank = 2;
384
chip->captureLimit = pcm_count * (pcm_periods - 1);
385
chip->capturePeriods = pcm_periods;
386
writew(PCTODSP_OFFSET(0 * DAQDS__size), chip->DARQ + JQS_wHead);
387
writew(PCTODSP_OFFSET(chip->last_recbank * DAQDS__size),
388
chip->DARQ + JQS_wTail);
389
390
#if 0 /* Critical section: bank 1 access. this is how the OSS driver does it:*/
391
spin_lock_irqsave(&chip->lock, flags);
392
outb(HPBLKSEL_1, chip->io + HP_BLKS);
393
memset_io(chip->mappedbase, 0, DAR_BUFF_SIZE * 3);
394
outb(HPBLKSEL_0, chip->io + HP_BLKS);
395
spin_unlock_irqrestore(&chip->lock, flags);
396
#endif
397
398
chip->capturePeriodBytes = pcm_count;
399
dev_dbg(chip->card->dev, "%s() %i\n", __func__, pcm_count);
400
401
pDAQ = chip->mappedbase + DARQ_DATA_BUFF;
402
403
for (n = 0; n < pcm_periods; ++n, pDAQ += DAQDS__size) {
404
u32 tmp = pcm_count * n;
405
406
writew(PCTODSP_BASED(tmp + 0x3000), pDAQ + DAQDS_wStart);
407
writew(pcm_count, pDAQ + DAQDS_wSize);
408
writew(1, pDAQ + DAQDS_wFormat);
409
writew(chip->capture_sample_size, pDAQ + DAQDS_wSampleSize);
410
writew(chip->capture_channels, pDAQ + DAQDS_wChannels);
411
writew(chip->capture_sample_rate, pDAQ + DAQDS_wSampleRate);
412
writew(HIMT_RECORD_DONE * 0x100 + n, pDAQ + DAQDS_wIntMsg);
413
writew(n, pDAQ + DAQDS_wFlags);
414
}
415
}
416
417
static const struct snd_pcm_hardware snd_msnd_playback = {
418
.info = SNDRV_PCM_INFO_MMAP_IOMEM |
419
SNDRV_PCM_INFO_INTERLEAVED |
420
SNDRV_PCM_INFO_MMAP_VALID |
421
SNDRV_PCM_INFO_BATCH,
422
.formats = SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE,
423
.rates = SNDRV_PCM_RATE_8000_48000,
424
.rate_min = 8000,
425
.rate_max = 48000,
426
.channels_min = 1,
427
.channels_max = 2,
428
.buffer_bytes_max = 0x3000,
429
.period_bytes_min = 0x40,
430
.period_bytes_max = 0x1800,
431
.periods_min = 2,
432
.periods_max = 3,
433
.fifo_size = 0,
434
};
435
436
static const struct snd_pcm_hardware snd_msnd_capture = {
437
.info = SNDRV_PCM_INFO_MMAP_IOMEM |
438
SNDRV_PCM_INFO_INTERLEAVED |
439
SNDRV_PCM_INFO_MMAP_VALID |
440
SNDRV_PCM_INFO_BATCH,
441
.formats = SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE,
442
.rates = SNDRV_PCM_RATE_8000_48000,
443
.rate_min = 8000,
444
.rate_max = 48000,
445
.channels_min = 1,
446
.channels_max = 2,
447
.buffer_bytes_max = 0x3000,
448
.period_bytes_min = 0x40,
449
.period_bytes_max = 0x1800,
450
.periods_min = 2,
451
.periods_max = 3,
452
.fifo_size = 0,
453
};
454
455
456
static int snd_msnd_playback_open(struct snd_pcm_substream *substream)
457
{
458
struct snd_pcm_runtime *runtime = substream->runtime;
459
struct snd_msnd *chip = snd_pcm_substream_chip(substream);
460
461
set_bit(F_AUDIO_WRITE_INUSE, &chip->flags);
462
clear_bit(F_WRITING, &chip->flags);
463
snd_msnd_enable_irq(chip);
464
465
runtime->dma_area = (__force void *)chip->mappedbase;
466
runtime->dma_addr = chip->base;
467
runtime->dma_bytes = 0x3000;
468
469
chip->playback_substream = substream;
470
runtime->hw = snd_msnd_playback;
471
return 0;
472
}
473
474
static int snd_msnd_playback_close(struct snd_pcm_substream *substream)
475
{
476
struct snd_msnd *chip = snd_pcm_substream_chip(substream);
477
478
snd_msnd_disable_irq(chip);
479
clear_bit(F_AUDIO_WRITE_INUSE, &chip->flags);
480
return 0;
481
}
482
483
484
static int snd_msnd_playback_hw_params(struct snd_pcm_substream *substream,
485
struct snd_pcm_hw_params *params)
486
{
487
int i;
488
struct snd_msnd *chip = snd_pcm_substream_chip(substream);
489
void __iomem *pDAQ = chip->mappedbase + DAPQ_DATA_BUFF;
490
491
chip->play_sample_size = snd_pcm_format_width(params_format(params));
492
chip->play_channels = params_channels(params);
493
chip->play_sample_rate = params_rate(params);
494
495
for (i = 0; i < 3; ++i, pDAQ += DAQDS__size) {
496
writew(chip->play_sample_size, pDAQ + DAQDS_wSampleSize);
497
writew(chip->play_channels, pDAQ + DAQDS_wChannels);
498
writew(chip->play_sample_rate, pDAQ + DAQDS_wSampleRate);
499
}
500
/* dont do this here:
501
* snd_msnd_calibrate_adc(chip->play_sample_rate);
502
*/
503
504
return 0;
505
}
506
507
static int snd_msnd_playback_prepare(struct snd_pcm_substream *substream)
508
{
509
struct snd_msnd *chip = snd_pcm_substream_chip(substream);
510
unsigned int pcm_size = snd_pcm_lib_buffer_bytes(substream);
511
unsigned int pcm_count = snd_pcm_lib_period_bytes(substream);
512
unsigned int pcm_periods = pcm_size / pcm_count;
513
514
snd_msnd_play_reset_queue(chip, pcm_periods, pcm_count);
515
chip->playDMAPos = 0;
516
return 0;
517
}
518
519
static int snd_msnd_playback_trigger(struct snd_pcm_substream *substream,
520
int cmd)
521
{
522
struct snd_msnd *chip = snd_pcm_substream_chip(substream);
523
int result = 0;
524
525
if (cmd == SNDRV_PCM_TRIGGER_START) {
526
dev_dbg(chip->card->dev, "%s(START)\n", __func__);
527
chip->banksPlayed = 0;
528
set_bit(F_WRITING, &chip->flags);
529
snd_msnd_DAPQ(chip, 1);
530
} else if (cmd == SNDRV_PCM_TRIGGER_STOP) {
531
dev_dbg(chip->card->dev, "%s(STOP)\n", __func__);
532
/* interrupt diagnostic, comment this out later */
533
clear_bit(F_WRITING, &chip->flags);
534
snd_msnd_send_dsp_cmd(chip, HDEX_PLAY_STOP);
535
} else {
536
dev_dbg(chip->card->dev, "%s(?????)\n", __func__);
537
result = -EINVAL;
538
}
539
540
dev_dbg(chip->card->dev, "%s() ENDE\n", __func__);
541
return result;
542
}
543
544
static snd_pcm_uframes_t
545
snd_msnd_playback_pointer(struct snd_pcm_substream *substream)
546
{
547
struct snd_msnd *chip = snd_pcm_substream_chip(substream);
548
549
return bytes_to_frames(substream->runtime, chip->playDMAPos);
550
}
551
552
553
static const struct snd_pcm_ops snd_msnd_playback_ops = {
554
.open = snd_msnd_playback_open,
555
.close = snd_msnd_playback_close,
556
.hw_params = snd_msnd_playback_hw_params,
557
.prepare = snd_msnd_playback_prepare,
558
.trigger = snd_msnd_playback_trigger,
559
.pointer = snd_msnd_playback_pointer,
560
.mmap = snd_pcm_lib_mmap_iomem,
561
};
562
563
static int snd_msnd_capture_open(struct snd_pcm_substream *substream)
564
{
565
struct snd_pcm_runtime *runtime = substream->runtime;
566
struct snd_msnd *chip = snd_pcm_substream_chip(substream);
567
568
set_bit(F_AUDIO_READ_INUSE, &chip->flags);
569
snd_msnd_enable_irq(chip);
570
runtime->dma_area = (__force void *)chip->mappedbase + 0x3000;
571
runtime->dma_addr = chip->base + 0x3000;
572
runtime->dma_bytes = 0x3000;
573
memset(runtime->dma_area, 0, runtime->dma_bytes);
574
chip->capture_substream = substream;
575
runtime->hw = snd_msnd_capture;
576
return 0;
577
}
578
579
static int snd_msnd_capture_close(struct snd_pcm_substream *substream)
580
{
581
struct snd_msnd *chip = snd_pcm_substream_chip(substream);
582
583
snd_msnd_disable_irq(chip);
584
clear_bit(F_AUDIO_READ_INUSE, &chip->flags);
585
return 0;
586
}
587
588
static int snd_msnd_capture_prepare(struct snd_pcm_substream *substream)
589
{
590
struct snd_msnd *chip = snd_pcm_substream_chip(substream);
591
unsigned int pcm_size = snd_pcm_lib_buffer_bytes(substream);
592
unsigned int pcm_count = snd_pcm_lib_period_bytes(substream);
593
unsigned int pcm_periods = pcm_size / pcm_count;
594
595
snd_msnd_capture_reset_queue(chip, pcm_periods, pcm_count);
596
chip->captureDMAPos = 0;
597
return 0;
598
}
599
600
static int snd_msnd_capture_trigger(struct snd_pcm_substream *substream,
601
int cmd)
602
{
603
struct snd_msnd *chip = snd_pcm_substream_chip(substream);
604
605
if (cmd == SNDRV_PCM_TRIGGER_START) {
606
chip->last_recbank = -1;
607
set_bit(F_READING, &chip->flags);
608
if (snd_msnd_send_dsp_cmd(chip, HDEX_RECORD_START) == 0)
609
return 0;
610
611
clear_bit(F_READING, &chip->flags);
612
} else if (cmd == SNDRV_PCM_TRIGGER_STOP) {
613
clear_bit(F_READING, &chip->flags);
614
snd_msnd_send_dsp_cmd(chip, HDEX_RECORD_STOP);
615
return 0;
616
}
617
return -EINVAL;
618
}
619
620
621
static snd_pcm_uframes_t
622
snd_msnd_capture_pointer(struct snd_pcm_substream *substream)
623
{
624
struct snd_pcm_runtime *runtime = substream->runtime;
625
struct snd_msnd *chip = snd_pcm_substream_chip(substream);
626
627
return bytes_to_frames(runtime, chip->captureDMAPos);
628
}
629
630
631
static int snd_msnd_capture_hw_params(struct snd_pcm_substream *substream,
632
struct snd_pcm_hw_params *params)
633
{
634
int i;
635
struct snd_msnd *chip = snd_pcm_substream_chip(substream);
636
void __iomem *pDAQ = chip->mappedbase + DARQ_DATA_BUFF;
637
638
chip->capture_sample_size = snd_pcm_format_width(params_format(params));
639
chip->capture_channels = params_channels(params);
640
chip->capture_sample_rate = params_rate(params);
641
642
for (i = 0; i < 3; ++i, pDAQ += DAQDS__size) {
643
writew(chip->capture_sample_size, pDAQ + DAQDS_wSampleSize);
644
writew(chip->capture_channels, pDAQ + DAQDS_wChannels);
645
writew(chip->capture_sample_rate, pDAQ + DAQDS_wSampleRate);
646
}
647
return 0;
648
}
649
650
651
static const struct snd_pcm_ops snd_msnd_capture_ops = {
652
.open = snd_msnd_capture_open,
653
.close = snd_msnd_capture_close,
654
.hw_params = snd_msnd_capture_hw_params,
655
.prepare = snd_msnd_capture_prepare,
656
.trigger = snd_msnd_capture_trigger,
657
.pointer = snd_msnd_capture_pointer,
658
.mmap = snd_pcm_lib_mmap_iomem,
659
};
660
661
662
int snd_msnd_pcm(struct snd_card *card, int device)
663
{
664
struct snd_msnd *chip = card->private_data;
665
struct snd_pcm *pcm;
666
int err;
667
668
err = snd_pcm_new(card, "MSNDPINNACLE", device, 1, 1, &pcm);
669
if (err < 0)
670
return err;
671
672
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_msnd_playback_ops);
673
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_msnd_capture_ops);
674
675
pcm->private_data = chip;
676
strscpy(pcm->name, "Hurricane");
677
678
return 0;
679
}
680
EXPORT_SYMBOL(snd_msnd_pcm);
681
682
MODULE_DESCRIPTION("Common routines for Turtle Beach Multisound drivers");
683
MODULE_LICENSE("GPL");
684
685
686