xonar_wm87x6.c 30 KB

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