pdaudiocf_pcm.c 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350
  1. /*
  2. * Driver for Sound Core PDAudioCF soundcards
  3. *
  4. * PCM part
  5. *
  6. * Copyright (c) 2003 by Jaroslav Kysela <perex@suse.cz>
  7. *
  8. * This program is free software; you can redistribute it and/or modify
  9. * it under the terms of the GNU General Public License as published by
  10. * the Free Software Foundation; either version 2 of the License, or
  11. * (at your option) any later version.
  12. *
  13. * This program is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. * GNU General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU General Public License
  19. * along with this program; if not, write to the Free Software
  20. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  21. */
  22. #include <sound/driver.h>
  23. #include <linux/slab.h>
  24. #include <linux/vmalloc.h>
  25. #include <linux/delay.h>
  26. #include <sound/core.h>
  27. #include <sound/asoundef.h>
  28. #include "pdaudiocf.h"
  29. /*
  30. * we use a vmalloc'ed (sg-)buffer
  31. */
  32. /* get the physical page pointer on the given offset */
  33. static struct page *snd_pcm_get_vmalloc_page(struct snd_pcm_substream *subs, unsigned long offset)
  34. {
  35. void *pageptr = subs->runtime->dma_area + offset;
  36. return vmalloc_to_page(pageptr);
  37. }
  38. /*
  39. * hw_params callback
  40. * NOTE: this may be called not only once per pcm open!
  41. */
  42. static int snd_pcm_alloc_vmalloc_buffer(struct snd_pcm_substream *subs, size_t size)
  43. {
  44. struct snd_pcm_runtime *runtime = subs->runtime;
  45. if (runtime->dma_area) {
  46. if (runtime->dma_bytes >= size)
  47. return 0; /* already enough large */
  48. vfree(runtime->dma_area);
  49. }
  50. runtime->dma_area = vmalloc_32(size);
  51. if (! runtime->dma_area)
  52. return -ENOMEM;
  53. runtime->dma_bytes = size;
  54. return 0;
  55. }
  56. /*
  57. * hw_free callback
  58. * NOTE: this may be called not only once per pcm open!
  59. */
  60. static int snd_pcm_free_vmalloc_buffer(struct snd_pcm_substream *subs)
  61. {
  62. struct snd_pcm_runtime *runtime = subs->runtime;
  63. vfree(runtime->dma_area);
  64. runtime->dma_area = NULL;
  65. return 0;
  66. }
  67. /*
  68. * clear the SRAM contents
  69. */
  70. static int pdacf_pcm_clear_sram(struct snd_pdacf *chip)
  71. {
  72. int max_loop = 64 * 1024;
  73. while (inw(chip->port + PDAUDIOCF_REG_RDP) != inw(chip->port + PDAUDIOCF_REG_WDP)) {
  74. if (max_loop-- < 0)
  75. return -EIO;
  76. inw(chip->port + PDAUDIOCF_REG_MD);
  77. }
  78. return 0;
  79. }
  80. /*
  81. * pdacf_pcm_trigger - trigger callback for capture
  82. */
  83. static int pdacf_pcm_trigger(struct snd_pcm_substream *subs, int cmd)
  84. {
  85. struct snd_pdacf *chip = snd_pcm_substream_chip(subs);
  86. struct snd_pcm_runtime *runtime = subs->runtime;
  87. int inc, ret = 0, rate;
  88. unsigned short mask, val, tmp;
  89. if (chip->chip_status & PDAUDIOCF_STAT_IS_STALE)
  90. return -EBUSY;
  91. switch (cmd) {
  92. case SNDRV_PCM_TRIGGER_START:
  93. chip->pcm_hwptr = 0;
  94. chip->pcm_tdone = 0;
  95. /* fall thru */
  96. case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
  97. case SNDRV_PCM_TRIGGER_RESUME:
  98. mask = 0;
  99. val = PDAUDIOCF_RECORD;
  100. inc = 1;
  101. rate = snd_ak4117_check_rate_and_errors(chip->ak4117, AK4117_CHECK_NO_STAT|AK4117_CHECK_NO_RATE);
  102. break;
  103. case SNDRV_PCM_TRIGGER_STOP:
  104. case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
  105. case SNDRV_PCM_TRIGGER_SUSPEND:
  106. mask = PDAUDIOCF_RECORD;
  107. val = 0;
  108. inc = -1;
  109. rate = 0;
  110. break;
  111. default:
  112. return -EINVAL;
  113. }
  114. spin_lock(&chip->reg_lock);
  115. chip->pcm_running += inc;
  116. tmp = pdacf_reg_read(chip, PDAUDIOCF_REG_SCR);
  117. if (chip->pcm_running) {
  118. if ((chip->ak4117->rcs0 & AK4117_UNLCK) || runtime->rate != rate) {
  119. chip->pcm_running -= inc;
  120. ret = -EIO;
  121. goto __end;
  122. }
  123. }
  124. tmp &= ~mask;
  125. tmp |= val;
  126. pdacf_reg_write(chip, PDAUDIOCF_REG_SCR, tmp);
  127. __end:
  128. spin_unlock(&chip->reg_lock);
  129. snd_ak4117_check_rate_and_errors(chip->ak4117, AK4117_CHECK_NO_RATE);
  130. return ret;
  131. }
  132. /*
  133. * pdacf_pcm_hw_params - hw_params callback for playback and capture
  134. */
  135. static int pdacf_pcm_hw_params(struct snd_pcm_substream *subs,
  136. struct snd_pcm_hw_params *hw_params)
  137. {
  138. return snd_pcm_alloc_vmalloc_buffer(subs, params_buffer_bytes(hw_params));
  139. }
  140. /*
  141. * pdacf_pcm_hw_free - hw_free callback for playback and capture
  142. */
  143. static int pdacf_pcm_hw_free(struct snd_pcm_substream *subs)
  144. {
  145. return snd_pcm_free_vmalloc_buffer(subs);
  146. }
  147. /*
  148. * pdacf_pcm_prepare - prepare callback for playback and capture
  149. */
  150. static int pdacf_pcm_prepare(struct snd_pcm_substream *subs)
  151. {
  152. struct snd_pdacf *chip = snd_pcm_substream_chip(subs);
  153. struct snd_pcm_runtime *runtime = subs->runtime;
  154. u16 val, nval, aval;
  155. if (chip->chip_status & PDAUDIOCF_STAT_IS_STALE)
  156. return -EBUSY;
  157. chip->pcm_channels = runtime->channels;
  158. chip->pcm_little = snd_pcm_format_little_endian(runtime->format) > 0;
  159. #ifdef SNDRV_LITTLE_ENDIAN
  160. chip->pcm_swab = snd_pcm_format_big_endian(runtime->format) > 0;
  161. #else
  162. chip->pcm_swab = chip->pcm_little;
  163. #endif
  164. if (snd_pcm_format_unsigned(runtime->format))
  165. chip->pcm_xor = 0x80008000;
  166. if (pdacf_pcm_clear_sram(chip) < 0)
  167. return -EIO;
  168. val = nval = pdacf_reg_read(chip, PDAUDIOCF_REG_SCR);
  169. nval &= ~(PDAUDIOCF_DATAFMT0|PDAUDIOCF_DATAFMT1);
  170. switch (runtime->format) {
  171. case SNDRV_PCM_FORMAT_S16_LE:
  172. case SNDRV_PCM_FORMAT_S16_BE:
  173. break;
  174. default: /* 24-bit */
  175. nval |= PDAUDIOCF_DATAFMT0 | PDAUDIOCF_DATAFMT1;
  176. break;
  177. }
  178. aval = 0;
  179. chip->pcm_sample = 4;
  180. switch (runtime->format) {
  181. case SNDRV_PCM_FORMAT_S16_LE:
  182. case SNDRV_PCM_FORMAT_S16_BE:
  183. aval = AK4117_DIF_16R;
  184. chip->pcm_frame = 2;
  185. chip->pcm_sample = 2;
  186. break;
  187. case SNDRV_PCM_FORMAT_S24_3LE:
  188. case SNDRV_PCM_FORMAT_S24_3BE:
  189. chip->pcm_sample = 3;
  190. /* fall through */
  191. default: /* 24-bit */
  192. aval = AK4117_DIF_24R;
  193. chip->pcm_frame = 3;
  194. chip->pcm_xor &= 0xffff0000;
  195. break;
  196. }
  197. if (val != nval) {
  198. snd_ak4117_reg_write(chip->ak4117, AK4117_REG_IO, AK4117_DIF2|AK4117_DIF1|AK4117_DIF0, aval);
  199. pdacf_reg_write(chip, PDAUDIOCF_REG_SCR, nval);
  200. }
  201. val = pdacf_reg_read(chip, PDAUDIOCF_REG_IER);
  202. val &= ~(PDAUDIOCF_IRQLVLEN1);
  203. val |= PDAUDIOCF_IRQLVLEN0;
  204. pdacf_reg_write(chip, PDAUDIOCF_REG_IER, val);
  205. chip->pcm_size = runtime->buffer_size;
  206. chip->pcm_period = runtime->period_size;
  207. chip->pcm_area = runtime->dma_area;
  208. return 0;
  209. }
  210. /*
  211. * capture hw information
  212. */
  213. static struct snd_pcm_hardware pdacf_pcm_capture_hw = {
  214. .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
  215. SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME |
  216. SNDRV_PCM_INFO_MMAP_VALID),
  217. .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S16_BE |
  218. SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S24_3BE |
  219. SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S32_BE,
  220. .rates = SNDRV_PCM_RATE_32000 |
  221. SNDRV_PCM_RATE_44100 |
  222. SNDRV_PCM_RATE_48000 |
  223. SNDRV_PCM_RATE_88200 |
  224. SNDRV_PCM_RATE_96000 |
  225. SNDRV_PCM_RATE_176400 |
  226. SNDRV_PCM_RATE_192000,
  227. .rate_min = 32000,
  228. .rate_max = 192000,
  229. .channels_min = 1,
  230. .channels_max = 2,
  231. .buffer_bytes_max = (512*1024),
  232. .period_bytes_min = 8*1024,
  233. .period_bytes_max = (64*1024),
  234. .periods_min = 2,
  235. .periods_max = 128,
  236. .fifo_size = 0,
  237. };
  238. /*
  239. * pdacf_pcm_capture_open - open callback for capture
  240. */
  241. static int pdacf_pcm_capture_open(struct snd_pcm_substream *subs)
  242. {
  243. struct snd_pcm_runtime *runtime = subs->runtime;
  244. struct snd_pdacf *chip = snd_pcm_substream_chip(subs);
  245. if (chip->chip_status & PDAUDIOCF_STAT_IS_STALE)
  246. return -EBUSY;
  247. runtime->hw = pdacf_pcm_capture_hw;
  248. runtime->private_data = chip;
  249. chip->pcm_substream = subs;
  250. return 0;
  251. }
  252. /*
  253. * pdacf_pcm_capture_close - close callback for capture
  254. */
  255. static int pdacf_pcm_capture_close(struct snd_pcm_substream *subs)
  256. {
  257. struct snd_pdacf *chip = snd_pcm_substream_chip(subs);
  258. if (!chip)
  259. return -EINVAL;
  260. pdacf_reinit(chip, 0);
  261. chip->pcm_substream = NULL;
  262. return 0;
  263. }
  264. /*
  265. * pdacf_pcm_capture_pointer - pointer callback for capture
  266. */
  267. static snd_pcm_uframes_t pdacf_pcm_capture_pointer(struct snd_pcm_substream *subs)
  268. {
  269. struct snd_pdacf *chip = snd_pcm_substream_chip(subs);
  270. return chip->pcm_hwptr;
  271. }
  272. /*
  273. * operators for PCM capture
  274. */
  275. static struct snd_pcm_ops pdacf_pcm_capture_ops = {
  276. .open = pdacf_pcm_capture_open,
  277. .close = pdacf_pcm_capture_close,
  278. .ioctl = snd_pcm_lib_ioctl,
  279. .hw_params = pdacf_pcm_hw_params,
  280. .hw_free = pdacf_pcm_hw_free,
  281. .prepare = pdacf_pcm_prepare,
  282. .trigger = pdacf_pcm_trigger,
  283. .pointer = pdacf_pcm_capture_pointer,
  284. .page = snd_pcm_get_vmalloc_page,
  285. };
  286. /*
  287. * snd_pdacf_pcm_new - create and initialize a pcm
  288. */
  289. int snd_pdacf_pcm_new(struct snd_pdacf *chip)
  290. {
  291. struct snd_pcm *pcm;
  292. int err;
  293. err = snd_pcm_new(chip->card, "PDAudioCF", 0, 0, 1, &pcm);
  294. if (err < 0)
  295. return err;
  296. snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &pdacf_pcm_capture_ops);
  297. pcm->private_data = chip;
  298. pcm->info_flags = 0;
  299. strcpy(pcm->name, chip->card->shortname);
  300. chip->pcm = pcm;
  301. err = snd_ak4117_build(chip->ak4117, pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream);
  302. if (err < 0)
  303. return err;
  304. return 0;
  305. }