msnd.c 19 KB

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