aboutsummaryrefslogtreecommitdiffstats
path: root/sound/pci/oxygen/xonar_pcm179x.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/pci/oxygen/xonar_pcm179x.c')
-rw-r--r--sound/pci/oxygen/xonar_pcm179x.c109
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
170struct xonar_pcm179x { 172struct 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,
204static void pcm1796_write(struct oxygen *chip, unsigned int codec, 206static 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
214static void cs2000_write(struct oxygen *chip, u8 reg, u8 value) 221static 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
219static void update_pcm1796_volume(struct oxygen *chip) 230static 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
230static void update_pcm1796_mute(struct oxygen *chip) 239static 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
243static void pcm1796_init(struct oxygen *chip) 248static 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
266static 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
257static void xonar_d2_init(struct oxygen *chip) 276static 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
439static void xonar_d2_resume(struct oxygen *chip) 455static 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
454static void xonar_stx_resume(struct oxygen *chip) 470static 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
494static 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
505static 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
478static void set_cs2000_params(struct oxygen *chip, 518static 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
508static void set_st_params(struct oxygen *chip, 547static void set_st_params(struct oxygen *chip,