xonar_wm87x6.c 31 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051
  1. /*
  2. * card driver for models with WM8776/WM8766 DACs (Xonar DS)
  3. *
  4. * Copyright (c) Clemens Ladisch <clemens@ladisch.de>
  5. *
  6. *
  7. * This driver is free software; you can redistribute it and/or modify
  8. * it under the terms of the GNU General Public License, version 2.
  9. *
  10. * This driver is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License
  16. * along with this driver; if not, see <http://www.gnu.org/licenses/>.
  17. */
  18. /*
  19. * Xonar DS
  20. * --------
  21. *
  22. * CMI8788:
  23. *
  24. * SPI 0 -> WM8766 (surround, center/LFE, back)
  25. * SPI 1 -> WM8776 (front, input)
  26. *
  27. * GPIO 4 <- headphone detect
  28. * GPIO 6 -> route input jack to input 1/2 (1/0)
  29. * GPIO 7 -> enable output to speakers
  30. * GPIO 8 -> enable output to speakers
  31. *
  32. * WM8766:
  33. *
  34. * input 1 <- line
  35. * input 2 <- mic
  36. * input 3 <- front mic
  37. * input 4 <- aux
  38. */
  39. #include <linux/pci.h>
  40. #include <linux/delay.h>
  41. #include <sound/control.h>
  42. #include <sound/core.h>
  43. #include <sound/pcm.h>
  44. #include <sound/pcm_params.h>
  45. #include <sound/tlv.h>
  46. #include "xonar.h"
  47. #include "wm8776.h"
  48. #include "wm8766.h"
  49. #define GPIO_DS_HP_DETECT 0x0010
  50. #define GPIO_DS_INPUT_ROUTE 0x0040
  51. #define GPIO_DS_OUTPUT_ENABLE 0x0180
  52. #define LC_CONTROL_LIMITER 0x40000000
  53. #define LC_CONTROL_ALC 0x20000000
  54. struct xonar_wm87x6 {
  55. struct xonar_generic generic;
  56. u16 wm8776_regs[0x17];
  57. u16 wm8766_regs[0x10];
  58. struct snd_kcontrol *line_adcmux_control;
  59. struct snd_kcontrol *mic_adcmux_control;
  60. struct snd_kcontrol *lc_controls[13];
  61. };
  62. static void wm8776_write(struct oxygen *chip,
  63. unsigned int reg, unsigned int value)
  64. {
  65. struct xonar_wm87x6 *data = chip->model_data;
  66. oxygen_write_spi(chip, OXYGEN_SPI_TRIGGER |
  67. OXYGEN_SPI_DATA_LENGTH_2 |
  68. OXYGEN_SPI_CLOCK_160 |
  69. (1 << OXYGEN_SPI_CODEC_SHIFT) |
  70. OXYGEN_SPI_CEN_LATCH_CLOCK_LO,
  71. (reg << 9) | value);
  72. if (reg < ARRAY_SIZE(data->wm8776_regs)) {
  73. if (reg >= WM8776_HPLVOL && reg <= WM8776_DACMASTER)
  74. value &= ~WM8776_UPDATE;
  75. data->wm8776_regs[reg] = value;
  76. }
  77. }
  78. static void wm8776_write_cached(struct oxygen *chip,
  79. unsigned int reg, unsigned int value)
  80. {
  81. struct xonar_wm87x6 *data = chip->model_data;
  82. if (reg >= ARRAY_SIZE(data->wm8776_regs) ||
  83. value != data->wm8776_regs[reg])
  84. wm8776_write(chip, reg, value);
  85. }
  86. static void wm8766_write(struct oxygen *chip,
  87. unsigned int reg, unsigned int value)
  88. {
  89. struct xonar_wm87x6 *data = chip->model_data;
  90. oxygen_write_spi(chip, OXYGEN_SPI_TRIGGER |
  91. OXYGEN_SPI_DATA_LENGTH_2 |
  92. OXYGEN_SPI_CLOCK_160 |
  93. (0 << OXYGEN_SPI_CODEC_SHIFT) |
  94. OXYGEN_SPI_CEN_LATCH_CLOCK_LO,
  95. (reg << 9) | value);
  96. if (reg < ARRAY_SIZE(data->wm8766_regs)) {
  97. if ((reg >= WM8766_LDA1 && reg <= WM8766_RDA1) ||
  98. (reg >= WM8766_LDA2 && reg <= WM8766_MASTDA))
  99. value &= ~WM8766_UPDATE;
  100. data->wm8766_regs[reg] = value;
  101. }
  102. }
  103. static void wm8766_write_cached(struct oxygen *chip,
  104. unsigned int reg, unsigned int value)
  105. {
  106. struct xonar_wm87x6 *data = chip->model_data;
  107. if (reg >= ARRAY_SIZE(data->wm8766_regs) ||
  108. value != data->wm8766_regs[reg])
  109. wm8766_write(chip, reg, value);
  110. }
  111. static void wm8776_registers_init(struct oxygen *chip)
  112. {
  113. struct xonar_wm87x6 *data = chip->model_data;
  114. wm8776_write(chip, WM8776_RESET, 0);
  115. wm8776_write(chip, WM8776_DACCTRL1, WM8776_DZCEN |
  116. WM8776_PL_LEFT_LEFT | WM8776_PL_RIGHT_RIGHT);
  117. wm8776_write(chip, WM8776_DACMUTE, chip->dac_mute ? WM8776_DMUTE : 0);
  118. wm8776_write(chip, WM8776_DACIFCTRL,
  119. WM8776_DACFMT_LJUST | WM8776_DACWL_24);
  120. wm8776_write(chip, WM8776_ADCIFCTRL,
  121. data->wm8776_regs[WM8776_ADCIFCTRL]);
  122. wm8776_write(chip, WM8776_MSTRCTRL, data->wm8776_regs[WM8776_MSTRCTRL]);
  123. wm8776_write(chip, WM8776_PWRDOWN, data->wm8776_regs[WM8776_PWRDOWN]);
  124. wm8776_write(chip, WM8776_HPLVOL, data->wm8776_regs[WM8776_HPLVOL]);
  125. wm8776_write(chip, WM8776_HPRVOL, data->wm8776_regs[WM8776_HPRVOL] |
  126. WM8776_UPDATE);
  127. wm8776_write(chip, WM8776_ADCLVOL, data->wm8776_regs[WM8776_ADCLVOL]);
  128. wm8776_write(chip, WM8776_ADCRVOL, data->wm8776_regs[WM8776_ADCRVOL]);
  129. wm8776_write(chip, WM8776_ADCMUX, data->wm8776_regs[WM8776_ADCMUX]);
  130. wm8776_write(chip, WM8776_DACLVOL, chip->dac_volume[0]);
  131. wm8776_write(chip, WM8776_DACRVOL, chip->dac_volume[1] | WM8776_UPDATE);
  132. }
  133. static void wm8766_registers_init(struct oxygen *chip)
  134. {
  135. wm8766_write(chip, WM8766_RESET, 0);
  136. wm8766_write(chip, WM8766_INT_CTRL, WM8766_FMT_LJUST | WM8766_IWL_24);
  137. wm8766_write(chip, WM8766_DAC_CTRL2,
  138. WM8766_ZCD | (chip->dac_mute ? WM8766_DMUTE_MASK : 0));
  139. wm8766_write(chip, WM8766_LDA1, chip->dac_volume[2]);
  140. wm8766_write(chip, WM8766_RDA1, chip->dac_volume[3]);
  141. wm8766_write(chip, WM8766_LDA2, chip->dac_volume[4]);
  142. wm8766_write(chip, WM8766_RDA2, chip->dac_volume[5]);
  143. wm8766_write(chip, WM8766_LDA3, chip->dac_volume[6]);
  144. wm8766_write(chip, WM8766_RDA3, chip->dac_volume[7] | WM8766_UPDATE);
  145. }
  146. static void wm8776_init(struct oxygen *chip)
  147. {
  148. struct xonar_wm87x6 *data = chip->model_data;
  149. data->wm8776_regs[WM8776_HPLVOL] = (0x79 - 60) | WM8776_HPZCEN;
  150. data->wm8776_regs[WM8776_HPRVOL] = (0x79 - 60) | WM8776_HPZCEN;
  151. data->wm8776_regs[WM8776_ADCIFCTRL] =
  152. WM8776_ADCFMT_LJUST | WM8776_ADCWL_24 | WM8776_ADCMCLK;
  153. data->wm8776_regs[WM8776_MSTRCTRL] =
  154. WM8776_ADCRATE_256 | WM8776_DACRATE_256;
  155. data->wm8776_regs[WM8776_PWRDOWN] = WM8776_HPPD;
  156. data->wm8776_regs[WM8776_ADCLVOL] = 0xa5 | WM8776_ZCA;
  157. data->wm8776_regs[WM8776_ADCRVOL] = 0xa5 | WM8776_ZCA;
  158. data->wm8776_regs[WM8776_ADCMUX] = 0x001;
  159. wm8776_registers_init(chip);
  160. }
  161. static void xonar_ds_init(struct oxygen *chip)
  162. {
  163. struct xonar_wm87x6 *data = chip->model_data;
  164. data->generic.anti_pop_delay = 300;
  165. data->generic.output_enable_bit = GPIO_DS_OUTPUT_ENABLE;
  166. wm8776_init(chip);
  167. wm8766_registers_init(chip);
  168. oxygen_write16_masked(chip, OXYGEN_GPIO_CONTROL, GPIO_DS_INPUT_ROUTE,
  169. GPIO_DS_HP_DETECT | GPIO_DS_INPUT_ROUTE);
  170. oxygen_set_bits16(chip, OXYGEN_GPIO_DATA, GPIO_DS_INPUT_ROUTE);
  171. oxygen_set_bits16(chip, OXYGEN_GPIO_INTERRUPT_MASK, GPIO_DS_HP_DETECT);
  172. chip->interrupt_mask |= OXYGEN_INT_GPIO;
  173. xonar_enable_output(chip);
  174. snd_component_add(chip->card, "WM8776");
  175. snd_component_add(chip->card, "WM8766");
  176. }
  177. static void xonar_ds_cleanup(struct oxygen *chip)
  178. {
  179. xonar_disable_output(chip);
  180. wm8776_write(chip, WM8776_RESET, 0);
  181. }
  182. static void xonar_ds_suspend(struct oxygen *chip)
  183. {
  184. xonar_ds_cleanup(chip);
  185. }
  186. static void xonar_ds_resume(struct oxygen *chip)
  187. {
  188. wm8776_registers_init(chip);
  189. wm8766_registers_init(chip);
  190. xonar_enable_output(chip);
  191. }
  192. static void wm8776_adc_hardware_filter(unsigned int channel,
  193. struct snd_pcm_hardware *hardware)
  194. {
  195. if (channel == PCM_A) {
  196. hardware->rates = SNDRV_PCM_RATE_32000 |
  197. SNDRV_PCM_RATE_44100 |
  198. SNDRV_PCM_RATE_48000 |
  199. SNDRV_PCM_RATE_64000 |
  200. SNDRV_PCM_RATE_88200 |
  201. SNDRV_PCM_RATE_96000;
  202. hardware->rate_max = 96000;
  203. }
  204. }
  205. static void set_wm87x6_dac_params(struct oxygen *chip,
  206. struct snd_pcm_hw_params *params)
  207. {
  208. }
  209. static void set_wm8776_adc_params(struct oxygen *chip,
  210. struct snd_pcm_hw_params *params)
  211. {
  212. u16 reg;
  213. reg = WM8776_ADCRATE_256 | WM8776_DACRATE_256;
  214. if (params_rate(params) > 48000)
  215. reg |= WM8776_ADCOSR;
  216. wm8776_write_cached(chip, WM8776_MSTRCTRL, reg);
  217. }
  218. static void update_wm8776_volume(struct oxygen *chip)
  219. {
  220. struct xonar_wm87x6 *data = chip->model_data;
  221. u8 to_change;
  222. if (chip->dac_volume[0] == chip->dac_volume[1]) {
  223. if (chip->dac_volume[0] != data->wm8776_regs[WM8776_DACLVOL] ||
  224. chip->dac_volume[1] != data->wm8776_regs[WM8776_DACRVOL]) {
  225. wm8776_write(chip, WM8776_DACMASTER,
  226. chip->dac_volume[0] | WM8776_UPDATE);
  227. data->wm8776_regs[WM8776_DACLVOL] = chip->dac_volume[0];
  228. data->wm8776_regs[WM8776_DACRVOL] = chip->dac_volume[0];
  229. }
  230. } else {
  231. to_change = (chip->dac_volume[0] !=
  232. data->wm8776_regs[WM8776_DACLVOL]) << 0;
  233. to_change |= (chip->dac_volume[1] !=
  234. data->wm8776_regs[WM8776_DACLVOL]) << 1;
  235. if (to_change & 1)
  236. wm8776_write(chip, WM8776_DACLVOL, chip->dac_volume[0] |
  237. ((to_change & 2) ? 0 : WM8776_UPDATE));
  238. if (to_change & 2)
  239. wm8776_write(chip, WM8776_DACRVOL,
  240. chip->dac_volume[1] | WM8776_UPDATE);
  241. }
  242. }
  243. static void update_wm87x6_volume(struct oxygen *chip)
  244. {
  245. static const u8 wm8766_regs[6] = {
  246. WM8766_LDA1, WM8766_RDA1,
  247. WM8766_LDA2, WM8766_RDA2,
  248. WM8766_LDA3, WM8766_RDA3,
  249. };
  250. struct xonar_wm87x6 *data = chip->model_data;
  251. unsigned int i;
  252. u8 to_change;
  253. update_wm8776_volume(chip);
  254. if (chip->dac_volume[2] == chip->dac_volume[3] &&
  255. chip->dac_volume[2] == chip->dac_volume[4] &&
  256. chip->dac_volume[2] == chip->dac_volume[5] &&
  257. chip->dac_volume[2] == chip->dac_volume[6] &&
  258. chip->dac_volume[2] == chip->dac_volume[7]) {
  259. to_change = 0;
  260. for (i = 0; i < 6; ++i)
  261. if (chip->dac_volume[2] !=
  262. data->wm8766_regs[wm8766_regs[i]])
  263. to_change = 1;
  264. if (to_change) {
  265. wm8766_write(chip, WM8766_MASTDA,
  266. chip->dac_volume[2] | WM8766_UPDATE);
  267. for (i = 0; i < 6; ++i)
  268. data->wm8766_regs[wm8766_regs[i]] =
  269. chip->dac_volume[2];
  270. }
  271. } else {
  272. to_change = 0;
  273. for (i = 0; i < 6; ++i)
  274. to_change |= (chip->dac_volume[2 + i] !=
  275. data->wm8766_regs[wm8766_regs[i]]) << i;
  276. for (i = 0; i < 6; ++i)
  277. if (to_change & (1 << i))
  278. wm8766_write(chip, wm8766_regs[i],
  279. chip->dac_volume[2 + i] |
  280. ((to_change & (0x3e << i))
  281. ? 0 : WM8766_UPDATE));
  282. }
  283. }
  284. static void update_wm8776_mute(struct oxygen *chip)
  285. {
  286. wm8776_write_cached(chip, WM8776_DACMUTE,
  287. chip->dac_mute ? WM8776_DMUTE : 0);
  288. }
  289. static void update_wm87x6_mute(struct oxygen *chip)
  290. {
  291. update_wm8776_mute(chip);
  292. wm8766_write_cached(chip, WM8766_DAC_CTRL2, WM8766_ZCD |
  293. (chip->dac_mute ? WM8766_DMUTE_MASK : 0));
  294. }
  295. static void xonar_ds_gpio_changed(struct oxygen *chip)
  296. {
  297. u16 bits;
  298. bits = oxygen_read16(chip, OXYGEN_GPIO_DATA);
  299. snd_printk(KERN_INFO "HP detect: %d\n", !!(bits & GPIO_DS_HP_DETECT));
  300. }
  301. static int wm8776_bit_switch_get(struct snd_kcontrol *ctl,
  302. struct snd_ctl_elem_value *value)
  303. {
  304. struct oxygen *chip = ctl->private_data;
  305. struct xonar_wm87x6 *data = chip->model_data;
  306. u16 bit = ctl->private_value & 0xffff;
  307. unsigned int reg_index = (ctl->private_value >> 16) & 0xff;
  308. bool invert = (ctl->private_value >> 24) & 1;
  309. value->value.integer.value[0] =
  310. ((data->wm8776_regs[reg_index] & bit) != 0) ^ invert;
  311. return 0;
  312. }
  313. static int wm8776_bit_switch_put(struct snd_kcontrol *ctl,
  314. struct snd_ctl_elem_value *value)
  315. {
  316. struct oxygen *chip = ctl->private_data;
  317. struct xonar_wm87x6 *data = chip->model_data;
  318. u16 bit = ctl->private_value & 0xffff;
  319. u16 reg_value;
  320. unsigned int reg_index = (ctl->private_value >> 16) & 0xff;
  321. bool invert = (ctl->private_value >> 24) & 1;
  322. int changed;
  323. mutex_lock(&chip->mutex);
  324. reg_value = data->wm8776_regs[reg_index] & ~bit;
  325. if (value->value.integer.value[0] ^ invert)
  326. reg_value |= bit;
  327. changed = reg_value != data->wm8776_regs[reg_index];
  328. if (changed)
  329. wm8776_write(chip, reg_index, reg_value);
  330. mutex_unlock(&chip->mutex);
  331. return changed;
  332. }
  333. static int wm8776_field_enum_info(struct snd_kcontrol *ctl,
  334. struct snd_ctl_elem_info *info)
  335. {
  336. static const char *const hld[16] = {
  337. "0 ms", "2.67 ms", "5.33 ms", "10.6 ms",
  338. "21.3 ms", "42.7 ms", "85.3 ms", "171 ms",
  339. "341 ms", "683 ms", "1.37 s", "2.73 s",
  340. "5.46 s", "10.9 s", "21.8 s", "43.7 s",
  341. };
  342. static const char *const atk_lim[11] = {
  343. "0.25 ms", "0.5 ms", "1 ms", "2 ms",
  344. "4 ms", "8 ms", "16 ms", "32 ms",
  345. "64 ms", "128 ms", "256 ms",
  346. };
  347. static const char *const atk_alc[11] = {
  348. "8.40 ms", "16.8 ms", "33.6 ms", "67.2 ms",
  349. "134 ms", "269 ms", "538 ms", "1.08 s",
  350. "2.15 s", "4.3 s", "8.6 s",
  351. };
  352. static const char *const dcy_lim[11] = {
  353. "1.2 ms", "2.4 ms", "4.8 ms", "9.6 ms",
  354. "19.2 ms", "38.4 ms", "76.8 ms", "154 ms",
  355. "307 ms", "614 ms", "1.23 s",
  356. };
  357. static const char *const dcy_alc[11] = {
  358. "33.5 ms", "67.0 ms", "134 ms", "268 ms",
  359. "536 ms", "1.07 s", "2.14 s", "4.29 s",
  360. "8.58 s", "17.2 s", "34.3 s",
  361. };
  362. static const char *const tranwin[8] = {
  363. "0 us", "62.5 us", "125 us", "250 us",
  364. "500 us", "1 ms", "2 ms", "4 ms",
  365. };
  366. u8 max;
  367. const char *const *names;
  368. max = (ctl->private_value >> 12) & 0xf;
  369. info->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
  370. info->count = 1;
  371. info->value.enumerated.items = max + 1;
  372. if (info->value.enumerated.item > max)
  373. info->value.enumerated.item = max;
  374. switch ((ctl->private_value >> 24) & 0x1f) {
  375. case WM8776_ALCCTRL2:
  376. names = hld;
  377. break;
  378. case WM8776_ALCCTRL3:
  379. if (((ctl->private_value >> 20) & 0xf) == 0) {
  380. if (ctl->private_value & LC_CONTROL_LIMITER)
  381. names = atk_lim;
  382. else
  383. names = atk_alc;
  384. } else {
  385. if (ctl->private_value & LC_CONTROL_LIMITER)
  386. names = dcy_lim;
  387. else
  388. names = dcy_alc;
  389. }
  390. break;
  391. case WM8776_LIMITER:
  392. names = tranwin;
  393. break;
  394. default:
  395. return -ENXIO;
  396. }
  397. strcpy(info->value.enumerated.name, names[info->value.enumerated.item]);
  398. return 0;
  399. }
  400. static int wm8776_field_volume_info(struct snd_kcontrol *ctl,
  401. struct snd_ctl_elem_info *info)
  402. {
  403. info->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
  404. info->count = 1;
  405. info->value.integer.min = (ctl->private_value >> 8) & 0xf;
  406. info->value.integer.max = (ctl->private_value >> 12) & 0xf;
  407. return 0;
  408. }
  409. static void wm8776_field_set_from_ctl(struct snd_kcontrol *ctl)
  410. {
  411. struct oxygen *chip = ctl->private_data;
  412. struct xonar_wm87x6 *data = chip->model_data;
  413. unsigned int value, reg_index, mode;
  414. u8 min, max, shift;
  415. u16 mask, reg_value;
  416. bool invert;
  417. if ((data->wm8776_regs[WM8776_ALCCTRL1] & WM8776_LCSEL_MASK) ==
  418. WM8776_LCSEL_LIMITER)
  419. mode = LC_CONTROL_LIMITER;
  420. else
  421. mode = LC_CONTROL_ALC;
  422. if (!(ctl->private_value & mode))
  423. return;
  424. value = ctl->private_value & 0xf;
  425. min = (ctl->private_value >> 8) & 0xf;
  426. max = (ctl->private_value >> 12) & 0xf;
  427. mask = (ctl->private_value >> 16) & 0xf;
  428. shift = (ctl->private_value >> 20) & 0xf;
  429. reg_index = (ctl->private_value >> 24) & 0x1f;
  430. invert = (ctl->private_value >> 29) & 0x1;
  431. if (invert)
  432. value = max - (value - min);
  433. reg_value = data->wm8776_regs[reg_index];
  434. reg_value &= ~(mask << shift);
  435. reg_value |= value << shift;
  436. wm8776_write_cached(chip, reg_index, reg_value);
  437. }
  438. static int wm8776_field_set(struct snd_kcontrol *ctl, unsigned int value)
  439. {
  440. struct oxygen *chip = ctl->private_data;
  441. u8 min, max;
  442. int changed;
  443. min = (ctl->private_value >> 8) & 0xf;
  444. max = (ctl->private_value >> 12) & 0xf;
  445. if (value < min || value > max)
  446. return -EINVAL;
  447. mutex_lock(&chip->mutex);
  448. changed = value != (ctl->private_value & 0xf);
  449. if (changed) {
  450. ctl->private_value = (ctl->private_value & ~0xf) | value;
  451. wm8776_field_set_from_ctl(ctl);
  452. }
  453. mutex_unlock(&chip->mutex);
  454. return changed;
  455. }
  456. static int wm8776_field_enum_get(struct snd_kcontrol *ctl,
  457. struct snd_ctl_elem_value *value)
  458. {
  459. value->value.enumerated.item[0] = ctl->private_value & 0xf;
  460. return 0;
  461. }
  462. static int wm8776_field_volume_get(struct snd_kcontrol *ctl,
  463. struct snd_ctl_elem_value *value)
  464. {
  465. value->value.integer.value[0] = ctl->private_value & 0xf;
  466. return 0;
  467. }
  468. static int wm8776_field_enum_put(struct snd_kcontrol *ctl,
  469. struct snd_ctl_elem_value *value)
  470. {
  471. return wm8776_field_set(ctl, value->value.enumerated.item[0]);
  472. }
  473. static int wm8776_field_volume_put(struct snd_kcontrol *ctl,
  474. struct snd_ctl_elem_value *value)
  475. {
  476. return wm8776_field_set(ctl, value->value.integer.value[0]);
  477. }
  478. static int wm8776_hp_vol_info(struct snd_kcontrol *ctl,
  479. struct snd_ctl_elem_info *info)
  480. {
  481. info->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
  482. info->count = 2;
  483. info->value.integer.min = 0x79 - 60;
  484. info->value.integer.max = 0x7f;
  485. return 0;
  486. }
  487. static int wm8776_hp_vol_get(struct snd_kcontrol *ctl,
  488. struct snd_ctl_elem_value *value)
  489. {
  490. struct oxygen *chip = ctl->private_data;
  491. struct xonar_wm87x6 *data = chip->model_data;
  492. mutex_lock(&chip->mutex);
  493. value->value.integer.value[0] =
  494. data->wm8776_regs[WM8776_HPLVOL] & WM8776_HPATT_MASK;
  495. value->value.integer.value[1] =
  496. data->wm8776_regs[WM8776_HPRVOL] & WM8776_HPATT_MASK;
  497. mutex_unlock(&chip->mutex);
  498. return 0;
  499. }
  500. static int wm8776_hp_vol_put(struct snd_kcontrol *ctl,
  501. struct snd_ctl_elem_value *value)
  502. {
  503. struct oxygen *chip = ctl->private_data;
  504. struct xonar_wm87x6 *data = chip->model_data;
  505. u8 to_update;
  506. mutex_lock(&chip->mutex);
  507. to_update = (value->value.integer.value[0] !=
  508. (data->wm8776_regs[WM8776_HPLVOL] & WM8776_HPATT_MASK))
  509. << 0;
  510. to_update |= (value->value.integer.value[1] !=
  511. (data->wm8776_regs[WM8776_HPRVOL] & WM8776_HPATT_MASK))
  512. << 1;
  513. if (value->value.integer.value[0] == value->value.integer.value[1]) {
  514. if (to_update) {
  515. wm8776_write(chip, WM8776_HPMASTER,
  516. value->value.integer.value[0] |
  517. WM8776_HPZCEN | WM8776_UPDATE);
  518. data->wm8776_regs[WM8776_HPLVOL] =
  519. value->value.integer.value[0] | WM8776_HPZCEN;
  520. data->wm8776_regs[WM8776_HPRVOL] =
  521. value->value.integer.value[0] | WM8776_HPZCEN;
  522. }
  523. } else {
  524. if (to_update & 1)
  525. wm8776_write(chip, WM8776_HPLVOL,
  526. value->value.integer.value[0] |
  527. WM8776_HPZCEN |
  528. ((to_update & 2) ? 0 : WM8776_UPDATE));
  529. if (to_update & 2)
  530. wm8776_write(chip, WM8776_HPRVOL,
  531. value->value.integer.value[1] |
  532. WM8776_HPZCEN | WM8776_UPDATE);
  533. }
  534. mutex_unlock(&chip->mutex);
  535. return to_update != 0;
  536. }
  537. static int wm8776_input_mux_get(struct snd_kcontrol *ctl,
  538. struct snd_ctl_elem_value *value)
  539. {
  540. struct oxygen *chip = ctl->private_data;
  541. struct xonar_wm87x6 *data = chip->model_data;
  542. unsigned int mux_bit = ctl->private_value;
  543. value->value.integer.value[0] =
  544. !!(data->wm8776_regs[WM8776_ADCMUX] & mux_bit);
  545. return 0;
  546. }
  547. static int wm8776_input_mux_put(struct snd_kcontrol *ctl,
  548. struct snd_ctl_elem_value *value)
  549. {
  550. struct oxygen *chip = ctl->private_data;
  551. struct xonar_wm87x6 *data = chip->model_data;
  552. struct snd_kcontrol *other_ctl;
  553. unsigned int mux_bit = ctl->private_value;
  554. u16 reg;
  555. int changed;
  556. mutex_lock(&chip->mutex);
  557. reg = data->wm8776_regs[WM8776_ADCMUX];
  558. if (value->value.integer.value[0]) {
  559. reg |= mux_bit;
  560. /* line-in and mic-in are exclusive */
  561. mux_bit ^= 3;
  562. if (reg & mux_bit) {
  563. reg &= ~mux_bit;
  564. if (mux_bit == 1)
  565. other_ctl = data->line_adcmux_control;
  566. else
  567. other_ctl = data->mic_adcmux_control;
  568. snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE,
  569. &other_ctl->id);
  570. }
  571. } else
  572. reg &= ~mux_bit;
  573. changed = reg != data->wm8776_regs[WM8776_ADCMUX];
  574. if (changed) {
  575. oxygen_write16_masked(chip, OXYGEN_GPIO_DATA,
  576. reg & 1 ? GPIO_DS_INPUT_ROUTE : 0,
  577. GPIO_DS_INPUT_ROUTE);
  578. wm8776_write(chip, WM8776_ADCMUX, reg);
  579. }
  580. mutex_unlock(&chip->mutex);
  581. return changed;
  582. }
  583. static int wm8776_input_vol_info(struct snd_kcontrol *ctl,
  584. struct snd_ctl_elem_info *info)
  585. {
  586. info->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
  587. info->count = 2;
  588. info->value.integer.min = 0xa5;
  589. info->value.integer.max = 0xff;
  590. return 0;
  591. }
  592. static int wm8776_input_vol_get(struct snd_kcontrol *ctl,
  593. struct snd_ctl_elem_value *value)
  594. {
  595. struct oxygen *chip = ctl->private_data;
  596. struct xonar_wm87x6 *data = chip->model_data;
  597. mutex_lock(&chip->mutex);
  598. value->value.integer.value[0] =
  599. data->wm8776_regs[WM8776_ADCLVOL] & WM8776_AGMASK;
  600. value->value.integer.value[1] =
  601. data->wm8776_regs[WM8776_ADCRVOL] & WM8776_AGMASK;
  602. mutex_unlock(&chip->mutex);
  603. return 0;
  604. }
  605. static int wm8776_input_vol_put(struct snd_kcontrol *ctl,
  606. struct snd_ctl_elem_value *value)
  607. {
  608. struct oxygen *chip = ctl->private_data;
  609. struct xonar_wm87x6 *data = chip->model_data;
  610. int changed = 0;
  611. mutex_lock(&chip->mutex);
  612. changed = (value->value.integer.value[0] !=
  613. (data->wm8776_regs[WM8776_ADCLVOL] & WM8776_AGMASK)) ||
  614. (value->value.integer.value[1] !=
  615. (data->wm8776_regs[WM8776_ADCRVOL] & WM8776_AGMASK));
  616. wm8776_write_cached(chip, WM8776_ADCLVOL,
  617. value->value.integer.value[0] | WM8776_ZCA);
  618. wm8776_write_cached(chip, WM8776_ADCRVOL,
  619. value->value.integer.value[1] | WM8776_ZCA);
  620. mutex_unlock(&chip->mutex);
  621. return changed;
  622. }
  623. static int wm8776_level_control_info(struct snd_kcontrol *ctl,
  624. struct snd_ctl_elem_info *info)
  625. {
  626. static const char *const names[3] = {
  627. "None", "Peak Limiter", "Automatic Level Control"
  628. };
  629. info->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
  630. info->count = 1;
  631. info->value.enumerated.items = 3;
  632. if (info->value.enumerated.item >= 3)
  633. info->value.enumerated.item = 2;
  634. strcpy(info->value.enumerated.name, names[info->value.enumerated.item]);
  635. return 0;
  636. }
  637. static int wm8776_level_control_get(struct snd_kcontrol *ctl,
  638. struct snd_ctl_elem_value *value)
  639. {
  640. struct oxygen *chip = ctl->private_data;
  641. struct xonar_wm87x6 *data = chip->model_data;
  642. if (!(data->wm8776_regs[WM8776_ALCCTRL2] & WM8776_LCEN))
  643. value->value.enumerated.item[0] = 0;
  644. else if ((data->wm8776_regs[WM8776_ALCCTRL1] & WM8776_LCSEL_MASK) ==
  645. WM8776_LCSEL_LIMITER)
  646. value->value.enumerated.item[0] = 1;
  647. else
  648. value->value.enumerated.item[0] = 2;
  649. return 0;
  650. }
  651. static void activate_control(struct oxygen *chip,
  652. struct snd_kcontrol *ctl, unsigned int mode)
  653. {
  654. unsigned int access;
  655. if (ctl->private_value & mode)
  656. access = 0;
  657. else
  658. access = SNDRV_CTL_ELEM_ACCESS_INACTIVE;
  659. if ((ctl->vd[0].access & SNDRV_CTL_ELEM_ACCESS_INACTIVE) != access) {
  660. ctl->vd[0].access ^= SNDRV_CTL_ELEM_ACCESS_INACTIVE;
  661. snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_INFO, &ctl->id);
  662. }
  663. }
  664. static int wm8776_level_control_put(struct snd_kcontrol *ctl,
  665. struct snd_ctl_elem_value *value)
  666. {
  667. struct oxygen *chip = ctl->private_data;
  668. struct xonar_wm87x6 *data = chip->model_data;
  669. unsigned int mode = 0, i;
  670. u16 ctrl1, ctrl2;
  671. int changed;
  672. if (value->value.enumerated.item[0] >= 3)
  673. return -EINVAL;
  674. mutex_lock(&chip->mutex);
  675. changed = value->value.enumerated.item[0] != ctl->private_value;
  676. if (changed) {
  677. ctl->private_value = value->value.enumerated.item[0];
  678. ctrl1 = data->wm8776_regs[WM8776_ALCCTRL1];
  679. ctrl2 = data->wm8776_regs[WM8776_ALCCTRL2];
  680. switch (value->value.enumerated.item[0]) {
  681. default:
  682. wm8776_write_cached(chip, WM8776_ALCCTRL2,
  683. ctrl2 & ~WM8776_LCEN);
  684. break;
  685. case 1:
  686. wm8776_write_cached(chip, WM8776_ALCCTRL1,
  687. (ctrl1 & ~WM8776_LCSEL_MASK) |
  688. WM8776_LCSEL_LIMITER);
  689. wm8776_write_cached(chip, WM8776_ALCCTRL2,
  690. ctrl2 | WM8776_LCEN);
  691. mode = LC_CONTROL_LIMITER;
  692. break;
  693. case 2:
  694. wm8776_write_cached(chip, WM8776_ALCCTRL1,
  695. (ctrl1 & ~WM8776_LCSEL_MASK) |
  696. WM8776_LCSEL_ALC_STEREO);
  697. wm8776_write_cached(chip, WM8776_ALCCTRL2,
  698. ctrl2 | WM8776_LCEN);
  699. mode = LC_CONTROL_ALC;
  700. break;
  701. }
  702. for (i = 0; i < ARRAY_SIZE(data->lc_controls); ++i)
  703. activate_control(chip, data->lc_controls[i], mode);
  704. }
  705. mutex_unlock(&chip->mutex);
  706. return changed;
  707. }
  708. static int hpf_info(struct snd_kcontrol *ctl, struct snd_ctl_elem_info *info)
  709. {
  710. static const char *const names[2] = {
  711. "None", "High-pass Filter"
  712. };
  713. info->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
  714. info->count = 1;
  715. info->value.enumerated.items = 2;
  716. if (info->value.enumerated.item >= 2)
  717. info->value.enumerated.item = 1;
  718. strcpy(info->value.enumerated.name, names[info->value.enumerated.item]);
  719. return 0;
  720. }
  721. static int hpf_get(struct snd_kcontrol *ctl, struct snd_ctl_elem_value *value)
  722. {
  723. struct oxygen *chip = ctl->private_data;
  724. struct xonar_wm87x6 *data = chip->model_data;
  725. value->value.enumerated.item[0] =
  726. !(data->wm8776_regs[WM8776_ADCIFCTRL] & WM8776_ADCHPD);
  727. return 0;
  728. }
  729. static int hpf_put(struct snd_kcontrol *ctl, struct snd_ctl_elem_value *value)
  730. {
  731. struct oxygen *chip = ctl->private_data;
  732. struct xonar_wm87x6 *data = chip->model_data;
  733. unsigned int reg;
  734. int changed;
  735. mutex_lock(&chip->mutex);
  736. reg = data->wm8776_regs[WM8776_ADCIFCTRL] & ~WM8776_ADCHPD;
  737. if (!value->value.enumerated.item[0])
  738. reg |= WM8776_ADCHPD;
  739. changed = reg != data->wm8776_regs[WM8776_ADCIFCTRL];
  740. if (changed)
  741. wm8776_write(chip, WM8776_ADCIFCTRL, reg);
  742. mutex_unlock(&chip->mutex);
  743. return changed;
  744. }
  745. #define WM8776_BIT_SWITCH(xname, reg, bit, invert, flags) { \
  746. .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
  747. .name = xname, \
  748. .info = snd_ctl_boolean_mono_info, \
  749. .get = wm8776_bit_switch_get, \
  750. .put = wm8776_bit_switch_put, \
  751. .private_value = ((reg) << 16) | (bit) | ((invert) << 24) | (flags), \
  752. }
  753. #define _WM8776_FIELD_CTL(xname, reg, shift, initval, min, max, mask, flags) \
  754. .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
  755. .name = xname, \
  756. .private_value = (initval) | ((min) << 8) | ((max) << 12) | \
  757. ((mask) << 16) | ((shift) << 20) | ((reg) << 24) | (flags)
  758. #define WM8776_FIELD_CTL_ENUM(xname, reg, shift, init, min, max, mask, flags) {\
  759. _WM8776_FIELD_CTL(xname " Capture Enum", \
  760. reg, shift, init, min, max, mask, flags), \
  761. .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | \
  762. SNDRV_CTL_ELEM_ACCESS_INACTIVE, \
  763. .info = wm8776_field_enum_info, \
  764. .get = wm8776_field_enum_get, \
  765. .put = wm8776_field_enum_put, \
  766. }
  767. #define WM8776_FIELD_CTL_VOLUME(a, b, c, d, e, f, g, h, tlv_p) { \
  768. _WM8776_FIELD_CTL(a " Capture Volume", b, c, d, e, f, g, h), \
  769. .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | \
  770. SNDRV_CTL_ELEM_ACCESS_INACTIVE | \
  771. SNDRV_CTL_ELEM_ACCESS_TLV_READ, \
  772. .info = wm8776_field_volume_info, \
  773. .get = wm8776_field_volume_get, \
  774. .put = wm8776_field_volume_put, \
  775. .tlv = { .p = tlv_p }, \
  776. }
  777. static const DECLARE_TLV_DB_SCALE(wm87x6_dac_db_scale, -6000, 50, 0);
  778. static const DECLARE_TLV_DB_SCALE(wm8776_adc_db_scale, -2100, 50, 0);
  779. static const DECLARE_TLV_DB_SCALE(wm8776_hp_db_scale, -6000, 100, 0);
  780. static const DECLARE_TLV_DB_SCALE(wm8776_lct_db_scale, -1600, 100, 0);
  781. static const DECLARE_TLV_DB_SCALE(wm8776_maxgain_db_scale, 0, 400, 0);
  782. static const DECLARE_TLV_DB_SCALE(wm8776_ngth_db_scale, -7800, 600, 0);
  783. static const DECLARE_TLV_DB_SCALE(wm8776_maxatten_lim_db_scale, -1200, 100, 0);
  784. static const DECLARE_TLV_DB_SCALE(wm8776_maxatten_alc_db_scale, -2100, 400, 0);
  785. static const struct snd_kcontrol_new ds_controls[] = {
  786. {
  787. .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
  788. .name = "Headphone Playback Volume",
  789. .info = wm8776_hp_vol_info,
  790. .get = wm8776_hp_vol_get,
  791. .put = wm8776_hp_vol_put,
  792. .tlv = { .p = wm8776_hp_db_scale },
  793. },
  794. WM8776_BIT_SWITCH("Headphone Playback Switch",
  795. WM8776_PWRDOWN, WM8776_HPPD, 1, 0),
  796. {
  797. .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
  798. .name = "Input Capture Volume",
  799. .info = wm8776_input_vol_info,
  800. .get = wm8776_input_vol_get,
  801. .put = wm8776_input_vol_put,
  802. .tlv = { .p = wm8776_adc_db_scale },
  803. },
  804. {
  805. .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
  806. .name = "Line Capture Switch",
  807. .info = snd_ctl_boolean_mono_info,
  808. .get = wm8776_input_mux_get,
  809. .put = wm8776_input_mux_put,
  810. .private_value = 1 << 0,
  811. },
  812. {
  813. .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
  814. .name = "Mic Capture Switch",
  815. .info = snd_ctl_boolean_mono_info,
  816. .get = wm8776_input_mux_get,
  817. .put = wm8776_input_mux_put,
  818. .private_value = 1 << 1,
  819. },
  820. WM8776_BIT_SWITCH("Front Mic Capture Switch",
  821. WM8776_ADCMUX, 1 << 2, 0, 0),
  822. WM8776_BIT_SWITCH("Aux Capture Switch",
  823. WM8776_ADCMUX, 1 << 3, 0, 0),
  824. {
  825. .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
  826. .name = "ADC Filter Capture Enum",
  827. .info = hpf_info,
  828. .get = hpf_get,
  829. .put = hpf_put,
  830. },
  831. {
  832. .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
  833. .name = "Level Control Capture Enum",
  834. .info = wm8776_level_control_info,
  835. .get = wm8776_level_control_get,
  836. .put = wm8776_level_control_put,
  837. .private_value = 0,
  838. },
  839. };
  840. static const struct snd_kcontrol_new lc_controls[] = {
  841. WM8776_FIELD_CTL_VOLUME("Limiter Threshold",
  842. WM8776_ALCCTRL1, 0, 11, 0, 15, 0xf,
  843. LC_CONTROL_LIMITER, wm8776_lct_db_scale),
  844. WM8776_FIELD_CTL_ENUM("Limiter Attack Time",
  845. WM8776_ALCCTRL3, 0, 2, 0, 10, 0xf,
  846. LC_CONTROL_LIMITER),
  847. WM8776_FIELD_CTL_ENUM("Limiter Decay Time",
  848. WM8776_ALCCTRL3, 4, 3, 0, 10, 0xf,
  849. LC_CONTROL_LIMITER),
  850. WM8776_FIELD_CTL_ENUM("Limiter Transient Window",
  851. WM8776_LIMITER, 4, 2, 0, 7, 0x7,
  852. LC_CONTROL_LIMITER),
  853. WM8776_FIELD_CTL_VOLUME("Limiter Maximum Attenuation",
  854. WM8776_LIMITER, 0, 6, 3, 12, 0xf,
  855. LC_CONTROL_LIMITER,
  856. wm8776_maxatten_lim_db_scale),
  857. WM8776_FIELD_CTL_VOLUME("ALC Target Level",
  858. WM8776_ALCCTRL1, 0, 11, 0, 15, 0xf,
  859. LC_CONTROL_ALC, wm8776_lct_db_scale),
  860. WM8776_FIELD_CTL_ENUM("ALC Attack Time",
  861. WM8776_ALCCTRL3, 0, 2, 0, 10, 0xf,
  862. LC_CONTROL_ALC),
  863. WM8776_FIELD_CTL_ENUM("ALC Decay Time",
  864. WM8776_ALCCTRL3, 4, 3, 0, 10, 0xf,
  865. LC_CONTROL_ALC),
  866. WM8776_FIELD_CTL_VOLUME("ALC Maximum Gain",
  867. WM8776_ALCCTRL1, 4, 7, 1, 7, 0x7,
  868. LC_CONTROL_ALC, wm8776_maxgain_db_scale),
  869. WM8776_FIELD_CTL_VOLUME("ALC Maximum Attenuation",
  870. WM8776_LIMITER, 0, 10, 10, 15, 0xf,
  871. LC_CONTROL_ALC, wm8776_maxatten_alc_db_scale),
  872. WM8776_FIELD_CTL_ENUM("ALC Hold Time",
  873. WM8776_ALCCTRL2, 0, 0, 0, 15, 0xf,
  874. LC_CONTROL_ALC),
  875. WM8776_BIT_SWITCH("Noise Gate Capture Switch",
  876. WM8776_NOISEGATE, WM8776_NGAT, 0,
  877. LC_CONTROL_ALC),
  878. WM8776_FIELD_CTL_VOLUME("Noise Gate Threshold",
  879. WM8776_NOISEGATE, 2, 0, 0, 7, 0x7,
  880. LC_CONTROL_ALC, wm8776_ngth_db_scale),
  881. };
  882. static int xonar_ds_control_filter(struct snd_kcontrol_new *template)
  883. {
  884. if (!strncmp(template->name, "CD Capture ", 11))
  885. return 1; /* no CD input */
  886. return 0;
  887. }
  888. static int xonar_ds_mixer_init(struct oxygen *chip)
  889. {
  890. struct xonar_wm87x6 *data = chip->model_data;
  891. unsigned int i;
  892. struct snd_kcontrol *ctl;
  893. int err;
  894. for (i = 0; i < ARRAY_SIZE(ds_controls); ++i) {
  895. ctl = snd_ctl_new1(&ds_controls[i], chip);
  896. if (!ctl)
  897. return -ENOMEM;
  898. err = snd_ctl_add(chip->card, ctl);
  899. if (err < 0)
  900. return err;
  901. if (!strcmp(ctl->id.name, "Line Capture Switch"))
  902. data->line_adcmux_control = ctl;
  903. else if (!strcmp(ctl->id.name, "Mic Capture Switch"))
  904. data->mic_adcmux_control = ctl;
  905. }
  906. if (!data->line_adcmux_control || !data->mic_adcmux_control)
  907. return -ENXIO;
  908. BUILD_BUG_ON(ARRAY_SIZE(lc_controls) != ARRAY_SIZE(data->lc_controls));
  909. for (i = 0; i < ARRAY_SIZE(lc_controls); ++i) {
  910. ctl = snd_ctl_new1(&lc_controls[i], chip);
  911. if (!ctl)
  912. return -ENOMEM;
  913. err = snd_ctl_add(chip->card, ctl);
  914. if (err < 0)
  915. return err;
  916. data->lc_controls[i] = ctl;
  917. }
  918. return 0;
  919. }
  920. static const struct oxygen_model model_xonar_ds = {
  921. .shortname = "Xonar DS",
  922. .longname = "Asus Virtuoso 200",
  923. .chip = "AV200",
  924. .init = xonar_ds_init,
  925. .control_filter = xonar_ds_control_filter,
  926. .mixer_init = xonar_ds_mixer_init,
  927. .cleanup = xonar_ds_cleanup,
  928. .suspend = xonar_ds_suspend,
  929. .resume = xonar_ds_resume,
  930. .pcm_hardware_filter = wm8776_adc_hardware_filter,
  931. .get_i2s_mclk = oxygen_default_i2s_mclk,
  932. .set_dac_params = set_wm87x6_dac_params,
  933. .set_adc_params = set_wm8776_adc_params,
  934. .update_dac_volume = update_wm87x6_volume,
  935. .update_dac_mute = update_wm87x6_mute,
  936. .gpio_changed = xonar_ds_gpio_changed,
  937. .dac_tlv = wm87x6_dac_db_scale,
  938. .model_data_size = sizeof(struct xonar_wm87x6),
  939. .device_config = PLAYBACK_0_TO_I2S |
  940. PLAYBACK_1_TO_SPDIF |
  941. CAPTURE_0_FROM_I2S_1,
  942. .dac_channels = 8,
  943. .dac_volume_min = 255 - 2*60,
  944. .dac_volume_max = 255,
  945. .function_flags = OXYGEN_FUNCTION_SPI,
  946. .dac_i2s_format = OXYGEN_I2S_FORMAT_LJUST,
  947. .adc_i2s_format = OXYGEN_I2S_FORMAT_LJUST,
  948. };
  949. int __devinit get_xonar_wm87x6_model(struct oxygen *chip,
  950. const struct pci_device_id *id)
  951. {
  952. switch (id->subdevice) {
  953. case 0x838e:
  954. chip->model = model_xonar_ds;
  955. break;
  956. default:
  957. return -EINVAL;
  958. }
  959. return 0;
  960. }