diff options
Diffstat (limited to 'sound/pci/oxygen/xonar_pcm179x.c')
-rw-r--r-- | sound/pci/oxygen/xonar_pcm179x.c | 109 |
1 files changed, 74 insertions, 35 deletions
diff --git a/sound/pci/oxygen/xonar_pcm179x.c b/sound/pci/oxygen/xonar_pcm179x.c index 97574dbec2b6..e17ee5e8e510 100644 --- a/sound/pci/oxygen/xonar_pcm179x.c +++ b/sound/pci/oxygen/xonar_pcm179x.c | |||
@@ -166,11 +166,13 @@ | |||
166 | #define I2C_DEVICE_PCM1796(i) (0x98 + ((i) << 1)) /* 10011, ii, /W=0 */ | 166 | #define I2C_DEVICE_PCM1796(i) (0x98 + ((i) << 1)) /* 10011, ii, /W=0 */ |
167 | #define I2C_DEVICE_CS2000 0x9c /* 100111, 0, /W=0 */ | 167 | #define I2C_DEVICE_CS2000 0x9c /* 100111, 0, /W=0 */ |
168 | 168 | ||
169 | #define PCM1796_REG_BASE 16 | ||
170 | |||
169 | 171 | ||
170 | struct xonar_pcm179x { | 172 | struct xonar_pcm179x { |
171 | struct xonar_generic generic; | 173 | struct xonar_generic generic; |
172 | unsigned int dacs; | 174 | unsigned int dacs; |
173 | u8 oversampling; | 175 | u8 pcm1796_regs[4][5]; |
174 | u8 cs2000_fun_cfg_1; | 176 | u8 cs2000_fun_cfg_1; |
175 | }; | 177 | }; |
176 | 178 | ||
@@ -204,54 +206,71 @@ static inline void pcm1796_write_i2c(struct oxygen *chip, unsigned int codec, | |||
204 | static void pcm1796_write(struct oxygen *chip, unsigned int codec, | 206 | static void pcm1796_write(struct oxygen *chip, unsigned int codec, |
205 | u8 reg, u8 value) | 207 | u8 reg, u8 value) |
206 | { | 208 | { |
209 | struct xonar_pcm179x *data = chip->model_data; | ||
210 | |||
207 | if ((chip->model.function_flags & OXYGEN_FUNCTION_2WIRE_SPI_MASK) == | 211 | if ((chip->model.function_flags & OXYGEN_FUNCTION_2WIRE_SPI_MASK) == |
208 | OXYGEN_FUNCTION_SPI) | 212 | OXYGEN_FUNCTION_SPI) |
209 | pcm1796_write_spi(chip, codec, reg, value); | 213 | pcm1796_write_spi(chip, codec, reg, value); |
210 | else | 214 | else |
211 | pcm1796_write_i2c(chip, codec, reg, value); | 215 | pcm1796_write_i2c(chip, codec, reg, value); |
216 | if ((unsigned int)(reg - PCM1796_REG_BASE) | ||
217 | < ARRAY_SIZE(data->pcm1796_regs[codec])) | ||
218 | data->pcm1796_regs[codec][reg - PCM1796_REG_BASE] = value; | ||
212 | } | 219 | } |
213 | 220 | ||
214 | static void cs2000_write(struct oxygen *chip, u8 reg, u8 value) | 221 | static void pcm1796_write_cached(struct oxygen *chip, unsigned int codec, |
222 | u8 reg, u8 value) | ||
215 | { | 223 | { |
216 | oxygen_write_i2c(chip, I2C_DEVICE_CS2000, reg, value); | 224 | struct xonar_pcm179x *data = chip->model_data; |
225 | |||
226 | if (value != data->pcm1796_regs[codec][reg - PCM1796_REG_BASE]) | ||
227 | pcm1796_write(chip, codec, reg, value); | ||
217 | } | 228 | } |
218 | 229 | ||
219 | static void update_pcm1796_volume(struct oxygen *chip) | 230 | static void cs2000_write(struct oxygen *chip, u8 reg, u8 value) |
220 | { | 231 | { |
221 | struct xonar_pcm179x *data = chip->model_data; | 232 | struct xonar_pcm179x *data = chip->model_data; |
222 | unsigned int i; | ||
223 | 233 | ||
224 | for (i = 0; i < data->dacs; ++i) { | 234 | oxygen_write_i2c(chip, I2C_DEVICE_CS2000, reg, value); |
225 | pcm1796_write(chip, i, 16, chip->dac_volume[i * 2]); | 235 | if (reg == CS2000_FUN_CFG_1) |
226 | pcm1796_write(chip, i, 17, chip->dac_volume[i * 2 + 1]); | 236 | data->cs2000_fun_cfg_1 = value; |
227 | } | ||
228 | } | 237 | } |
229 | 238 | ||
230 | static void update_pcm1796_mute(struct oxygen *chip) | 239 | static void cs2000_write_cached(struct oxygen *chip, u8 reg, u8 value) |
231 | { | 240 | { |
232 | struct xonar_pcm179x *data = chip->model_data; | 241 | struct xonar_pcm179x *data = chip->model_data; |
233 | unsigned int i; | ||
234 | u8 value; | ||
235 | 242 | ||
236 | value = PCM1796_DMF_DISABLED | PCM1796_FMT_24_LJUST | PCM1796_ATLD; | 243 | if (reg != CS2000_FUN_CFG_1 || |
237 | if (chip->dac_mute) | 244 | value != data->cs2000_fun_cfg_1) |
238 | value |= PCM1796_MUTE; | 245 | cs2000_write(chip, reg, value); |
239 | for (i = 0; i < data->dacs; ++i) | ||
240 | pcm1796_write(chip, i, 18, value); | ||
241 | } | 246 | } |
242 | 247 | ||
243 | static void pcm1796_init(struct oxygen *chip) | 248 | static void pcm1796_registers_init(struct oxygen *chip) |
244 | { | 249 | { |
245 | struct xonar_pcm179x *data = chip->model_data; | 250 | struct xonar_pcm179x *data = chip->model_data; |
246 | unsigned int i; | 251 | unsigned int i; |
247 | 252 | ||
248 | for (i = 0; i < data->dacs; ++i) { | 253 | for (i = 0; i < data->dacs; ++i) { |
254 | /* set ATLD before ATL/ATR */ | ||
255 | pcm1796_write(chip, i, 18, | ||
256 | data->pcm1796_regs[0][18 - PCM1796_REG_BASE]); | ||
257 | pcm1796_write(chip, i, 16, chip->dac_volume[i * 2]); | ||
258 | pcm1796_write(chip, i, 17, chip->dac_volume[i * 2 + 1]); | ||
249 | pcm1796_write(chip, i, 19, PCM1796_FLT_SHARP | PCM1796_ATS_1); | 259 | pcm1796_write(chip, i, 19, PCM1796_FLT_SHARP | PCM1796_ATS_1); |
250 | pcm1796_write(chip, i, 20, data->oversampling); | 260 | pcm1796_write(chip, i, 20, |
261 | data->pcm1796_regs[0][20 - PCM1796_REG_BASE]); | ||
251 | pcm1796_write(chip, i, 21, 0); | 262 | pcm1796_write(chip, i, 21, 0); |
252 | } | 263 | } |
253 | update_pcm1796_mute(chip); /* set ATLD before ATL/ATR */ | 264 | } |
254 | update_pcm1796_volume(chip); | 265 | |
266 | static void pcm1796_init(struct oxygen *chip) | ||
267 | { | ||
268 | struct xonar_pcm179x *data = chip->model_data; | ||
269 | |||
270 | data->pcm1796_regs[0][18 - PCM1796_REG_BASE] = PCM1796_MUTE | | ||
271 | PCM1796_DMF_DISABLED | PCM1796_FMT_24_LJUST | PCM1796_ATLD; | ||
272 | data->pcm1796_regs[0][20 - PCM1796_REG_BASE] = PCM1796_OS_64; | ||
273 | pcm1796_registers_init(chip); | ||
255 | } | 274 | } |
256 | 275 | ||
257 | static void xonar_d2_init(struct oxygen *chip) | 276 | static void xonar_d2_init(struct oxygen *chip) |
@@ -261,7 +280,6 @@ static void xonar_d2_init(struct oxygen *chip) | |||
261 | data->generic.anti_pop_delay = 300; | 280 | data->generic.anti_pop_delay = 300; |
262 | data->generic.output_enable_bit = GPIO_D2_OUTPUT_ENABLE; | 281 | data->generic.output_enable_bit = GPIO_D2_OUTPUT_ENABLE; |
263 | data->dacs = 4; | 282 | data->dacs = 4; |
264 | data->oversampling = PCM1796_OS_64; | ||
265 | 283 | ||
266 | pcm1796_init(chip); | 284 | pcm1796_init(chip); |
267 | 285 | ||
@@ -304,7 +322,6 @@ static void xonar_hdav_init(struct oxygen *chip) | |||
304 | data->pcm179x.generic.ext_power_int_reg = OXYGEN_GPI_INTERRUPT_MASK; | 322 | data->pcm179x.generic.ext_power_int_reg = OXYGEN_GPI_INTERRUPT_MASK; |
305 | data->pcm179x.generic.ext_power_bit = GPI_EXT_POWER; | 323 | data->pcm179x.generic.ext_power_bit = GPI_EXT_POWER; |
306 | data->pcm179x.dacs = chip->model.private_data ? 4 : 1; | 324 | data->pcm179x.dacs = chip->model.private_data ? 4 : 1; |
307 | data->pcm179x.oversampling = PCM1796_OS_64; | ||
308 | 325 | ||
309 | pcm1796_init(chip); | 326 | pcm1796_init(chip); |
310 | 327 | ||
@@ -335,7 +352,6 @@ static void xonar_st_init_common(struct oxygen *chip) | |||
335 | data->generic.anti_pop_delay = 100; | 352 | data->generic.anti_pop_delay = 100; |
336 | data->generic.output_enable_bit = GPIO_ST_OUTPUT_ENABLE; | 353 | data->generic.output_enable_bit = GPIO_ST_OUTPUT_ENABLE; |
337 | data->dacs = chip->model.private_data ? 4 : 1; | 354 | data->dacs = chip->model.private_data ? 4 : 1; |
338 | data->oversampling = PCM1796_OS_64; | ||
339 | 355 | ||
340 | pcm1796_init(chip); | 356 | pcm1796_init(chip); |
341 | 357 | ||
@@ -438,7 +454,7 @@ static void xonar_st_suspend(struct oxygen *chip) | |||
438 | 454 | ||
439 | static void xonar_d2_resume(struct oxygen *chip) | 455 | static void xonar_d2_resume(struct oxygen *chip) |
440 | { | 456 | { |
441 | pcm1796_init(chip); | 457 | pcm1796_registers_init(chip); |
442 | xonar_enable_output(chip); | 458 | xonar_enable_output(chip); |
443 | } | 459 | } |
444 | 460 | ||
@@ -446,14 +462,14 @@ static void xonar_hdav_resume(struct oxygen *chip) | |||
446 | { | 462 | { |
447 | struct xonar_hdav *data = chip->model_data; | 463 | struct xonar_hdav *data = chip->model_data; |
448 | 464 | ||
449 | pcm1796_init(chip); | 465 | pcm1796_registers_init(chip); |
450 | xonar_hdmi_resume(chip, &data->hdmi); | 466 | xonar_hdmi_resume(chip, &data->hdmi); |
451 | xonar_enable_output(chip); | 467 | xonar_enable_output(chip); |
452 | } | 468 | } |
453 | 469 | ||
454 | static void xonar_stx_resume(struct oxygen *chip) | 470 | static void xonar_stx_resume(struct oxygen *chip) |
455 | { | 471 | { |
456 | pcm1796_init(chip); | 472 | pcm1796_registers_init(chip); |
457 | xonar_enable_output(chip); | 473 | xonar_enable_output(chip); |
458 | } | 474 | } |
459 | 475 | ||
@@ -468,11 +484,35 @@ static void set_pcm1796_params(struct oxygen *chip, | |||
468 | { | 484 | { |
469 | struct xonar_pcm179x *data = chip->model_data; | 485 | struct xonar_pcm179x *data = chip->model_data; |
470 | unsigned int i; | 486 | unsigned int i; |
487 | u8 reg; | ||
488 | |||
489 | reg = params_rate(params) >= 96000 ? PCM1796_OS_32 : PCM1796_OS_64; | ||
490 | for (i = 0; i < data->dacs; ++i) | ||
491 | pcm1796_write_cached(chip, i, 20, reg); | ||
492 | } | ||
493 | |||
494 | static void update_pcm1796_volume(struct oxygen *chip) | ||
495 | { | ||
496 | struct xonar_pcm179x *data = chip->model_data; | ||
497 | unsigned int i; | ||
498 | |||
499 | for (i = 0; i < data->dacs; ++i) { | ||
500 | pcm1796_write_cached(chip, i, 16, chip->dac_volume[i * 2]); | ||
501 | pcm1796_write_cached(chip, i, 17, chip->dac_volume[i * 2 + 1]); | ||
502 | } | ||
503 | } | ||
504 | |||
505 | static void update_pcm1796_mute(struct oxygen *chip) | ||
506 | { | ||
507 | struct xonar_pcm179x *data = chip->model_data; | ||
508 | unsigned int i; | ||
509 | u8 value; | ||
471 | 510 | ||
472 | data->oversampling = | 511 | value = PCM1796_DMF_DISABLED | PCM1796_FMT_24_LJUST | PCM1796_ATLD; |
473 | params_rate(params) >= 96000 ? PCM1796_OS_32 : PCM1796_OS_64; | 512 | if (chip->dac_mute) |
513 | value |= PCM1796_MUTE; | ||
474 | for (i = 0; i < data->dacs; ++i) | 514 | for (i = 0; i < data->dacs; ++i) |
475 | pcm1796_write(chip, i, 20, data->oversampling); | 515 | pcm1796_write_cached(chip, i, 18, value); |
476 | } | 516 | } |
477 | 517 | ||
478 | static void set_cs2000_params(struct oxygen *chip, | 518 | static void set_cs2000_params(struct oxygen *chip, |
@@ -489,9 +529,8 @@ static void set_cs2000_params(struct oxygen *chip, | |||
489 | [OXYGEN_RATE_176400] = OXYGEN_RATE_44100 | OXYGEN_I2S_MCLK_256, | 529 | [OXYGEN_RATE_176400] = OXYGEN_RATE_44100 | OXYGEN_I2S_MCLK_256, |
490 | [OXYGEN_RATE_192000] = OXYGEN_RATE_48000 | OXYGEN_I2S_MCLK_256, | 530 | [OXYGEN_RATE_192000] = OXYGEN_RATE_48000 | OXYGEN_I2S_MCLK_256, |
491 | }; | 531 | }; |
492 | struct xonar_pcm179x *data = chip->model_data; | ||
493 | unsigned int rate_index; | 532 | unsigned int rate_index; |
494 | u8 rate_mclk; | 533 | u8 rate_mclk, reg; |
495 | 534 | ||
496 | rate_index = oxygen_read16(chip, OXYGEN_I2S_MULTICH_FORMAT) | 535 | rate_index = oxygen_read16(chip, OXYGEN_I2S_MULTICH_FORMAT) |
497 | & OXYGEN_I2S_RATE_MASK; | 536 | & OXYGEN_I2S_RATE_MASK; |
@@ -499,10 +538,10 @@ static void set_cs2000_params(struct oxygen *chip, | |||
499 | oxygen_write16_masked(chip, OXYGEN_I2S_A_FORMAT, rate_mclk, | 538 | oxygen_write16_masked(chip, OXYGEN_I2S_A_FORMAT, rate_mclk, |
500 | OXYGEN_I2S_RATE_MASK | OXYGEN_I2S_MCLK_MASK); | 539 | OXYGEN_I2S_RATE_MASK | OXYGEN_I2S_MCLK_MASK); |
501 | if ((rate_mclk & OXYGEN_I2S_MCLK_MASK) <= OXYGEN_I2S_MCLK_128) | 540 | if ((rate_mclk & OXYGEN_I2S_MCLK_MASK) <= OXYGEN_I2S_MCLK_128) |
502 | data->cs2000_fun_cfg_1 = CS2000_REF_CLK_DIV_1; | 541 | reg = CS2000_REF_CLK_DIV_1; |
503 | else | 542 | else |
504 | data->cs2000_fun_cfg_1 = CS2000_REF_CLK_DIV_2; | 543 | reg = CS2000_REF_CLK_DIV_2; |
505 | cs2000_write(chip, CS2000_FUN_CFG_1, data->cs2000_fun_cfg_1); | 544 | cs2000_write_cached(chip, CS2000_FUN_CFG_1, reg); |
506 | } | 545 | } |
507 | 546 | ||
508 | static void set_st_params(struct oxygen *chip, | 547 | static void set_st_params(struct oxygen *chip, |