aboutsummaryrefslogtreecommitdiffstats
path: root/sound/pci/oxygen/xonar_cs43xx.c
diff options
context:
space:
mode:
authorClemens Ladisch <clemens@ladisch.de>2009-09-28 05:21:21 -0400
committerTakashi Iwai <tiwai@suse.de>2009-09-28 05:55:00 -0400
commit4852ad02476ab2bbc874f6f8fda9e677e0f09c87 (patch)
tree0edcea50bffb7a643e3a72e29bcc920dd7ab71dc /sound/pci/oxygen/xonar_cs43xx.c
parent973dca93a3d46cca7e4743300f8a510b779906af (diff)
sound: oxygen: add digital filter control
Add a control to select between sharp and slow roll-of filter responses of the DACs. Signed-off-by: Clemens Ladisch <clemens@ladisch.de> Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/pci/oxygen/xonar_cs43xx.c')
-rw-r--r--sound/pci/oxygen/xonar_cs43xx.c82
1 files changed, 77 insertions, 5 deletions
diff --git a/sound/pci/oxygen/xonar_cs43xx.c b/sound/pci/oxygen/xonar_cs43xx.c
index a83f827feb34..16c226bfcd2b 100644
--- a/sound/pci/oxygen/xonar_cs43xx.c
+++ b/sound/pci/oxygen/xonar_cs43xx.c
@@ -69,7 +69,7 @@
69 69
70struct xonar_cs43xx { 70struct xonar_cs43xx {
71 struct xonar_generic generic; 71 struct xonar_generic generic;
72 u8 cs4398_regs[7]; 72 u8 cs4398_regs[8];
73 u8 cs4362a_regs[15]; 73 u8 cs4362a_regs[15];
74}; 74};
75 75
@@ -121,12 +121,11 @@ static void cs43xx_registers_init(struct oxygen *chip)
121 cs4398_write(chip, 4, data->cs4398_regs[4]); 121 cs4398_write(chip, 4, data->cs4398_regs[4]);
122 cs4398_write(chip, 5, data->cs4398_regs[5]); 122 cs4398_write(chip, 5, data->cs4398_regs[5]);
123 cs4398_write(chip, 6, data->cs4398_regs[6]); 123 cs4398_write(chip, 6, data->cs4398_regs[6]);
124 cs4398_write(chip, 7, CS4398_RMP_DN | CS4398_RMP_UP | 124 cs4398_write(chip, 7, data->cs4398_regs[7]);
125 CS4398_ZERO_CROSS | CS4398_SOFT_RAMP);
126 cs4362a_write(chip, 0x02, CS4362A_DIF_LJUST); 125 cs4362a_write(chip, 0x02, CS4362A_DIF_LJUST);
127 cs4362a_write(chip, 0x03, CS4362A_MUTEC_6 | CS4362A_AMUTE | 126 cs4362a_write(chip, 0x03, CS4362A_MUTEC_6 | CS4362A_AMUTE |
128 CS4362A_RMP_UP | CS4362A_ZERO_CROSS | CS4362A_SOFT_RAMP); 127 CS4362A_RMP_UP | CS4362A_ZERO_CROSS | CS4362A_SOFT_RAMP);
129 cs4362a_write(chip, 0x04, CS4362A_RMP_DN | CS4362A_DEM_NONE); 128 cs4362a_write(chip, 0x04, data->cs4362a_regs[0x04]);
130 cs4362a_write(chip, 0x05, 0); 129 cs4362a_write(chip, 0x05, 0);
131 for (i = 6; i <= 14; ++i) 130 for (i = 6; i <= 14; ++i)
132 cs4362a_write(chip, i, data->cs4362a_regs[i]); 131 cs4362a_write(chip, i, data->cs4362a_regs[i]);
@@ -147,6 +146,9 @@ static void xonar_d1_init(struct oxygen *chip)
147 CS4398_MUTE_B | CS4398_MUTE_A | CS4398_PAMUTE; 146 CS4398_MUTE_B | CS4398_MUTE_A | CS4398_PAMUTE;
148 data->cs4398_regs[5] = 60 * 2; 147 data->cs4398_regs[5] = 60 * 2;
149 data->cs4398_regs[6] = 60 * 2; 148 data->cs4398_regs[6] = 60 * 2;
149 data->cs4398_regs[7] = CS4398_RMP_DN | CS4398_RMP_UP |
150 CS4398_ZERO_CROSS | CS4398_SOFT_RAMP;
151 data->cs4362a_regs[4] = CS4362A_RMP_DN | CS4362A_DEM_NONE;
150 data->cs4362a_regs[6] = CS4362A_FM_SINGLE | 152 data->cs4362a_regs[6] = CS4362A_FM_SINGLE |
151 CS4362A_ATAPI_B_R | CS4362A_ATAPI_A_L; 153 CS4362A_ATAPI_B_R | CS4362A_ATAPI_A_L;
152 data->cs4362a_regs[7] = 60 | CS4362A_MUTE; 154 data->cs4362a_regs[7] = 60 | CS4362A_MUTE;
@@ -286,6 +288,68 @@ static const struct snd_kcontrol_new front_panel_switch = {
286 .private_value = GPIO_D1_FRONT_PANEL, 288 .private_value = GPIO_D1_FRONT_PANEL,
287}; 289};
288 290
291static int rolloff_info(struct snd_kcontrol *ctl,
292 struct snd_ctl_elem_info *info)
293{
294 static const char *const names[2] = {
295 "Fast Roll-off", "Slow Roll-off"
296 };
297
298 info->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
299 info->count = 1;
300 info->value.enumerated.items = 2;
301 if (info->value.enumerated.item >= 2)
302 info->value.enumerated.item = 1;
303 strcpy(info->value.enumerated.name, names[info->value.enumerated.item]);
304 return 0;
305}
306
307static int rolloff_get(struct snd_kcontrol *ctl,
308 struct snd_ctl_elem_value *value)
309{
310 struct oxygen *chip = ctl->private_data;
311 struct xonar_cs43xx *data = chip->model_data;
312
313 value->value.enumerated.item[0] =
314 (data->cs4398_regs[7] & CS4398_FILT_SEL) != 0;
315 return 0;
316}
317
318static int rolloff_put(struct snd_kcontrol *ctl,
319 struct snd_ctl_elem_value *value)
320{
321 struct oxygen *chip = ctl->private_data;
322 struct xonar_cs43xx *data = chip->model_data;
323 int changed;
324 u8 reg;
325
326 mutex_lock(&chip->mutex);
327 reg = data->cs4398_regs[7];
328 if (value->value.enumerated.item[0])
329 reg |= CS4398_FILT_SEL;
330 else
331 reg &= ~CS4398_FILT_SEL;
332 changed = reg != data->cs4398_regs[7];
333 if (changed) {
334 cs4398_write(chip, 7, reg);
335 if (reg & CS4398_FILT_SEL)
336 reg = data->cs4362a_regs[0x04] | CS4362A_FILT_SEL;
337 else
338 reg = data->cs4362a_regs[0x04] & ~CS4362A_FILT_SEL;
339 cs4362a_write(chip, 0x04, reg);
340 }
341 mutex_unlock(&chip->mutex);
342 return changed;
343}
344
345static const struct snd_kcontrol_new rolloff_control = {
346 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
347 .name = "DAC Filter Playback Enum",
348 .info = rolloff_info,
349 .get = rolloff_get,
350 .put = rolloff_put,
351};
352
289static void xonar_d1_line_mic_ac97_switch(struct oxygen *chip, 353static void xonar_d1_line_mic_ac97_switch(struct oxygen *chip,
290 unsigned int reg, unsigned int mute) 354 unsigned int reg, unsigned int mute)
291{ 355{
@@ -309,7 +373,15 @@ static int xonar_d1_control_filter(struct snd_kcontrol_new *template)
309 373
310static int xonar_d1_mixer_init(struct oxygen *chip) 374static int xonar_d1_mixer_init(struct oxygen *chip)
311{ 375{
312 return snd_ctl_add(chip->card, snd_ctl_new1(&front_panel_switch, chip)); 376 int err;
377
378 err = snd_ctl_add(chip->card, snd_ctl_new1(&front_panel_switch, chip));
379 if (err < 0)
380 return err;
381 err = snd_ctl_add(chip->card, snd_ctl_new1(&rolloff_control, chip));
382 if (err < 0)
383 return err;
384 return 0;
313} 385}
314 386
315static const struct oxygen_model model_xonar_d1 = { 387static const struct oxygen_model model_xonar_d1 = {