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