msnd.c 19 KB

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