ALSA: oxygen: Xonar DG(X): modify initialization functions

Change CS4245 initialization: different sequence and GPIO values,
according to datasheets and reverse-engineering information.
Change cleanup/resume/suspend functions, since they use
initialization.

Signed-off-by: Roman Volkov <v1ron@mail.ru>
Signed-off-by: Clemens Ladisch <clemens@ladisch.de>

authored by Roman Volkov and committed by Clemens Ladisch 3c1611dd bed61935

+44 -67
+44 -66
sound/pci/oxygen/xonar_dg.c
··· 135 135 CS4245_SPI_ADDRESS_S | 136 136 CS4245_SPI_WRITE_S | 137 137 (reg << 8) | value); 138 - data->cs4245_regs[reg] = value; 138 + data->cs4245_shadow[reg] = value; 139 139 } 140 140 141 141 static void cs4245_write_cached(struct oxygen *chip, unsigned int reg, u8 value) 142 142 { 143 143 struct dg *data = chip->model_data; 144 144 145 - if (value != data->cs4245_regs[reg]) 145 + if (value != data->cs4245_shadow[reg]) 146 146 cs4245_write(chip, reg, value); 147 - } 148 - 149 - static void cs4245_registers_init(struct oxygen *chip) 150 - { 151 - struct dg *data = chip->model_data; 152 - 153 - cs4245_write(chip, CS4245_POWER_CTRL, CS4245_PDN); 154 - cs4245_write(chip, CS4245_DAC_CTRL_1, 155 - data->cs4245_regs[CS4245_DAC_CTRL_1]); 156 - cs4245_write(chip, CS4245_ADC_CTRL, 157 - data->cs4245_regs[CS4245_ADC_CTRL]); 158 - cs4245_write(chip, CS4245_SIGNAL_SEL, 159 - data->cs4245_regs[CS4245_SIGNAL_SEL]); 160 - cs4245_write(chip, CS4245_PGA_B_CTRL, 161 - data->cs4245_regs[CS4245_PGA_B_CTRL]); 162 - cs4245_write(chip, CS4245_PGA_A_CTRL, 163 - data->cs4245_regs[CS4245_PGA_A_CTRL]); 164 - cs4245_write(chip, CS4245_ANALOG_IN, 165 - data->cs4245_regs[CS4245_ANALOG_IN]); 166 - cs4245_write(chip, CS4245_DAC_A_CTRL, 167 - data->cs4245_regs[CS4245_DAC_A_CTRL]); 168 - cs4245_write(chip, CS4245_DAC_B_CTRL, 169 - data->cs4245_regs[CS4245_DAC_B_CTRL]); 170 - cs4245_write(chip, CS4245_DAC_CTRL_2, 171 - CS4245_DAC_SOFT | CS4245_DAC_ZERO | CS4245_INVERT_DAC); 172 - cs4245_write(chip, CS4245_INT_MASK, 0); 173 - cs4245_write(chip, CS4245_POWER_CTRL, 0); 174 147 } 175 148 176 149 static void cs4245_init(struct oxygen *chip) 177 150 { 178 151 struct dg *data = chip->model_data; 179 152 180 - data->cs4245_regs[CS4245_DAC_CTRL_1] = 181 - CS4245_DAC_FM_SINGLE | CS4245_DAC_DIF_LJUST; 182 - data->cs4245_regs[CS4245_ADC_CTRL] = 183 - CS4245_ADC_FM_SINGLE | CS4245_ADC_DIF_LJUST; 184 - data->cs4245_regs[CS4245_SIGNAL_SEL] = 185 - CS4245_A_OUT_SEL_HIZ | CS4245_ASYNCH; 186 - data->cs4245_regs[CS4245_PGA_B_CTRL] = 0; 187 - data->cs4245_regs[CS4245_PGA_A_CTRL] = 0; 188 - data->cs4245_regs[CS4245_ANALOG_IN] = 189 - CS4245_PGA_SOFT | CS4245_PGA_ZERO | CS4245_SEL_INPUT_4; 190 - data->cs4245_regs[CS4245_DAC_A_CTRL] = 0; 191 - data->cs4245_regs[CS4245_DAC_B_CTRL] = 0; 192 - cs4245_registers_init(chip); 193 - snd_component_add(chip->card, "CS4245"); 194 - } 153 + /* save the initial state: codec version, registers */ 154 + cs4245_shadow_control(chip, CS4245_SAVE_TO_SHADOW); 195 155 196 - static void dg_output_enable(struct oxygen *chip) 197 - { 198 - msleep(2500); 199 - oxygen_set_bits16(chip, OXYGEN_GPIO_DATA, GPIO_OUTPUT_ENABLE); 156 + /* 157 + * Power up the CODEC internals, enable soft ramp & zero cross, work in 158 + * async. mode, enable aux output from DAC. Invert DAC output as in the 159 + * Windows driver. 160 + */ 161 + data->cs4245_shadow[CS4245_POWER_CTRL] = 0; 162 + data->cs4245_shadow[CS4245_SIGNAL_SEL] = 163 + CS4245_A_OUT_SEL_DAC | CS4245_ASYNCH; 164 + data->cs4245_shadow[CS4245_DAC_CTRL_1] = 165 + CS4245_DAC_FM_SINGLE | CS4245_DAC_DIF_LJUST; 166 + data->cs4245_shadow[CS4245_DAC_CTRL_2] = 167 + CS4245_DAC_SOFT | CS4245_DAC_ZERO | CS4245_INVERT_DAC; 168 + data->cs4245_shadow[CS4245_ADC_CTRL] = 169 + CS4245_ADC_FM_SINGLE | CS4245_ADC_DIF_LJUST; 170 + data->cs4245_shadow[CS4245_ANALOG_IN] = 171 + CS4245_PGA_SOFT | CS4245_PGA_ZERO; 172 + data->cs4245_shadow[CS4245_PGA_B_CTRL] = 0; 173 + data->cs4245_shadow[CS4245_PGA_A_CTRL] = 0; 174 + data->cs4245_shadow[CS4245_DAC_A_CTRL] = 4; 175 + data->cs4245_shadow[CS4245_DAC_B_CTRL] = 4; 176 + 177 + cs4245_shadow_control(chip, CS4245_LOAD_FROM_SHADOW); 178 + snd_component_add(chip->card, "CS4245"); 200 179 } 201 180 202 181 static void dg_init(struct oxygen *chip) ··· 187 208 data->hp_vol_att = 2 * 16; 188 209 189 210 cs4245_init(chip); 190 - 191 - oxygen_clear_bits16(chip, OXYGEN_GPIO_CONTROL, 192 - GPIO_MAGIC | GPIO_HP_DETECT); 193 - oxygen_set_bits16(chip, OXYGEN_GPIO_CONTROL, 194 - GPIO_INPUT_ROUTE | GPIO_HP_REAR | GPIO_OUTPUT_ENABLE); 195 - oxygen_clear_bits16(chip, OXYGEN_GPIO_DATA, 196 - GPIO_INPUT_ROUTE | GPIO_HP_REAR); 197 - dg_output_enable(chip); 211 + oxygen_write16(chip, OXYGEN_GPIO_CONTROL, 212 + GPIO_OUTPUT_ENABLE | GPIO_HP_REAR | GPIO_INPUT_ROUTE); 213 + oxygen_write16(chip, OXYGEN_GPIO_DATA, GPIO_INPUT_ROUTE); 214 + msleep(2500); /* anti-pop delay */ 215 + oxygen_write16(chip, OXYGEN_GPIO_DATA, 216 + GPIO_OUTPUT_ENABLE | GPIO_INPUT_ROUTE); 198 217 } 199 218 200 219 static void dg_cleanup(struct oxygen *chip) ··· 207 230 208 231 static void dg_resume(struct oxygen *chip) 209 232 { 210 - cs4245_registers_init(chip); 211 - dg_output_enable(chip); 233 + cs4245_shadow_control(chip, CS4245_LOAD_FROM_SHADOW); 234 + msleep(2500); 235 + oxygen_set_bits16(chip, OXYGEN_GPIO_DATA, GPIO_OUTPUT_ENABLE); 212 236 } 213 237 214 238 static void set_cs4245_dac_params(struct oxygen *chip, ··· 218 240 struct dg *data = chip->model_data; 219 241 u8 value; 220 242 221 - value = data->cs4245_regs[CS4245_DAC_CTRL_1] & ~CS4245_DAC_FM_MASK; 243 + value = data->cs4245_shadow[CS4245_DAC_CTRL_1] & ~CS4245_DAC_FM_MASK; 222 244 if (params_rate(params) <= 50000) 223 245 value |= CS4245_DAC_FM_SINGLE; 224 246 else if (params_rate(params) <= 100000) ··· 234 256 struct dg *data = chip->model_data; 235 257 u8 value; 236 258 237 - value = data->cs4245_regs[CS4245_ADC_CTRL] & ~CS4245_ADC_FM_MASK; 259 + value = data->cs4245_shadow[CS4245_ADC_CTRL] & ~CS4245_ADC_FM_MASK; 238 260 if (params_rate(params) <= 50000) 239 261 value |= CS4245_ADC_FM_SINGLE; 240 262 else if (params_rate(params) <= 100000) ··· 311 333 if (changed) { 312 334 data->output_sel = value->value.enumerated.item[0]; 313 335 314 - reg = data->cs4245_regs[CS4245_SIGNAL_SEL] & 336 + reg = data->cs4245_shadow[CS4245_SIGNAL_SEL] & 315 337 ~CS4245_A_OUT_SEL_MASK; 316 338 reg |= data->output_sel == 2 ? 317 339 CS4245_A_OUT_SEL_DAC : CS4245_A_OUT_SEL_HIZ; ··· 482 504 data->input_sel = value->value.enumerated.item[0]; 483 505 484 506 cs4245_write(chip, CS4245_ANALOG_IN, 485 - (data->cs4245_regs[CS4245_ANALOG_IN] & 507 + (data->cs4245_shadow[CS4245_ANALOG_IN] & 486 508 ~CS4245_SEL_MASK) | 487 509 sel_values[data->input_sel]); 488 510 ··· 512 534 struct dg *data = chip->model_data; 513 535 514 536 value->value.enumerated.item[0] = 515 - !!(data->cs4245_regs[CS4245_ADC_CTRL] & CS4245_HPF_FREEZE); 537 + !!(data->cs4245_shadow[CS4245_ADC_CTRL] & CS4245_HPF_FREEZE); 516 538 return 0; 517 539 } 518 540 ··· 524 546 int changed; 525 547 526 548 mutex_lock(&chip->mutex); 527 - reg = data->cs4245_regs[CS4245_ADC_CTRL] & ~CS4245_HPF_FREEZE; 549 + reg = data->cs4245_shadow[CS4245_ADC_CTRL] & ~CS4245_HPF_FREEZE; 528 550 if (value->value.enumerated.item[0]) 529 551 reg |= CS4245_HPF_FREEZE; 530 - changed = reg != data->cs4245_regs[CS4245_ADC_CTRL]; 552 + changed = reg != data->cs4245_shadow[CS4245_ADC_CTRL]; 531 553 if (changed) 532 554 cs4245_write(chip, CS4245_ADC_CTRL, reg); 533 555 mutex_unlock(&chip->mutex); ··· 607 629 608 630 snd_iprintf(buffer, "\nCS4245:"); 609 631 for (i = 1; i <= 0x10; ++i) 610 - snd_iprintf(buffer, " %02x", data->cs4245_regs[i]); 632 + snd_iprintf(buffer, " %02x", data->cs4245_shadow[i]); 611 633 snd_iprintf(buffer, "\n"); 612 634 } 613 635
-1
sound/pci/oxygen/xonar_dg.h
··· 30 30 s8 input_vol[4][2]; 31 31 unsigned int input_sel; 32 32 u8 hp_vol_att; 33 - u8 cs4245_regs[0x11]; 34 33 }; 35 34 36 35 extern struct oxygen_model model_xonar_dg;