1 /* 2 * card driver for the Xonar DG 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 /* 20 * Xonar DG 21 * -------- 22 * 23 * CMI8788: 24 * 25 * SPI 0 -> CS4245 26 * 27 * GPIO 3 <- ? 28 * GPIO 4 <- headphone detect 29 * GPIO 5 -> route input jack to line-in (0) or mic-in (1) 30 * GPIO 6 -> route input jack to line-in (0) or mic-in (1) 31 * GPIO 7 -> enable rear headphone amp 32 * GPIO 8 -> enable output to speakers 33 * 34 * CS4245: 35 * 36 * input 1 <- aux 37 * input 2 <- front mic 38 * input 4 <- line/mic 39 * aux out -> front panel headphones 40 */ 41 42 #include <linux/pci.h> 43 #include <sound/control.h> 44 #include <sound/core.h> 45 #include <sound/info.h> 46 #include <sound/pcm.h> 47 #include <sound/tlv.h> 48 #include "oxygen.h" 49 #include "xonar_dg.h" 50 #include "cs4245.h" 51 52 #define GPIO_MAGIC 0x0008 53 #define GPIO_HP_DETECT 0x0010 54 #define GPIO_INPUT_ROUTE 0x0060 55 #define GPIO_HP_REAR 0x0080 56 #define GPIO_OUTPUT_ENABLE 0x0100 57 58 struct dg { 59 unsigned int output_sel; 60 s8 input_vol[4][2]; 61 unsigned int input_sel; 62 u8 hp_vol_att; 63 u8 cs4245_regs[0x11]; 64 }; 65 66 static void cs4245_write(struct oxygen *chip, unsigned int reg, u8 value) 67 { 68 struct dg *data = chip->model_data; 69 70 oxygen_write_spi(chip, OXYGEN_SPI_TRIGGER | 71 OXYGEN_SPI_DATA_LENGTH_3 | 72 OXYGEN_SPI_CLOCK_1280 | 73 (0 << OXYGEN_SPI_CODEC_SHIFT) | 74 OXYGEN_SPI_CEN_LATCH_CLOCK_HI, 75 CS4245_SPI_ADDRESS | 76 CS4245_SPI_WRITE | 77 (value << 8) | reg); 78 data->cs4245_regs[reg] = value; 79 } 80 81 static void cs4245_write_cached(struct oxygen *chip, unsigned int reg, u8 value) 82 { 83 struct dg *data = chip->model_data; 84 85 if (value != data->cs4245_regs[reg]) 86 cs4245_write(chip, reg, value); 87 } 88 89 static void cs4245_registers_init(struct oxygen *chip) 90 { 91 struct dg *data = chip->model_data; 92 93 cs4245_write(chip, CS4245_POWER_CTRL, CS4245_PDN); 94 cs4245_write(chip, CS4245_DAC_CTRL_1, 95 data->cs4245_regs[CS4245_DAC_CTRL_1]); 96 cs4245_write(chip, CS4245_ADC_CTRL, 97 data->cs4245_regs[CS4245_ADC_CTRL]); 98 cs4245_write(chip, CS4245_SIGNAL_SEL, 99 data->cs4245_regs[CS4245_SIGNAL_SEL]); 100 cs4245_write(chip, CS4245_PGA_B_CTRL, 101 data->cs4245_regs[CS4245_PGA_B_CTRL]); 102 cs4245_write(chip, CS4245_PGA_A_CTRL, 103 data->cs4245_regs[CS4245_PGA_A_CTRL]); 104 cs4245_write(chip, CS4245_ANALOG_IN, 105 data->cs4245_regs[CS4245_ANALOG_IN]); 106 cs4245_write(chip, CS4245_DAC_A_CTRL, 107 data->cs4245_regs[CS4245_DAC_A_CTRL]); 108 cs4245_write(chip, CS4245_DAC_B_CTRL, 109 data->cs4245_regs[CS4245_DAC_B_CTRL]); 110 cs4245_write(chip, CS4245_DAC_CTRL_2, 111 CS4245_DAC_SOFT | CS4245_DAC_ZERO | CS4245_INVERT_DAC); 112 cs4245_write(chip, CS4245_INT_MASK, 0); 113 cs4245_write(chip, CS4245_POWER_CTRL, 0); 114 } 115 116 static void cs4245_init(struct oxygen *chip) 117 { 118 struct dg *data = chip->model_data; 119 120 data->cs4245_regs[CS4245_DAC_CTRL_1] = 121 CS4245_DAC_FM_SINGLE | CS4245_DAC_DIF_LJUST; 122 data->cs4245_regs[CS4245_ADC_CTRL] = 123 CS4245_ADC_FM_SINGLE | CS4245_ADC_DIF_LJUST; 124 data->cs4245_regs[CS4245_SIGNAL_SEL] = 125 CS4245_A_OUT_SEL_HIZ | CS4245_ASYNCH; 126 data->cs4245_regs[CS4245_PGA_B_CTRL] = 0; 127 data->cs4245_regs[CS4245_PGA_A_CTRL] = 0; 128 data->cs4245_regs[CS4245_ANALOG_IN] = 129 CS4245_PGA_SOFT | CS4245_PGA_ZERO | CS4245_SEL_INPUT_4; 130 data->cs4245_regs[CS4245_DAC_A_CTRL] = 0; 131 data->cs4245_regs[CS4245_DAC_B_CTRL] = 0; 132 cs4245_registers_init(chip); 133 snd_component_add(chip->card, "CS4245"); 134 } 135 136 static void dg_output_enable(struct oxygen *chip) 137 { 138 msleep(2500); 139 oxygen_set_bits16(chip, OXYGEN_GPIO_DATA, GPIO_OUTPUT_ENABLE); 140 } 141 142 static void dg_init(struct oxygen *chip) 143 { 144 struct dg *data = chip->model_data; 145 146 data->output_sel = 0; 147 data->input_sel = 3; 148 data->hp_vol_att = 2 * 16; 149 150 cs4245_init(chip); 151 152 oxygen_clear_bits16(chip, OXYGEN_GPIO_CONTROL, 153 GPIO_MAGIC | GPIO_HP_DETECT); 154 oxygen_set_bits16(chip, OXYGEN_GPIO_CONTROL, 155 GPIO_INPUT_ROUTE | GPIO_HP_REAR | GPIO_OUTPUT_ENABLE); 156 oxygen_clear_bits16(chip, OXYGEN_GPIO_DATA, 157 GPIO_INPUT_ROUTE | GPIO_HP_REAR); 158 dg_output_enable(chip); 159 } 160 161 static void dg_cleanup(struct oxygen *chip) 162 { 163 oxygen_clear_bits16(chip, OXYGEN_GPIO_DATA, GPIO_OUTPUT_ENABLE); 164 } 165 166 static void dg_suspend(struct oxygen *chip) 167 { 168 dg_cleanup(chip); 169 } 170 171 static void dg_resume(struct oxygen *chip) 172 { 173 cs4245_registers_init(chip); 174 dg_output_enable(chip); 175 } 176 177 static void set_cs4245_dac_params(struct oxygen *chip, 178 struct snd_pcm_hw_params *params) 179 { 180 struct dg *data = chip->model_data; 181 u8 value; 182 183 value = data->cs4245_regs[CS4245_DAC_CTRL_1] & ~CS4245_DAC_FM_MASK; 184 if (params_rate(params) <= 50000) 185 value |= CS4245_DAC_FM_SINGLE; 186 else if (params_rate(params) <= 100000) 187 value |= CS4245_DAC_FM_DOUBLE; 188 else 189 value |= CS4245_DAC_FM_QUAD; 190 cs4245_write_cached(chip, CS4245_DAC_CTRL_1, value); 191 } 192 193 static void set_cs4245_adc_params(struct oxygen *chip, 194 struct snd_pcm_hw_params *params) 195 { 196 struct dg *data = chip->model_data; 197 u8 value; 198 199 value = data->cs4245_regs[CS4245_ADC_CTRL] & ~CS4245_ADC_FM_MASK; 200 if (params_rate(params) <= 50000) 201 value |= CS4245_ADC_FM_SINGLE; 202 else if (params_rate(params) <= 100000) 203 value |= CS4245_ADC_FM_DOUBLE; 204 else 205 value |= CS4245_ADC_FM_QUAD; 206 cs4245_write_cached(chip, CS4245_ADC_CTRL, value); 207 } 208 209 static int output_switch_info(struct snd_kcontrol *ctl, 210 struct snd_ctl_elem_info *info) 211 { 212 static const char *const names[3] = { 213 "Speakers", "Headphones", "FP Headphones" 214 }; 215 216 info->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; 217 info->count = 1; 218 info->value.enumerated.items = 3; 219 if (info->value.enumerated.item >= 3) 220 info->value.enumerated.item = 2; 221 strcpy(info->value.enumerated.name, names[info->value.enumerated.item]); 222 return 0; 223 } 224 225 static int output_switch_get(struct snd_kcontrol *ctl, 226 struct snd_ctl_elem_value *value) 227 { 228 struct oxygen *chip = ctl->private_data; 229 struct dg *data = chip->model_data; 230 231 mutex_lock(&chip->mutex); 232 value->value.enumerated.item[0] = data->output_sel; 233 mutex_unlock(&chip->mutex); 234 return 0; 235 } 236 237 static int output_switch_put(struct snd_kcontrol *ctl, 238 struct snd_ctl_elem_value *value) 239 { 240 struct oxygen *chip = ctl->private_data; 241 struct dg *data = chip->model_data; 242 u8 reg; 243 int changed; 244 245 if (value->value.enumerated.item[0] > 2) 246 return -EINVAL; 247 248 mutex_lock(&chip->mutex); 249 changed = value->value.enumerated.item[0] != data->output_sel; 250 if (changed) { 251 data->output_sel = value->value.enumerated.item[0]; 252 253 reg = data->cs4245_regs[CS4245_SIGNAL_SEL] & 254 ~CS4245_A_OUT_SEL_MASK; 255 reg |= data->output_sel == 2 ? 256 CS4245_A_OUT_SEL_DAC : CS4245_A_OUT_SEL_HIZ; 257 cs4245_write_cached(chip, CS4245_SIGNAL_SEL, reg); 258 259 cs4245_write_cached(chip, CS4245_DAC_A_CTRL, 260 data->output_sel ? data->hp_vol_att : 0); 261 cs4245_write_cached(chip, CS4245_DAC_B_CTRL, 262 data->output_sel ? data->hp_vol_att : 0); 263 264 oxygen_write16_masked(chip, OXYGEN_GPIO_DATA, 265 data->output_sel == 1 ? GPIO_HP_REAR : 0, 266 GPIO_HP_REAR); 267 } 268 mutex_unlock(&chip->mutex); 269 return changed; 270 } 271 272 static int hp_volume_offset_info(struct snd_kcontrol *ctl, 273 struct snd_ctl_elem_info *info) 274 { 275 static const char *const names[3] = { 276 "< 64 ohms", "64-150 ohms", "150-300 ohms" 277 }; 278 279 info->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; 280 info->count = 1; 281 info->value.enumerated.items = 3; 282 if (info->value.enumerated.item >= 3) 283 info->value.enumerated.item = 2; 284 strcpy(info->value.enumerated.name, names[info->value.enumerated.item]); 285 return 0; 286 } 287 288 static int hp_volume_offset_get(struct snd_kcontrol *ctl, 289 struct snd_ctl_elem_value *value) 290 { 291 struct oxygen *chip = ctl->private_data; 292 struct dg *data = chip->model_data; 293 294 mutex_lock(&chip->mutex); 295 if (data->hp_vol_att > 2 * 7) 296 value->value.enumerated.item[0] = 0; 297 else if (data->hp_vol_att > 0) 298 value->value.enumerated.item[0] = 1; 299 else 300 value->value.enumerated.item[0] = 2; 301 mutex_unlock(&chip->mutex); 302 return 0; 303 } 304 305 static int hp_volume_offset_put(struct snd_kcontrol *ctl, 306 struct snd_ctl_elem_value *value) 307 { 308 static const s8 atts[3] = { 2 * 16, 2 * 7, 0 }; 309 struct oxygen *chip = ctl->private_data; 310 struct dg *data = chip->model_data; 311 s8 att; 312 int changed; 313 314 if (value->value.enumerated.item[0] > 2) 315 return -EINVAL; 316 att = atts[value->value.enumerated.item[0]]; 317 mutex_lock(&chip->mutex); 318 changed = att != data->hp_vol_att; 319 if (changed) { 320 data->hp_vol_att = att; 321 if (data->output_sel) { 322 cs4245_write_cached(chip, CS4245_DAC_A_CTRL, att); 323 cs4245_write_cached(chip, CS4245_DAC_B_CTRL, att); 324 } 325 } 326 mutex_unlock(&chip->mutex); 327 return changed; 328 } 329 330 static int input_vol_info(struct snd_kcontrol *ctl, 331 struct snd_ctl_elem_info *info) 332 { 333 info->type = SNDRV_CTL_ELEM_TYPE_INTEGER; 334 info->count = 2; 335 info->value.integer.min = 2 * -12; 336 info->value.integer.max = 2 * 12; 337 return 0; 338 } 339 340 static int input_vol_get(struct snd_kcontrol *ctl, 341 struct snd_ctl_elem_value *value) 342 { 343 struct oxygen *chip = ctl->private_data; 344 struct dg *data = chip->model_data; 345 unsigned int idx = ctl->private_value; 346 347 mutex_lock(&chip->mutex); 348 value->value.integer.value[0] = data->input_vol[idx][0]; 349 value->value.integer.value[1] = data->input_vol[idx][1]; 350 mutex_unlock(&chip->mutex); 351 return 0; 352 } 353 354 static int input_vol_put(struct snd_kcontrol *ctl, 355 struct snd_ctl_elem_value *value) 356 { 357 struct oxygen *chip = ctl->private_data; 358 struct dg *data = chip->model_data; 359 unsigned int idx = ctl->private_value; 360 int changed = 0; 361 362 if (value->value.integer.value[0] < 2 * -12 || 363 value->value.integer.value[0] > 2 * 12 || 364 value->value.integer.value[1] < 2 * -12 || 365 value->value.integer.value[1] > 2 * 12) 366 return -EINVAL; 367 mutex_lock(&chip->mutex); 368 changed = data->input_vol[idx][0] != value->value.integer.value[0] || 369 data->input_vol[idx][1] != value->value.integer.value[1]; 370 if (changed) { 371 data->input_vol[idx][0] = value->value.integer.value[0]; 372 data->input_vol[idx][1] = value->value.integer.value[1]; 373 if (idx == data->input_sel) { 374 cs4245_write_cached(chip, CS4245_PGA_A_CTRL, 375 data->input_vol[idx][0]); 376 cs4245_write_cached(chip, CS4245_PGA_B_CTRL, 377 data->input_vol[idx][1]); 378 } 379 } 380 mutex_unlock(&chip->mutex); 381 return changed; 382 } 383 384 static DECLARE_TLV_DB_SCALE(cs4245_pga_db_scale, -1200, 50, 0); 385 386 static int input_sel_info(struct snd_kcontrol *ctl, 387 struct snd_ctl_elem_info *info) 388 { 389 static const char *const names[4] = { 390 "Mic", "Aux", "Front Mic", "Line" 391 }; 392 393 info->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; 394 info->count = 1; 395 info->value.enumerated.items = 4; 396 info->value.enumerated.item &= 3; 397 strcpy(info->value.enumerated.name, names[info->value.enumerated.item]); 398 return 0; 399 } 400 401 static int input_sel_get(struct snd_kcontrol *ctl, 402 struct snd_ctl_elem_value *value) 403 { 404 struct oxygen *chip = ctl->private_data; 405 struct dg *data = chip->model_data; 406 407 mutex_lock(&chip->mutex); 408 value->value.enumerated.item[0] = data->input_sel; 409 mutex_unlock(&chip->mutex); 410 return 0; 411 } 412 413 static int input_sel_put(struct snd_kcontrol *ctl, 414 struct snd_ctl_elem_value *value) 415 { 416 static const u8 sel_values[4] = { 417 CS4245_SEL_MIC, 418 CS4245_SEL_INPUT_1, 419 CS4245_SEL_INPUT_2, 420 CS4245_SEL_INPUT_4 421 }; 422 struct oxygen *chip = ctl->private_data; 423 struct dg *data = chip->model_data; 424 int changed; 425 426 if (value->value.enumerated.item[0] > 3) 427 return -EINVAL; 428 429 mutex_lock(&chip->mutex); 430 changed = value->value.enumerated.item[0] != data->input_sel; 431 if (changed) { 432 data->input_sel = value->value.enumerated.item[0]; 433 434 cs4245_write(chip, CS4245_ANALOG_IN, 435 (data->cs4245_regs[CS4245_ANALOG_IN] & 436 ~CS4245_SEL_MASK) | 437 sel_values[data->input_sel]); 438 439 cs4245_write_cached(chip, CS4245_PGA_A_CTRL, 440 data->input_vol[data->input_sel][0]); 441 cs4245_write_cached(chip, CS4245_PGA_B_CTRL, 442 data->input_vol[data->input_sel][1]); 443 444 oxygen_write16_masked(chip, OXYGEN_GPIO_DATA, 445 data->input_sel ? 0 : GPIO_INPUT_ROUTE, 446 GPIO_INPUT_ROUTE); 447 } 448 mutex_unlock(&chip->mutex); 449 return changed; 450 } 451 452 static int hpf_info(struct snd_kcontrol *ctl, struct snd_ctl_elem_info *info) 453 { 454 static const char *const names[2] = { "Active", "Frozen" }; 455 456 info->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; 457 info->count = 1; 458 info->value.enumerated.items = 2; 459 info->value.enumerated.item &= 1; 460 strcpy(info->value.enumerated.name, names[info->value.enumerated.item]); 461 return 0; 462 } 463 464 static int hpf_get(struct snd_kcontrol *ctl, struct snd_ctl_elem_value *value) 465 { 466 struct oxygen *chip = ctl->private_data; 467 struct dg *data = chip->model_data; 468 469 value->value.enumerated.item[0] = 470 !!(data->cs4245_regs[CS4245_ADC_CTRL] & CS4245_HPF_FREEZE); 471 return 0; 472 } 473 474 static int hpf_put(struct snd_kcontrol *ctl, struct snd_ctl_elem_value *value) 475 { 476 struct oxygen *chip = ctl->private_data; 477 struct dg *data = chip->model_data; 478 u8 reg; 479 int changed; 480 481 mutex_lock(&chip->mutex); 482 reg = data->cs4245_regs[CS4245_ADC_CTRL] & ~CS4245_HPF_FREEZE; 483 if (value->value.enumerated.item[0]) 484 reg |= CS4245_HPF_FREEZE; 485 changed = reg != data->cs4245_regs[CS4245_ADC_CTRL]; 486 if (changed) 487 cs4245_write(chip, CS4245_ADC_CTRL, reg); 488 mutex_unlock(&chip->mutex); 489 return changed; 490 } 491 492 #define INPUT_VOLUME(xname, index) { \ 493 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ 494 .name = xname, \ 495 .info = input_vol_info, \ 496 .get = input_vol_get, \ 497 .put = input_vol_put, \ 498 .tlv = { .p = cs4245_pga_db_scale }, \ 499 .private_value = index, \ 500 } 501 static const struct snd_kcontrol_new dg_controls[] = { 502 { 503 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 504 .name = "Analog Output Playback Enum", 505 .info = output_switch_info, 506 .get = output_switch_get, 507 .put = output_switch_put, 508 }, 509 { 510 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 511 .name = "Headphones Impedance Playback Enum", 512 .info = hp_volume_offset_info, 513 .get = hp_volume_offset_get, 514 .put = hp_volume_offset_put, 515 }, 516 INPUT_VOLUME("Mic Capture Volume", 0), 517 INPUT_VOLUME("Aux Capture Volume", 1), 518 INPUT_VOLUME("Front Mic Capture Volume", 2), 519 INPUT_VOLUME("Line Capture Volume", 3), 520 { 521 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 522 .name = "Capture Source", 523 .info = input_sel_info, 524 .get = input_sel_get, 525 .put = input_sel_put, 526 }, 527 { 528 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 529 .name = "ADC High-pass Filter Capture Enum", 530 .info = hpf_info, 531 .get = hpf_get, 532 .put = hpf_put, 533 }, 534 }; 535 536 static int dg_control_filter(struct snd_kcontrol_new *template) 537 { 538 if (!strncmp(template->name, "Master Playback ", 16)) 539 return 1; 540 return 0; 541 } 542 543 static int dg_mixer_init(struct oxygen *chip) 544 { 545 unsigned int i; 546 int err; 547 548 for (i = 0; i < ARRAY_SIZE(dg_controls); ++i) { 549 err = snd_ctl_add(chip->card, 550 snd_ctl_new1(&dg_controls[i], chip)); 551 if (err < 0) 552 return err; 553 } 554 return 0; 555 } 556 557 static void dump_cs4245_registers(struct oxygen *chip, 558 struct snd_info_buffer *buffer) 559 { 560 struct dg *data = chip->model_data; 561 unsigned int i; 562 563 snd_iprintf(buffer, "\nCS4245:"); 564 for (i = 1; i <= 0x10; ++i) 565 snd_iprintf(buffer, " %02x", data->cs4245_regs[i]); 566 snd_iprintf(buffer, "\n"); 567 } 568 569 struct oxygen_model model_xonar_dg = { 570 .shortname = "Xonar DG", 571 .longname = "C-Media Oxygen HD Audio", 572 .chip = "CMI8786", 573 .init = dg_init, 574 .control_filter = dg_control_filter, 575 .mixer_init = dg_mixer_init, 576 .cleanup = dg_cleanup, 577 .suspend = dg_suspend, 578 .resume = dg_resume, 579 .set_dac_params = set_cs4245_dac_params, 580 .set_adc_params = set_cs4245_adc_params, 581 .dump_registers = dump_cs4245_registers, 582 .model_data_size = sizeof(struct dg), 583 .device_config = PLAYBACK_0_TO_I2S | 584 PLAYBACK_1_TO_SPDIF | 585 CAPTURE_0_FROM_I2S_1, 586 .dac_channels_pcm = 6, 587 .dac_channels_mixer = 0, 588 .function_flags = OXYGEN_FUNCTION_SPI, 589 .dac_mclks = OXYGEN_MCLKS(256, 128, 128), 590 .adc_mclks = OXYGEN_MCLKS(256, 128, 128), 591 .dac_i2s_format = OXYGEN_I2S_FORMAT_LJUST, 592 .adc_i2s_format = OXYGEN_I2S_FORMAT_LJUST, 593 }; 594