PageRenderTime 27ms CodeModel.GetById 14ms RepoModel.GetById 0ms app.codeStats 1ms

/sound/isa/msnd/msnd.c

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