0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025 #include <linux/kernel.h>
0026 #include <linux/sched/signal.h>
0027 #include <linux/types.h>
0028 #include <linux/interrupt.h>
0029 #include <linux/io.h>
0030 #include <linux/fs.h>
0031 #include <linux/delay.h>
0032 #include <linux/module.h>
0033
0034 #include <sound/core.h>
0035 #include <sound/initval.h>
0036 #include <sound/pcm.h>
0037 #include <sound/pcm_params.h>
0038
0039 #include "msnd.h"
0040
0041 #define LOGNAME "msnd"
0042
0043
0044 void snd_msnd_init_queue(void __iomem *base, int start, int size)
0045 {
0046 writew(PCTODSP_BASED(start), base + JQS_wStart);
0047 writew(PCTODSP_OFFSET(size) - 1, base + JQS_wSize);
0048 writew(0, base + JQS_wHead);
0049 writew(0, base + JQS_wTail);
0050 }
0051 EXPORT_SYMBOL(snd_msnd_init_queue);
0052
0053 static int snd_msnd_wait_TXDE(struct snd_msnd *dev)
0054 {
0055 unsigned int io = dev->io;
0056 int timeout = 1000;
0057
0058 while (timeout-- > 0)
0059 if (inb(io + HP_ISR) & HPISR_TXDE)
0060 return 0;
0061
0062 return -EIO;
0063 }
0064
0065 static int snd_msnd_wait_HC0(struct snd_msnd *dev)
0066 {
0067 unsigned int io = dev->io;
0068 int timeout = 1000;
0069
0070 while (timeout-- > 0)
0071 if (!(inb(io + HP_CVR) & HPCVR_HC))
0072 return 0;
0073
0074 return -EIO;
0075 }
0076
0077 int snd_msnd_send_dsp_cmd(struct snd_msnd *dev, u8 cmd)
0078 {
0079 unsigned long flags;
0080
0081 spin_lock_irqsave(&dev->lock, flags);
0082 if (snd_msnd_wait_HC0(dev) == 0) {
0083 outb(cmd, dev->io + HP_CVR);
0084 spin_unlock_irqrestore(&dev->lock, flags);
0085 return 0;
0086 }
0087 spin_unlock_irqrestore(&dev->lock, flags);
0088
0089 snd_printd(KERN_ERR LOGNAME ": Send DSP command timeout\n");
0090
0091 return -EIO;
0092 }
0093 EXPORT_SYMBOL(snd_msnd_send_dsp_cmd);
0094
0095 int snd_msnd_send_word(struct snd_msnd *dev, unsigned char high,
0096 unsigned char mid, unsigned char low)
0097 {
0098 unsigned int io = dev->io;
0099
0100 if (snd_msnd_wait_TXDE(dev) == 0) {
0101 outb(high, io + HP_TXH);
0102 outb(mid, io + HP_TXM);
0103 outb(low, io + HP_TXL);
0104 return 0;
0105 }
0106
0107 snd_printd(KERN_ERR LOGNAME ": Send host word timeout\n");
0108
0109 return -EIO;
0110 }
0111 EXPORT_SYMBOL(snd_msnd_send_word);
0112
0113 int snd_msnd_upload_host(struct snd_msnd *dev, const u8 *bin, int len)
0114 {
0115 int i;
0116
0117 if (len % 3 != 0) {
0118 snd_printk(KERN_ERR LOGNAME
0119 ": Upload host data not multiple of 3!\n");
0120 return -EINVAL;
0121 }
0122
0123 for (i = 0; i < len; i += 3)
0124 if (snd_msnd_send_word(dev, bin[i], bin[i + 1], bin[i + 2]))
0125 return -EIO;
0126
0127 inb(dev->io + HP_RXL);
0128 inb(dev->io + HP_CVR);
0129
0130 return 0;
0131 }
0132 EXPORT_SYMBOL(snd_msnd_upload_host);
0133
0134 int snd_msnd_enable_irq(struct snd_msnd *dev)
0135 {
0136 unsigned long flags;
0137
0138 if (dev->irq_ref++)
0139 return 0;
0140
0141 snd_printdd(LOGNAME ": Enabling IRQ\n");
0142
0143 spin_lock_irqsave(&dev->lock, flags);
0144 if (snd_msnd_wait_TXDE(dev) == 0) {
0145 outb(inb(dev->io + HP_ICR) | HPICR_TREQ, dev->io + HP_ICR);
0146 if (dev->type == msndClassic)
0147 outb(dev->irqid, dev->io + HP_IRQM);
0148
0149 outb(inb(dev->io + HP_ICR) & ~HPICR_TREQ, dev->io + HP_ICR);
0150 outb(inb(dev->io + HP_ICR) | HPICR_RREQ, dev->io + HP_ICR);
0151 enable_irq(dev->irq);
0152 snd_msnd_init_queue(dev->DSPQ, dev->dspq_data_buff,
0153 dev->dspq_buff_size);
0154 spin_unlock_irqrestore(&dev->lock, flags);
0155 return 0;
0156 }
0157 spin_unlock_irqrestore(&dev->lock, flags);
0158
0159 snd_printd(KERN_ERR LOGNAME ": Enable IRQ failed\n");
0160
0161 return -EIO;
0162 }
0163 EXPORT_SYMBOL(snd_msnd_enable_irq);
0164
0165 int snd_msnd_disable_irq(struct snd_msnd *dev)
0166 {
0167 unsigned long flags;
0168
0169 if (--dev->irq_ref > 0)
0170 return 0;
0171
0172 if (dev->irq_ref < 0)
0173 snd_printd(KERN_WARNING LOGNAME ": IRQ ref count is %d\n",
0174 dev->irq_ref);
0175
0176 snd_printdd(LOGNAME ": Disabling IRQ\n");
0177
0178 spin_lock_irqsave(&dev->lock, flags);
0179 if (snd_msnd_wait_TXDE(dev) == 0) {
0180 outb(inb(dev->io + HP_ICR) & ~HPICR_RREQ, dev->io + HP_ICR);
0181 if (dev->type == msndClassic)
0182 outb(HPIRQ_NONE, dev->io + HP_IRQM);
0183 disable_irq(dev->irq);
0184 spin_unlock_irqrestore(&dev->lock, flags);
0185 return 0;
0186 }
0187 spin_unlock_irqrestore(&dev->lock, flags);
0188
0189 snd_printd(KERN_ERR LOGNAME ": Disable IRQ failed\n");
0190
0191 return -EIO;
0192 }
0193 EXPORT_SYMBOL(snd_msnd_disable_irq);
0194
0195 static inline long get_play_delay_jiffies(struct snd_msnd *chip, long size)
0196 {
0197 long tmp = (size * HZ * chip->play_sample_size) / 8;
0198 return tmp / (chip->play_sample_rate * chip->play_channels);
0199 }
0200
0201 static void snd_msnd_dsp_write_flush(struct snd_msnd *chip)
0202 {
0203 if (!(chip->mode & FMODE_WRITE) || !test_bit(F_WRITING, &chip->flags))
0204 return;
0205 set_bit(F_WRITEFLUSH, &chip->flags);
0206
0207
0208
0209 clear_bit(F_WRITEFLUSH, &chip->flags);
0210 if (!signal_pending(current))
0211 schedule_timeout_interruptible(
0212 get_play_delay_jiffies(chip, chip->play_period_bytes));
0213 clear_bit(F_WRITING, &chip->flags);
0214 }
0215
0216 void snd_msnd_dsp_halt(struct snd_msnd *chip, struct file *file)
0217 {
0218 if ((file ? file->f_mode : chip->mode) & FMODE_READ) {
0219 clear_bit(F_READING, &chip->flags);
0220 snd_msnd_send_dsp_cmd(chip, HDEX_RECORD_STOP);
0221 snd_msnd_disable_irq(chip);
0222 if (file) {
0223 snd_printd(KERN_INFO LOGNAME
0224 ": Stopping read for %p\n", file);
0225 chip->mode &= ~FMODE_READ;
0226 }
0227 clear_bit(F_AUDIO_READ_INUSE, &chip->flags);
0228 }
0229 if ((file ? file->f_mode : chip->mode) & FMODE_WRITE) {
0230 if (test_bit(F_WRITING, &chip->flags)) {
0231 snd_msnd_dsp_write_flush(chip);
0232 snd_msnd_send_dsp_cmd(chip, HDEX_PLAY_STOP);
0233 }
0234 snd_msnd_disable_irq(chip);
0235 if (file) {
0236 snd_printd(KERN_INFO
0237 LOGNAME ": Stopping write for %p\n", file);
0238 chip->mode &= ~FMODE_WRITE;
0239 }
0240 clear_bit(F_AUDIO_WRITE_INUSE, &chip->flags);
0241 }
0242 }
0243 EXPORT_SYMBOL(snd_msnd_dsp_halt);
0244
0245
0246 int snd_msnd_DARQ(struct snd_msnd *chip, int bank)
0247 {
0248 int timeout = 3;
0249 u16 wTmp;
0250
0251
0252
0253 wTmp = readw(chip->DARQ + JQS_wTail) + PCTODSP_OFFSET(DAQDS__size);
0254 if (wTmp > readw(chip->DARQ + JQS_wSize))
0255 wTmp = 0;
0256 while (wTmp == readw(chip->DARQ + JQS_wHead) && timeout--)
0257 udelay(1);
0258
0259 if (chip->capturePeriods == 2) {
0260 void __iomem *pDAQ = chip->mappedbase + DARQ_DATA_BUFF +
0261 bank * DAQDS__size + DAQDS_wStart;
0262 unsigned short offset = 0x3000 + chip->capturePeriodBytes;
0263
0264 if (readw(pDAQ) != PCTODSP_BASED(0x3000))
0265 offset = 0x3000;
0266 writew(PCTODSP_BASED(offset), pDAQ);
0267 }
0268
0269 writew(wTmp, chip->DARQ + JQS_wTail);
0270
0271 #if 0
0272
0273 DAQD = bank * DAQDS__size + chip->mappedbase + DARQ_DATA_BUFF;
0274
0275
0276 size = readw(DAQD + DAQDS_wSize);
0277
0278
0279
0280 outb(HPBLKSEL_1, chip->io + HP_BLKS);
0281 n = msnd_fifo_write(&chip->DARF,
0282 (char *)(chip->base + bank * DAR_BUFF_SIZE),
0283 size, 0);
0284 if (n <= 0) {
0285 outb(HPBLKSEL_0, chip->io + HP_BLKS);
0286 return n;
0287 }
0288 outb(HPBLKSEL_0, chip->io + HP_BLKS);
0289 #endif
0290
0291 return 1;
0292 }
0293 EXPORT_SYMBOL(snd_msnd_DARQ);
0294
0295 int snd_msnd_DAPQ(struct snd_msnd *chip, int start)
0296 {
0297 u16 DAPQ_tail;
0298 int protect = start, nbanks = 0;
0299 void __iomem *DAQD;
0300 static int play_banks_submitted;
0301
0302
0303
0304 DAPQ_tail = readw(chip->DAPQ + JQS_wTail);
0305 while (DAPQ_tail != readw(chip->DAPQ + JQS_wHead) || start) {
0306 int bank_num = DAPQ_tail / PCTODSP_OFFSET(DAQDS__size);
0307
0308 if (start) {
0309 start = 0;
0310 play_banks_submitted = 0;
0311 }
0312
0313
0314 DAQD = bank_num * DAQDS__size + chip->mappedbase +
0315 DAPQ_DATA_BUFF;
0316
0317
0318 writew(chip->play_period_bytes, DAQD + DAQDS_wSize);
0319 if (play_banks_submitted < 3)
0320 ++play_banks_submitted;
0321 else if (chip->playPeriods == 2) {
0322 unsigned short offset = chip->play_period_bytes;
0323
0324 if (readw(DAQD + DAQDS_wStart) != PCTODSP_BASED(0x0))
0325 offset = 0;
0326
0327 writew(PCTODSP_BASED(offset), DAQD + DAQDS_wStart);
0328 }
0329 ++nbanks;
0330
0331
0332
0333
0334
0335
0336
0337
0338 DAPQ_tail = (++bank_num % 3) * PCTODSP_OFFSET(DAQDS__size);
0339 writew(DAPQ_tail, chip->DAPQ + JQS_wTail);
0340
0341 snd_msnd_send_dsp_cmd(chip, HDEX_PLAY_START);
0342 if (protect)
0343 if (2 == bank_num)
0344 break;
0345 }
0346
0347
0348
0349
0350
0351 return nbanks;
0352 }
0353 EXPORT_SYMBOL(snd_msnd_DAPQ);
0354
0355 static void snd_msnd_play_reset_queue(struct snd_msnd *chip,
0356 unsigned int pcm_periods,
0357 unsigned int pcm_count)
0358 {
0359 int n;
0360 void __iomem *pDAQ = chip->mappedbase + DAPQ_DATA_BUFF;
0361
0362 chip->last_playbank = -1;
0363 chip->playLimit = pcm_count * (pcm_periods - 1);
0364 chip->playPeriods = pcm_periods;
0365 writew(PCTODSP_OFFSET(0 * DAQDS__size), chip->DAPQ + JQS_wHead);
0366 writew(PCTODSP_OFFSET(0 * DAQDS__size), chip->DAPQ + JQS_wTail);
0367
0368 chip->play_period_bytes = pcm_count;
0369
0370 for (n = 0; n < pcm_periods; ++n, pDAQ += DAQDS__size) {
0371 writew(PCTODSP_BASED((u32)(pcm_count * n)),
0372 pDAQ + DAQDS_wStart);
0373 writew(0, pDAQ + DAQDS_wSize);
0374 writew(1, pDAQ + DAQDS_wFormat);
0375 writew(chip->play_sample_size, pDAQ + DAQDS_wSampleSize);
0376 writew(chip->play_channels, pDAQ + DAQDS_wChannels);
0377 writew(chip->play_sample_rate, pDAQ + DAQDS_wSampleRate);
0378 writew(HIMT_PLAY_DONE * 0x100 + n, pDAQ + DAQDS_wIntMsg);
0379 writew(n, pDAQ + DAQDS_wFlags);
0380 }
0381 }
0382
0383 static void snd_msnd_capture_reset_queue(struct snd_msnd *chip,
0384 unsigned int pcm_periods,
0385 unsigned int pcm_count)
0386 {
0387 int n;
0388 void __iomem *pDAQ;
0389
0390
0391
0392
0393 chip->last_recbank = 2;
0394 chip->captureLimit = pcm_count * (pcm_periods - 1);
0395 chip->capturePeriods = pcm_periods;
0396 writew(PCTODSP_OFFSET(0 * DAQDS__size), chip->DARQ + JQS_wHead);
0397 writew(PCTODSP_OFFSET(chip->last_recbank * DAQDS__size),
0398 chip->DARQ + JQS_wTail);
0399
0400 #if 0
0401 spin_lock_irqsave(&chip->lock, flags);
0402 outb(HPBLKSEL_1, chip->io + HP_BLKS);
0403 memset_io(chip->mappedbase, 0, DAR_BUFF_SIZE * 3);
0404 outb(HPBLKSEL_0, chip->io + HP_BLKS);
0405 spin_unlock_irqrestore(&chip->lock, flags);
0406 #endif
0407
0408 chip->capturePeriodBytes = pcm_count;
0409 snd_printdd("snd_msnd_capture_reset_queue() %i\n", pcm_count);
0410
0411 pDAQ = chip->mappedbase + DARQ_DATA_BUFF;
0412
0413 for (n = 0; n < pcm_periods; ++n, pDAQ += DAQDS__size) {
0414 u32 tmp = pcm_count * n;
0415
0416 writew(PCTODSP_BASED(tmp + 0x3000), pDAQ + DAQDS_wStart);
0417 writew(pcm_count, pDAQ + DAQDS_wSize);
0418 writew(1, pDAQ + DAQDS_wFormat);
0419 writew(chip->capture_sample_size, pDAQ + DAQDS_wSampleSize);
0420 writew(chip->capture_channels, pDAQ + DAQDS_wChannels);
0421 writew(chip->capture_sample_rate, pDAQ + DAQDS_wSampleRate);
0422 writew(HIMT_RECORD_DONE * 0x100 + n, pDAQ + DAQDS_wIntMsg);
0423 writew(n, pDAQ + DAQDS_wFlags);
0424 }
0425 }
0426
0427 static const struct snd_pcm_hardware snd_msnd_playback = {
0428 .info = SNDRV_PCM_INFO_MMAP_IOMEM |
0429 SNDRV_PCM_INFO_INTERLEAVED |
0430 SNDRV_PCM_INFO_MMAP_VALID |
0431 SNDRV_PCM_INFO_BATCH,
0432 .formats = SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE,
0433 .rates = SNDRV_PCM_RATE_8000_48000,
0434 .rate_min = 8000,
0435 .rate_max = 48000,
0436 .channels_min = 1,
0437 .channels_max = 2,
0438 .buffer_bytes_max = 0x3000,
0439 .period_bytes_min = 0x40,
0440 .period_bytes_max = 0x1800,
0441 .periods_min = 2,
0442 .periods_max = 3,
0443 .fifo_size = 0,
0444 };
0445
0446 static const struct snd_pcm_hardware snd_msnd_capture = {
0447 .info = SNDRV_PCM_INFO_MMAP_IOMEM |
0448 SNDRV_PCM_INFO_INTERLEAVED |
0449 SNDRV_PCM_INFO_MMAP_VALID |
0450 SNDRV_PCM_INFO_BATCH,
0451 .formats = SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE,
0452 .rates = SNDRV_PCM_RATE_8000_48000,
0453 .rate_min = 8000,
0454 .rate_max = 48000,
0455 .channels_min = 1,
0456 .channels_max = 2,
0457 .buffer_bytes_max = 0x3000,
0458 .period_bytes_min = 0x40,
0459 .period_bytes_max = 0x1800,
0460 .periods_min = 2,
0461 .periods_max = 3,
0462 .fifo_size = 0,
0463 };
0464
0465
0466 static int snd_msnd_playback_open(struct snd_pcm_substream *substream)
0467 {
0468 struct snd_pcm_runtime *runtime = substream->runtime;
0469 struct snd_msnd *chip = snd_pcm_substream_chip(substream);
0470
0471 set_bit(F_AUDIO_WRITE_INUSE, &chip->flags);
0472 clear_bit(F_WRITING, &chip->flags);
0473 snd_msnd_enable_irq(chip);
0474
0475 runtime->dma_area = (__force void *)chip->mappedbase;
0476 runtime->dma_addr = chip->base;
0477 runtime->dma_bytes = 0x3000;
0478
0479 chip->playback_substream = substream;
0480 runtime->hw = snd_msnd_playback;
0481 return 0;
0482 }
0483
0484 static int snd_msnd_playback_close(struct snd_pcm_substream *substream)
0485 {
0486 struct snd_msnd *chip = snd_pcm_substream_chip(substream);
0487
0488 snd_msnd_disable_irq(chip);
0489 clear_bit(F_AUDIO_WRITE_INUSE, &chip->flags);
0490 return 0;
0491 }
0492
0493
0494 static int snd_msnd_playback_hw_params(struct snd_pcm_substream *substream,
0495 struct snd_pcm_hw_params *params)
0496 {
0497 int i;
0498 struct snd_msnd *chip = snd_pcm_substream_chip(substream);
0499 void __iomem *pDAQ = chip->mappedbase + DAPQ_DATA_BUFF;
0500
0501 chip->play_sample_size = snd_pcm_format_width(params_format(params));
0502 chip->play_channels = params_channels(params);
0503 chip->play_sample_rate = params_rate(params);
0504
0505 for (i = 0; i < 3; ++i, pDAQ += DAQDS__size) {
0506 writew(chip->play_sample_size, pDAQ + DAQDS_wSampleSize);
0507 writew(chip->play_channels, pDAQ + DAQDS_wChannels);
0508 writew(chip->play_sample_rate, pDAQ + DAQDS_wSampleRate);
0509 }
0510
0511
0512
0513
0514 return 0;
0515 }
0516
0517 static int snd_msnd_playback_prepare(struct snd_pcm_substream *substream)
0518 {
0519 struct snd_msnd *chip = snd_pcm_substream_chip(substream);
0520 unsigned int pcm_size = snd_pcm_lib_buffer_bytes(substream);
0521 unsigned int pcm_count = snd_pcm_lib_period_bytes(substream);
0522 unsigned int pcm_periods = pcm_size / pcm_count;
0523
0524 snd_msnd_play_reset_queue(chip, pcm_periods, pcm_count);
0525 chip->playDMAPos = 0;
0526 return 0;
0527 }
0528
0529 static int snd_msnd_playback_trigger(struct snd_pcm_substream *substream,
0530 int cmd)
0531 {
0532 struct snd_msnd *chip = snd_pcm_substream_chip(substream);
0533 int result = 0;
0534
0535 if (cmd == SNDRV_PCM_TRIGGER_START) {
0536 snd_printdd("snd_msnd_playback_trigger(START)\n");
0537 chip->banksPlayed = 0;
0538 set_bit(F_WRITING, &chip->flags);
0539 snd_msnd_DAPQ(chip, 1);
0540 } else if (cmd == SNDRV_PCM_TRIGGER_STOP) {
0541 snd_printdd("snd_msnd_playback_trigger(STop)\n");
0542
0543 clear_bit(F_WRITING, &chip->flags);
0544 snd_msnd_send_dsp_cmd(chip, HDEX_PLAY_STOP);
0545 } else {
0546 snd_printd(KERN_ERR "snd_msnd_playback_trigger(?????)\n");
0547 result = -EINVAL;
0548 }
0549
0550 snd_printdd("snd_msnd_playback_trigger() ENDE\n");
0551 return result;
0552 }
0553
0554 static snd_pcm_uframes_t
0555 snd_msnd_playback_pointer(struct snd_pcm_substream *substream)
0556 {
0557 struct snd_msnd *chip = snd_pcm_substream_chip(substream);
0558
0559 return bytes_to_frames(substream->runtime, chip->playDMAPos);
0560 }
0561
0562
0563 static const struct snd_pcm_ops snd_msnd_playback_ops = {
0564 .open = snd_msnd_playback_open,
0565 .close = snd_msnd_playback_close,
0566 .hw_params = snd_msnd_playback_hw_params,
0567 .prepare = snd_msnd_playback_prepare,
0568 .trigger = snd_msnd_playback_trigger,
0569 .pointer = snd_msnd_playback_pointer,
0570 .mmap = snd_pcm_lib_mmap_iomem,
0571 };
0572
0573 static int snd_msnd_capture_open(struct snd_pcm_substream *substream)
0574 {
0575 struct snd_pcm_runtime *runtime = substream->runtime;
0576 struct snd_msnd *chip = snd_pcm_substream_chip(substream);
0577
0578 set_bit(F_AUDIO_READ_INUSE, &chip->flags);
0579 snd_msnd_enable_irq(chip);
0580 runtime->dma_area = (__force void *)chip->mappedbase + 0x3000;
0581 runtime->dma_addr = chip->base + 0x3000;
0582 runtime->dma_bytes = 0x3000;
0583 memset(runtime->dma_area, 0, runtime->dma_bytes);
0584 chip->capture_substream = substream;
0585 runtime->hw = snd_msnd_capture;
0586 return 0;
0587 }
0588
0589 static int snd_msnd_capture_close(struct snd_pcm_substream *substream)
0590 {
0591 struct snd_msnd *chip = snd_pcm_substream_chip(substream);
0592
0593 snd_msnd_disable_irq(chip);
0594 clear_bit(F_AUDIO_READ_INUSE, &chip->flags);
0595 return 0;
0596 }
0597
0598 static int snd_msnd_capture_prepare(struct snd_pcm_substream *substream)
0599 {
0600 struct snd_msnd *chip = snd_pcm_substream_chip(substream);
0601 unsigned int pcm_size = snd_pcm_lib_buffer_bytes(substream);
0602 unsigned int pcm_count = snd_pcm_lib_period_bytes(substream);
0603 unsigned int pcm_periods = pcm_size / pcm_count;
0604
0605 snd_msnd_capture_reset_queue(chip, pcm_periods, pcm_count);
0606 chip->captureDMAPos = 0;
0607 return 0;
0608 }
0609
0610 static int snd_msnd_capture_trigger(struct snd_pcm_substream *substream,
0611 int cmd)
0612 {
0613 struct snd_msnd *chip = snd_pcm_substream_chip(substream);
0614
0615 if (cmd == SNDRV_PCM_TRIGGER_START) {
0616 chip->last_recbank = -1;
0617 set_bit(F_READING, &chip->flags);
0618 if (snd_msnd_send_dsp_cmd(chip, HDEX_RECORD_START) == 0)
0619 return 0;
0620
0621 clear_bit(F_READING, &chip->flags);
0622 } else if (cmd == SNDRV_PCM_TRIGGER_STOP) {
0623 clear_bit(F_READING, &chip->flags);
0624 snd_msnd_send_dsp_cmd(chip, HDEX_RECORD_STOP);
0625 return 0;
0626 }
0627 return -EINVAL;
0628 }
0629
0630
0631 static snd_pcm_uframes_t
0632 snd_msnd_capture_pointer(struct snd_pcm_substream *substream)
0633 {
0634 struct snd_pcm_runtime *runtime = substream->runtime;
0635 struct snd_msnd *chip = snd_pcm_substream_chip(substream);
0636
0637 return bytes_to_frames(runtime, chip->captureDMAPos);
0638 }
0639
0640
0641 static int snd_msnd_capture_hw_params(struct snd_pcm_substream *substream,
0642 struct snd_pcm_hw_params *params)
0643 {
0644 int i;
0645 struct snd_msnd *chip = snd_pcm_substream_chip(substream);
0646 void __iomem *pDAQ = chip->mappedbase + DARQ_DATA_BUFF;
0647
0648 chip->capture_sample_size = snd_pcm_format_width(params_format(params));
0649 chip->capture_channels = params_channels(params);
0650 chip->capture_sample_rate = params_rate(params);
0651
0652 for (i = 0; i < 3; ++i, pDAQ += DAQDS__size) {
0653 writew(chip->capture_sample_size, pDAQ + DAQDS_wSampleSize);
0654 writew(chip->capture_channels, pDAQ + DAQDS_wChannels);
0655 writew(chip->capture_sample_rate, pDAQ + DAQDS_wSampleRate);
0656 }
0657 return 0;
0658 }
0659
0660
0661 static const struct snd_pcm_ops snd_msnd_capture_ops = {
0662 .open = snd_msnd_capture_open,
0663 .close = snd_msnd_capture_close,
0664 .hw_params = snd_msnd_capture_hw_params,
0665 .prepare = snd_msnd_capture_prepare,
0666 .trigger = snd_msnd_capture_trigger,
0667 .pointer = snd_msnd_capture_pointer,
0668 .mmap = snd_pcm_lib_mmap_iomem,
0669 };
0670
0671
0672 int snd_msnd_pcm(struct snd_card *card, int device)
0673 {
0674 struct snd_msnd *chip = card->private_data;
0675 struct snd_pcm *pcm;
0676 int err;
0677
0678 err = snd_pcm_new(card, "MSNDPINNACLE", device, 1, 1, &pcm);
0679 if (err < 0)
0680 return err;
0681
0682 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_msnd_playback_ops);
0683 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_msnd_capture_ops);
0684
0685 pcm->private_data = chip;
0686 strcpy(pcm->name, "Hurricane");
0687
0688 return 0;
0689 }
0690 EXPORT_SYMBOL(snd_msnd_pcm);
0691
0692 MODULE_DESCRIPTION("Common routines for Turtle Beach Multisound drivers");
0693 MODULE_LICENSE("GPL");
0694