xonar_dg_mixer.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478
  1. /*
  2. * Mixer controls for the Xonar DG/DGX
  3. *
  4. * Copyright (c) Clemens Ladisch <clemens@ladisch.de>
  5. * Copyright (c) Roman Volkov <v1ron@mail.ru>
  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. #include <linux/pci.h>
  19. #include <linux/delay.h>
  20. #include <sound/control.h>
  21. #include <sound/core.h>
  22. #include <sound/info.h>
  23. #include <sound/pcm.h>
  24. #include <sound/tlv.h>
  25. #include "oxygen.h"
  26. #include "xonar_dg.h"
  27. #include "cs4245.h"
  28. /* analog output select */
  29. static int output_select_apply(struct oxygen *chip)
  30. {
  31. struct dg *data = chip->model_data;
  32. data->cs4245_shadow[CS4245_SIGNAL_SEL] &= ~CS4245_A_OUT_SEL_MASK;
  33. if (data->output_sel == PLAYBACK_DST_HP) {
  34. /* mute FP (aux output) amplifier, switch rear jack to CS4245 */
  35. oxygen_set_bits8(chip, OXYGEN_GPIO_DATA, GPIO_HP_REAR);
  36. } else if (data->output_sel == PLAYBACK_DST_HP_FP) {
  37. /*
  38. * Unmute FP amplifier, switch rear jack to CS4361;
  39. * I2S channels 2,3,4 should be inactive.
  40. */
  41. oxygen_clear_bits8(chip, OXYGEN_GPIO_DATA, GPIO_HP_REAR);
  42. data->cs4245_shadow[CS4245_SIGNAL_SEL] |= CS4245_A_OUT_SEL_DAC;
  43. } else {
  44. /*
  45. * 2.0, 4.0, 5.1: switch to CS4361, mute FP amp.,
  46. * and change playback routing.
  47. */
  48. oxygen_clear_bits8(chip, OXYGEN_GPIO_DATA, GPIO_HP_REAR);
  49. }
  50. return cs4245_write_spi(chip, CS4245_SIGNAL_SEL);
  51. }
  52. static int output_select_info(struct snd_kcontrol *ctl,
  53. struct snd_ctl_elem_info *info)
  54. {
  55. static const char *const names[3] = {
  56. "Stereo Headphones",
  57. "Stereo Headphones FP",
  58. "Multichannel",
  59. };
  60. return snd_ctl_enum_info(info, 1, 3, names);
  61. }
  62. static int output_select_get(struct snd_kcontrol *ctl,
  63. struct snd_ctl_elem_value *value)
  64. {
  65. struct oxygen *chip = ctl->private_data;
  66. struct dg *data = chip->model_data;
  67. mutex_lock(&chip->mutex);
  68. value->value.enumerated.item[0] = data->output_sel;
  69. mutex_unlock(&chip->mutex);
  70. return 0;
  71. }
  72. static int output_select_put(struct snd_kcontrol *ctl,
  73. struct snd_ctl_elem_value *value)
  74. {
  75. struct oxygen *chip = ctl->private_data;
  76. struct dg *data = chip->model_data;
  77. unsigned int new = value->value.enumerated.item[0];
  78. int changed = 0;
  79. int ret;
  80. mutex_lock(&chip->mutex);
  81. if (data->output_sel != new) {
  82. data->output_sel = new;
  83. ret = output_select_apply(chip);
  84. changed = ret >= 0 ? 1 : ret;
  85. oxygen_update_dac_routing(chip);
  86. }
  87. mutex_unlock(&chip->mutex);
  88. return changed;
  89. }
  90. /* CS4245 Headphone Channels A&B Volume Control */
  91. static int hp_stereo_volume_info(struct snd_kcontrol *ctl,
  92. struct snd_ctl_elem_info *info)
  93. {
  94. info->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
  95. info->count = 2;
  96. info->value.integer.min = 0;
  97. info->value.integer.max = 255;
  98. return 0;
  99. }
  100. static int hp_stereo_volume_get(struct snd_kcontrol *ctl,
  101. struct snd_ctl_elem_value *val)
  102. {
  103. struct oxygen *chip = ctl->private_data;
  104. struct dg *data = chip->model_data;
  105. unsigned int tmp;
  106. mutex_lock(&chip->mutex);
  107. tmp = (~data->cs4245_shadow[CS4245_DAC_A_CTRL]) & 255;
  108. val->value.integer.value[0] = tmp;
  109. tmp = (~data->cs4245_shadow[CS4245_DAC_B_CTRL]) & 255;
  110. val->value.integer.value[1] = tmp;
  111. mutex_unlock(&chip->mutex);
  112. return 0;
  113. }
  114. static int hp_stereo_volume_put(struct snd_kcontrol *ctl,
  115. struct snd_ctl_elem_value *val)
  116. {
  117. struct oxygen *chip = ctl->private_data;
  118. struct dg *data = chip->model_data;
  119. int ret;
  120. int changed = 0;
  121. long new1 = val->value.integer.value[0];
  122. long new2 = val->value.integer.value[1];
  123. if ((new1 > 255) || (new1 < 0) || (new2 > 255) || (new2 < 0))
  124. return -EINVAL;
  125. mutex_lock(&chip->mutex);
  126. if ((data->cs4245_shadow[CS4245_DAC_A_CTRL] != ~new1) ||
  127. (data->cs4245_shadow[CS4245_DAC_B_CTRL] != ~new2)) {
  128. data->cs4245_shadow[CS4245_DAC_A_CTRL] = ~new1;
  129. data->cs4245_shadow[CS4245_DAC_B_CTRL] = ~new2;
  130. ret = cs4245_write_spi(chip, CS4245_DAC_A_CTRL);
  131. if (ret >= 0)
  132. ret = cs4245_write_spi(chip, CS4245_DAC_B_CTRL);
  133. changed = ret >= 0 ? 1 : ret;
  134. }
  135. mutex_unlock(&chip->mutex);
  136. return changed;
  137. }
  138. /* Headphone Mute */
  139. static int hp_mute_get(struct snd_kcontrol *ctl,
  140. struct snd_ctl_elem_value *val)
  141. {
  142. struct oxygen *chip = ctl->private_data;
  143. struct dg *data = chip->model_data;
  144. mutex_lock(&chip->mutex);
  145. val->value.integer.value[0] =
  146. !(data->cs4245_shadow[CS4245_DAC_CTRL_1] & CS4245_MUTE_DAC);
  147. mutex_unlock(&chip->mutex);
  148. return 0;
  149. }
  150. static int hp_mute_put(struct snd_kcontrol *ctl,
  151. struct snd_ctl_elem_value *val)
  152. {
  153. struct oxygen *chip = ctl->private_data;
  154. struct dg *data = chip->model_data;
  155. int ret;
  156. int changed;
  157. if (val->value.integer.value[0] > 1)
  158. return -EINVAL;
  159. mutex_lock(&chip->mutex);
  160. data->cs4245_shadow[CS4245_DAC_CTRL_1] &= ~CS4245_MUTE_DAC;
  161. data->cs4245_shadow[CS4245_DAC_CTRL_1] |=
  162. (~val->value.integer.value[0] << 2) & CS4245_MUTE_DAC;
  163. ret = cs4245_write_spi(chip, CS4245_DAC_CTRL_1);
  164. changed = ret >= 0 ? 1 : ret;
  165. mutex_unlock(&chip->mutex);
  166. return changed;
  167. }
  168. /* capture volume for all sources */
  169. static int input_volume_apply(struct oxygen *chip, char left, char right)
  170. {
  171. struct dg *data = chip->model_data;
  172. int ret;
  173. data->cs4245_shadow[CS4245_PGA_A_CTRL] = left;
  174. data->cs4245_shadow[CS4245_PGA_B_CTRL] = right;
  175. ret = cs4245_write_spi(chip, CS4245_PGA_A_CTRL);
  176. if (ret < 0)
  177. return ret;
  178. return cs4245_write_spi(chip, CS4245_PGA_B_CTRL);
  179. }
  180. static int input_vol_info(struct snd_kcontrol *ctl,
  181. struct snd_ctl_elem_info *info)
  182. {
  183. info->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
  184. info->count = 2;
  185. info->value.integer.min = 2 * -12;
  186. info->value.integer.max = 2 * 12;
  187. return 0;
  188. }
  189. static int input_vol_get(struct snd_kcontrol *ctl,
  190. struct snd_ctl_elem_value *value)
  191. {
  192. struct oxygen *chip = ctl->private_data;
  193. struct dg *data = chip->model_data;
  194. unsigned int idx = ctl->private_value;
  195. mutex_lock(&chip->mutex);
  196. value->value.integer.value[0] = data->input_vol[idx][0];
  197. value->value.integer.value[1] = data->input_vol[idx][1];
  198. mutex_unlock(&chip->mutex);
  199. return 0;
  200. }
  201. static int input_vol_put(struct snd_kcontrol *ctl,
  202. struct snd_ctl_elem_value *value)
  203. {
  204. struct oxygen *chip = ctl->private_data;
  205. struct dg *data = chip->model_data;
  206. unsigned int idx = ctl->private_value;
  207. int changed = 0;
  208. int ret = 0;
  209. if (value->value.integer.value[0] < 2 * -12 ||
  210. value->value.integer.value[0] > 2 * 12 ||
  211. value->value.integer.value[1] < 2 * -12 ||
  212. value->value.integer.value[1] > 2 * 12)
  213. return -EINVAL;
  214. mutex_lock(&chip->mutex);
  215. changed = data->input_vol[idx][0] != value->value.integer.value[0] ||
  216. data->input_vol[idx][1] != value->value.integer.value[1];
  217. if (changed) {
  218. data->input_vol[idx][0] = value->value.integer.value[0];
  219. data->input_vol[idx][1] = value->value.integer.value[1];
  220. if (idx == data->input_sel) {
  221. ret = input_volume_apply(chip,
  222. data->input_vol[idx][0],
  223. data->input_vol[idx][1]);
  224. }
  225. changed = ret >= 0 ? 1 : ret;
  226. }
  227. mutex_unlock(&chip->mutex);
  228. return changed;
  229. }
  230. /* Capture Source */
  231. static int input_source_apply(struct oxygen *chip)
  232. {
  233. struct dg *data = chip->model_data;
  234. data->cs4245_shadow[CS4245_ANALOG_IN] &= ~CS4245_SEL_MASK;
  235. if (data->input_sel == CAPTURE_SRC_FP_MIC)
  236. data->cs4245_shadow[CS4245_ANALOG_IN] |= CS4245_SEL_INPUT_2;
  237. else if (data->input_sel == CAPTURE_SRC_LINE)
  238. data->cs4245_shadow[CS4245_ANALOG_IN] |= CS4245_SEL_INPUT_4;
  239. else if (data->input_sel != CAPTURE_SRC_MIC)
  240. data->cs4245_shadow[CS4245_ANALOG_IN] |= CS4245_SEL_INPUT_1;
  241. return cs4245_write_spi(chip, CS4245_ANALOG_IN);
  242. }
  243. static int input_sel_info(struct snd_kcontrol *ctl,
  244. struct snd_ctl_elem_info *info)
  245. {
  246. static const char *const names[4] = {
  247. "Mic", "Front Mic", "Line", "Aux"
  248. };
  249. return snd_ctl_enum_info(info, 1, 4, names);
  250. }
  251. static int input_sel_get(struct snd_kcontrol *ctl,
  252. struct snd_ctl_elem_value *value)
  253. {
  254. struct oxygen *chip = ctl->private_data;
  255. struct dg *data = chip->model_data;
  256. mutex_lock(&chip->mutex);
  257. value->value.enumerated.item[0] = data->input_sel;
  258. mutex_unlock(&chip->mutex);
  259. return 0;
  260. }
  261. static int input_sel_put(struct snd_kcontrol *ctl,
  262. struct snd_ctl_elem_value *value)
  263. {
  264. struct oxygen *chip = ctl->private_data;
  265. struct dg *data = chip->model_data;
  266. int changed;
  267. int ret;
  268. if (value->value.enumerated.item[0] > 3)
  269. return -EINVAL;
  270. mutex_lock(&chip->mutex);
  271. changed = value->value.enumerated.item[0] != data->input_sel;
  272. if (changed) {
  273. data->input_sel = value->value.enumerated.item[0];
  274. ret = input_source_apply(chip);
  275. if (ret >= 0)
  276. ret = input_volume_apply(chip,
  277. data->input_vol[data->input_sel][0],
  278. data->input_vol[data->input_sel][1]);
  279. changed = ret >= 0 ? 1 : ret;
  280. }
  281. mutex_unlock(&chip->mutex);
  282. return changed;
  283. }
  284. /* ADC high-pass filter */
  285. static int hpf_info(struct snd_kcontrol *ctl, struct snd_ctl_elem_info *info)
  286. {
  287. static const char *const names[2] = { "Active", "Frozen" };
  288. return snd_ctl_enum_info(info, 1, 2, names);
  289. }
  290. static int hpf_get(struct snd_kcontrol *ctl, struct snd_ctl_elem_value *value)
  291. {
  292. struct oxygen *chip = ctl->private_data;
  293. struct dg *data = chip->model_data;
  294. value->value.enumerated.item[0] =
  295. !!(data->cs4245_shadow[CS4245_ADC_CTRL] & CS4245_HPF_FREEZE);
  296. return 0;
  297. }
  298. static int hpf_put(struct snd_kcontrol *ctl, struct snd_ctl_elem_value *value)
  299. {
  300. struct oxygen *chip = ctl->private_data;
  301. struct dg *data = chip->model_data;
  302. u8 reg;
  303. int changed;
  304. mutex_lock(&chip->mutex);
  305. reg = data->cs4245_shadow[CS4245_ADC_CTRL] & ~CS4245_HPF_FREEZE;
  306. if (value->value.enumerated.item[0])
  307. reg |= CS4245_HPF_FREEZE;
  308. changed = reg != data->cs4245_shadow[CS4245_ADC_CTRL];
  309. if (changed) {
  310. data->cs4245_shadow[CS4245_ADC_CTRL] = reg;
  311. cs4245_write_spi(chip, CS4245_ADC_CTRL);
  312. }
  313. mutex_unlock(&chip->mutex);
  314. return changed;
  315. }
  316. #define INPUT_VOLUME(xname, index) { \
  317. .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
  318. .name = xname, \
  319. .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | \
  320. SNDRV_CTL_ELEM_ACCESS_TLV_READ, \
  321. .info = input_vol_info, \
  322. .get = input_vol_get, \
  323. .put = input_vol_put, \
  324. .tlv = { .p = pga_db_scale }, \
  325. .private_value = index, \
  326. }
  327. static const DECLARE_TLV_DB_MINMAX(hp_db_scale, -12550, 0);
  328. static const DECLARE_TLV_DB_MINMAX(pga_db_scale, -1200, 1200);
  329. static const struct snd_kcontrol_new dg_controls[] = {
  330. {
  331. .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
  332. .name = "Analog Output Playback Enum",
  333. .info = output_select_info,
  334. .get = output_select_get,
  335. .put = output_select_put,
  336. },
  337. {
  338. .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
  339. .name = "Headphone Playback Volume",
  340. .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
  341. SNDRV_CTL_ELEM_ACCESS_TLV_READ,
  342. .info = hp_stereo_volume_info,
  343. .get = hp_stereo_volume_get,
  344. .put = hp_stereo_volume_put,
  345. .tlv = { .p = hp_db_scale, },
  346. },
  347. {
  348. .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
  349. .name = "Headphone Playback Switch",
  350. .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
  351. .info = snd_ctl_boolean_mono_info,
  352. .get = hp_mute_get,
  353. .put = hp_mute_put,
  354. },
  355. INPUT_VOLUME("Mic Capture Volume", CAPTURE_SRC_MIC),
  356. INPUT_VOLUME("Front Mic Capture Volume", CAPTURE_SRC_FP_MIC),
  357. INPUT_VOLUME("Line Capture Volume", CAPTURE_SRC_LINE),
  358. INPUT_VOLUME("Aux Capture Volume", CAPTURE_SRC_AUX),
  359. {
  360. .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
  361. .name = "Capture Source",
  362. .info = input_sel_info,
  363. .get = input_sel_get,
  364. .put = input_sel_put,
  365. },
  366. {
  367. .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
  368. .name = "ADC High-pass Filter Capture Enum",
  369. .info = hpf_info,
  370. .get = hpf_get,
  371. .put = hpf_put,
  372. },
  373. };
  374. static int dg_control_filter(struct snd_kcontrol_new *template)
  375. {
  376. if (!strncmp(template->name, "Master Playback ", 16))
  377. return 1;
  378. return 0;
  379. }
  380. static int dg_mixer_init(struct oxygen *chip)
  381. {
  382. unsigned int i;
  383. int err;
  384. output_select_apply(chip);
  385. input_source_apply(chip);
  386. oxygen_update_dac_routing(chip);
  387. for (i = 0; i < ARRAY_SIZE(dg_controls); ++i) {
  388. err = snd_ctl_add(chip->card,
  389. snd_ctl_new1(&dg_controls[i], chip));
  390. if (err < 0)
  391. return err;
  392. }
  393. return 0;
  394. }
  395. struct oxygen_model model_xonar_dg = {
  396. .longname = "C-Media Oxygen HD Audio",
  397. .chip = "CMI8786",
  398. .init = dg_init,
  399. .control_filter = dg_control_filter,
  400. .mixer_init = dg_mixer_init,
  401. .cleanup = dg_cleanup,
  402. .suspend = dg_suspend,
  403. .resume = dg_resume,
  404. .set_dac_params = set_cs4245_dac_params,
  405. .set_adc_params = set_cs4245_adc_params,
  406. .adjust_dac_routing = adjust_dg_dac_routing,
  407. .dump_registers = dump_cs4245_registers,
  408. .model_data_size = sizeof(struct dg),
  409. .device_config = PLAYBACK_0_TO_I2S |
  410. PLAYBACK_1_TO_SPDIF |
  411. CAPTURE_0_FROM_I2S_1 |
  412. CAPTURE_1_FROM_SPDIF,
  413. .dac_channels_pcm = 6,
  414. .dac_channels_mixer = 0,
  415. .function_flags = OXYGEN_FUNCTION_SPI,
  416. .dac_mclks = OXYGEN_MCLKS(256, 128, 128),
  417. .adc_mclks = OXYGEN_MCLKS(256, 128, 128),
  418. .dac_i2s_format = OXYGEN_I2S_FORMAT_LJUST,
  419. .adc_i2s_format = OXYGEN_I2S_FORMAT_LJUST,
  420. };