root/sound/isa/msnd/msnd.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. snd_msnd_init_queue
  2. snd_msnd_wait_TXDE
  3. snd_msnd_wait_HC0
  4. snd_msnd_send_dsp_cmd
  5. snd_msnd_send_word
  6. snd_msnd_upload_host
  7. snd_msnd_enable_irq
  8. snd_msnd_disable_irq
  9. get_play_delay_jiffies
  10. snd_msnd_dsp_write_flush
  11. snd_msnd_dsp_halt
  12. snd_msnd_DARQ
  13. snd_msnd_DAPQ
  14. snd_msnd_play_reset_queue
  15. snd_msnd_capture_reset_queue
  16. snd_msnd_playback_open
  17. snd_msnd_playback_close
  18. snd_msnd_playback_hw_params
  19. snd_msnd_playback_prepare
  20. snd_msnd_playback_trigger
  21. snd_msnd_playback_pointer
  22. snd_msnd_capture_open
  23. snd_msnd_capture_close
  24. snd_msnd_capture_prepare
  25. snd_msnd_capture_trigger
  26. snd_msnd_capture_pointer
  27. snd_msnd_capture_hw_params
  28. snd_msnd_pcm

   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         snd_printd(KERN_ERR 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         snd_printd(KERN_ERR 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                 snd_printk(KERN_ERR 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         snd_printdd(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         snd_printd(KERN_ERR 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                 snd_printd(KERN_WARNING LOGNAME ": IRQ ref count is %d\n",
 174                            dev->irq_ref);
 175 
 176         snd_printdd(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         snd_printd(KERN_ERR 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                         snd_printd(KERN_INFO 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                         snd_printd(KERN_INFO
 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                 /*
 333                 if (protect)
 334                         snd_printd(KERN_INFO "B %X %lX\n",
 335                                    bank_num, xtime.tv_usec);
 336                 */
 337 
 338                 DAPQ_tail = (++bank_num % 3) * PCTODSP_OFFSET(DAQDS__size);
 339                 writew(DAPQ_tail, chip->DAPQ + JQS_wTail);
 340                 /* Tell the DSP to play the bank */
 341                 snd_msnd_send_dsp_cmd(chip, HDEX_PLAY_START);
 342                 if (protect)
 343                         if (2 == bank_num)
 344                                 break;
 345         }
 346         /*
 347         if (protect)
 348                 snd_printd(KERN_INFO "%lX\n", xtime.tv_usec);
 349         */
 350         /* spin_unlock_irqrestore(&chip->lock, flags); not necessary */
 351         return nbanks;
 352 }
 353 EXPORT_SYMBOL(snd_msnd_DAPQ);
 354 
 355 static void snd_msnd_play_reset_queue(struct snd_msnd *chip,
 356                                       unsigned int pcm_periods,
 357                                       unsigned int pcm_count)
 358 {
 359         int     n;
 360         void    __iomem *pDAQ = chip->mappedbase + DAPQ_DATA_BUFF;
 361 
 362         chip->last_playbank = -1;
 363         chip->playLimit = pcm_count * (pcm_periods - 1);
 364         chip->playPeriods = pcm_periods;
 365         writew(PCTODSP_OFFSET(0 * DAQDS__size), chip->DAPQ + JQS_wHead);
 366         writew(PCTODSP_OFFSET(0 * DAQDS__size), chip->DAPQ + JQS_wTail);
 367 
 368         chip->play_period_bytes = pcm_count;
 369 
 370         for (n = 0; n < pcm_periods; ++n, pDAQ += DAQDS__size) {
 371                 writew(PCTODSP_BASED((u32)(pcm_count * n)),
 372                         pDAQ + DAQDS_wStart);
 373                 writew(0, pDAQ + DAQDS_wSize);
 374                 writew(1, pDAQ + DAQDS_wFormat);
 375                 writew(chip->play_sample_size, pDAQ + DAQDS_wSampleSize);
 376                 writew(chip->play_channels, pDAQ + DAQDS_wChannels);
 377                 writew(chip->play_sample_rate, pDAQ + DAQDS_wSampleRate);
 378                 writew(HIMT_PLAY_DONE * 0x100 + n, pDAQ + DAQDS_wIntMsg);
 379                 writew(n, pDAQ + DAQDS_wFlags);
 380         }
 381 }
 382 
 383 static void snd_msnd_capture_reset_queue(struct snd_msnd *chip,
 384                                          unsigned int pcm_periods,
 385                                          unsigned int pcm_count)
 386 {
 387         int             n;
 388         void            __iomem *pDAQ;
 389         /* unsigned long        flags; */
 390 
 391         /* snd_msnd_init_queue(chip->DARQ, DARQ_DATA_BUFF, DARQ_BUFF_SIZE); */
 392 
 393         chip->last_recbank = 2;
 394         chip->captureLimit = pcm_count * (pcm_periods - 1);
 395         chip->capturePeriods = pcm_periods;
 396         writew(PCTODSP_OFFSET(0 * DAQDS__size), chip->DARQ + JQS_wHead);
 397         writew(PCTODSP_OFFSET(chip->last_recbank * DAQDS__size),
 398                 chip->DARQ + JQS_wTail);
 399 
 400 #if 0 /* Critical section: bank 1 access. this is how the OSS driver does it:*/
 401         spin_lock_irqsave(&chip->lock, flags);
 402         outb(HPBLKSEL_1, chip->io + HP_BLKS);
 403         memset_io(chip->mappedbase, 0, DAR_BUFF_SIZE * 3);
 404         outb(HPBLKSEL_0, chip->io + HP_BLKS);
 405         spin_unlock_irqrestore(&chip->lock, flags);
 406 #endif
 407 
 408         chip->capturePeriodBytes = pcm_count;
 409         snd_printdd("snd_msnd_capture_reset_queue() %i\n", pcm_count);
 410 
 411         pDAQ = chip->mappedbase + DARQ_DATA_BUFF;
 412 
 413         for (n = 0; n < pcm_periods; ++n, pDAQ += DAQDS__size) {
 414                 u32 tmp = pcm_count * n;
 415 
 416                 writew(PCTODSP_BASED(tmp + 0x3000), pDAQ + DAQDS_wStart);
 417                 writew(pcm_count, pDAQ + DAQDS_wSize);
 418                 writew(1, pDAQ + DAQDS_wFormat);
 419                 writew(chip->capture_sample_size, pDAQ + DAQDS_wSampleSize);
 420                 writew(chip->capture_channels, pDAQ + DAQDS_wChannels);
 421                 writew(chip->capture_sample_rate, pDAQ + DAQDS_wSampleRate);
 422                 writew(HIMT_RECORD_DONE * 0x100 + n, pDAQ + DAQDS_wIntMsg);
 423                 writew(n, pDAQ + DAQDS_wFlags);
 424         }
 425 }
 426 
 427 static const struct snd_pcm_hardware snd_msnd_playback = {
 428         .info =                 SNDRV_PCM_INFO_MMAP |
 429                                 SNDRV_PCM_INFO_INTERLEAVED |
 430                                 SNDRV_PCM_INFO_MMAP_VALID |
 431                                 SNDRV_PCM_INFO_BATCH,
 432         .formats =              SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE,
 433         .rates =                SNDRV_PCM_RATE_8000_48000,
 434         .rate_min =             8000,
 435         .rate_max =             48000,
 436         .channels_min =         1,
 437         .channels_max =         2,
 438         .buffer_bytes_max =     0x3000,
 439         .period_bytes_min =     0x40,
 440         .period_bytes_max =     0x1800,
 441         .periods_min =          2,
 442         .periods_max =          3,
 443         .fifo_size =            0,
 444 };
 445 
 446 static const struct snd_pcm_hardware snd_msnd_capture = {
 447         .info =                 SNDRV_PCM_INFO_MMAP |
 448                                 SNDRV_PCM_INFO_INTERLEAVED |
 449                                 SNDRV_PCM_INFO_MMAP_VALID |
 450                                 SNDRV_PCM_INFO_BATCH,
 451         .formats =              SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE,
 452         .rates =                SNDRV_PCM_RATE_8000_48000,
 453         .rate_min =             8000,
 454         .rate_max =             48000,
 455         .channels_min =         1,
 456         .channels_max =         2,
 457         .buffer_bytes_max =     0x3000,
 458         .period_bytes_min =     0x40,
 459         .period_bytes_max =     0x1800,
 460         .periods_min =          2,
 461         .periods_max =          3,
 462         .fifo_size =            0,
 463 };
 464 
 465 
 466 static int snd_msnd_playback_open(struct snd_pcm_substream *substream)
 467 {
 468         struct snd_pcm_runtime *runtime = substream->runtime;
 469         struct snd_msnd *chip = snd_pcm_substream_chip(substream);
 470 
 471         set_bit(F_AUDIO_WRITE_INUSE, &chip->flags);
 472         clear_bit(F_WRITING, &chip->flags);
 473         snd_msnd_enable_irq(chip);
 474 
 475         runtime->dma_area = (__force void *)chip->mappedbase;
 476         runtime->dma_bytes = 0x3000;
 477 
 478         chip->playback_substream = substream;
 479         runtime->hw = snd_msnd_playback;
 480         return 0;
 481 }
 482 
 483 static int snd_msnd_playback_close(struct snd_pcm_substream *substream)
 484 {
 485         struct snd_msnd *chip = snd_pcm_substream_chip(substream);
 486 
 487         snd_msnd_disable_irq(chip);
 488         clear_bit(F_AUDIO_WRITE_INUSE, &chip->flags);
 489         return 0;
 490 }
 491 
 492 
 493 static int snd_msnd_playback_hw_params(struct snd_pcm_substream *substream,
 494                                         struct snd_pcm_hw_params *params)
 495 {
 496         int     i;
 497         struct snd_msnd *chip = snd_pcm_substream_chip(substream);
 498         void    __iomem *pDAQ = chip->mappedbase + DAPQ_DATA_BUFF;
 499 
 500         chip->play_sample_size = snd_pcm_format_width(params_format(params));
 501         chip->play_channels = params_channels(params);
 502         chip->play_sample_rate = params_rate(params);
 503 
 504         for (i = 0; i < 3; ++i, pDAQ += DAQDS__size) {
 505                 writew(chip->play_sample_size, pDAQ + DAQDS_wSampleSize);
 506                 writew(chip->play_channels, pDAQ + DAQDS_wChannels);
 507                 writew(chip->play_sample_rate, pDAQ + DAQDS_wSampleRate);
 508         }
 509         /* dont do this here:
 510          * snd_msnd_calibrate_adc(chip->play_sample_rate);
 511          */
 512 
 513         return 0;
 514 }
 515 
 516 static int snd_msnd_playback_prepare(struct snd_pcm_substream *substream)
 517 {
 518         struct snd_msnd *chip = snd_pcm_substream_chip(substream);
 519         unsigned int pcm_size = snd_pcm_lib_buffer_bytes(substream);
 520         unsigned int pcm_count = snd_pcm_lib_period_bytes(substream);
 521         unsigned int pcm_periods = pcm_size / pcm_count;
 522 
 523         snd_msnd_play_reset_queue(chip, pcm_periods, pcm_count);
 524         chip->playDMAPos = 0;
 525         return 0;
 526 }
 527 
 528 static int snd_msnd_playback_trigger(struct snd_pcm_substream *substream,
 529                                      int cmd)
 530 {
 531         struct snd_msnd *chip = snd_pcm_substream_chip(substream);
 532         int     result = 0;
 533 
 534         if (cmd == SNDRV_PCM_TRIGGER_START) {
 535                 snd_printdd("snd_msnd_playback_trigger(START)\n");
 536                 chip->banksPlayed = 0;
 537                 set_bit(F_WRITING, &chip->flags);
 538                 snd_msnd_DAPQ(chip, 1);
 539         } else if (cmd == SNDRV_PCM_TRIGGER_STOP) {
 540                 snd_printdd("snd_msnd_playback_trigger(STop)\n");
 541                 /* interrupt diagnostic, comment this out later */
 542                 clear_bit(F_WRITING, &chip->flags);
 543                 snd_msnd_send_dsp_cmd(chip, HDEX_PLAY_STOP);
 544         } else {
 545                 snd_printd(KERN_ERR "snd_msnd_playback_trigger(?????)\n");
 546                 result = -EINVAL;
 547         }
 548 
 549         snd_printdd("snd_msnd_playback_trigger() ENDE\n");
 550         return result;
 551 }
 552 
 553 static snd_pcm_uframes_t
 554 snd_msnd_playback_pointer(struct snd_pcm_substream *substream)
 555 {
 556         struct snd_msnd *chip = snd_pcm_substream_chip(substream);
 557 
 558         return bytes_to_frames(substream->runtime, chip->playDMAPos);
 559 }
 560 
 561 
 562 static const struct snd_pcm_ops snd_msnd_playback_ops = {
 563         .open =         snd_msnd_playback_open,
 564         .close =        snd_msnd_playback_close,
 565         .ioctl =        snd_pcm_lib_ioctl,
 566         .hw_params =    snd_msnd_playback_hw_params,
 567         .prepare =      snd_msnd_playback_prepare,
 568         .trigger =      snd_msnd_playback_trigger,
 569         .pointer =      snd_msnd_playback_pointer,
 570 };
 571 
 572 static int snd_msnd_capture_open(struct snd_pcm_substream *substream)
 573 {
 574         struct snd_pcm_runtime *runtime = substream->runtime;
 575         struct snd_msnd *chip = snd_pcm_substream_chip(substream);
 576 
 577         set_bit(F_AUDIO_READ_INUSE, &chip->flags);
 578         snd_msnd_enable_irq(chip);
 579         runtime->dma_area = (__force void *)chip->mappedbase + 0x3000;
 580         runtime->dma_bytes = 0x3000;
 581         memset(runtime->dma_area, 0, runtime->dma_bytes);
 582         chip->capture_substream = substream;
 583         runtime->hw = snd_msnd_capture;
 584         return 0;
 585 }
 586 
 587 static int snd_msnd_capture_close(struct snd_pcm_substream *substream)
 588 {
 589         struct snd_msnd *chip = snd_pcm_substream_chip(substream);
 590 
 591         snd_msnd_disable_irq(chip);
 592         clear_bit(F_AUDIO_READ_INUSE, &chip->flags);
 593         return 0;
 594 }
 595 
 596 static int snd_msnd_capture_prepare(struct snd_pcm_substream *substream)
 597 {
 598         struct snd_msnd *chip = snd_pcm_substream_chip(substream);
 599         unsigned int pcm_size = snd_pcm_lib_buffer_bytes(substream);
 600         unsigned int pcm_count = snd_pcm_lib_period_bytes(substream);
 601         unsigned int pcm_periods = pcm_size / pcm_count;
 602 
 603         snd_msnd_capture_reset_queue(chip, pcm_periods, pcm_count);
 604         chip->captureDMAPos = 0;
 605         return 0;
 606 }
 607 
 608 static int snd_msnd_capture_trigger(struct snd_pcm_substream *substream,
 609                                     int cmd)
 610 {
 611         struct snd_msnd *chip = snd_pcm_substream_chip(substream);
 612 
 613         if (cmd == SNDRV_PCM_TRIGGER_START) {
 614                 chip->last_recbank = -1;
 615                 set_bit(F_READING, &chip->flags);
 616                 if (snd_msnd_send_dsp_cmd(chip, HDEX_RECORD_START) == 0)
 617                         return 0;
 618 
 619                 clear_bit(F_READING, &chip->flags);
 620         } else if (cmd == SNDRV_PCM_TRIGGER_STOP) {
 621                 clear_bit(F_READING, &chip->flags);
 622                 snd_msnd_send_dsp_cmd(chip, HDEX_RECORD_STOP);
 623                 return 0;
 624         }
 625         return -EINVAL;
 626 }
 627 
 628 
 629 static snd_pcm_uframes_t
 630 snd_msnd_capture_pointer(struct snd_pcm_substream *substream)
 631 {
 632         struct snd_pcm_runtime *runtime = substream->runtime;
 633         struct snd_msnd *chip = snd_pcm_substream_chip(substream);
 634 
 635         return bytes_to_frames(runtime, chip->captureDMAPos);
 636 }
 637 
 638 
 639 static int snd_msnd_capture_hw_params(struct snd_pcm_substream *substream,
 640                                         struct snd_pcm_hw_params *params)
 641 {
 642         int             i;
 643         struct snd_msnd *chip = snd_pcm_substream_chip(substream);
 644         void            __iomem *pDAQ = chip->mappedbase + DARQ_DATA_BUFF;
 645 
 646         chip->capture_sample_size = snd_pcm_format_width(params_format(params));
 647         chip->capture_channels = params_channels(params);
 648         chip->capture_sample_rate = params_rate(params);
 649 
 650         for (i = 0; i < 3; ++i, pDAQ += DAQDS__size) {
 651                 writew(chip->capture_sample_size, pDAQ + DAQDS_wSampleSize);
 652                 writew(chip->capture_channels, pDAQ + DAQDS_wChannels);
 653                 writew(chip->capture_sample_rate, pDAQ + DAQDS_wSampleRate);
 654         }
 655         return 0;
 656 }
 657 
 658 
 659 static const struct snd_pcm_ops snd_msnd_capture_ops = {
 660         .open =         snd_msnd_capture_open,
 661         .close =        snd_msnd_capture_close,
 662         .ioctl =        snd_pcm_lib_ioctl,
 663         .hw_params =    snd_msnd_capture_hw_params,
 664         .prepare =      snd_msnd_capture_prepare,
 665         .trigger =      snd_msnd_capture_trigger,
 666         .pointer =      snd_msnd_capture_pointer,
 667 };
 668 
 669 
 670 int snd_msnd_pcm(struct snd_card *card, int device)
 671 {
 672         struct snd_msnd *chip = card->private_data;
 673         struct snd_pcm  *pcm;
 674         int err;
 675 
 676         err = snd_pcm_new(card, "MSNDPINNACLE", device, 1, 1, &pcm);
 677         if (err < 0)
 678                 return err;
 679 
 680         snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_msnd_playback_ops);
 681         snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_msnd_capture_ops);
 682 
 683         pcm->private_data = chip;
 684         strcpy(pcm->name, "Hurricane");
 685 
 686         return 0;
 687 }
 688 EXPORT_SYMBOL(snd_msnd_pcm);
 689 
 690 MODULE_DESCRIPTION("Common routines for Turtle Beach Multisound drivers");
 691 MODULE_LICENSE("GPL");
 692 

/* [<][>][^][v][top][bottom][index][help] */