msnd.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694
  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. snd_printd(KERN_ERR 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. snd_printd(KERN_ERR 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. snd_printk(KERN_ERR 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. snd_printdd(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. snd_printd(KERN_ERR 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. snd_printd(KERN_WARNING LOGNAME ": IRQ ref count is %d\n",
  139. dev->irq_ref);
  140. snd_printdd(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. snd_printd(KERN_ERR 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. snd_printd(KERN_INFO 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. snd_printd(KERN_INFO
  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. /*
  273. if (protect)
  274. snd_printd(KERN_INFO "B %X %lX\n",
  275. bank_num, xtime.tv_usec);
  276. */
  277. DAPQ_tail = (++bank_num % 3) * PCTODSP_OFFSET(DAQDS__size);
  278. writew(DAPQ_tail, chip->DAPQ + JQS_wTail);
  279. /* Tell the DSP to play the bank */
  280. snd_msnd_send_dsp_cmd(chip, HDEX_PLAY_START);
  281. if (protect)
  282. if (2 == bank_num)
  283. break;
  284. }
  285. /*
  286. if (protect)
  287. snd_printd(KERN_INFO "%lX\n", xtime.tv_usec);
  288. */
  289. /* spin_unlock_irqrestore(&chip->lock, flags); not necessary */
  290. return nbanks;
  291. }
  292. EXPORT_SYMBOL(snd_msnd_DAPQ);
  293. static void snd_msnd_play_reset_queue(struct snd_msnd *chip,
  294. unsigned int pcm_periods,
  295. unsigned int pcm_count)
  296. {
  297. int n;
  298. void __iomem *pDAQ = chip->mappedbase + DAPQ_DATA_BUFF;
  299. chip->last_playbank = -1;
  300. chip->playLimit = pcm_count * (pcm_periods - 1);
  301. chip->playPeriods = pcm_periods;
  302. writew(PCTODSP_OFFSET(0 * DAQDS__size), chip->DAPQ + JQS_wHead);
  303. writew(PCTODSP_OFFSET(0 * DAQDS__size), chip->DAPQ + JQS_wTail);
  304. chip->play_period_bytes = pcm_count;
  305. for (n = 0; n < pcm_periods; ++n, pDAQ += DAQDS__size) {
  306. writew(PCTODSP_BASED((u32)(pcm_count * n)),
  307. pDAQ + DAQDS_wStart);
  308. writew(0, pDAQ + DAQDS_wSize);
  309. writew(1, pDAQ + DAQDS_wFormat);
  310. writew(chip->play_sample_size, pDAQ + DAQDS_wSampleSize);
  311. writew(chip->play_channels, pDAQ + DAQDS_wChannels);
  312. writew(chip->play_sample_rate, pDAQ + DAQDS_wSampleRate);
  313. writew(HIMT_PLAY_DONE * 0x100 + n, pDAQ + DAQDS_wIntMsg);
  314. writew(n, pDAQ + DAQDS_wFlags);
  315. }
  316. }
  317. static void snd_msnd_capture_reset_queue(struct snd_msnd *chip,
  318. unsigned int pcm_periods,
  319. unsigned int pcm_count)
  320. {
  321. int n;
  322. void __iomem *pDAQ;
  323. /* unsigned long flags; */
  324. /* snd_msnd_init_queue(chip->DARQ, DARQ_DATA_BUFF, DARQ_BUFF_SIZE); */
  325. chip->last_recbank = 2;
  326. chip->captureLimit = pcm_count * (pcm_periods - 1);
  327. chip->capturePeriods = pcm_periods;
  328. writew(PCTODSP_OFFSET(0 * DAQDS__size), chip->DARQ + JQS_wHead);
  329. writew(PCTODSP_OFFSET(chip->last_recbank * DAQDS__size),
  330. chip->DARQ + JQS_wTail);
  331. #if 0 /* Critical section: bank 1 access. this is how the OSS driver does it:*/
  332. spin_lock_irqsave(&chip->lock, flags);
  333. outb(HPBLKSEL_1, chip->io + HP_BLKS);
  334. memset_io(chip->mappedbase, 0, DAR_BUFF_SIZE * 3);
  335. outb(HPBLKSEL_0, chip->io + HP_BLKS);
  336. spin_unlock_irqrestore(&chip->lock, flags);
  337. #endif
  338. chip->capturePeriodBytes = pcm_count;
  339. snd_printdd("snd_msnd_capture_reset_queue() %i\n", pcm_count);
  340. pDAQ = chip->mappedbase + DARQ_DATA_BUFF;
  341. for (n = 0; n < pcm_periods; ++n, pDAQ += DAQDS__size) {
  342. u32 tmp = pcm_count * n;
  343. writew(PCTODSP_BASED(tmp + 0x3000), pDAQ + DAQDS_wStart);
  344. writew(pcm_count, pDAQ + DAQDS_wSize);
  345. writew(1, pDAQ + DAQDS_wFormat);
  346. writew(chip->capture_sample_size, pDAQ + DAQDS_wSampleSize);
  347. writew(chip->capture_channels, pDAQ + DAQDS_wChannels);
  348. writew(chip->capture_sample_rate, pDAQ + DAQDS_wSampleRate);
  349. writew(HIMT_RECORD_DONE * 0x100 + n, pDAQ + DAQDS_wIntMsg);
  350. writew(n, pDAQ + DAQDS_wFlags);
  351. }
  352. }
  353. static const struct snd_pcm_hardware snd_msnd_playback = {
  354. .info = SNDRV_PCM_INFO_MMAP_IOMEM |
  355. SNDRV_PCM_INFO_INTERLEAVED |
  356. SNDRV_PCM_INFO_MMAP_VALID |
  357. SNDRV_PCM_INFO_BATCH,
  358. .formats = SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE,
  359. .rates = SNDRV_PCM_RATE_8000_48000,
  360. .rate_min = 8000,
  361. .rate_max = 48000,
  362. .channels_min = 1,
  363. .channels_max = 2,
  364. .buffer_bytes_max = 0x3000,
  365. .period_bytes_min = 0x40,
  366. .period_bytes_max = 0x1800,
  367. .periods_min = 2,
  368. .periods_max = 3,
  369. .fifo_size = 0,
  370. };
  371. static const struct snd_pcm_hardware snd_msnd_capture = {
  372. .info = SNDRV_PCM_INFO_MMAP_IOMEM |
  373. SNDRV_PCM_INFO_INTERLEAVED |
  374. SNDRV_PCM_INFO_MMAP_VALID |
  375. SNDRV_PCM_INFO_BATCH,
  376. .formats = SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE,
  377. .rates = SNDRV_PCM_RATE_8000_48000,
  378. .rate_min = 8000,
  379. .rate_max = 48000,
  380. .channels_min = 1,
  381. .channels_max = 2,
  382. .buffer_bytes_max = 0x3000,
  383. .period_bytes_min = 0x40,
  384. .period_bytes_max = 0x1800,
  385. .periods_min = 2,
  386. .periods_max = 3,
  387. .fifo_size = 0,
  388. };
  389. static int snd_msnd_playback_open(struct snd_pcm_substream *substream)
  390. {
  391. struct snd_pcm_runtime *runtime = substream->runtime;
  392. struct snd_msnd *chip = snd_pcm_substream_chip(substream);
  393. set_bit(F_AUDIO_WRITE_INUSE, &chip->flags);
  394. clear_bit(F_WRITING, &chip->flags);
  395. snd_msnd_enable_irq(chip);
  396. runtime->dma_area = (__force void *)chip->mappedbase;
  397. runtime->dma_addr = chip->base;
  398. runtime->dma_bytes = 0x3000;
  399. chip->playback_substream = substream;
  400. runtime->hw = snd_msnd_playback;
  401. return 0;
  402. }
  403. static int snd_msnd_playback_close(struct snd_pcm_substream *substream)
  404. {
  405. struct snd_msnd *chip = snd_pcm_substream_chip(substream);
  406. snd_msnd_disable_irq(chip);
  407. clear_bit(F_AUDIO_WRITE_INUSE, &chip->flags);
  408. return 0;
  409. }
  410. static int snd_msnd_playback_hw_params(struct snd_pcm_substream *substream,
  411. struct snd_pcm_hw_params *params)
  412. {
  413. int i;
  414. struct snd_msnd *chip = snd_pcm_substream_chip(substream);
  415. void __iomem *pDAQ = chip->mappedbase + DAPQ_DATA_BUFF;
  416. chip->play_sample_size = snd_pcm_format_width(params_format(params));
  417. chip->play_channels = params_channels(params);
  418. chip->play_sample_rate = params_rate(params);
  419. for (i = 0; i < 3; ++i, pDAQ += DAQDS__size) {
  420. writew(chip->play_sample_size, pDAQ + DAQDS_wSampleSize);
  421. writew(chip->play_channels, pDAQ + DAQDS_wChannels);
  422. writew(chip->play_sample_rate, pDAQ + DAQDS_wSampleRate);
  423. }
  424. /* dont do this here:
  425. * snd_msnd_calibrate_adc(chip->play_sample_rate);
  426. */
  427. return 0;
  428. }
  429. static int snd_msnd_playback_prepare(struct snd_pcm_substream *substream)
  430. {
  431. struct snd_msnd *chip = snd_pcm_substream_chip(substream);
  432. unsigned int pcm_size = snd_pcm_lib_buffer_bytes(substream);
  433. unsigned int pcm_count = snd_pcm_lib_period_bytes(substream);
  434. unsigned int pcm_periods = pcm_size / pcm_count;
  435. snd_msnd_play_reset_queue(chip, pcm_periods, pcm_count);
  436. chip->playDMAPos = 0;
  437. return 0;
  438. }
  439. static int snd_msnd_playback_trigger(struct snd_pcm_substream *substream,
  440. int cmd)
  441. {
  442. struct snd_msnd *chip = snd_pcm_substream_chip(substream);
  443. int result = 0;
  444. if (cmd == SNDRV_PCM_TRIGGER_START) {
  445. snd_printdd("snd_msnd_playback_trigger(START)\n");
  446. chip->banksPlayed = 0;
  447. set_bit(F_WRITING, &chip->flags);
  448. snd_msnd_DAPQ(chip, 1);
  449. } else if (cmd == SNDRV_PCM_TRIGGER_STOP) {
  450. snd_printdd("snd_msnd_playback_trigger(STop)\n");
  451. /* interrupt diagnostic, comment this out later */
  452. clear_bit(F_WRITING, &chip->flags);
  453. snd_msnd_send_dsp_cmd(chip, HDEX_PLAY_STOP);
  454. } else {
  455. snd_printd(KERN_ERR "snd_msnd_playback_trigger(?????)\n");
  456. result = -EINVAL;
  457. }
  458. snd_printdd("snd_msnd_playback_trigger() ENDE\n");
  459. return result;
  460. }
  461. static snd_pcm_uframes_t
  462. snd_msnd_playback_pointer(struct snd_pcm_substream *substream)
  463. {
  464. struct snd_msnd *chip = snd_pcm_substream_chip(substream);
  465. return bytes_to_frames(substream->runtime, chip->playDMAPos);
  466. }
  467. static const struct snd_pcm_ops snd_msnd_playback_ops = {
  468. .open = snd_msnd_playback_open,
  469. .close = snd_msnd_playback_close,
  470. .hw_params = snd_msnd_playback_hw_params,
  471. .prepare = snd_msnd_playback_prepare,
  472. .trigger = snd_msnd_playback_trigger,
  473. .pointer = snd_msnd_playback_pointer,
  474. .mmap = snd_pcm_lib_mmap_iomem,
  475. };
  476. static int snd_msnd_capture_open(struct snd_pcm_substream *substream)
  477. {
  478. struct snd_pcm_runtime *runtime = substream->runtime;
  479. struct snd_msnd *chip = snd_pcm_substream_chip(substream);
  480. set_bit(F_AUDIO_READ_INUSE, &chip->flags);
  481. snd_msnd_enable_irq(chip);
  482. runtime->dma_area = (__force void *)chip->mappedbase + 0x3000;
  483. runtime->dma_addr = chip->base + 0x3000;
  484. runtime->dma_bytes = 0x3000;
  485. memset(runtime->dma_area, 0, runtime->dma_bytes);
  486. chip->capture_substream = substream;
  487. runtime->hw = snd_msnd_capture;
  488. return 0;
  489. }
  490. static int snd_msnd_capture_close(struct snd_pcm_substream *substream)
  491. {
  492. struct snd_msnd *chip = snd_pcm_substream_chip(substream);
  493. snd_msnd_disable_irq(chip);
  494. clear_bit(F_AUDIO_READ_INUSE, &chip->flags);
  495. return 0;
  496. }
  497. static int snd_msnd_capture_prepare(struct snd_pcm_substream *substream)
  498. {
  499. struct snd_msnd *chip = snd_pcm_substream_chip(substream);
  500. unsigned int pcm_size = snd_pcm_lib_buffer_bytes(substream);
  501. unsigned int pcm_count = snd_pcm_lib_period_bytes(substream);
  502. unsigned int pcm_periods = pcm_size / pcm_count;
  503. snd_msnd_capture_reset_queue(chip, pcm_periods, pcm_count);
  504. chip->captureDMAPos = 0;
  505. return 0;
  506. }
  507. static int snd_msnd_capture_trigger(struct snd_pcm_substream *substream,
  508. int cmd)
  509. {
  510. struct snd_msnd *chip = snd_pcm_substream_chip(substream);
  511. if (cmd == SNDRV_PCM_TRIGGER_START) {
  512. chip->last_recbank = -1;
  513. set_bit(F_READING, &chip->flags);
  514. if (snd_msnd_send_dsp_cmd(chip, HDEX_RECORD_START) == 0)
  515. return 0;
  516. clear_bit(F_READING, &chip->flags);
  517. } else if (cmd == SNDRV_PCM_TRIGGER_STOP) {
  518. clear_bit(F_READING, &chip->flags);
  519. snd_msnd_send_dsp_cmd(chip, HDEX_RECORD_STOP);
  520. return 0;
  521. }
  522. return -EINVAL;
  523. }
  524. static snd_pcm_uframes_t
  525. snd_msnd_capture_pointer(struct snd_pcm_substream *substream)
  526. {
  527. struct snd_pcm_runtime *runtime = substream->runtime;
  528. struct snd_msnd *chip = snd_pcm_substream_chip(substream);
  529. return bytes_to_frames(runtime, chip->captureDMAPos);
  530. }
  531. static int snd_msnd_capture_hw_params(struct snd_pcm_substream *substream,
  532. struct snd_pcm_hw_params *params)
  533. {
  534. int i;
  535. struct snd_msnd *chip = snd_pcm_substream_chip(substream);
  536. void __iomem *pDAQ = chip->mappedbase + DARQ_DATA_BUFF;
  537. chip->capture_sample_size = snd_pcm_format_width(params_format(params));
  538. chip->capture_channels = params_channels(params);
  539. chip->capture_sample_rate = params_rate(params);
  540. for (i = 0; i < 3; ++i, pDAQ += DAQDS__size) {
  541. writew(chip->capture_sample_size, pDAQ + DAQDS_wSampleSize);
  542. writew(chip->capture_channels, pDAQ + DAQDS_wChannels);
  543. writew(chip->capture_sample_rate, pDAQ + DAQDS_wSampleRate);
  544. }
  545. return 0;
  546. }
  547. static const struct snd_pcm_ops snd_msnd_capture_ops = {
  548. .open = snd_msnd_capture_open,
  549. .close = snd_msnd_capture_close,
  550. .hw_params = snd_msnd_capture_hw_params,
  551. .prepare = snd_msnd_capture_prepare,
  552. .trigger = snd_msnd_capture_trigger,
  553. .pointer = snd_msnd_capture_pointer,
  554. .mmap = snd_pcm_lib_mmap_iomem,
  555. };
  556. int snd_msnd_pcm(struct snd_card *card, int device)
  557. {
  558. struct snd_msnd *chip = card->private_data;
  559. struct snd_pcm *pcm;
  560. int err;
  561. err = snd_pcm_new(card, "MSNDPINNACLE", device, 1, 1, &pcm);
  562. if (err < 0)
  563. return err;
  564. snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_msnd_playback_ops);
  565. snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_msnd_capture_ops);
  566. pcm->private_data = chip;
  567. strcpy(pcm->name, "Hurricane");
  568. return 0;
  569. }
  570. EXPORT_SYMBOL(snd_msnd_pcm);
  571. MODULE_DESCRIPTION("Common routines for Turtle Beach Multisound drivers");
  572. MODULE_LICENSE("GPL");