diff options
author | Roman Volkov <v1ron@mail.ru> | 2014-01-24 07:18:09 -0500 |
---|---|---|
committer | Clemens Ladisch <clemens@ladisch.de> | 2014-01-29 14:45:47 -0500 |
commit | 3c1611ddd1b67628bd946111edae8f5366a14edf (patch) | |
tree | b230f7510a6e45f6a3b4aac9158ea01ad8e079cb /sound | |
parent | bed61935cc5b70f84480dfd465c0e15a060c1f2c (diff) |
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>
Diffstat (limited to 'sound')
-rw-r--r-- | sound/pci/oxygen/xonar_dg.c | 106 | ||||
-rw-r--r-- | sound/pci/oxygen/xonar_dg.h | 1 |
2 files changed, 42 insertions, 65 deletions
diff --git a/sound/pci/oxygen/xonar_dg.c b/sound/pci/oxygen/xonar_dg.c index 2518c611d5c5..4177fb131086 100644 --- a/sound/pci/oxygen/xonar_dg.c +++ b/sound/pci/oxygen/xonar_dg.c | |||
@@ -135,70 +135,49 @@ static void cs4245_write(struct oxygen *chip, unsigned int reg, u8 value) | |||
135 | CS4245_SPI_ADDRESS_S | | 135 | CS4245_SPI_ADDRESS_S | |
136 | CS4245_SPI_WRITE_S | | 136 | CS4245_SPI_WRITE_S | |
137 | (reg << 8) | value); | 137 | (reg << 8) | value); |
138 | data->cs4245_regs[reg] = value; | 138 | data->cs4245_shadow[reg] = value; |
139 | } | 139 | } |
140 | 140 | ||
141 | static void cs4245_write_cached(struct oxygen *chip, unsigned int reg, u8 value) | 141 | static void cs4245_write_cached(struct oxygen *chip, unsigned int reg, u8 value) |
142 | { | 142 | { |
143 | struct dg *data = chip->model_data; | 143 | struct dg *data = chip->model_data; |
144 | 144 | ||
145 | if (value != data->cs4245_regs[reg]) | 145 | if (value != data->cs4245_shadow[reg]) |
146 | cs4245_write(chip, reg, value); | 146 | cs4245_write(chip, reg, value); |
147 | } | 147 | } |
148 | 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 | } | ||
175 | |||
176 | static void cs4245_init(struct oxygen *chip) | 149 | static void cs4245_init(struct oxygen *chip) |
177 | { | 150 | { |
178 | struct dg *data = chip->model_data; | 151 | struct dg *data = chip->model_data; |
179 | 152 | ||
180 | data->cs4245_regs[CS4245_DAC_CTRL_1] = | 153 | /* save the initial state: codec version, registers */ |
154 | cs4245_shadow_control(chip, CS4245_SAVE_TO_SHADOW); | ||
155 | |||
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] = | ||
181 | CS4245_DAC_FM_SINGLE | CS4245_DAC_DIF_LJUST; | 165 | CS4245_DAC_FM_SINGLE | CS4245_DAC_DIF_LJUST; |
182 | data->cs4245_regs[CS4245_ADC_CTRL] = | 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] = | ||
183 | CS4245_ADC_FM_SINGLE | CS4245_ADC_DIF_LJUST; | 169 | CS4245_ADC_FM_SINGLE | CS4245_ADC_DIF_LJUST; |
184 | data->cs4245_regs[CS4245_SIGNAL_SEL] = | 170 | data->cs4245_shadow[CS4245_ANALOG_IN] = |
185 | CS4245_A_OUT_SEL_HIZ | CS4245_ASYNCH; | 171 | CS4245_PGA_SOFT | CS4245_PGA_ZERO; |
186 | data->cs4245_regs[CS4245_PGA_B_CTRL] = 0; | 172 | data->cs4245_shadow[CS4245_PGA_B_CTRL] = 0; |
187 | data->cs4245_regs[CS4245_PGA_A_CTRL] = 0; | 173 | data->cs4245_shadow[CS4245_PGA_A_CTRL] = 0; |
188 | data->cs4245_regs[CS4245_ANALOG_IN] = | 174 | data->cs4245_shadow[CS4245_DAC_A_CTRL] = 4; |
189 | CS4245_PGA_SOFT | CS4245_PGA_ZERO | CS4245_SEL_INPUT_4; | 175 | data->cs4245_shadow[CS4245_DAC_B_CTRL] = 4; |
190 | data->cs4245_regs[CS4245_DAC_A_CTRL] = 0; | 176 | |
191 | data->cs4245_regs[CS4245_DAC_B_CTRL] = 0; | 177 | cs4245_shadow_control(chip, CS4245_LOAD_FROM_SHADOW); |
192 | cs4245_registers_init(chip); | ||
193 | snd_component_add(chip->card, "CS4245"); | 178 | snd_component_add(chip->card, "CS4245"); |
194 | } | 179 | } |
195 | 180 | ||
196 | static void dg_output_enable(struct oxygen *chip) | ||
197 | { | ||
198 | msleep(2500); | ||
199 | oxygen_set_bits16(chip, OXYGEN_GPIO_DATA, GPIO_OUTPUT_ENABLE); | ||
200 | } | ||
201 | |||
202 | static void dg_init(struct oxygen *chip) | 181 | static void dg_init(struct oxygen *chip) |
203 | { | 182 | { |
204 | struct dg *data = chip->model_data; | 183 | struct dg *data = chip->model_data; |
@@ -208,14 +187,12 @@ static void dg_init(struct oxygen *chip) | |||
208 | data->hp_vol_att = 2 * 16; | 187 | data->hp_vol_att = 2 * 16; |
209 | 188 | ||
210 | cs4245_init(chip); | 189 | cs4245_init(chip); |
211 | 190 | oxygen_write16(chip, OXYGEN_GPIO_CONTROL, | |
212 | oxygen_clear_bits16(chip, OXYGEN_GPIO_CONTROL, | 191 | GPIO_OUTPUT_ENABLE | GPIO_HP_REAR | GPIO_INPUT_ROUTE); |
213 | GPIO_MAGIC | GPIO_HP_DETECT); | 192 | oxygen_write16(chip, OXYGEN_GPIO_DATA, GPIO_INPUT_ROUTE); |
214 | oxygen_set_bits16(chip, OXYGEN_GPIO_CONTROL, | 193 | msleep(2500); /* anti-pop delay */ |
215 | GPIO_INPUT_ROUTE | GPIO_HP_REAR | GPIO_OUTPUT_ENABLE); | 194 | oxygen_write16(chip, OXYGEN_GPIO_DATA, |
216 | oxygen_clear_bits16(chip, OXYGEN_GPIO_DATA, | 195 | GPIO_OUTPUT_ENABLE | GPIO_INPUT_ROUTE); |
217 | GPIO_INPUT_ROUTE | GPIO_HP_REAR); | ||
218 | dg_output_enable(chip); | ||
219 | } | 196 | } |
220 | 197 | ||
221 | static void dg_cleanup(struct oxygen *chip) | 198 | static void dg_cleanup(struct oxygen *chip) |
@@ -230,8 +207,9 @@ static void dg_suspend(struct oxygen *chip) | |||
230 | 207 | ||
231 | static void dg_resume(struct oxygen *chip) | 208 | static void dg_resume(struct oxygen *chip) |
232 | { | 209 | { |
233 | cs4245_registers_init(chip); | 210 | cs4245_shadow_control(chip, CS4245_LOAD_FROM_SHADOW); |
234 | dg_output_enable(chip); | 211 | msleep(2500); |
212 | oxygen_set_bits16(chip, OXYGEN_GPIO_DATA, GPIO_OUTPUT_ENABLE); | ||
235 | } | 213 | } |
236 | 214 | ||
237 | static void set_cs4245_dac_params(struct oxygen *chip, | 215 | static void set_cs4245_dac_params(struct oxygen *chip, |
@@ -240,7 +218,7 @@ static void set_cs4245_dac_params(struct oxygen *chip, | |||
240 | struct dg *data = chip->model_data; | 218 | struct dg *data = chip->model_data; |
241 | u8 value; | 219 | u8 value; |
242 | 220 | ||
243 | value = data->cs4245_regs[CS4245_DAC_CTRL_1] & ~CS4245_DAC_FM_MASK; | 221 | value = data->cs4245_shadow[CS4245_DAC_CTRL_1] & ~CS4245_DAC_FM_MASK; |
244 | if (params_rate(params) <= 50000) | 222 | if (params_rate(params) <= 50000) |
245 | value |= CS4245_DAC_FM_SINGLE; | 223 | value |= CS4245_DAC_FM_SINGLE; |
246 | else if (params_rate(params) <= 100000) | 224 | else if (params_rate(params) <= 100000) |
@@ -256,7 +234,7 @@ static void set_cs4245_adc_params(struct oxygen *chip, | |||
256 | struct dg *data = chip->model_data; | 234 | struct dg *data = chip->model_data; |
257 | u8 value; | 235 | u8 value; |
258 | 236 | ||
259 | value = data->cs4245_regs[CS4245_ADC_CTRL] & ~CS4245_ADC_FM_MASK; | 237 | value = data->cs4245_shadow[CS4245_ADC_CTRL] & ~CS4245_ADC_FM_MASK; |
260 | if (params_rate(params) <= 50000) | 238 | if (params_rate(params) <= 50000) |
261 | value |= CS4245_ADC_FM_SINGLE; | 239 | value |= CS4245_ADC_FM_SINGLE; |
262 | else if (params_rate(params) <= 100000) | 240 | else if (params_rate(params) <= 100000) |
@@ -333,7 +311,7 @@ static int output_switch_put(struct snd_kcontrol *ctl, | |||
333 | if (changed) { | 311 | if (changed) { |
334 | data->output_sel = value->value.enumerated.item[0]; | 312 | data->output_sel = value->value.enumerated.item[0]; |
335 | 313 | ||
336 | reg = data->cs4245_regs[CS4245_SIGNAL_SEL] & | 314 | reg = data->cs4245_shadow[CS4245_SIGNAL_SEL] & |
337 | ~CS4245_A_OUT_SEL_MASK; | 315 | ~CS4245_A_OUT_SEL_MASK; |
338 | reg |= data->output_sel == 2 ? | 316 | reg |= data->output_sel == 2 ? |
339 | CS4245_A_OUT_SEL_DAC : CS4245_A_OUT_SEL_HIZ; | 317 | CS4245_A_OUT_SEL_DAC : CS4245_A_OUT_SEL_HIZ; |
@@ -504,7 +482,7 @@ static int input_sel_put(struct snd_kcontrol *ctl, | |||
504 | data->input_sel = value->value.enumerated.item[0]; | 482 | data->input_sel = value->value.enumerated.item[0]; |
505 | 483 | ||
506 | cs4245_write(chip, CS4245_ANALOG_IN, | 484 | cs4245_write(chip, CS4245_ANALOG_IN, |
507 | (data->cs4245_regs[CS4245_ANALOG_IN] & | 485 | (data->cs4245_shadow[CS4245_ANALOG_IN] & |
508 | ~CS4245_SEL_MASK) | | 486 | ~CS4245_SEL_MASK) | |
509 | sel_values[data->input_sel]); | 487 | sel_values[data->input_sel]); |
510 | 488 | ||
@@ -534,7 +512,7 @@ static int hpf_get(struct snd_kcontrol *ctl, struct snd_ctl_elem_value *value) | |||
534 | struct dg *data = chip->model_data; | 512 | struct dg *data = chip->model_data; |
535 | 513 | ||
536 | value->value.enumerated.item[0] = | 514 | value->value.enumerated.item[0] = |
537 | !!(data->cs4245_regs[CS4245_ADC_CTRL] & CS4245_HPF_FREEZE); | 515 | !!(data->cs4245_shadow[CS4245_ADC_CTRL] & CS4245_HPF_FREEZE); |
538 | return 0; | 516 | return 0; |
539 | } | 517 | } |
540 | 518 | ||
@@ -546,10 +524,10 @@ static int hpf_put(struct snd_kcontrol *ctl, struct snd_ctl_elem_value *value) | |||
546 | int changed; | 524 | int changed; |
547 | 525 | ||
548 | mutex_lock(&chip->mutex); | 526 | mutex_lock(&chip->mutex); |
549 | reg = data->cs4245_regs[CS4245_ADC_CTRL] & ~CS4245_HPF_FREEZE; | 527 | reg = data->cs4245_shadow[CS4245_ADC_CTRL] & ~CS4245_HPF_FREEZE; |
550 | if (value->value.enumerated.item[0]) | 528 | if (value->value.enumerated.item[0]) |
551 | reg |= CS4245_HPF_FREEZE; | 529 | reg |= CS4245_HPF_FREEZE; |
552 | changed = reg != data->cs4245_regs[CS4245_ADC_CTRL]; | 530 | changed = reg != data->cs4245_shadow[CS4245_ADC_CTRL]; |
553 | if (changed) | 531 | if (changed) |
554 | cs4245_write(chip, CS4245_ADC_CTRL, reg); | 532 | cs4245_write(chip, CS4245_ADC_CTRL, reg); |
555 | mutex_unlock(&chip->mutex); | 533 | mutex_unlock(&chip->mutex); |
@@ -629,7 +607,7 @@ static void dump_cs4245_registers(struct oxygen *chip, | |||
629 | 607 | ||
630 | snd_iprintf(buffer, "\nCS4245:"); | 608 | snd_iprintf(buffer, "\nCS4245:"); |
631 | for (i = 1; i <= 0x10; ++i) | 609 | for (i = 1; i <= 0x10; ++i) |
632 | snd_iprintf(buffer, " %02x", data->cs4245_regs[i]); | 610 | snd_iprintf(buffer, " %02x", data->cs4245_shadow[i]); |
633 | snd_iprintf(buffer, "\n"); | 611 | snd_iprintf(buffer, "\n"); |
634 | } | 612 | } |
635 | 613 | ||
diff --git a/sound/pci/oxygen/xonar_dg.h b/sound/pci/oxygen/xonar_dg.h index f2fa846d7246..944685edfce4 100644 --- a/sound/pci/oxygen/xonar_dg.h +++ b/sound/pci/oxygen/xonar_dg.h | |||
@@ -30,7 +30,6 @@ struct dg { | |||
30 | s8 input_vol[4][2]; | 30 | s8 input_vol[4][2]; |
31 | unsigned int input_sel; | 31 | unsigned int input_sel; |
32 | u8 hp_vol_att; | 32 | u8 hp_vol_att; |
33 | u8 cs4245_regs[0x11]; | ||
34 | }; | 33 | }; |
35 | 34 | ||
36 | extern struct oxygen_model model_xonar_dg; | 35 | extern struct oxygen_model model_xonar_dg; |