diff options
| -rw-r--r-- | sound/pci/oxygen/cs2000.h | 83 | ||||
| -rw-r--r-- | sound/pci/oxygen/xonar_pcm179x.c | 113 |
2 files changed, 190 insertions, 6 deletions
diff --git a/sound/pci/oxygen/cs2000.h b/sound/pci/oxygen/cs2000.h new file mode 100644 index 000000000000..c3501bdb5edc --- /dev/null +++ b/sound/pci/oxygen/cs2000.h | |||
| @@ -0,0 +1,83 @@ | |||
| 1 | #ifndef CS2000_H_INCLUDED | ||
| 2 | #define CS2000_H_INCLUDED | ||
| 3 | |||
| 4 | #define CS2000_DEV_ID 0x01 | ||
| 5 | #define CS2000_DEV_CTRL 0x02 | ||
| 6 | #define CS2000_DEV_CFG_1 0x03 | ||
| 7 | #define CS2000_DEV_CFG_2 0x04 | ||
| 8 | #define CS2000_GLOBAL_CFG 0x05 | ||
| 9 | #define CS2000_RATIO_0 0x06 /* 32 bits, big endian */ | ||
| 10 | #define CS2000_RATIO_1 0x0a | ||
| 11 | #define CS2000_RATIO_2 0x0e | ||
| 12 | #define CS2000_RATIO_3 0x12 | ||
| 13 | #define CS2000_FUN_CFG_1 0x16 | ||
| 14 | #define CS2000_FUN_CFG_2 0x17 | ||
| 15 | #define CS2000_FUN_CFG_3 0x1e | ||
| 16 | |||
| 17 | /* DEV_ID */ | ||
| 18 | #define CS2000_DEVICE_MASK 0xf8 | ||
| 19 | #define CS2000_REVISION_MASK 0x07 | ||
| 20 | |||
| 21 | /* DEV_CTRL */ | ||
| 22 | #define CS2000_UNLOCK 0x80 | ||
| 23 | #define CS2000_AUX_OUT_DIS 0x02 | ||
| 24 | #define CS2000_CLK_OUT_DIS 0x01 | ||
| 25 | |||
| 26 | /* DEV_CFG_1 */ | ||
| 27 | #define CS2000_R_MOD_SEL_MASK 0xe0 | ||
| 28 | #define CS2000_R_MOD_SEL_1 0x00 | ||
| 29 | #define CS2000_R_MOD_SEL_2 0x20 | ||
| 30 | #define CS2000_R_MOD_SEL_4 0x40 | ||
| 31 | #define CS2000_R_MOD_SEL_8 0x60 | ||
| 32 | #define CS2000_R_MOD_SEL_1_2 0x80 | ||
| 33 | #define CS2000_R_MOD_SEL_1_4 0xa0 | ||
| 34 | #define CS2000_R_MOD_SEL_1_8 0xc0 | ||
| 35 | #define CS2000_R_MOD_SEL_1_16 0xe0 | ||
| 36 | #define CS2000_R_SEL_MASK 0x18 | ||
| 37 | #define CS2000_R_SEL_SHIFT 3 | ||
| 38 | #define CS2000_AUX_OUT_SRC_MASK 0x06 | ||
| 39 | #define CS2000_AUX_OUT_SRC_REF_CLK 0x00 | ||
| 40 | #define CS2000_AUX_OUT_SRC_CLK_IN 0x02 | ||
| 41 | #define CS2000_AUX_OUT_SRC_CLK_OUT 0x04 | ||
| 42 | #define CS2000_AUX_OUT_SRC_PLL_LOCK 0x06 | ||
| 43 | #define CS2000_EN_DEV_CFG_1 0x01 | ||
| 44 | |||
| 45 | /* DEV_CFG_2 */ | ||
| 46 | #define CS2000_LOCK_CLK_MASK 0x06 | ||
| 47 | #define CS2000_LOCK_CLK_SHIFT 1 | ||
| 48 | #define CS2000_FRAC_N_SRC_MASK 0x01 | ||
| 49 | #define CS2000_FRAC_N_SRC_STATIC 0x00 | ||
| 50 | #define CS2000_FRAC_N_SRC_DYNAMIC 0x01 | ||
| 51 | |||
| 52 | /* GLOBAL_CFG */ | ||
| 53 | #define CS2000_FREEZE 0x08 | ||
| 54 | #define CS2000_EN_DEV_CFG_2 0x01 | ||
| 55 | |||
| 56 | /* FUN_CFG_1 */ | ||
| 57 | #define CS2000_CLK_SKIP_EN 0x80 | ||
| 58 | #define CS2000_AUX_LOCK_CFG_MASK 0x40 | ||
| 59 | #define CS2000_AUX_LOCK_CFG_PP_HIGH 0x00 | ||
| 60 | #define CS2000_AUX_LOCK_CFG_OD_LOW 0x40 | ||
| 61 | #define CS2000_REF_CLK_DIV_MASK 0x18 | ||
| 62 | #define CS2000_REF_CLK_DIV_4 0x00 | ||
| 63 | #define CS2000_REF_CLK_DIV_2 0x08 | ||
| 64 | #define CS2000_REF_CLK_DIV_1 0x10 | ||
| 65 | |||
| 66 | /* FUN_CFG_2 */ | ||
| 67 | #define CS2000_CLK_OUT_UNL 0x10 | ||
| 68 | #define CS2000_L_F_RATIO_CFG_MASK 0x08 | ||
| 69 | #define CS2000_L_F_RATIO_CFG_20_12 0x00 | ||
| 70 | #define CS2000_L_F_RATIO_CFG_12_20 0x08 | ||
| 71 | |||
| 72 | /* FUN_CFG_3 */ | ||
| 73 | #define CS2000_CLK_IN_BW_MASK 0x70 | ||
| 74 | #define CS2000_CLK_IN_BW_1 0x00 | ||
| 75 | #define CS2000_CLK_IN_BW_2 0x10 | ||
| 76 | #define CS2000_CLK_IN_BW_4 0x20 | ||
| 77 | #define CS2000_CLK_IN_BW_8 0x30 | ||
| 78 | #define CS2000_CLK_IN_BW_16 0x40 | ||
| 79 | #define CS2000_CLK_IN_BW_32 0x50 | ||
| 80 | #define CS2000_CLK_IN_BW_64 0x60 | ||
| 81 | #define CS2000_CLK_IN_BW_128 0x70 | ||
| 82 | |||
| 83 | #endif | ||
diff --git a/sound/pci/oxygen/xonar_pcm179x.c b/sound/pci/oxygen/xonar_pcm179x.c index eb5f015fcd23..522efde0d52e 100644 --- a/sound/pci/oxygen/xonar_pcm179x.c +++ b/sound/pci/oxygen/xonar_pcm179x.c | |||
| @@ -91,6 +91,9 @@ | |||
| 91 | * CMI8788: | 91 | * CMI8788: |
| 92 | * | 92 | * |
| 93 | * I²C <-> PCM1792A | 93 | * I²C <-> PCM1792A |
| 94 | * <-> CS2000 (ST only) | ||
| 95 | * | ||
| 96 | * ADC1 MCLK -> REF_CLK of CS2000 (ST only) | ||
| 94 | * | 97 | * |
| 95 | * GPI 0 <- external power present (STX only) | 98 | * GPI 0 <- external power present (STX only) |
| 96 | * | 99 | * |
| @@ -124,6 +127,7 @@ | |||
| 124 | #include "xonar.h" | 127 | #include "xonar.h" |
| 125 | #include "cm9780.h" | 128 | #include "cm9780.h" |
| 126 | #include "pcm1796.h" | 129 | #include "pcm1796.h" |
| 130 | #include "cs2000.h" | ||
| 127 | 131 | ||
| 128 | 132 | ||
| 129 | #define GPIO_D2X_EXT_POWER 0x0020 | 133 | #define GPIO_D2X_EXT_POWER 0x0020 |
| @@ -143,12 +147,14 @@ | |||
| 143 | #define GPIO_ST_HP 0x0080 | 147 | #define GPIO_ST_HP 0x0080 |
| 144 | 148 | ||
| 145 | #define I2C_DEVICE_PCM1796(i) (0x98 + ((i) << 1)) /* 10011, ii, /W=0 */ | 149 | #define I2C_DEVICE_PCM1796(i) (0x98 + ((i) << 1)) /* 10011, ii, /W=0 */ |
| 150 | #define I2C_DEVICE_CS2000 0x9c /* 100111, 0, /W=0 */ | ||
| 146 | 151 | ||
| 147 | 152 | ||
| 148 | struct xonar_pcm179x { | 153 | struct xonar_pcm179x { |
| 149 | struct xonar_generic generic; | 154 | struct xonar_generic generic; |
| 150 | unsigned int dacs; | 155 | unsigned int dacs; |
| 151 | u8 oversampling; | 156 | u8 oversampling; |
| 157 | u8 cs2000_fun_cfg_1; | ||
| 152 | }; | 158 | }; |
| 153 | 159 | ||
| 154 | struct xonar_hdav { | 160 | struct xonar_hdav { |
| @@ -188,6 +194,11 @@ static void pcm1796_write(struct oxygen *chip, unsigned int codec, | |||
| 188 | pcm1796_write_i2c(chip, codec, reg, value); | 194 | pcm1796_write_i2c(chip, codec, reg, value); |
| 189 | } | 195 | } |
| 190 | 196 | ||
| 197 | static void cs2000_write(struct oxygen *chip, u8 reg, u8 value) | ||
| 198 | { | ||
| 199 | oxygen_write_i2c(chip, I2C_DEVICE_CS2000, reg, value); | ||
| 200 | } | ||
| 201 | |||
| 191 | static void update_pcm1796_volume(struct oxygen *chip) | 202 | static void update_pcm1796_volume(struct oxygen *chip) |
| 192 | { | 203 | { |
| 193 | struct xonar_pcm179x *data = chip->model_data; | 204 | struct xonar_pcm179x *data = chip->model_data; |
| @@ -292,14 +303,17 @@ static void xonar_hdav_init(struct oxygen *chip) | |||
| 292 | snd_component_add(chip->card, "CS5381"); | 303 | snd_component_add(chip->card, "CS5381"); |
| 293 | } | 304 | } |
| 294 | 305 | ||
| 295 | static void xonar_st_init(struct oxygen *chip) | 306 | static void xonar_st_init_i2c(struct oxygen *chip) |
| 296 | { | 307 | { |
| 297 | struct xonar_pcm179x *data = chip->model_data; | ||
| 298 | |||
| 299 | oxygen_write16(chip, OXYGEN_2WIRE_BUS_STATUS, | 308 | oxygen_write16(chip, OXYGEN_2WIRE_BUS_STATUS, |
| 300 | OXYGEN_2WIRE_LENGTH_8 | | 309 | OXYGEN_2WIRE_LENGTH_8 | |
| 301 | OXYGEN_2WIRE_INTERRUPT_MASK | | 310 | OXYGEN_2WIRE_INTERRUPT_MASK | |
| 302 | OXYGEN_2WIRE_SPEED_FAST); | 311 | OXYGEN_2WIRE_SPEED_FAST); |
| 312 | } | ||
| 313 | |||
| 314 | static void xonar_st_init_common(struct oxygen *chip) | ||
| 315 | { | ||
| 316 | struct xonar_pcm179x *data = chip->model_data; | ||
| 303 | 317 | ||
| 304 | data->generic.anti_pop_delay = 100; | 318 | data->generic.anti_pop_delay = 100; |
| 305 | data->generic.output_enable_bit = GPIO_ST_OUTPUT_ENABLE; | 319 | data->generic.output_enable_bit = GPIO_ST_OUTPUT_ENABLE; |
| @@ -320,15 +334,57 @@ static void xonar_st_init(struct oxygen *chip) | |||
| 320 | snd_component_add(chip->card, "CS5381"); | 334 | snd_component_add(chip->card, "CS5381"); |
| 321 | } | 335 | } |
| 322 | 336 | ||
| 337 | static void cs2000_registers_init(struct oxygen *chip) | ||
| 338 | { | ||
| 339 | struct xonar_pcm179x *data = chip->model_data; | ||
| 340 | |||
| 341 | cs2000_write(chip, CS2000_GLOBAL_CFG, CS2000_FREEZE); | ||
| 342 | cs2000_write(chip, CS2000_DEV_CTRL, 0); | ||
| 343 | cs2000_write(chip, CS2000_DEV_CFG_1, | ||
| 344 | CS2000_R_MOD_SEL_1 | | ||
| 345 | (0 << CS2000_R_SEL_SHIFT) | | ||
| 346 | CS2000_AUX_OUT_SRC_REF_CLK | | ||
| 347 | CS2000_EN_DEV_CFG_1); | ||
| 348 | cs2000_write(chip, CS2000_DEV_CFG_2, | ||
| 349 | (0 << CS2000_LOCK_CLK_SHIFT) | | ||
| 350 | CS2000_FRAC_N_SRC_STATIC); | ||
| 351 | cs2000_write(chip, CS2000_RATIO_0 + 0, 0x00); /* 1.0 */ | ||
| 352 | cs2000_write(chip, CS2000_RATIO_0 + 1, 0x10); | ||
| 353 | cs2000_write(chip, CS2000_RATIO_0 + 2, 0x00); | ||
| 354 | cs2000_write(chip, CS2000_RATIO_0 + 3, 0x00); | ||
| 355 | cs2000_write(chip, CS2000_FUN_CFG_1, data->cs2000_fun_cfg_1); | ||
| 356 | cs2000_write(chip, CS2000_FUN_CFG_2, 0); | ||
| 357 | cs2000_write(chip, CS2000_GLOBAL_CFG, CS2000_EN_DEV_CFG_2); | ||
| 358 | } | ||
| 359 | |||
| 360 | static void xonar_st_init(struct oxygen *chip) | ||
| 361 | { | ||
| 362 | struct xonar_pcm179x *data = chip->model_data; | ||
| 363 | |||
| 364 | data->cs2000_fun_cfg_1 = CS2000_REF_CLK_DIV_1; | ||
| 365 | |||
| 366 | oxygen_write16(chip, OXYGEN_I2S_A_FORMAT, | ||
| 367 | OXYGEN_RATE_48000 | OXYGEN_I2S_FORMAT_I2S | | ||
| 368 | OXYGEN_I2S_MCLK_128 | OXYGEN_I2S_BITS_16 | | ||
| 369 | OXYGEN_I2S_MASTER | OXYGEN_I2S_BCLK_64); | ||
| 370 | |||
| 371 | xonar_st_init_i2c(chip); | ||
| 372 | cs2000_registers_init(chip); | ||
| 373 | xonar_st_init_common(chip); | ||
| 374 | |||
| 375 | snd_component_add(chip->card, "CS2000"); | ||
| 376 | } | ||
| 377 | |||
| 323 | static void xonar_stx_init(struct oxygen *chip) | 378 | static void xonar_stx_init(struct oxygen *chip) |
| 324 | { | 379 | { |
| 325 | struct xonar_pcm179x *data = chip->model_data; | 380 | struct xonar_pcm179x *data = chip->model_data; |
| 326 | 381 | ||
| 382 | xonar_st_init_i2c(chip); | ||
| 327 | data->generic.ext_power_reg = OXYGEN_GPI_DATA; | 383 | data->generic.ext_power_reg = OXYGEN_GPI_DATA; |
| 328 | data->generic.ext_power_int_reg = OXYGEN_GPI_INTERRUPT_MASK; | 384 | data->generic.ext_power_int_reg = OXYGEN_GPI_INTERRUPT_MASK; |
| 329 | data->generic.ext_power_bit = GPI_EXT_POWER; | 385 | data->generic.ext_power_bit = GPI_EXT_POWER; |
| 330 | xonar_init_ext_power(chip); | 386 | xonar_init_ext_power(chip); |
| 331 | xonar_st_init(chip); | 387 | xonar_st_init_common(chip); |
| 332 | } | 388 | } |
| 333 | 389 | ||
| 334 | static void xonar_d2_cleanup(struct oxygen *chip) | 390 | static void xonar_d2_cleanup(struct oxygen *chip) |
| @@ -378,12 +434,18 @@ static void xonar_hdav_resume(struct oxygen *chip) | |||
| 378 | xonar_enable_output(chip); | 434 | xonar_enable_output(chip); |
| 379 | } | 435 | } |
| 380 | 436 | ||
| 381 | static void xonar_st_resume(struct oxygen *chip) | 437 | static void xonar_stx_resume(struct oxygen *chip) |
| 382 | { | 438 | { |
| 383 | pcm1796_init(chip); | 439 | pcm1796_init(chip); |
| 384 | xonar_enable_output(chip); | 440 | xonar_enable_output(chip); |
| 385 | } | 441 | } |
| 386 | 442 | ||
| 443 | static void xonar_st_resume(struct oxygen *chip) | ||
| 444 | { | ||
| 445 | cs2000_registers_init(chip); | ||
| 446 | xonar_stx_resume(chip); | ||
| 447 | } | ||
| 448 | |||
| 387 | static void set_pcm1796_params(struct oxygen *chip, | 449 | static void set_pcm1796_params(struct oxygen *chip, |
| 388 | struct snd_pcm_hw_params *params) | 450 | struct snd_pcm_hw_params *params) |
| 389 | { | 451 | { |
| @@ -396,6 +458,43 @@ static void set_pcm1796_params(struct oxygen *chip, | |||
| 396 | pcm1796_write(chip, i, 20, data->oversampling); | 458 | pcm1796_write(chip, i, 20, data->oversampling); |
| 397 | } | 459 | } |
| 398 | 460 | ||
| 461 | static void set_cs2000_params(struct oxygen *chip, | ||
| 462 | struct snd_pcm_hw_params *params) | ||
| 463 | { | ||
| 464 | /* XXX Why is the I2S A MCLK half the actual I2S multich MCLK? */ | ||
| 465 | static const u8 rate_mclks[] = { | ||
| 466 | [OXYGEN_RATE_32000] = OXYGEN_RATE_32000 | OXYGEN_I2S_MCLK_128, | ||
| 467 | [OXYGEN_RATE_44100] = OXYGEN_RATE_44100 | OXYGEN_I2S_MCLK_128, | ||
| 468 | [OXYGEN_RATE_48000] = OXYGEN_RATE_48000 | OXYGEN_I2S_MCLK_128, | ||
| 469 | [OXYGEN_RATE_64000] = OXYGEN_RATE_32000 | OXYGEN_I2S_MCLK_256, | ||
| 470 | [OXYGEN_RATE_88200] = OXYGEN_RATE_44100 | OXYGEN_I2S_MCLK_256, | ||
| 471 | [OXYGEN_RATE_96000] = OXYGEN_RATE_48000 | OXYGEN_I2S_MCLK_256, | ||
| 472 | [OXYGEN_RATE_176400] = OXYGEN_RATE_44100 | OXYGEN_I2S_MCLK_256, | ||
| 473 | [OXYGEN_RATE_192000] = OXYGEN_RATE_48000 | OXYGEN_I2S_MCLK_256, | ||
| 474 | }; | ||
| 475 | struct xonar_pcm179x *data = chip->model_data; | ||
| 476 | unsigned int rate_index; | ||
| 477 | u8 rate_mclk; | ||
| 478 | |||
| 479 | rate_index = oxygen_read16(chip, OXYGEN_I2S_MULTICH_FORMAT) | ||
| 480 | & OXYGEN_I2S_RATE_MASK; | ||
| 481 | rate_mclk = rate_mclks[rate_index]; | ||
| 482 | oxygen_write16_masked(chip, OXYGEN_I2S_A_FORMAT, rate_mclk, | ||
| 483 | OXYGEN_I2S_RATE_MASK | OXYGEN_I2S_MCLK_MASK); | ||
| 484 | if ((rate_mclk & OXYGEN_I2S_MCLK_MASK) <= OXYGEN_I2S_MCLK_128) | ||
| 485 | data->cs2000_fun_cfg_1 = CS2000_REF_CLK_DIV_1; | ||
| 486 | else | ||
| 487 | data->cs2000_fun_cfg_1 = CS2000_REF_CLK_DIV_2; | ||
| 488 | cs2000_write(chip, CS2000_FUN_CFG_1, data->cs2000_fun_cfg_1); | ||
| 489 | } | ||
| 490 | |||
| 491 | static void set_st_params(struct oxygen *chip, | ||
| 492 | struct snd_pcm_hw_params *params) | ||
| 493 | { | ||
| 494 | set_cs2000_params(chip, params); | ||
| 495 | set_pcm1796_params(chip, params); | ||
| 496 | } | ||
| 497 | |||
| 399 | static void set_hdav_params(struct oxygen *chip, | 498 | static void set_hdav_params(struct oxygen *chip, |
| 400 | struct snd_pcm_hw_params *params) | 499 | struct snd_pcm_hw_params *params) |
| 401 | { | 500 | { |
| @@ -590,7 +689,7 @@ static const struct oxygen_model model_xonar_st = { | |||
| 590 | .cleanup = xonar_st_cleanup, | 689 | .cleanup = xonar_st_cleanup, |
| 591 | .suspend = xonar_st_suspend, | 690 | .suspend = xonar_st_suspend, |
| 592 | .resume = xonar_st_resume, | 691 | .resume = xonar_st_resume, |
| 593 | .set_dac_params = set_pcm1796_params, | 692 | .set_dac_params = set_st_params, |
| 594 | .set_adc_params = xonar_set_cs53x1_params, | 693 | .set_adc_params = xonar_set_cs53x1_params, |
| 595 | .update_dac_volume = update_pcm1796_volume, | 694 | .update_dac_volume = update_pcm1796_volume, |
| 596 | .update_dac_mute = update_pcm1796_mute, | 695 | .update_dac_mute = update_pcm1796_mute, |
| @@ -652,6 +751,8 @@ int __devinit get_xonar_pcm179x_model(struct oxygen *chip, | |||
| 652 | chip->model = model_xonar_st; | 751 | chip->model = model_xonar_st; |
| 653 | chip->model.shortname = "Xonar STX"; | 752 | chip->model.shortname = "Xonar STX"; |
| 654 | chip->model.init = xonar_stx_init; | 753 | chip->model.init = xonar_stx_init; |
| 754 | chip->model.resume = xonar_stx_resume; | ||
| 755 | chip->model.set_dac_params = set_pcm1796_params; | ||
| 655 | break; | 756 | break; |
| 656 | default: | 757 | default: |
| 657 | return -EINVAL; | 758 | return -EINVAL; |
