p16v.c 35 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041
  1. /*
  2. * Copyright (c) by James Courtier-Dutton <James@superbug.demon.co.uk>
  3. * Driver p16v chips
  4. * Version: 0.25
  5. *
  6. * FEATURES currently supported:
  7. * Output fixed at S32_LE, 2 channel to hw:0,0
  8. * Rates: 44.1, 48, 96, 192.
  9. *
  10. * Changelog:
  11. * 0.8
  12. * Use separate card based buffer for periods table.
  13. * 0.9
  14. * Use 2 channel output streams instead of 8 channel.
  15. * (8 channel output streams might be good for ASIO type output)
  16. * Corrected speaker output, so Front -> Front etc.
  17. * 0.10
  18. * Fixed missed interrupts.
  19. * 0.11
  20. * Add Sound card model number and names.
  21. * Add Analog volume controls.
  22. * 0.12
  23. * Corrected playback interrupts. Now interrupt per period, instead of half period.
  24. * 0.13
  25. * Use single trigger for multichannel.
  26. * 0.14
  27. * Mic capture now works at fixed: S32_LE, 96000Hz, Stereo.
  28. * 0.15
  29. * Force buffer_size / period_size == INTEGER.
  30. * 0.16
  31. * Update p16v.c to work with changed alsa api.
  32. * 0.17
  33. * Update p16v.c to work with changed alsa api. Removed boot_devs.
  34. * 0.18
  35. * Merging with snd-emu10k1 driver.
  36. * 0.19
  37. * One stereo channel at 24bit now works.
  38. * 0.20
  39. * Added better register defines.
  40. * 0.21
  41. * Integrated with snd-emu10k1 driver.
  42. * 0.22
  43. * Removed #if 0 ... #endif
  44. * 0.23
  45. * Implement different capture rates.
  46. * 0.24
  47. * Implement different capture source channels.
  48. * e.g. When HD Capture source is set to SPDIF,
  49. * setting HD Capture channel to 0 captures from CDROM digital input.
  50. * setting HD Capture channel to 1 captures from SPDIF in.
  51. * 0.25
  52. * Include capture buffer sizes.
  53. *
  54. * BUGS:
  55. * Some stability problems when unloading the snd-p16v kernel module.
  56. * --
  57. *
  58. * TODO:
  59. * SPDIF out.
  60. * Find out how to change capture sample rates. E.g. To record SPDIF at 48000Hz.
  61. * Currently capture fixed at 48000Hz.
  62. *
  63. * --
  64. * GENERAL INFO:
  65. * Model: SB0240
  66. * P16V Chip: CA0151-DBS
  67. * Audigy 2 Chip: CA0102-IAT
  68. * AC97 Codec: STAC 9721
  69. * ADC: Philips 1361T (Stereo 24bit)
  70. * DAC: CS4382-K (8-channel, 24bit, 192Khz)
  71. *
  72. * This code was initally based on code from ALSA's emu10k1x.c which is:
  73. * Copyright (c) by Francisco Moraes <fmoraes@nc.rr.com>
  74. *
  75. * This program is free software; you can redistribute it and/or modify
  76. * it under the terms of the GNU General Public License as published by
  77. * the Free Software Foundation; either version 2 of the License, or
  78. * (at your option) any later version.
  79. *
  80. * This program is distributed in the hope that it will be useful,
  81. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  82. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  83. * GNU General Public License for more details.
  84. *
  85. * You should have received a copy of the GNU General Public License
  86. * along with this program; if not, write to the Free Software
  87. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  88. *
  89. */
  90. #include <sound/driver.h>
  91. #include <linux/delay.h>
  92. #include <linux/init.h>
  93. #include <linux/interrupt.h>
  94. #include <linux/pci.h>
  95. #include <linux/slab.h>
  96. #include <linux/moduleparam.h>
  97. #include <sound/core.h>
  98. #include <sound/initval.h>
  99. #include <sound/pcm.h>
  100. #include <sound/ac97_codec.h>
  101. #include <sound/info.h>
  102. #include <sound/emu10k1.h>
  103. #include "p16v.h"
  104. #define SET_CHANNEL 0 /* Testing channel outputs 0=Front, 1=Center/LFE, 2=Unknown, 3=Rear */
  105. #define PCM_FRONT_CHANNEL 0
  106. #define PCM_REAR_CHANNEL 1
  107. #define PCM_CENTER_LFE_CHANNEL 2
  108. #define PCM_UNKNOWN_CHANNEL 3
  109. #define CONTROL_FRONT_CHANNEL 0
  110. #define CONTROL_REAR_CHANNEL 3
  111. #define CONTROL_CENTER_LFE_CHANNEL 1
  112. #define CONTROL_UNKNOWN_CHANNEL 2
  113. /* Card IDs:
  114. * Class 0401: 1102:0004 (rev 04) Subsystem: 1102:2002 -> Audigy2 ZS 7.1 Model:SB0350
  115. * Class 0401: 1102:0004 (rev 04) Subsystem: 1102:1007 -> Audigy2 6.1 Model:SB0240
  116. * Class 0401: 1102:0004 (rev 04) Subsystem: 1102:1002 -> Audigy2 Platinum Model:SB msb0240230009266
  117. * Class 0401: 1102:0004 (rev 04) Subsystem: 1102:2007 -> Audigy4 Pro Model:SB0380 M1SB0380472001901E
  118. *
  119. */
  120. /* hardware definition */
  121. static snd_pcm_hardware_t snd_p16v_playback_hw = {
  122. .info = (SNDRV_PCM_INFO_MMAP |
  123. SNDRV_PCM_INFO_INTERLEAVED |
  124. SNDRV_PCM_INFO_BLOCK_TRANSFER |
  125. SNDRV_PCM_INFO_MMAP_VALID),
  126. .formats = SNDRV_PCM_FMTBIT_S32_LE, /* Only supports 24-bit samples padded to 32 bits. */
  127. .rates = SNDRV_PCM_RATE_192000 | SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_44100,
  128. .rate_min = 44100,
  129. .rate_max = 192000,
  130. .channels_min = 8,
  131. .channels_max = 8,
  132. .buffer_bytes_max = ((65536 - 64) * 8),
  133. .period_bytes_min = 64,
  134. .period_bytes_max = (65536 - 64),
  135. .periods_min = 2,
  136. .periods_max = 8,
  137. .fifo_size = 0,
  138. };
  139. static snd_pcm_hardware_t snd_p16v_capture_hw = {
  140. .info = (SNDRV_PCM_INFO_MMAP |
  141. SNDRV_PCM_INFO_INTERLEAVED |
  142. SNDRV_PCM_INFO_BLOCK_TRANSFER |
  143. SNDRV_PCM_INFO_MMAP_VALID),
  144. .formats = SNDRV_PCM_FMTBIT_S32_LE,
  145. .rates = SNDRV_PCM_RATE_192000 | SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_44100,
  146. .rate_min = 44100,
  147. .rate_max = 192000,
  148. .channels_min = 2,
  149. .channels_max = 2,
  150. .buffer_bytes_max = (65536 - 64),
  151. .period_bytes_min = 64,
  152. .period_bytes_max = (65536 - 128) >> 1, /* size has to be N*64 bytes */
  153. .periods_min = 2,
  154. .periods_max = 2,
  155. .fifo_size = 0,
  156. };
  157. static void snd_p16v_pcm_free_substream(snd_pcm_runtime_t *runtime)
  158. {
  159. emu10k1_pcm_t *epcm = runtime->private_data;
  160. if (epcm) {
  161. //snd_printk("epcm free: %p\n", epcm);
  162. kfree(epcm);
  163. }
  164. }
  165. /* open_playback callback */
  166. static int snd_p16v_pcm_open_playback_channel(snd_pcm_substream_t *substream, int channel_id)
  167. {
  168. emu10k1_t *emu = snd_pcm_substream_chip(substream);
  169. emu10k1_voice_t *channel = &(emu->p16v_voices[channel_id]);
  170. emu10k1_pcm_t *epcm;
  171. snd_pcm_runtime_t *runtime = substream->runtime;
  172. int err;
  173. epcm = kcalloc(1, sizeof(*epcm), GFP_KERNEL);
  174. //snd_printk("epcm kcalloc: %p\n", epcm);
  175. if (epcm == NULL)
  176. return -ENOMEM;
  177. epcm->emu = emu;
  178. epcm->substream = substream;
  179. //snd_printk("epcm device=%d, channel_id=%d\n", substream->pcm->device, channel_id);
  180. runtime->private_data = epcm;
  181. runtime->private_free = snd_p16v_pcm_free_substream;
  182. runtime->hw = snd_p16v_playback_hw;
  183. channel->emu = emu;
  184. channel->number = channel_id;
  185. channel->use=1;
  186. //snd_printk("p16v: open channel_id=%d, channel=%p, use=0x%x\n", channel_id, channel, channel->use);
  187. //printk("open:channel_id=%d, chip=%p, channel=%p\n",channel_id, chip, channel);
  188. //channel->interrupt = snd_p16v_pcm_channel_interrupt;
  189. channel->epcm=epcm;
  190. if ((err = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS)) < 0)
  191. return err;
  192. return 0;
  193. }
  194. /* open_capture callback */
  195. static int snd_p16v_pcm_open_capture_channel(snd_pcm_substream_t *substream, int channel_id)
  196. {
  197. emu10k1_t *emu = snd_pcm_substream_chip(substream);
  198. emu10k1_voice_t *channel = &(emu->p16v_capture_voice);
  199. emu10k1_pcm_t *epcm;
  200. snd_pcm_runtime_t *runtime = substream->runtime;
  201. int err;
  202. epcm = kcalloc(1, sizeof(*epcm), GFP_KERNEL);
  203. //snd_printk("epcm kcalloc: %p\n", epcm);
  204. if (epcm == NULL)
  205. return -ENOMEM;
  206. epcm->emu = emu;
  207. epcm->substream = substream;
  208. //snd_printk("epcm device=%d, channel_id=%d\n", substream->pcm->device, channel_id);
  209. runtime->private_data = epcm;
  210. runtime->private_free = snd_p16v_pcm_free_substream;
  211. runtime->hw = snd_p16v_capture_hw;
  212. channel->emu = emu;
  213. channel->number = channel_id;
  214. channel->use=1;
  215. //snd_printk("p16v: open channel_id=%d, channel=%p, use=0x%x\n", channel_id, channel, channel->use);
  216. //printk("open:channel_id=%d, chip=%p, channel=%p\n",channel_id, chip, channel);
  217. //channel->interrupt = snd_p16v_pcm_channel_interrupt;
  218. channel->epcm=epcm;
  219. if ((err = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS)) < 0)
  220. return err;
  221. return 0;
  222. }
  223. /* close callback */
  224. static int snd_p16v_pcm_close_playback(snd_pcm_substream_t *substream)
  225. {
  226. emu10k1_t *emu = snd_pcm_substream_chip(substream);
  227. //snd_pcm_runtime_t *runtime = substream->runtime;
  228. //emu10k1_pcm_t *epcm = runtime->private_data;
  229. emu->p16v_voices[substream->pcm->device - emu->p16v_device_offset].use=0;
  230. /* FIXME: maybe zero others */
  231. return 0;
  232. }
  233. /* close callback */
  234. static int snd_p16v_pcm_close_capture(snd_pcm_substream_t *substream)
  235. {
  236. emu10k1_t *emu = snd_pcm_substream_chip(substream);
  237. //snd_pcm_runtime_t *runtime = substream->runtime;
  238. //emu10k1_pcm_t *epcm = runtime->private_data;
  239. emu->p16v_capture_voice.use=0;
  240. /* FIXME: maybe zero others */
  241. return 0;
  242. }
  243. static int snd_p16v_pcm_open_playback_front(snd_pcm_substream_t *substream)
  244. {
  245. return snd_p16v_pcm_open_playback_channel(substream, PCM_FRONT_CHANNEL);
  246. }
  247. static int snd_p16v_pcm_open_capture(snd_pcm_substream_t *substream)
  248. {
  249. // Only using channel 0 for now, but the card has 2 channels.
  250. return snd_p16v_pcm_open_capture_channel(substream, 0);
  251. }
  252. /* hw_params callback */
  253. static int snd_p16v_pcm_hw_params_playback(snd_pcm_substream_t *substream,
  254. snd_pcm_hw_params_t * hw_params)
  255. {
  256. int result;
  257. result = snd_pcm_lib_malloc_pages(substream,
  258. params_buffer_bytes(hw_params));
  259. return result;
  260. }
  261. /* hw_params callback */
  262. static int snd_p16v_pcm_hw_params_capture(snd_pcm_substream_t *substream,
  263. snd_pcm_hw_params_t * hw_params)
  264. {
  265. int result;
  266. result = snd_pcm_lib_malloc_pages(substream,
  267. params_buffer_bytes(hw_params));
  268. return result;
  269. }
  270. /* hw_free callback */
  271. static int snd_p16v_pcm_hw_free_playback(snd_pcm_substream_t *substream)
  272. {
  273. int result;
  274. result = snd_pcm_lib_free_pages(substream);
  275. return result;
  276. }
  277. /* hw_free callback */
  278. static int snd_p16v_pcm_hw_free_capture(snd_pcm_substream_t *substream)
  279. {
  280. int result;
  281. result = snd_pcm_lib_free_pages(substream);
  282. return result;
  283. }
  284. /* prepare playback callback */
  285. static int snd_p16v_pcm_prepare_playback(snd_pcm_substream_t *substream)
  286. {
  287. emu10k1_t *emu = snd_pcm_substream_chip(substream);
  288. snd_pcm_runtime_t *runtime = substream->runtime;
  289. int channel = substream->pcm->device - emu->p16v_device_offset;
  290. u32 *table_base = (u32 *)(emu->p16v_buffer.area+(8*16*channel));
  291. u32 period_size_bytes = frames_to_bytes(runtime, runtime->period_size);
  292. int i;
  293. u32 tmp;
  294. //snd_printk("prepare:channel_number=%d, rate=%d, format=0x%x, channels=%d, buffer_size=%ld, period_size=%ld, periods=%u, frames_to_bytes=%d\n",channel, runtime->rate, runtime->format, runtime->channels, runtime->buffer_size, runtime->period_size, runtime->periods, frames_to_bytes(runtime, 1));
  295. //snd_printk("dma_addr=%x, dma_area=%p, table_base=%p\n",runtime->dma_addr, runtime->dma_area, table_base);
  296. //snd_printk("dma_addr=%x, dma_area=%p, dma_bytes(size)=%x\n",emu->p16v_buffer.addr, emu->p16v_buffer.area, emu->p16v_buffer.bytes);
  297. tmp = snd_emu10k1_ptr_read(emu, A_SPDIF_SAMPLERATE, channel);
  298. switch (runtime->rate) {
  299. case 44100:
  300. snd_emu10k1_ptr_write(emu, A_SPDIF_SAMPLERATE, channel, (tmp & ~0xe0e0) | 0x8080);
  301. break;
  302. case 96000:
  303. snd_emu10k1_ptr_write(emu, A_SPDIF_SAMPLERATE, channel, (tmp & ~0xe0e0) | 0x4040);
  304. break;
  305. case 192000:
  306. snd_emu10k1_ptr_write(emu, A_SPDIF_SAMPLERATE, channel, (tmp & ~0xe0e0) | 0x2020);
  307. break;
  308. case 48000:
  309. default:
  310. snd_emu10k1_ptr_write(emu, A_SPDIF_SAMPLERATE, channel, (tmp & ~0xe0e0) | 0x0000);
  311. break;
  312. }
  313. /* FIXME: Check emu->buffer.size before actually writing to it. */
  314. for(i=0; i < runtime->periods; i++) {
  315. table_base[i*2]=runtime->dma_addr+(i*period_size_bytes);
  316. table_base[(i*2)+1]=period_size_bytes<<16;
  317. }
  318. snd_emu10k1_ptr20_write(emu, PLAYBACK_LIST_ADDR, channel, emu->p16v_buffer.addr+(8*16*channel));
  319. snd_emu10k1_ptr20_write(emu, PLAYBACK_LIST_SIZE, channel, (runtime->periods - 1) << 19);
  320. snd_emu10k1_ptr20_write(emu, PLAYBACK_LIST_PTR, channel, 0);
  321. snd_emu10k1_ptr20_write(emu, PLAYBACK_DMA_ADDR, channel, runtime->dma_addr);
  322. //snd_emu10k1_ptr20_write(emu, PLAYBACK_PERIOD_SIZE, channel, frames_to_bytes(runtime, runtime->period_size)<<16); // buffer size in bytes
  323. snd_emu10k1_ptr20_write(emu, PLAYBACK_PERIOD_SIZE, channel, 0); // buffer size in bytes
  324. snd_emu10k1_ptr20_write(emu, PLAYBACK_POINTER, channel, 0);
  325. snd_emu10k1_ptr20_write(emu, 0x07, channel, 0x0);
  326. snd_emu10k1_ptr20_write(emu, 0x08, channel, 0);
  327. return 0;
  328. }
  329. /* prepare capture callback */
  330. static int snd_p16v_pcm_prepare_capture(snd_pcm_substream_t *substream)
  331. {
  332. emu10k1_t *emu = snd_pcm_substream_chip(substream);
  333. snd_pcm_runtime_t *runtime = substream->runtime;
  334. int channel = substream->pcm->device - emu->p16v_device_offset;
  335. u32 tmp;
  336. //printk("prepare capture:channel_number=%d, rate=%d, format=0x%x, channels=%d, buffer_size=%ld, period_size=%ld, frames_to_bytes=%d\n",channel, runtime->rate, runtime->format, runtime->channels, runtime->buffer_size, runtime->period_size, frames_to_bytes(runtime, 1));
  337. tmp = snd_emu10k1_ptr_read(emu, A_SPDIF_SAMPLERATE, channel);
  338. switch (runtime->rate) {
  339. case 44100:
  340. snd_emu10k1_ptr_write(emu, A_SPDIF_SAMPLERATE, channel, (tmp & ~0x0e00) | 0x0800);
  341. break;
  342. case 96000:
  343. snd_emu10k1_ptr_write(emu, A_SPDIF_SAMPLERATE, channel, (tmp & ~0x0e00) | 0x0400);
  344. break;
  345. case 192000:
  346. snd_emu10k1_ptr_write(emu, A_SPDIF_SAMPLERATE, channel, (tmp & ~0x0e00) | 0x0200);
  347. break;
  348. case 48000:
  349. default:
  350. snd_emu10k1_ptr_write(emu, A_SPDIF_SAMPLERATE, channel, (tmp & ~0x0e00) | 0x0000);
  351. break;
  352. }
  353. /* FIXME: Check emu->buffer.size before actually writing to it. */
  354. snd_emu10k1_ptr20_write(emu, 0x13, channel, 0);
  355. snd_emu10k1_ptr20_write(emu, CAPTURE_DMA_ADDR, channel, runtime->dma_addr);
  356. snd_emu10k1_ptr20_write(emu, CAPTURE_BUFFER_SIZE, channel, frames_to_bytes(runtime, runtime->buffer_size)<<16); // buffer size in bytes
  357. snd_emu10k1_ptr20_write(emu, CAPTURE_POINTER, channel, 0);
  358. //snd_emu10k1_ptr20_write(emu, CAPTURE_SOURCE, 0x0, 0x333300e4); /* Select MIC or Line in */
  359. //snd_emu10k1_ptr20_write(emu, EXTENDED_INT_MASK, 0, snd_emu10k1_ptr20_read(emu, EXTENDED_INT_MASK, 0) | (0x110000<<channel));
  360. return 0;
  361. }
  362. static void snd_p16v_intr_enable(emu10k1_t *emu, unsigned int intrenb)
  363. {
  364. unsigned long flags;
  365. unsigned int enable;
  366. spin_lock_irqsave(&emu->emu_lock, flags);
  367. enable = inl(emu->port + INTE2) | intrenb;
  368. outl(enable, emu->port + INTE2);
  369. spin_unlock_irqrestore(&emu->emu_lock, flags);
  370. }
  371. static void snd_p16v_intr_disable(emu10k1_t *emu, unsigned int intrenb)
  372. {
  373. unsigned long flags;
  374. unsigned int disable;
  375. spin_lock_irqsave(&emu->emu_lock, flags);
  376. disable = inl(emu->port + INTE2) & (~intrenb);
  377. outl(disable, emu->port + INTE2);
  378. spin_unlock_irqrestore(&emu->emu_lock, flags);
  379. }
  380. /* trigger_playback callback */
  381. static int snd_p16v_pcm_trigger_playback(snd_pcm_substream_t *substream,
  382. int cmd)
  383. {
  384. emu10k1_t *emu = snd_pcm_substream_chip(substream);
  385. snd_pcm_runtime_t *runtime;
  386. emu10k1_pcm_t *epcm;
  387. int channel;
  388. int result = 0;
  389. struct list_head *pos;
  390. snd_pcm_substream_t *s;
  391. u32 basic = 0;
  392. u32 inte = 0;
  393. int running=0;
  394. switch (cmd) {
  395. case SNDRV_PCM_TRIGGER_START:
  396. running=1;
  397. break;
  398. case SNDRV_PCM_TRIGGER_STOP:
  399. default:
  400. running=0;
  401. break;
  402. }
  403. snd_pcm_group_for_each(pos, substream) {
  404. s = snd_pcm_group_substream_entry(pos);
  405. runtime = s->runtime;
  406. epcm = runtime->private_data;
  407. channel = substream->pcm->device-emu->p16v_device_offset;
  408. //snd_printk("p16v channel=%d\n",channel);
  409. epcm->running = running;
  410. basic |= (0x1<<channel);
  411. inte |= (INTE2_PLAYBACK_CH_0_LOOP<<channel);
  412. snd_pcm_trigger_done(s, substream);
  413. }
  414. //snd_printk("basic=0x%x, inte=0x%x\n",basic, inte);
  415. switch (cmd) {
  416. case SNDRV_PCM_TRIGGER_START:
  417. snd_p16v_intr_enable(emu, inte);
  418. snd_emu10k1_ptr20_write(emu, BASIC_INTERRUPT, 0, snd_emu10k1_ptr20_read(emu, BASIC_INTERRUPT, 0)| (basic));
  419. break;
  420. case SNDRV_PCM_TRIGGER_STOP:
  421. snd_emu10k1_ptr20_write(emu, BASIC_INTERRUPT, 0, snd_emu10k1_ptr20_read(emu, BASIC_INTERRUPT, 0) & ~(basic));
  422. snd_p16v_intr_disable(emu, inte);
  423. break;
  424. default:
  425. result = -EINVAL;
  426. break;
  427. }
  428. return result;
  429. }
  430. /* trigger_capture callback */
  431. static int snd_p16v_pcm_trigger_capture(snd_pcm_substream_t *substream,
  432. int cmd)
  433. {
  434. emu10k1_t *emu = snd_pcm_substream_chip(substream);
  435. snd_pcm_runtime_t *runtime = substream->runtime;
  436. emu10k1_pcm_t *epcm = runtime->private_data;
  437. int channel = 0;
  438. int result = 0;
  439. u32 inte = INTE2_CAPTURE_CH_0_LOOP | INTE2_CAPTURE_CH_0_HALF_LOOP;
  440. switch (cmd) {
  441. case SNDRV_PCM_TRIGGER_START:
  442. snd_p16v_intr_enable(emu, inte);
  443. snd_emu10k1_ptr20_write(emu, BASIC_INTERRUPT, 0, snd_emu10k1_ptr20_read(emu, BASIC_INTERRUPT, 0)|(0x100<<channel));
  444. epcm->running = 1;
  445. break;
  446. case SNDRV_PCM_TRIGGER_STOP:
  447. snd_emu10k1_ptr20_write(emu, BASIC_INTERRUPT, 0, snd_emu10k1_ptr20_read(emu, BASIC_INTERRUPT, 0) & ~(0x100<<channel));
  448. snd_p16v_intr_disable(emu, inte);
  449. //snd_emu10k1_ptr20_write(emu, EXTENDED_INT_MASK, 0, snd_emu10k1_ptr20_read(emu, EXTENDED_INT_MASK, 0) & ~(0x110000<<channel));
  450. epcm->running = 0;
  451. break;
  452. default:
  453. result = -EINVAL;
  454. break;
  455. }
  456. return result;
  457. }
  458. /* pointer_playback callback */
  459. static snd_pcm_uframes_t
  460. snd_p16v_pcm_pointer_playback(snd_pcm_substream_t *substream)
  461. {
  462. emu10k1_t *emu = snd_pcm_substream_chip(substream);
  463. snd_pcm_runtime_t *runtime = substream->runtime;
  464. emu10k1_pcm_t *epcm = runtime->private_data;
  465. snd_pcm_uframes_t ptr, ptr1, ptr2,ptr3,ptr4 = 0;
  466. int channel = substream->pcm->device - emu->p16v_device_offset;
  467. if (!epcm->running)
  468. return 0;
  469. ptr3 = snd_emu10k1_ptr20_read(emu, PLAYBACK_LIST_PTR, channel);
  470. ptr1 = snd_emu10k1_ptr20_read(emu, PLAYBACK_POINTER, channel);
  471. ptr4 = snd_emu10k1_ptr20_read(emu, PLAYBACK_LIST_PTR, channel);
  472. if (ptr3 != ptr4) ptr1 = snd_emu10k1_ptr20_read(emu, PLAYBACK_POINTER, channel);
  473. ptr2 = bytes_to_frames(runtime, ptr1);
  474. ptr2+= (ptr4 >> 3) * runtime->period_size;
  475. ptr=ptr2;
  476. if (ptr >= runtime->buffer_size)
  477. ptr -= runtime->buffer_size;
  478. return ptr;
  479. }
  480. /* pointer_capture callback */
  481. static snd_pcm_uframes_t
  482. snd_p16v_pcm_pointer_capture(snd_pcm_substream_t *substream)
  483. {
  484. emu10k1_t *emu = snd_pcm_substream_chip(substream);
  485. snd_pcm_runtime_t *runtime = substream->runtime;
  486. emu10k1_pcm_t *epcm = runtime->private_data;
  487. snd_pcm_uframes_t ptr, ptr1, ptr2 = 0;
  488. int channel = 0;
  489. if (!epcm->running)
  490. return 0;
  491. ptr1 = snd_emu10k1_ptr20_read(emu, CAPTURE_POINTER, channel);
  492. ptr2 = bytes_to_frames(runtime, ptr1);
  493. ptr=ptr2;
  494. if (ptr >= runtime->buffer_size) {
  495. ptr -= runtime->buffer_size;
  496. printk("buffer capture limited!\n");
  497. }
  498. //printk("ptr1 = 0x%lx, ptr2=0x%lx, ptr=0x%lx, buffer_size = 0x%x, period_size = 0x%x, bits=%d, rate=%d\n", ptr1, ptr2, ptr, (int)runtime->buffer_size, (int)runtime->period_size, (int)runtime->frame_bits, (int)runtime->rate);
  499. return ptr;
  500. }
  501. /* operators */
  502. static snd_pcm_ops_t snd_p16v_playback_front_ops = {
  503. .open = snd_p16v_pcm_open_playback_front,
  504. .close = snd_p16v_pcm_close_playback,
  505. .ioctl = snd_pcm_lib_ioctl,
  506. .hw_params = snd_p16v_pcm_hw_params_playback,
  507. .hw_free = snd_p16v_pcm_hw_free_playback,
  508. .prepare = snd_p16v_pcm_prepare_playback,
  509. .trigger = snd_p16v_pcm_trigger_playback,
  510. .pointer = snd_p16v_pcm_pointer_playback,
  511. };
  512. static snd_pcm_ops_t snd_p16v_capture_ops = {
  513. .open = snd_p16v_pcm_open_capture,
  514. .close = snd_p16v_pcm_close_capture,
  515. .ioctl = snd_pcm_lib_ioctl,
  516. .hw_params = snd_p16v_pcm_hw_params_capture,
  517. .hw_free = snd_p16v_pcm_hw_free_capture,
  518. .prepare = snd_p16v_pcm_prepare_capture,
  519. .trigger = snd_p16v_pcm_trigger_capture,
  520. .pointer = snd_p16v_pcm_pointer_capture,
  521. };
  522. int snd_p16v_free(emu10k1_t *chip)
  523. {
  524. // release the data
  525. if (chip->p16v_buffer.area) {
  526. snd_dma_free_pages(&chip->p16v_buffer);
  527. //snd_printk("period lables free: %p\n", &chip->p16v_buffer);
  528. }
  529. return 0;
  530. }
  531. static void snd_p16v_pcm_free(snd_pcm_t *pcm)
  532. {
  533. emu10k1_t *emu = pcm->private_data;
  534. //snd_printk("snd_p16v_pcm_free pcm: called\n");
  535. snd_pcm_lib_preallocate_free_for_all(pcm);
  536. emu->pcm = NULL;
  537. }
  538. int snd_p16v_pcm(emu10k1_t *emu, int device, snd_pcm_t **rpcm)
  539. {
  540. snd_pcm_t *pcm;
  541. snd_pcm_substream_t *substream;
  542. int err;
  543. int capture=1;
  544. //snd_printk("snd_p16v_pcm called. device=%d\n", device);
  545. emu->p16v_device_offset = device;
  546. if (rpcm)
  547. *rpcm = NULL;
  548. if ((err = snd_pcm_new(emu->card, "p16v", device, 1, capture, &pcm)) < 0)
  549. return err;
  550. pcm->private_data = emu;
  551. pcm->private_free = snd_p16v_pcm_free;
  552. // Single playback 8 channel device.
  553. // Single capture 2 channel device.
  554. snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_p16v_playback_front_ops);
  555. snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_p16v_capture_ops);
  556. pcm->info_flags = 0;
  557. pcm->dev_subclass = SNDRV_PCM_SUBCLASS_GENERIC_MIX;
  558. strcpy(pcm->name, "p16v");
  559. emu->pcm = pcm;
  560. for(substream = pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream;
  561. substream;
  562. substream = substream->next) {
  563. if ((err = snd_pcm_lib_preallocate_pages(substream,
  564. SNDRV_DMA_TYPE_DEV,
  565. snd_dma_pci_data(emu->pci),
  566. ((65536 - 64) * 8), ((65536 - 64) * 8))) < 0)
  567. return err;
  568. //snd_printk("preallocate playback substream: err=%d\n", err);
  569. }
  570. for (substream = pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream;
  571. substream;
  572. substream = substream->next) {
  573. if ((err = snd_pcm_lib_preallocate_pages(substream,
  574. SNDRV_DMA_TYPE_DEV,
  575. snd_dma_pci_data(emu->pci),
  576. 65536 - 64, 65536 - 64)) < 0)
  577. return err;
  578. //snd_printk("preallocate capture substream: err=%d\n", err);
  579. }
  580. if (rpcm)
  581. *rpcm = pcm;
  582. return 0;
  583. }
  584. static int snd_p16v_volume_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
  585. {
  586. uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
  587. uinfo->count = 2;
  588. uinfo->value.integer.min = 0;
  589. uinfo->value.integer.max = 255;
  590. return 0;
  591. }
  592. static int snd_p16v_volume_get(snd_kcontrol_t * kcontrol,
  593. snd_ctl_elem_value_t * ucontrol, int reg, int high_low)
  594. {
  595. emu10k1_t *emu = snd_kcontrol_chip(kcontrol);
  596. u32 value;
  597. value = snd_emu10k1_ptr20_read(emu, reg, high_low);
  598. if (high_low == 1) {
  599. ucontrol->value.integer.value[0] = 0xff - ((value >> 24) & 0xff); /* Left */
  600. ucontrol->value.integer.value[1] = 0xff - ((value >> 16) & 0xff); /* Right */
  601. } else {
  602. ucontrol->value.integer.value[0] = 0xff - ((value >> 8) & 0xff); /* Left */
  603. ucontrol->value.integer.value[1] = 0xff - ((value >> 0) & 0xff); /* Right */
  604. }
  605. return 0;
  606. }
  607. static int snd_p16v_volume_get_spdif_front(snd_kcontrol_t * kcontrol,
  608. snd_ctl_elem_value_t * ucontrol)
  609. {
  610. int high_low = 0;
  611. int reg = PLAYBACK_VOLUME_MIXER7;
  612. return snd_p16v_volume_get(kcontrol, ucontrol, reg, high_low);
  613. }
  614. static int snd_p16v_volume_get_spdif_center_lfe(snd_kcontrol_t * kcontrol,
  615. snd_ctl_elem_value_t * ucontrol)
  616. {
  617. int high_low = 1;
  618. int reg = PLAYBACK_VOLUME_MIXER7;
  619. return snd_p16v_volume_get(kcontrol, ucontrol, reg, high_low);
  620. }
  621. static int snd_p16v_volume_get_spdif_unknown(snd_kcontrol_t * kcontrol,
  622. snd_ctl_elem_value_t * ucontrol)
  623. {
  624. int high_low = 0;
  625. int reg = PLAYBACK_VOLUME_MIXER8;
  626. return snd_p16v_volume_get(kcontrol, ucontrol, reg, high_low);
  627. }
  628. static int snd_p16v_volume_get_spdif_rear(snd_kcontrol_t * kcontrol,
  629. snd_ctl_elem_value_t * ucontrol)
  630. {
  631. int high_low = 1;
  632. int reg = PLAYBACK_VOLUME_MIXER8;
  633. return snd_p16v_volume_get(kcontrol, ucontrol, reg, high_low);
  634. }
  635. static int snd_p16v_volume_get_analog_front(snd_kcontrol_t * kcontrol,
  636. snd_ctl_elem_value_t * ucontrol)
  637. {
  638. int high_low = 0;
  639. int reg = PLAYBACK_VOLUME_MIXER9;
  640. return snd_p16v_volume_get(kcontrol, ucontrol, reg, high_low);
  641. }
  642. static int snd_p16v_volume_get_analog_center_lfe(snd_kcontrol_t * kcontrol,
  643. snd_ctl_elem_value_t * ucontrol)
  644. {
  645. int high_low = 1;
  646. int reg = PLAYBACK_VOLUME_MIXER9;
  647. return snd_p16v_volume_get(kcontrol, ucontrol, reg, high_low);
  648. }
  649. static int snd_p16v_volume_get_analog_rear(snd_kcontrol_t * kcontrol,
  650. snd_ctl_elem_value_t * ucontrol)
  651. {
  652. int high_low = 1;
  653. int reg = PLAYBACK_VOLUME_MIXER10;
  654. return snd_p16v_volume_get(kcontrol, ucontrol, reg, high_low);
  655. }
  656. static int snd_p16v_volume_get_analog_unknown(snd_kcontrol_t * kcontrol,
  657. snd_ctl_elem_value_t * ucontrol)
  658. {
  659. int high_low = 0;
  660. int reg = PLAYBACK_VOLUME_MIXER10;
  661. return snd_p16v_volume_get(kcontrol, ucontrol, reg, high_low);
  662. }
  663. static int snd_p16v_volume_put(snd_kcontrol_t * kcontrol,
  664. snd_ctl_elem_value_t * ucontrol, int reg, int high_low)
  665. {
  666. emu10k1_t *emu = snd_kcontrol_chip(kcontrol);
  667. u32 value;
  668. value = snd_emu10k1_ptr20_read(emu, reg, 0);
  669. //value = value & 0xffff;
  670. if (high_low == 1) {
  671. value &= 0xffff;
  672. value = value | ((0xff - ucontrol->value.integer.value[0]) << 24) | ((0xff - ucontrol->value.integer.value[1]) << 16);
  673. } else {
  674. value &= 0xffff0000;
  675. value = value | ((0xff - ucontrol->value.integer.value[0]) << 8) | ((0xff - ucontrol->value.integer.value[1]) );
  676. }
  677. snd_emu10k1_ptr20_write(emu, reg, 0, value);
  678. return 1;
  679. }
  680. static int snd_p16v_volume_put_spdif_front(snd_kcontrol_t * kcontrol,
  681. snd_ctl_elem_value_t * ucontrol)
  682. {
  683. int high_low = 0;
  684. int reg = PLAYBACK_VOLUME_MIXER7;
  685. return snd_p16v_volume_put(kcontrol, ucontrol, reg, high_low);
  686. }
  687. static int snd_p16v_volume_put_spdif_center_lfe(snd_kcontrol_t * kcontrol,
  688. snd_ctl_elem_value_t * ucontrol)
  689. {
  690. int high_low = 1;
  691. int reg = PLAYBACK_VOLUME_MIXER7;
  692. return snd_p16v_volume_put(kcontrol, ucontrol, reg, high_low);
  693. }
  694. static int snd_p16v_volume_put_spdif_unknown(snd_kcontrol_t * kcontrol,
  695. snd_ctl_elem_value_t * ucontrol)
  696. {
  697. int high_low = 0;
  698. int reg = PLAYBACK_VOLUME_MIXER8;
  699. return snd_p16v_volume_put(kcontrol, ucontrol, reg, high_low);
  700. }
  701. static int snd_p16v_volume_put_spdif_rear(snd_kcontrol_t * kcontrol,
  702. snd_ctl_elem_value_t * ucontrol)
  703. {
  704. int high_low = 1;
  705. int reg = PLAYBACK_VOLUME_MIXER8;
  706. return snd_p16v_volume_put(kcontrol, ucontrol, reg, high_low);
  707. }
  708. static int snd_p16v_volume_put_analog_front(snd_kcontrol_t * kcontrol,
  709. snd_ctl_elem_value_t * ucontrol)
  710. {
  711. int high_low = 0;
  712. int reg = PLAYBACK_VOLUME_MIXER9;
  713. return snd_p16v_volume_put(kcontrol, ucontrol, reg, high_low);
  714. }
  715. static int snd_p16v_volume_put_analog_center_lfe(snd_kcontrol_t * kcontrol,
  716. snd_ctl_elem_value_t * ucontrol)
  717. {
  718. int high_low = 1;
  719. int reg = PLAYBACK_VOLUME_MIXER9;
  720. return snd_p16v_volume_put(kcontrol, ucontrol, reg, high_low);
  721. }
  722. static int snd_p16v_volume_put_analog_rear(snd_kcontrol_t * kcontrol,
  723. snd_ctl_elem_value_t * ucontrol)
  724. {
  725. int high_low = 1;
  726. int reg = PLAYBACK_VOLUME_MIXER10;
  727. return snd_p16v_volume_put(kcontrol, ucontrol, reg, high_low);
  728. }
  729. static int snd_p16v_volume_put_analog_unknown(snd_kcontrol_t * kcontrol,
  730. snd_ctl_elem_value_t * ucontrol)
  731. {
  732. int high_low = 0;
  733. int reg = PLAYBACK_VOLUME_MIXER10;
  734. return snd_p16v_volume_put(kcontrol, ucontrol, reg, high_low);
  735. }
  736. static snd_kcontrol_new_t snd_p16v_volume_control_analog_front =
  737. {
  738. .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
  739. .name = "HD Analog Front Playback Volume",
  740. .info = snd_p16v_volume_info,
  741. .get = snd_p16v_volume_get_analog_front,
  742. .put = snd_p16v_volume_put_analog_front
  743. };
  744. static snd_kcontrol_new_t snd_p16v_volume_control_analog_center_lfe =
  745. {
  746. .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
  747. .name = "HD Analog Center/LFE Playback Volume",
  748. .info = snd_p16v_volume_info,
  749. .get = snd_p16v_volume_get_analog_center_lfe,
  750. .put = snd_p16v_volume_put_analog_center_lfe
  751. };
  752. static snd_kcontrol_new_t snd_p16v_volume_control_analog_unknown =
  753. {
  754. .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
  755. .name = "HD Analog Unknown Playback Volume",
  756. .info = snd_p16v_volume_info,
  757. .get = snd_p16v_volume_get_analog_unknown,
  758. .put = snd_p16v_volume_put_analog_unknown
  759. };
  760. static snd_kcontrol_new_t snd_p16v_volume_control_analog_rear =
  761. {
  762. .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
  763. .name = "HD Analog Rear Playback Volume",
  764. .info = snd_p16v_volume_info,
  765. .get = snd_p16v_volume_get_analog_rear,
  766. .put = snd_p16v_volume_put_analog_rear
  767. };
  768. static snd_kcontrol_new_t snd_p16v_volume_control_spdif_front =
  769. {
  770. .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
  771. .name = "HD SPDIF Front Playback Volume",
  772. .info = snd_p16v_volume_info,
  773. .get = snd_p16v_volume_get_spdif_front,
  774. .put = snd_p16v_volume_put_spdif_front
  775. };
  776. static snd_kcontrol_new_t snd_p16v_volume_control_spdif_center_lfe =
  777. {
  778. .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
  779. .name = "HD SPDIF Center/LFE Playback Volume",
  780. .info = snd_p16v_volume_info,
  781. .get = snd_p16v_volume_get_spdif_center_lfe,
  782. .put = snd_p16v_volume_put_spdif_center_lfe
  783. };
  784. static snd_kcontrol_new_t snd_p16v_volume_control_spdif_unknown =
  785. {
  786. .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
  787. .name = "HD SPDIF Unknown Playback Volume",
  788. .info = snd_p16v_volume_info,
  789. .get = snd_p16v_volume_get_spdif_unknown,
  790. .put = snd_p16v_volume_put_spdif_unknown
  791. };
  792. static snd_kcontrol_new_t snd_p16v_volume_control_spdif_rear =
  793. {
  794. .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
  795. .name = "HD SPDIF Rear Playback Volume",
  796. .info = snd_p16v_volume_info,
  797. .get = snd_p16v_volume_get_spdif_rear,
  798. .put = snd_p16v_volume_put_spdif_rear
  799. };
  800. static int snd_p16v_capture_source_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
  801. {
  802. static char *texts[8] = { "SPDIF", "I2S", "SRC48", "SRCMulti_SPDIF", "SRCMulti_I2S", "CDIF", "FX", "AC97" };
  803. uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
  804. uinfo->count = 1;
  805. uinfo->value.enumerated.items = 8;
  806. if (uinfo->value.enumerated.item > 7)
  807. uinfo->value.enumerated.item = 7;
  808. strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
  809. return 0;
  810. }
  811. static int snd_p16v_capture_source_get(snd_kcontrol_t * kcontrol,
  812. snd_ctl_elem_value_t * ucontrol)
  813. {
  814. emu10k1_t *emu = snd_kcontrol_chip(kcontrol);
  815. ucontrol->value.enumerated.item[0] = emu->p16v_capture_source;
  816. return 0;
  817. }
  818. static int snd_p16v_capture_source_put(snd_kcontrol_t * kcontrol,
  819. snd_ctl_elem_value_t * ucontrol)
  820. {
  821. emu10k1_t *emu = snd_kcontrol_chip(kcontrol);
  822. unsigned int val;
  823. int change = 0;
  824. u32 mask;
  825. u32 source;
  826. val = ucontrol->value.enumerated.item[0] ;
  827. change = (emu->p16v_capture_source != val);
  828. if (change) {
  829. emu->p16v_capture_source = val;
  830. source = (val << 28) | (val << 24) | (val << 20) | (val << 16);
  831. mask = snd_emu10k1_ptr20_read(emu, BASIC_INTERRUPT, 0) & 0xffff;
  832. snd_emu10k1_ptr20_write(emu, BASIC_INTERRUPT, 0, source | mask);
  833. }
  834. return change;
  835. }
  836. static snd_kcontrol_new_t snd_p16v_capture_source __devinitdata =
  837. {
  838. .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
  839. .name = "HD source Capture",
  840. .info = snd_p16v_capture_source_info,
  841. .get = snd_p16v_capture_source_get,
  842. .put = snd_p16v_capture_source_put
  843. };
  844. static int snd_p16v_capture_channel_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
  845. {
  846. static char *texts[4] = { "0", "1", "2", "3", };
  847. uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
  848. uinfo->count = 1;
  849. uinfo->value.enumerated.items = 4;
  850. if (uinfo->value.enumerated.item > 3)
  851. uinfo->value.enumerated.item = 3;
  852. strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
  853. return 0;
  854. }
  855. static int snd_p16v_capture_channel_get(snd_kcontrol_t * kcontrol,
  856. snd_ctl_elem_value_t * ucontrol)
  857. {
  858. emu10k1_t *emu = snd_kcontrol_chip(kcontrol);
  859. ucontrol->value.enumerated.item[0] = emu->p16v_capture_channel;
  860. return 0;
  861. }
  862. static int snd_p16v_capture_channel_put(snd_kcontrol_t * kcontrol,
  863. snd_ctl_elem_value_t * ucontrol)
  864. {
  865. emu10k1_t *emu = snd_kcontrol_chip(kcontrol);
  866. unsigned int val;
  867. int change = 0;
  868. u32 tmp;
  869. val = ucontrol->value.enumerated.item[0] ;
  870. change = (emu->p16v_capture_channel != val);
  871. if (change) {
  872. emu->p16v_capture_channel = val;
  873. tmp = snd_emu10k1_ptr20_read(emu, CAPTURE_P16V_SOURCE, 0) & 0xfffc;
  874. snd_emu10k1_ptr20_write(emu, CAPTURE_P16V_SOURCE, 0, tmp | val);
  875. }
  876. return change;
  877. }
  878. static snd_kcontrol_new_t snd_p16v_capture_channel __devinitdata =
  879. {
  880. .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
  881. .name = "HD channel Capture",
  882. .info = snd_p16v_capture_channel_info,
  883. .get = snd_p16v_capture_channel_get,
  884. .put = snd_p16v_capture_channel_put
  885. };
  886. int snd_p16v_mixer(emu10k1_t *emu)
  887. {
  888. int err;
  889. snd_kcontrol_t *kctl;
  890. snd_card_t *card = emu->card;
  891. if ((kctl = snd_ctl_new1(&snd_p16v_volume_control_analog_front, emu)) == NULL)
  892. return -ENOMEM;
  893. if ((err = snd_ctl_add(card, kctl)))
  894. return err;
  895. if ((kctl = snd_ctl_new1(&snd_p16v_volume_control_analog_rear, emu)) == NULL)
  896. return -ENOMEM;
  897. if ((err = snd_ctl_add(card, kctl)))
  898. return err;
  899. if ((kctl = snd_ctl_new1(&snd_p16v_volume_control_analog_center_lfe, emu)) == NULL)
  900. return -ENOMEM;
  901. if ((err = snd_ctl_add(card, kctl)))
  902. return err;
  903. if ((kctl = snd_ctl_new1(&snd_p16v_volume_control_analog_unknown, emu)) == NULL)
  904. return -ENOMEM;
  905. if ((err = snd_ctl_add(card, kctl)))
  906. return err;
  907. if ((kctl = snd_ctl_new1(&snd_p16v_volume_control_spdif_front, emu)) == NULL)
  908. return -ENOMEM;
  909. if ((err = snd_ctl_add(card, kctl)))
  910. return err;
  911. if ((kctl = snd_ctl_new1(&snd_p16v_volume_control_spdif_rear, emu)) == NULL)
  912. return -ENOMEM;
  913. if ((err = snd_ctl_add(card, kctl)))
  914. return err;
  915. if ((kctl = snd_ctl_new1(&snd_p16v_volume_control_spdif_center_lfe, emu)) == NULL)
  916. return -ENOMEM;
  917. if ((err = snd_ctl_add(card, kctl)))
  918. return err;
  919. if ((kctl = snd_ctl_new1(&snd_p16v_volume_control_spdif_unknown, emu)) == NULL)
  920. return -ENOMEM;
  921. if ((err = snd_ctl_add(card, kctl)))
  922. return err;
  923. if ((kctl = snd_ctl_new1(&snd_p16v_capture_source, emu)) == NULL)
  924. return -ENOMEM;
  925. if ((err = snd_ctl_add(card, kctl)))
  926. return err;
  927. if ((kctl = snd_ctl_new1(&snd_p16v_capture_channel, emu)) == NULL)
  928. return -ENOMEM;
  929. if ((err = snd_ctl_add(card, kctl)))
  930. return err;
  931. return 0;
  932. }