diff options
author | Clemens Ladisch <clemens@ladisch.de> | 2009-09-28 05:21:51 -0400 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2009-09-28 05:55:08 -0400 |
commit | 1ff048869eb8e8408856e23b3dc6af094491f837 (patch) | |
tree | d8162f02384305e8f37baab7696db62d7cded27b | |
parent | 4852ad02476ab2bbc874f6f8fda9e677e0f09c87 (diff) |
sound: oxygen: add high-pass filter control
Add a control that allows disabling the high-pass filter of the WM8785 ADC.
Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
-rw-r--r-- | sound/pci/oxygen/oxygen.c | 73 |
1 files changed, 71 insertions, 2 deletions
diff --git a/sound/pci/oxygen/oxygen.c b/sound/pci/oxygen/oxygen.c index 3ad9eb00aebd..acbedebcffd9 100644 --- a/sound/pci/oxygen/oxygen.c +++ b/sound/pci/oxygen/oxygen.c | |||
@@ -98,7 +98,7 @@ MODULE_DEVICE_TABLE(pci, oxygen_ids); | |||
98 | 98 | ||
99 | struct generic_data { | 99 | struct generic_data { |
100 | u8 ak4396_regs[4][5]; | 100 | u8 ak4396_regs[4][5]; |
101 | u16 wm8785_regs[1]; | 101 | u16 wm8785_regs[3]; |
102 | }; | 102 | }; |
103 | 103 | ||
104 | static void ak4396_write(struct oxygen *chip, unsigned int codec, | 104 | static void ak4396_write(struct oxygen *chip, unsigned int codec, |
@@ -184,6 +184,7 @@ static void wm8785_registers_init(struct oxygen *chip) | |||
184 | 184 | ||
185 | wm8785_write(chip, WM8785_R7, 0); | 185 | wm8785_write(chip, WM8785_R7, 0); |
186 | wm8785_write(chip, WM8785_R0, data->wm8785_regs[0]); | 186 | wm8785_write(chip, WM8785_R0, data->wm8785_regs[0]); |
187 | wm8785_write(chip, WM8785_R2, data->wm8785_regs[2]); | ||
187 | } | 188 | } |
188 | 189 | ||
189 | static void wm8785_init(struct oxygen *chip) | 190 | static void wm8785_init(struct oxygen *chip) |
@@ -192,6 +193,7 @@ static void wm8785_init(struct oxygen *chip) | |||
192 | 193 | ||
193 | data->wm8785_regs[0] = | 194 | data->wm8785_regs[0] = |
194 | WM8785_MCR_SLAVE | WM8785_OSR_SINGLE | WM8785_FORMAT_LJUST; | 195 | WM8785_MCR_SLAVE | WM8785_OSR_SINGLE | WM8785_FORMAT_LJUST; |
196 | data->wm8785_regs[2] = WM8785_HPFR | WM8785_HPFL; | ||
195 | wm8785_registers_init(chip); | 197 | wm8785_registers_init(chip); |
196 | snd_component_add(chip->card, "WM8785"); | 198 | snd_component_add(chip->card, "WM8785"); |
197 | } | 199 | } |
@@ -334,6 +336,7 @@ static void set_wm8785_params(struct oxygen *chip, | |||
334 | if (value != data->wm8785_regs[0]) { | 336 | if (value != data->wm8785_regs[0]) { |
335 | wm8785_write(chip, WM8785_R7, 0); | 337 | wm8785_write(chip, WM8785_R7, 0); |
336 | wm8785_write(chip, WM8785_R0, value); | 338 | wm8785_write(chip, WM8785_R0, value); |
339 | wm8785_write(chip, WM8785_R2, data->wm8785_regs[2]); | ||
337 | } | 340 | } |
338 | } | 341 | } |
339 | 342 | ||
@@ -411,11 +414,75 @@ static const struct snd_kcontrol_new rolloff_control = { | |||
411 | .put = rolloff_put, | 414 | .put = rolloff_put, |
412 | }; | 415 | }; |
413 | 416 | ||
417 | static int hpf_info(struct snd_kcontrol *ctl, struct snd_ctl_elem_info *info) | ||
418 | { | ||
419 | static const char *const names[2] = { | ||
420 | "None", "High-pass Filter" | ||
421 | }; | ||
422 | |||
423 | info->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | ||
424 | info->count = 1; | ||
425 | info->value.enumerated.items = 2; | ||
426 | if (info->value.enumerated.item >= 2) | ||
427 | info->value.enumerated.item = 1; | ||
428 | strcpy(info->value.enumerated.name, names[info->value.enumerated.item]); | ||
429 | return 0; | ||
430 | } | ||
431 | |||
432 | static int hpf_get(struct snd_kcontrol *ctl, struct snd_ctl_elem_value *value) | ||
433 | { | ||
434 | struct oxygen *chip = ctl->private_data; | ||
435 | struct generic_data *data = chip->model_data; | ||
436 | |||
437 | value->value.enumerated.item[0] = | ||
438 | (data->wm8785_regs[WM8785_R2] & WM8785_HPFR) != 0; | ||
439 | return 0; | ||
440 | } | ||
441 | |||
442 | static int hpf_put(struct snd_kcontrol *ctl, struct snd_ctl_elem_value *value) | ||
443 | { | ||
444 | struct oxygen *chip = ctl->private_data; | ||
445 | struct generic_data *data = chip->model_data; | ||
446 | unsigned int reg; | ||
447 | int changed; | ||
448 | |||
449 | mutex_lock(&chip->mutex); | ||
450 | reg = data->wm8785_regs[WM8785_R2] & ~(WM8785_HPFR | WM8785_HPFL); | ||
451 | if (value->value.enumerated.item[0]) | ||
452 | reg |= WM8785_HPFR | WM8785_HPFL; | ||
453 | changed = reg != data->wm8785_regs[WM8785_R2]; | ||
454 | if (changed) | ||
455 | wm8785_write(chip, WM8785_R2, reg); | ||
456 | mutex_unlock(&chip->mutex); | ||
457 | return changed; | ||
458 | } | ||
459 | |||
460 | static const struct snd_kcontrol_new hpf_control = { | ||
461 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
462 | .name = "ADC Filter Capture Enum", | ||
463 | .info = hpf_info, | ||
464 | .get = hpf_get, | ||
465 | .put = hpf_put, | ||
466 | }; | ||
467 | |||
414 | static int generic_mixer_init(struct oxygen *chip) | 468 | static int generic_mixer_init(struct oxygen *chip) |
415 | { | 469 | { |
416 | return snd_ctl_add(chip->card, snd_ctl_new1(&rolloff_control, chip)); | 470 | return snd_ctl_add(chip->card, snd_ctl_new1(&rolloff_control, chip)); |
417 | } | 471 | } |
418 | 472 | ||
473 | static int generic_wm8785_mixer_init(struct oxygen *chip) | ||
474 | { | ||
475 | int err; | ||
476 | |||
477 | err = generic_mixer_init(chip); | ||
478 | if (err < 0) | ||
479 | return err; | ||
480 | err = snd_ctl_add(chip->card, snd_ctl_new1(&hpf_control, chip)); | ||
481 | if (err < 0) | ||
482 | return err; | ||
483 | return 0; | ||
484 | } | ||
485 | |||
419 | static const DECLARE_TLV_DB_LINEAR(ak4396_db_scale, TLV_DB_GAIN_MUTE, 0); | 486 | static const DECLARE_TLV_DB_LINEAR(ak4396_db_scale, TLV_DB_GAIN_MUTE, 0); |
420 | 487 | ||
421 | static const struct oxygen_model model_generic = { | 488 | static const struct oxygen_model model_generic = { |
@@ -423,7 +490,7 @@ static const struct oxygen_model model_generic = { | |||
423 | .longname = "C-Media Oxygen HD Audio", | 490 | .longname = "C-Media Oxygen HD Audio", |
424 | .chip = "CMI8788", | 491 | .chip = "CMI8788", |
425 | .init = generic_init, | 492 | .init = generic_init, |
426 | .mixer_init = generic_mixer_init, | 493 | .mixer_init = generic_wm8785_mixer_init, |
427 | .cleanup = generic_cleanup, | 494 | .cleanup = generic_cleanup, |
428 | .resume = generic_resume, | 495 | .resume = generic_resume, |
429 | .get_i2s_mclk = oxygen_default_i2s_mclk, | 496 | .get_i2s_mclk = oxygen_default_i2s_mclk, |
@@ -455,6 +522,7 @@ static int __devinit get_oxygen_model(struct oxygen *chip, | |||
455 | switch (id->driver_data) { | 522 | switch (id->driver_data) { |
456 | case MODEL_MERIDIAN: | 523 | case MODEL_MERIDIAN: |
457 | chip->model.init = meridian_init; | 524 | chip->model.init = meridian_init; |
525 | chip->model.mixer_init = generic_mixer_init; | ||
458 | chip->model.resume = meridian_resume; | 526 | chip->model.resume = meridian_resume; |
459 | chip->model.set_adc_params = set_ak5385_params; | 527 | chip->model.set_adc_params = set_ak5385_params; |
460 | chip->model.device_config = PLAYBACK_0_TO_I2S | | 528 | chip->model.device_config = PLAYBACK_0_TO_I2S | |
@@ -470,6 +538,7 @@ static int __devinit get_oxygen_model(struct oxygen *chip, | |||
470 | break; | 538 | break; |
471 | case MODEL_CLARO_HALO: | 539 | case MODEL_CLARO_HALO: |
472 | chip->model.init = claro_halo_init; | 540 | chip->model.init = claro_halo_init; |
541 | chip->model.mixer_init = generic_mixer_init; | ||
473 | chip->model.cleanup = claro_cleanup; | 542 | chip->model.cleanup = claro_cleanup; |
474 | chip->model.suspend = claro_suspend; | 543 | chip->model.suspend = claro_suspend; |
475 | chip->model.resume = claro_resume; | 544 | chip->model.resume = claro_resume; |