msnd.c 19 KB

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