cardwi.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:9k
源码类别:

Linux/Unix编程

开发平台:

Unix_Linux

  1. /*
  2.  **********************************************************************
  3.  *     cardwi.c - PCM input HAL for emu10k1 driver
  4.  *     Copyright 1999, 2000 Creative Labs, Inc.
  5.  *
  6.  **********************************************************************
  7.  *
  8.  *     Date                 Author          Summary of changes
  9.  *     ----                 ------          ------------------
  10.  *     October 20, 1999     Bertrand Lee    base code release
  11.  *
  12.  **********************************************************************
  13.  *
  14.  *     This program is free software; you can redistribute it and/or
  15.  *     modify it under the terms of the GNU General Public License as
  16.  *     published by the Free Software Foundation; either version 2 of
  17.  *     the License, or (at your option) any later version.
  18.  *
  19.  *     This program is distributed in the hope that it will be useful,
  20.  *     but WITHOUT ANY WARRANTY; without even the implied warranty of
  21.  *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  22.  *     GNU General Public License for more details.
  23.  *
  24.  *     You should have received a copy of the GNU General Public
  25.  *     License along with this program; if not, write to the Free
  26.  *     Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139,
  27.  *     USA.
  28.  *
  29.  **********************************************************************
  30.  */
  31. #include <linux/poll.h>
  32. #include "hwaccess.h"
  33. #include "timer.h"
  34. #include "recmgr.h"
  35. #include "audio.h"
  36. #include "cardwi.h"
  37. /**
  38.  * query_format - returns a valid sound format
  39.  *
  40.  * This function will return a valid sound format as close
  41.  * to the requested one as possible. 
  42.  */
  43. void query_format(int recsrc, struct wave_format *wave_fmt)
  44. {
  45. switch (recsrc) {
  46. case WAVERECORD_AC97:
  47. if ((wave_fmt->channels != 1) && (wave_fmt->channels != 2))
  48. wave_fmt->channels = 2;
  49. if (wave_fmt->samplingrate >= (0xBB80 + 0xAC44) / 2)
  50. wave_fmt->samplingrate = 0xBB80;
  51. else if (wave_fmt->samplingrate >= (0xAC44 + 0x7D00) / 2)
  52. wave_fmt->samplingrate = 0xAC44;
  53. else if (wave_fmt->samplingrate >= (0x7D00 + 0x5DC0) / 2)
  54. wave_fmt->samplingrate = 0x7D00;
  55. else if (wave_fmt->samplingrate >= (0x5DC0 + 0x5622) / 2)
  56. wave_fmt->samplingrate = 0x5DC0;
  57. else if (wave_fmt->samplingrate >= (0x5622 + 0x3E80) / 2)
  58. wave_fmt->samplingrate = 0x5622;
  59. else if (wave_fmt->samplingrate >= (0x3E80 + 0x2B11) / 2)
  60. wave_fmt->samplingrate = 0x3E80;
  61. else if (wave_fmt->samplingrate >= (0x2B11 + 0x1F40) / 2)
  62. wave_fmt->samplingrate = 0x2B11;
  63. else
  64. wave_fmt->samplingrate = 0x1F40;
  65. switch (wave_fmt->id) {
  66. case AFMT_S16_LE:
  67. wave_fmt->bitsperchannel = 16;
  68. break;
  69. case AFMT_U8:
  70. wave_fmt->bitsperchannel = 8;
  71. break;
  72. default:
  73. wave_fmt->id = AFMT_S16_LE;
  74. wave_fmt->bitsperchannel = 16;
  75. break;
  76. }
  77. break;
  78. /* these can't be changed from the original values */
  79. case WAVERECORD_MIC:
  80. case WAVERECORD_FX:
  81. break;
  82. default:
  83. BUG();
  84. break;
  85. }
  86. wave_fmt->bytesperchannel = wave_fmt->bitsperchannel >> 3;
  87. wave_fmt->bytespersample = wave_fmt->channels * wave_fmt->bytesperchannel;
  88. wave_fmt->bytespersec = wave_fmt->bytespersample * wave_fmt->samplingrate;
  89. wave_fmt->bytespervoicesample = wave_fmt->bytespersample;
  90. }
  91. static int alloc_buffer(struct emu10k1_card *card, struct wavein_buffer *buffer)
  92. {
  93. buffer->addr = pci_alloc_consistent(card->pci_dev, buffer->size * buffer->cov,
  94.     &buffer->dma_handle);
  95. if (buffer->addr == NULL)
  96. return -1;
  97. return 0;
  98. }
  99. static void free_buffer(struct emu10k1_card *card, struct wavein_buffer *buffer)
  100. {
  101. if (buffer->addr != NULL)
  102. pci_free_consistent(card->pci_dev, buffer->size * buffer->cov,
  103.     buffer->addr, buffer->dma_handle);
  104. }
  105. int emu10k1_wavein_open(struct emu10k1_wavedevice *wave_dev)
  106. {
  107. struct emu10k1_card *card = wave_dev->card;
  108. struct wiinst *wiinst = wave_dev->wiinst;
  109. struct wiinst **wiinst_tmp = NULL;
  110. u16 delay;
  111. unsigned long flags;
  112. DPF(2, "emu10k1_wavein_open()n");
  113. switch (wiinst->recsrc) {
  114. case WAVERECORD_AC97:
  115. wiinst_tmp = &card->wavein.ac97;
  116. break;
  117. case WAVERECORD_MIC:
  118. wiinst_tmp = &card->wavein.mic;
  119. break;
  120. case WAVERECORD_FX:
  121. wiinst_tmp = &card->wavein.fx;
  122. break;
  123. default:
  124. BUG();
  125. break;
  126. }
  127. spin_lock_irqsave(&card->lock, flags);
  128. if (*wiinst_tmp != NULL) {
  129. spin_unlock_irqrestore(&card->lock, flags);
  130. return -1;
  131. }
  132. *wiinst_tmp = wiinst;
  133. spin_unlock_irqrestore(&card->lock, flags);
  134. /* handle 8 bit recording */
  135. if (wiinst->format.bytesperchannel == 1) {
  136. if (wiinst->buffer.size > 0x8000) {
  137. wiinst->buffer.size = 0x8000;
  138. wiinst->buffer.sizeregval = 0x1f;
  139. } else
  140. wiinst->buffer.sizeregval += 4;
  141. wiinst->buffer.cov = 2;
  142. } else
  143. wiinst->buffer.cov = 1;
  144. if (alloc_buffer(card, &wiinst->buffer) < 0) {
  145. ERROR();
  146. emu10k1_wavein_close(wave_dev);
  147. return -1;
  148. }
  149. emu10k1_set_record_src(card, wiinst);
  150. emu10k1_reset_record(card, &wiinst->buffer);
  151. wiinst->buffer.hw_pos = 0;
  152. wiinst->buffer.pos = 0;
  153. wiinst->buffer.bytestocopy = 0;
  154. delay = (48000 * wiinst->buffer.fragment_size) / wiinst->format.bytespersec;
  155. emu10k1_timer_install(card, &wiinst->timer, delay / 2);
  156. wiinst->state = WAVE_STATE_OPEN;
  157. return 0;
  158. }
  159. void emu10k1_wavein_close(struct emu10k1_wavedevice *wave_dev)
  160. {
  161. struct emu10k1_card *card = wave_dev->card;
  162. struct wiinst *wiinst = wave_dev->wiinst;
  163. unsigned long flags;
  164. DPF(2, "emu10k1_wavein_close()n");
  165. emu10k1_wavein_stop(wave_dev);
  166. emu10k1_timer_uninstall(card, &wiinst->timer);
  167. free_buffer(card, &wiinst->buffer);
  168. spin_lock_irqsave(&card->lock, flags);
  169. switch (wave_dev->wiinst->recsrc) {
  170. case WAVERECORD_AC97:
  171. card->wavein.ac97 = NULL;
  172. break;
  173. case WAVERECORD_MIC:
  174. card->wavein.mic = NULL;
  175. break;
  176. case WAVERECORD_FX:
  177. card->wavein.fx = NULL;
  178. break;
  179. default:
  180. BUG();
  181. break;
  182. }
  183. spin_unlock_irqrestore(&card->lock, flags);
  184. wiinst->state = WAVE_STATE_CLOSED;
  185. }
  186. void emu10k1_wavein_start(struct emu10k1_wavedevice *wave_dev)
  187. {
  188. struct emu10k1_card *card = wave_dev->card;
  189. struct wiinst *wiinst = wave_dev->wiinst;
  190. DPF(2, "emu10k1_wavein_start()n");
  191. emu10k1_start_record(card, &wiinst->buffer);
  192. emu10k1_timer_enable(wave_dev->card, &wiinst->timer);
  193. wiinst->state |= WAVE_STATE_STARTED;
  194. }
  195. void emu10k1_wavein_stop(struct emu10k1_wavedevice *wave_dev)
  196. {
  197. struct emu10k1_card *card = wave_dev->card;
  198. struct wiinst *wiinst = wave_dev->wiinst;
  199. DPF(2, "emu10k1_wavein_stop()n");
  200. if (!(wiinst->state & WAVE_STATE_STARTED))
  201. return;
  202. emu10k1_timer_disable(card, &wiinst->timer);
  203. emu10k1_stop_record(card, &wiinst->buffer);
  204. wiinst->state &= ~WAVE_STATE_STARTED;
  205. }
  206. int emu10k1_wavein_setformat(struct emu10k1_wavedevice *wave_dev, struct wave_format *format)
  207. {
  208. struct emu10k1_card *card = wave_dev->card;
  209. struct wiinst *wiinst = wave_dev->wiinst;
  210. u16 delay;
  211. DPF(2, "emu10k1_wavein_setformat()n");
  212. if (wiinst->state & WAVE_STATE_STARTED)
  213. return -1;
  214. query_format(wiinst->recsrc, format);
  215. if ((wiinst->format.samplingrate != format->samplingrate)
  216.     || (wiinst->format.bitsperchannel != format->bitsperchannel)
  217.     || (wiinst->format.channels != format->channels)) {
  218. wiinst->format = *format;
  219. if (wiinst->state == WAVE_STATE_CLOSED)
  220. return 0;
  221. wiinst->buffer.size *= wiinst->buffer.cov;
  222. if (wiinst->format.bytesperchannel == 1) {
  223. wiinst->buffer.cov = 2;
  224. wiinst->buffer.size /= wiinst->buffer.cov;
  225. } else
  226. wiinst->buffer.cov = 1;
  227. emu10k1_timer_uninstall(card, &wiinst->timer);
  228. delay = (48000 * wiinst->buffer.fragment_size) / wiinst->format.bytespersec;
  229. emu10k1_timer_install(card, &wiinst->timer, delay / 2);
  230. }
  231. return 0;
  232. }
  233. void emu10k1_wavein_getxfersize(struct wiinst *wiinst, u32 * size)
  234. {
  235. struct wavein_buffer *buffer = &wiinst->buffer;
  236. *size = buffer->bytestocopy;
  237. if (wiinst->mmapped)
  238. return;
  239. if (*size > buffer->size) {
  240. *size = buffer->size;
  241. buffer->pos = buffer->hw_pos;
  242. buffer->bytestocopy = buffer->size;
  243. DPF(1, "buffer overrunn");
  244. }
  245. }
  246. static void copy_block(u8 *dst, u8 * src, u32 str, u32 len, u8 cov)
  247. {
  248. if (cov == 1)
  249. __copy_to_user(dst, src + str, len);
  250. else {
  251. u8 byte;
  252. u32 i;
  253. src += 1 + 2 * str;
  254. for (i = 0; i < len; i++) {
  255. byte = src[2 * i] ^ 0x80;
  256. __copy_to_user(dst + i, &byte, 1);
  257. }
  258. }
  259. }
  260. void emu10k1_wavein_xferdata(struct wiinst *wiinst, u8 * data, u32 * size)
  261. {
  262. struct wavein_buffer *buffer = &wiinst->buffer;
  263. u32 sizetocopy, sizetocopy_now, start;
  264. unsigned long flags;
  265. sizetocopy = min_t(u32, buffer->size, *size);
  266. *size = sizetocopy;
  267. if (!sizetocopy)
  268. return;
  269. spin_lock_irqsave(&wiinst->lock, flags);
  270. start = buffer->pos;
  271. buffer->pos += sizetocopy;
  272. buffer->pos %= buffer->size;
  273. buffer->bytestocopy -= sizetocopy;
  274. sizetocopy_now = buffer->size - start;
  275. spin_unlock_irqrestore(&wiinst->lock, flags);
  276. if (sizetocopy > sizetocopy_now) {
  277. sizetocopy -= sizetocopy_now;
  278. copy_block(data, buffer->addr, start, sizetocopy_now, buffer->cov);
  279. copy_block(data + sizetocopy_now, buffer->addr, 0, sizetocopy, buffer->cov);
  280. } else {
  281. copy_block(data, buffer->addr, start, sizetocopy, buffer->cov);
  282. }
  283. }
  284. void emu10k1_wavein_update(struct emu10k1_card *card, struct wiinst *wiinst)
  285. {
  286. u32 hw_pos;
  287. u32 diff;
  288. /* There is no actual start yet */
  289. if (!(wiinst->state & WAVE_STATE_STARTED)) {
  290. hw_pos = wiinst->buffer.hw_pos;
  291. } else {
  292. /* hw_pos in byte units */
  293. hw_pos = sblive_readptr(card, wiinst->buffer.idxreg, 0) / wiinst->buffer.cov;
  294. }
  295. diff = (wiinst->buffer.size + hw_pos - wiinst->buffer.hw_pos) % wiinst->buffer.size;
  296. wiinst->total_recorded += diff;
  297. wiinst->buffer.bytestocopy += diff;
  298. wiinst->buffer.hw_pos = hw_pos;
  299. }