aboutsummaryrefslogtreecommitdiffstats
path: root/sound
diff options
context:
space:
mode:
authorRoman Volkov <v1ron@mail.ru>2014-01-24 07:18:09 -0500
committerClemens Ladisch <clemens@ladisch.de>2014-01-29 14:45:47 -0500
commit3c1611ddd1b67628bd946111edae8f5366a14edf (patch)
treeb230f7510a6e45f6a3b4aac9158ea01ad8e079cb /sound
parentbed61935cc5b70f84480dfd465c0e15a060c1f2c (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.c106
-rw-r--r--sound/pci/oxygen/xonar_dg.h1
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
141static void cs4245_write_cached(struct oxygen *chip, unsigned int reg, u8 value) 141static 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
149static 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
176static void cs4245_init(struct oxygen *chip) 149static 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
196static void dg_output_enable(struct oxygen *chip)
197{
198 msleep(2500);
199 oxygen_set_bits16(chip, OXYGEN_GPIO_DATA, GPIO_OUTPUT_ENABLE);
200}
201
202static void dg_init(struct oxygen *chip) 181static 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
221static void dg_cleanup(struct oxygen *chip) 198static void dg_cleanup(struct oxygen *chip)
@@ -230,8 +207,9 @@ static void dg_suspend(struct oxygen *chip)
230 207
231static void dg_resume(struct oxygen *chip) 208static 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
237static void set_cs4245_dac_params(struct oxygen *chip, 215static 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
36extern struct oxygen_model model_xonar_dg; 35extern struct oxygen_model model_xonar_dg;