xonar_wm87x6.c 31 KB

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