[alsa-devel] [PATCH 00/16] ALSA: hda - GPIO cleanups
Hi,
this is a series of cleanup patches for GPIO handlings in HD-audio codec drivers. Not really fixing bugs but mostly for straightening the code flow.
Takashi
===
Takashi Iwai (16): ALSA: hda/realtek - Allow skipping spec->init_amp detection ALSA: hda/realtek - Manage GPIO bits commonly ALSA: hda/realtek - Add GPIO data update helper ALSA: hda/realtek - Consolidate gpio_data and gpio_led ALSA: hda/realtek - Simplify alc885_fixup_macpro_gpio() ALSA: hda/realtek - Simplify mute LED GPIO handling ALSA: hda/realtek - Convert some manual GPIO setups ALSA: hda/realtek - Simplify Dell XPS13 GPIO handling ALSA: hda/realtek - Use common GPIO mask for ALC660VD ASUS fixup ALSA: hda/realtek - Use common helper for creating ALC268 beep controls ALSA: hda/realtek - Use common helper for creating beep controls ALSA: hda/conexant - Clean up beep code ALSA: hda/cirrus - Simplify creation of new controls ALSA: hda/via - Rewrite with error goto ALSA: hda/via - Simplify control management ALSA: hda/via - Use standard verb containers
sound/pci/hda/patch_cirrus.c | 29 +- sound/pci/hda/patch_conexant.c | 85 ++--- sound/pci/hda/patch_realtek.c | 639 +++++++++++++++------------------ sound/pci/hda/patch_via.c | 294 +++++++-------- 4 files changed, 462 insertions(+), 585 deletions(-)
Some devices have the overrides of spec->init_amp at HDA_FIXUP_ACT_PROBE just because alc_ssid_check() gives the false-positive values from the SSID.
For more consistent behavior, define the logic in the following way:
- Define ALC_INIT_UNDEFINED as the default value before calling alc_ssid_check() - Each fixup may set up spec->init_amp with another value at HDA_FIXUP_ACT_PRE_PROBE - At detection, check whether spec->init_amp is ALC_INIT_UNDEFINED or not; if it's different, we skip the detection
Also, it turned out that ASUS TX300 requires the spec->init_amp override, too; currently it ignores the GPIO bits implicitly by its static init verb, but this will be changed in the later patchset.
Signed-off-by: Takashi Iwai tiwai@suse.de --- sound/pci/hda/patch_realtek.c | 44 +++++++++++++++++------------------ 1 file changed, 21 insertions(+), 23 deletions(-)
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 7934c5df4d80..1f054e5ae2b3 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -43,6 +43,7 @@
/* extra amp-initialization sequence types */ enum { + ALC_INIT_UNDEFINED, ALC_INIT_NONE, ALC_INIT_DEFAULT, ALC_INIT_GPIO1, @@ -656,20 +657,22 @@ static int alc_subsystem_id(struct hda_codec *codec, const hda_nid_t *ports) * 7~6 : Reserved */ tmp = (ass & 0x38) >> 3; /* external Amp control */ - switch (tmp) { - case 1: - spec->init_amp = ALC_INIT_GPIO1; - break; - case 3: - spec->init_amp = ALC_INIT_GPIO2; - break; - case 7: - spec->init_amp = ALC_INIT_GPIO3; - break; - case 5: - default: - spec->init_amp = ALC_INIT_DEFAULT; - break; + if (spec->init_amp == ALC_INIT_UNDEFINED) { + switch (tmp) { + case 1: + spec->init_amp = ALC_INIT_GPIO1; + break; + case 3: + spec->init_amp = ALC_INIT_GPIO2; + break; + case 7: + spec->init_amp = ALC_INIT_GPIO3; + break; + case 5: + default: + spec->init_amp = ALC_INIT_DEFAULT; + break; + } }
/* is laptop or Desktop and enable the function "Mute internal speaker @@ -1589,8 +1592,6 @@ static void alc260_fixup_kn1(struct hda_codec *codec, switch (action) { case HDA_FIXUP_ACT_PRE_PROBE: snd_hda_apply_pincfgs(codec, pincfgs); - break; - case HDA_FIXUP_ACT_PROBE: spec->init_amp = ALC_INIT_NONE; break; } @@ -1600,7 +1601,7 @@ static void alc260_fixup_fsc_s7020(struct hda_codec *codec, const struct hda_fixup *fix, int action) { struct alc_spec *spec = codec->spec; - if (action == HDA_FIXUP_ACT_PROBE) + if (action == HDA_FIXUP_ACT_PRE_PROBE) spec->init_amp = ALC_INIT_NONE; }
@@ -3892,6 +3893,7 @@ static void alc280_fixup_hp_gpio2_mic_hotkey(struct hda_codec *codec, struct alc_spec *spec = codec->spec;
if (action == HDA_FIXUP_ACT_PRE_PROBE) { + spec->init_amp = ALC_INIT_DEFAULT; if (alc_register_micmute_input_device(codec) != 0) return;
@@ -3914,9 +3916,6 @@ static void alc280_fixup_hp_gpio2_mic_hotkey(struct hda_codec *codec, return;
switch (action) { - case HDA_FIXUP_ACT_PROBE: - spec->init_amp = ALC_INIT_DEFAULT; - break; case HDA_FIXUP_ACT_FREE: input_unregister_device(spec->kb_dev); spec->kb_dev = NULL; @@ -3937,6 +3936,7 @@ static void alc233_fixup_lenovo_line2_mic_hotkey(struct hda_codec *codec, struct alc_spec *spec = codec->spec;
if (action == HDA_FIXUP_ACT_PRE_PROBE) { + spec->init_amp = ALC_INIT_DEFAULT; if (alc_register_micmute_input_device(codec) != 0) return;
@@ -3955,9 +3955,6 @@ static void alc233_fixup_lenovo_line2_mic_hotkey(struct hda_codec *codec, return;
switch (action) { - case HDA_FIXUP_ACT_PROBE: - spec->init_amp = ALC_INIT_DEFAULT; - break; case HDA_FIXUP_ACT_FREE: input_unregister_device(spec->kb_dev); spec->kb_dev = NULL; @@ -5227,6 +5224,7 @@ static void alc282_fixup_asus_tx300(struct hda_codec *codec,
switch (action) { case HDA_FIXUP_ACT_PRE_PROBE: + spec->init_amp = ALC_INIT_DEFAULT; snd_hda_add_verbs(codec, gpio2_verbs); snd_hda_apply_pincfgs(codec, dock_pins); spec->gen.auto_mute_via_amp = 1;
Currently the GPIO bits are managed by individual verbs in some cases while toggled dynamically in other cases. For simplifying the GPIO management, define the GPIO mask, dir and data bits in alc_spec fields, and refer to / set them consistently from all places.
As a first step, along with the definition of the new gpio_* fields, this patch replaces the static verbs that are used at initialization and fixups with the common helper functions.
Signed-off-by: Takashi Iwai tiwai@suse.de --- sound/pci/hda/patch_realtek.c | 129 +++++++++++++++++++++------------- 1 file changed, 81 insertions(+), 48 deletions(-)
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 1f054e5ae2b3..489075b23652 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -46,9 +46,6 @@ enum { ALC_INIT_UNDEFINED, ALC_INIT_NONE, ALC_INIT_DEFAULT, - ALC_INIT_GPIO1, - ALC_INIT_GPIO2, - ALC_INIT_GPIO3, };
enum { @@ -93,6 +90,11 @@ struct alc_spec { struct alc_customize_define cdefine; unsigned int parse_flags; /* flag for snd_hda_parse_pin_defcfg() */
+ /* GPIO bits */ + unsigned int gpio_mask; + unsigned int gpio_dir; + unsigned int gpio_data; + /* mute LED for HP laptops, see alc269_fixup_mic_mute_hook() */ int mute_led_polarity; hda_nid_t mute_led_nid; @@ -220,27 +222,63 @@ static void add_mixer(struct alc_spec *spec, const struct snd_kcontrol_new *mix) /* * GPIO setup tables, used in initialization */ + /* Enable GPIO mask and set output */ -static const struct hda_verb alc_gpio1_init_verbs[] = { - {0x01, AC_VERB_SET_GPIO_MASK, 0x01}, - {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x01}, - {0x01, AC_VERB_SET_GPIO_DATA, 0x01}, - { } -}; +static void alc_setup_gpio(struct hda_codec *codec, unsigned int mask) +{ + struct alc_spec *spec = codec->spec;
-static const struct hda_verb alc_gpio2_init_verbs[] = { - {0x01, AC_VERB_SET_GPIO_MASK, 0x02}, - {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x02}, - {0x01, AC_VERB_SET_GPIO_DATA, 0x02}, - { } -}; + spec->gpio_mask |= mask; + spec->gpio_dir |= mask; + spec->gpio_data |= mask; +}
-static const struct hda_verb alc_gpio3_init_verbs[] = { - {0x01, AC_VERB_SET_GPIO_MASK, 0x03}, - {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x03}, - {0x01, AC_VERB_SET_GPIO_DATA, 0x03}, - { } -}; +static void alc_write_gpio_data(struct hda_codec *codec) +{ + struct alc_spec *spec = codec->spec; + + snd_hda_codec_write(codec, 0x01, 0, AC_VERB_SET_GPIO_DATA, + spec->gpio_data); +} + +static void alc_write_gpio(struct hda_codec *codec) +{ + struct alc_spec *spec = codec->spec; + + if (!spec->gpio_mask) + return; + + snd_hda_codec_write(codec, codec->core.afg, 0, + AC_VERB_SET_GPIO_MASK, spec->gpio_mask); + snd_hda_codec_write(codec, codec->core.afg, 0, + AC_VERB_SET_GPIO_DIRECTION, spec->gpio_dir); + alc_write_gpio_data(codec); +} + +static void alc_fixup_gpio(struct hda_codec *codec, int action, + unsigned int mask) +{ + if (action == HDA_FIXUP_ACT_PRE_PROBE) + alc_setup_gpio(codec, mask); +} + +static void alc_fixup_gpio1(struct hda_codec *codec, + const struct hda_fixup *fix, int action) +{ + alc_fixup_gpio(codec, action, 0x01); +} + +static void alc_fixup_gpio2(struct hda_codec *codec, + const struct hda_fixup *fix, int action) +{ + alc_fixup_gpio(codec, action, 0x02); +} + +static void alc_fixup_gpio3(struct hda_codec *codec, + const struct hda_fixup *fix, int action) +{ + alc_fixup_gpio(codec, action, 0x03); +}
/* * Fix hardware PLL issue @@ -448,16 +486,8 @@ static void alc_auto_init_amp(struct hda_codec *codec, int type) { alc_fill_eapd_coef(codec); alc_auto_setup_eapd(codec, true); + alc_write_gpio(codec); switch (type) { - case ALC_INIT_GPIO1: - snd_hda_sequence_write(codec, alc_gpio1_init_verbs); - break; - case ALC_INIT_GPIO2: - snd_hda_sequence_write(codec, alc_gpio2_init_verbs); - break; - case ALC_INIT_GPIO3: - snd_hda_sequence_write(codec, alc_gpio3_init_verbs); - break; case ALC_INIT_DEFAULT: switch (codec->core.vendor_id) { case 0x10ec0260: @@ -660,13 +690,13 @@ static int alc_subsystem_id(struct hda_codec *codec, const hda_nid_t *ports) if (spec->init_amp == ALC_INIT_UNDEFINED) { switch (tmp) { case 1: - spec->init_amp = ALC_INIT_GPIO1; + alc_setup_gpio(codec, 0x01); break; case 3: - spec->init_amp = ALC_INIT_GPIO2; + alc_setup_gpio(codec, 0x02); break; case 7: - spec->init_amp = ALC_INIT_GPIO3; + alc_setup_gpio(codec, 0x03); break; case 5: default: @@ -1107,12 +1137,12 @@ static void alc880_fixup_vol_knob(struct hda_codec *codec,
static const struct hda_fixup alc880_fixups[] = { [ALC880_FIXUP_GPIO1] = { - .type = HDA_FIXUP_VERBS, - .v.verbs = alc_gpio1_init_verbs, + .type = HDA_FIXUP_FUNC, + .v.func = alc_fixup_gpio1, }, [ALC880_FIXUP_GPIO2] = { - .type = HDA_FIXUP_VERBS, - .v.verbs = alc_gpio2_init_verbs, + .type = HDA_FIXUP_FUNC, + .v.func = alc_fixup_gpio2, }, [ALC880_FIXUP_MEDION_RIM] = { .type = HDA_FIXUP_VERBS, @@ -1565,7 +1595,7 @@ static void alc260_fixup_gpio1_toggle(struct hda_codec *codec, spec->gen.autocfg.hp_pins[0] = 0x0f; /* copy it for automute */ snd_hda_jack_detect_enable_callback(codec, 0x0f, snd_hda_gen_hp_automute); - snd_hda_add_verbs(codec, alc_gpio1_init_verbs); + alc_setup_gpio(codec, 0x01); } }
@@ -1639,8 +1669,8 @@ static const struct hda_fixup alc260_fixups[] = { }, }, [ALC260_FIXUP_GPIO1] = { - .type = HDA_FIXUP_VERBS, - .v.verbs = alc_gpio1_init_verbs, + .type = HDA_FIXUP_FUNC, + .v.func = alc_fixup_gpio1, }, [ALC260_FIXUP_GPIO1_TOGGLE] = { .type = HDA_FIXUP_FUNC, @@ -2144,20 +2174,20 @@ static const struct hda_fixup alc882_fixups[] = { } }, [ALC882_FIXUP_GPIO1] = { - .type = HDA_FIXUP_VERBS, - .v.verbs = alc_gpio1_init_verbs, + .type = HDA_FIXUP_FUNC, + .v.func = alc_fixup_gpio1, }, [ALC882_FIXUP_GPIO2] = { - .type = HDA_FIXUP_VERBS, - .v.verbs = alc_gpio2_init_verbs, + .type = HDA_FIXUP_FUNC, + .v.func = alc_fixup_gpio2, }, [ALC882_FIXUP_GPIO3] = { - .type = HDA_FIXUP_VERBS, - .v.verbs = alc_gpio3_init_verbs, + .type = HDA_FIXUP_FUNC, + .v.func = alc_fixup_gpio3, }, [ALC882_FIXUP_ASUS_W2JC] = { - .type = HDA_FIXUP_VERBS, - .v.verbs = alc_gpio1_init_verbs, + .type = HDA_FIXUP_FUNC, + .v.func = alc_fixup_gpio1, .chained = true, .chain_id = ALC882_FIXUP_EAPD, }, @@ -5232,6 +5262,9 @@ static void alc282_fixup_asus_tx300(struct hda_codec *codec, snd_hda_jack_detect_enable_callback(codec, 0x1b, snd_hda_gen_hp_automute); break; + case HDA_FIXUP_ACT_PROBE: + spec->init_amp = ALC_INIT_DEFAULT; + break; case HDA_FIXUP_ACT_BUILD: /* this is a bit tricky; give more sane names for the main * (tablet) speaker and the dock speaker, respectively
For updating GPIO bits dynamically, provide a new helper, and use it from the alc260 automute hook. This helper will be used by other places in future, too.
Signed-off-by: Takashi Iwai tiwai@suse.de --- sound/pci/hda/patch_realtek.c | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-)
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 489075b23652..bd54d9e25440 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -241,6 +241,20 @@ static void alc_write_gpio_data(struct hda_codec *codec) spec->gpio_data); }
+static void alc_update_gpio_data(struct hda_codec *codec, unsigned int mask, + bool on) +{ + struct alc_spec *spec = codec->spec; + unsigned int oldval = spec->gpio_data; + + if (on) + spec->gpio_data |= mask; + else + spec->gpio_data &= ~mask; + if (oldval != spec->gpio_data) + alc_write_gpio_data(codec); +} + static void alc_write_gpio(struct hda_codec *codec) { struct alc_spec *spec = codec->spec; @@ -1577,8 +1591,8 @@ enum { static void alc260_gpio1_automute(struct hda_codec *codec) { struct alc_spec *spec = codec->spec; - snd_hda_codec_write(codec, 0x01, 0, AC_VERB_SET_GPIO_DATA, - spec->gen.hp_jack_present); + + alc_update_gpio_data(codec, 0x01, spec->gen.hp_jack_present); }
static void alc260_fixup_gpio1_toggle(struct hda_codec *codec,
Until now, two fields, gpio_data and gpio_led, coexist in alc_spec although basically both of them serve for the same purpose -- the GPIO data bits.
This patch consolidates both usages and eliminates the superfluous gpio_led field.
Signed-off-by: Takashi Iwai tiwai@suse.de --- sound/pci/hda/patch_realtek.c | 28 ++++------------------------ 1 file changed, 4 insertions(+), 24 deletions(-)
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index bd54d9e25440..0db8329aa114 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -100,7 +100,6 @@ struct alc_spec { hda_nid_t mute_led_nid; hda_nid_t cap_mute_led_nid;
- unsigned int gpio_led; /* used for alc269_fixup_hp_gpio_led() */ unsigned int gpio_mute_led_mask; unsigned int gpio_mic_led_mask;
@@ -3497,9 +3496,8 @@ static int alc269_resume(struct hda_codec *codec) * suspend, and won't restore the data after resume, so we restore it * in the driver. */ - if (spec->gpio_led) - snd_hda_codec_write(codec, codec->core.afg, 0, AC_VERB_SET_GPIO_DATA, - spec->gpio_led); + if (spec->gpio_data) + alc_write_gpio_data(codec);
if (spec->has_alc5505_dsp) alc5505_dsp_resume(codec); @@ -3739,18 +3737,10 @@ static void alc_update_gpio_led(struct hda_codec *codec, unsigned int mask, bool enabled) { struct alc_spec *spec = codec->spec; - unsigned int oldval = spec->gpio_led;
if (spec->mute_led_polarity) enabled = !enabled; - - if (enabled) - spec->gpio_led &= ~mask; - else - spec->gpio_led |= mask; - if (spec->gpio_led != oldval) - snd_hda_codec_write(codec, 0x01, 0, AC_VERB_SET_GPIO_DATA, - spec->gpio_led); + alc_update_gpio_data(codec, mask, !enabled); /* muted -> LED on */ }
/* turn on/off mute LED via GPIO per vmaster hook */ @@ -3783,7 +3773,6 @@ static void alc269_fixup_hp_gpio_led(struct hda_codec *codec,
if (action == HDA_FIXUP_ACT_PRE_PROBE) { spec->gen.vmaster_mute.hook = alc_fixup_gpio_mute_hook; - spec->gpio_led = 0; spec->mute_led_polarity = 0; spec->gpio_mute_led_mask = 0x08; spec->gpio_mic_led_mask = 0x10; @@ -3804,7 +3793,6 @@ static void alc286_fixup_hp_gpio_led(struct hda_codec *codec,
if (action == HDA_FIXUP_ACT_PRE_PROBE) { spec->gen.vmaster_mute.hook = alc_fixup_gpio_mute_hook; - spec->gpio_led = 0; spec->mute_led_polarity = 0; spec->gpio_mute_led_mask = 0x02; spec->gpio_mic_led_mask = 0x20; @@ -3842,7 +3830,6 @@ static void alc269_fixup_hp_gpio_mic1_led(struct hda_codec *codec,
if (action == HDA_FIXUP_ACT_PRE_PROBE) { spec->gen.vmaster_mute.hook = alc_fixup_gpio_mute_hook; - spec->gpio_led = 0; spec->mute_led_polarity = 0; spec->gpio_mute_led_mask = 0x08; spec->cap_mute_led_nid = 0x18; @@ -3865,7 +3852,6 @@ static void alc280_fixup_hp_gpio4(struct hda_codec *codec,
if (action == HDA_FIXUP_ACT_PRE_PROBE) { spec->gen.vmaster_mute.hook = alc_fixup_gpio_mute_hook; - spec->gpio_led = 0; spec->mute_led_polarity = 0; spec->gpio_mute_led_mask = 0x08; spec->cap_mute_led_nid = 0x18; @@ -3948,7 +3934,6 @@ static void alc280_fixup_hp_gpio2_mic_hotkey(struct hda_codec *codec, gpio2_mic_hotkey_event);
spec->gen.vmaster_mute.hook = alc_fixup_gpio_mute_hook; - spec->gpio_led = 0; spec->mute_led_polarity = 0; spec->gpio_mute_led_mask = 0x08; spec->gpio_mic_led_mask = 0x10; @@ -3988,7 +3973,6 @@ static void alc233_fixup_lenovo_line2_mic_hotkey(struct hda_codec *codec, snd_hda_jack_detect_enable_callback(codec, 0x1b, gpio2_mic_hotkey_event);
- spec->gpio_led = 0; spec->mute_led_polarity = 0; spec->gpio_mic_led_mask = 0x04; snd_hda_gen_add_micmute_led(codec, alc_gpio_micmute_update); @@ -5365,9 +5349,6 @@ static void alc280_fixup_hp_9480m(struct hda_codec *codec, spec->gen.vmaster_mute.hook = alc_fixup_gpio_mute_hook; spec->gen.hp_automute_hook = alc280_hp_gpio4_automute_hook;
- /* The GPIOs are currently off */ - spec->gpio_led = 0; - /* GPIO3 is connected to the output mute LED, * high is on, low is off */ @@ -7592,7 +7573,7 @@ static unsigned int gpio_led_power_filter(struct hda_codec *codec, unsigned int power_state) { struct alc_spec *spec = codec->spec; - if (nid == codec->core.afg && power_state == AC_PWRST_D3 && spec->gpio_led) + if (nid == codec->core.afg && power_state == AC_PWRST_D3 && spec->gpio_data) return AC_PWRST_D0; return power_state; } @@ -7609,7 +7590,6 @@ static void alc662_fixup_led_gpio1(struct hda_codec *codec,
if (action == HDA_FIXUP_ACT_PRE_PROBE) { spec->gen.vmaster_mute.hook = alc_fixup_gpio_mute_hook; - spec->gpio_led = 0; spec->mute_led_polarity = 1; spec->gpio_mute_led_mask = 0x01; snd_hda_add_verbs(codec, gpio_init);
The fixup for Macbook Pro is nothing but setting the GPIO bits as usual but with one exception: it adds some delay at writing the GPIO bits.
Add a flag to put the conditional delay in the common helper, and clean up alc885_fixup_macpro_gpio() with the new flag.
Signed-off-by: Takashi Iwai tiwai@suse.de --- sound/pci/hda/patch_realtek.c | 44 ++++++----------------------------- 1 file changed, 7 insertions(+), 37 deletions(-)
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 0db8329aa114..786b29eb2ba9 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -94,6 +94,7 @@ struct alc_spec { unsigned int gpio_mask; unsigned int gpio_dir; unsigned int gpio_data; + bool gpio_write_delay; /* add a delay before writing gpio_data */
/* mute LED for HP laptops, see alc269_fixup_mic_mute_hook() */ int mute_led_polarity; @@ -265,6 +266,8 @@ static void alc_write_gpio(struct hda_codec *codec) AC_VERB_SET_GPIO_MASK, spec->gpio_mask); snd_hda_codec_write(codec, codec->core.afg, 0, AC_VERB_SET_GPIO_DIRECTION, spec->gpio_dir); + if (spec->gpio_write_delay) + msleep(1); alc_write_gpio_data(codec); }
@@ -1868,47 +1871,14 @@ static void alc889_fixup_coef(struct hda_codec *codec, alc_update_coef_idx(codec, 7, 0, 0x2030); }
-/* toggle speaker-output according to the hp-jack state */ -static void alc882_gpio_mute(struct hda_codec *codec, int pin, int muted) -{ - unsigned int gpiostate, gpiomask, gpiodir; - - gpiostate = snd_hda_codec_read(codec, codec->core.afg, 0, - AC_VERB_GET_GPIO_DATA, 0); - - if (!muted) - gpiostate |= (1 << pin); - else - gpiostate &= ~(1 << pin); - - gpiomask = snd_hda_codec_read(codec, codec->core.afg, 0, - AC_VERB_GET_GPIO_MASK, 0); - gpiomask |= (1 << pin); - - gpiodir = snd_hda_codec_read(codec, codec->core.afg, 0, - AC_VERB_GET_GPIO_DIRECTION, 0); - gpiodir |= (1 << pin); - - - snd_hda_codec_write(codec, codec->core.afg, 0, - AC_VERB_SET_GPIO_MASK, gpiomask); - snd_hda_codec_write(codec, codec->core.afg, 0, - AC_VERB_SET_GPIO_DIRECTION, gpiodir); - - msleep(1); - - snd_hda_codec_write(codec, codec->core.afg, 0, - AC_VERB_SET_GPIO_DATA, gpiostate); -} - /* set up GPIO at initialization */ static void alc885_fixup_macpro_gpio(struct hda_codec *codec, const struct hda_fixup *fix, int action) { - if (action != HDA_FIXUP_ACT_INIT) - return; - alc882_gpio_mute(codec, 0, 0); - alc882_gpio_mute(codec, 1, 0); + struct alc_spec *spec = codec->spec; + + spec->gpio_write_delay = true; + alc_fixup_gpio3(codec, fix, action); }
/* Fix the connection of some pins for ALC889:
Now we can simplify the mute LED GPIO handling as well. Each fixup dealing with GPIO for the mute LED controls defined the static init verbs, and they are converted to the common GPIO bit fields with the new helper, alc_fixup_hp_gpio_led().
Signed-off-by: Takashi Iwai tiwai@suse.de --- sound/pci/hda/patch_realtek.c | 149 +++++++++++----------------------- 1 file changed, 46 insertions(+), 103 deletions(-)
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 786b29eb2ba9..a0881ffcd9d7 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -3731,44 +3731,38 @@ static void alc_gpio_micmute_update(struct hda_codec *codec) spec->gen.micmute_led.led_value); }
-static void alc269_fixup_hp_gpio_led(struct hda_codec *codec, - const struct hda_fixup *fix, int action) +/* setup mute and mic-mute GPIO bits, add hooks appropriately */ +static void alc_fixup_hp_gpio_led(struct hda_codec *codec, + int action, + unsigned int mute_mask, + unsigned int micmute_mask) { struct alc_spec *spec = codec->spec; - static const struct hda_verb gpio_init[] = { - { 0x01, AC_VERB_SET_GPIO_MASK, 0x18 }, - { 0x01, AC_VERB_SET_GPIO_DIRECTION, 0x18 }, - {} - };
- if (action == HDA_FIXUP_ACT_PRE_PROBE) { + alc_fixup_gpio(codec, action, mute_mask | micmute_mask); + + if (action != HDA_FIXUP_ACT_PRE_PROBE) + return; + if (mute_mask) { + spec->gpio_mute_led_mask = mute_mask; spec->gen.vmaster_mute.hook = alc_fixup_gpio_mute_hook; - spec->mute_led_polarity = 0; - spec->gpio_mute_led_mask = 0x08; - spec->gpio_mic_led_mask = 0x10; - snd_hda_add_verbs(codec, gpio_init); + } + if (micmute_mask) { + spec->gpio_mic_led_mask = micmute_mask; snd_hda_gen_add_micmute_led(codec, alc_gpio_micmute_update); } }
-static void alc286_fixup_hp_gpio_led(struct hda_codec *codec, +static void alc269_fixup_hp_gpio_led(struct hda_codec *codec, const struct hda_fixup *fix, int action) { - struct alc_spec *spec = codec->spec; - static const struct hda_verb gpio_init[] = { - { 0x01, AC_VERB_SET_GPIO_MASK, 0x22 }, - { 0x01, AC_VERB_SET_GPIO_DIRECTION, 0x22 }, - {} - }; + alc_fixup_hp_gpio_led(codec, action, 0x08, 0x10); +}
- if (action == HDA_FIXUP_ACT_PRE_PROBE) { - spec->gen.vmaster_mute.hook = alc_fixup_gpio_mute_hook; - spec->mute_led_polarity = 0; - spec->gpio_mute_led_mask = 0x02; - spec->gpio_mic_led_mask = 0x20; - snd_hda_add_verbs(codec, gpio_init); - snd_hda_gen_add_micmute_led(codec, alc_gpio_micmute_update); - } +static void alc286_fixup_hp_gpio_led(struct hda_codec *codec, + const struct hda_fixup *fix, int action) +{ + alc_fixup_hp_gpio_led(codec, action, 0x02, 0x20); }
/* turn on/off mic-mute LED per capture hook */ @@ -3792,18 +3786,15 @@ static void alc269_fixup_hp_gpio_mic1_led(struct hda_codec *codec, const struct hda_fixup *fix, int action) { struct alc_spec *spec = codec->spec; - static const struct hda_verb gpio_init[] = { - { 0x01, AC_VERB_SET_GPIO_MASK, 0x08 }, - { 0x01, AC_VERB_SET_GPIO_DIRECTION, 0x08 }, - {} - };
+ alc_fixup_hp_gpio_led(codec, action, 0x08, 0); if (action == HDA_FIXUP_ACT_PRE_PROBE) { - spec->gen.vmaster_mute.hook = alc_fixup_gpio_mute_hook; - spec->mute_led_polarity = 0; - spec->gpio_mute_led_mask = 0x08; + /* Like hp_gpio_mic1_led, but also needs GPIO4 low to + * enable headphone amp + */ + spec->gpio_mask |= 0x10; + spec->gpio_dir |= 0x10; spec->cap_mute_led_nid = 0x18; - snd_hda_add_verbs(codec, gpio_init); snd_hda_gen_add_micmute_led(codec, alc_cap_micmute_update); codec->power_filter = led_power_filter; } @@ -3812,20 +3803,11 @@ static void alc269_fixup_hp_gpio_mic1_led(struct hda_codec *codec, static void alc280_fixup_hp_gpio4(struct hda_codec *codec, const struct hda_fixup *fix, int action) { - /* Like hp_gpio_mic1_led, but also needs GPIO4 low to enable headphone amp */ struct alc_spec *spec = codec->spec; - static const struct hda_verb gpio_init[] = { - { 0x01, AC_VERB_SET_GPIO_MASK, 0x18 }, - { 0x01, AC_VERB_SET_GPIO_DIRECTION, 0x18 }, - {} - };
+ alc_fixup_hp_gpio_led(codec, action, 0x08, 0); if (action == HDA_FIXUP_ACT_PRE_PROBE) { - spec->gen.vmaster_mute.hook = alc_fixup_gpio_mute_hook; - spec->mute_led_polarity = 0; - spec->gpio_mute_led_mask = 0x08; spec->cap_mute_led_nid = 0x18; - snd_hda_add_verbs(codec, gpio_init); snd_hda_gen_add_micmute_led(codec, alc_cap_micmute_update); codec->power_filter = led_power_filter; } @@ -3876,38 +3858,29 @@ static int alc_register_micmute_input_device(struct hda_codec *codec) return 0; }
+/* GPIO1 = set according to SKU external amp + * GPIO2 = mic mute hotkey + * GPIO3 = mute LED + * GPIO4 = mic mute LED + */ static void alc280_fixup_hp_gpio2_mic_hotkey(struct hda_codec *codec, const struct hda_fixup *fix, int action) { - /* GPIO1 = set according to SKU external amp - GPIO2 = mic mute hotkey - GPIO3 = mute LED - GPIO4 = mic mute LED */ - static const struct hda_verb gpio_init[] = { - { 0x01, AC_VERB_SET_GPIO_MASK, 0x1e }, - { 0x01, AC_VERB_SET_GPIO_DIRECTION, 0x1a }, - { 0x01, AC_VERB_SET_GPIO_DATA, 0x02 }, - {} - }; - struct alc_spec *spec = codec->spec;
+ alc_fixup_hp_gpio_led(codec, action, 0x08, 0x10); if (action == HDA_FIXUP_ACT_PRE_PROBE) { spec->init_amp = ALC_INIT_DEFAULT; if (alc_register_micmute_input_device(codec) != 0) return;
- snd_hda_add_verbs(codec, gpio_init); + spec->gpio_mask |= 0x06; + spec->gpio_dir |= 0x02; + spec->gpio_data |= 0x02; snd_hda_codec_write_cache(codec, codec->core.afg, 0, AC_VERB_SET_GPIO_UNSOLICITED_RSP_MASK, 0x04); snd_hda_jack_detect_enable_callback(codec, codec->core.afg, gpio2_mic_hotkey_event); - - spec->gen.vmaster_mute.hook = alc_fixup_gpio_mute_hook; - spec->mute_led_polarity = 0; - spec->gpio_mute_led_mask = 0x08; - spec->gpio_mic_led_mask = 0x10; - snd_hda_gen_add_micmute_led(codec, alc_gpio_micmute_update); return; }
@@ -3921,31 +3894,22 @@ static void alc280_fixup_hp_gpio2_mic_hotkey(struct hda_codec *codec, } }
+/* Line2 = mic mute hotkey + * GPIO2 = mic mute LED + */ static void alc233_fixup_lenovo_line2_mic_hotkey(struct hda_codec *codec, const struct hda_fixup *fix, int action) { - /* Line2 = mic mute hotkey - GPIO2 = mic mute LED */ - static const struct hda_verb gpio_init[] = { - { 0x01, AC_VERB_SET_GPIO_MASK, 0x04 }, - { 0x01, AC_VERB_SET_GPIO_DIRECTION, 0x04 }, - {} - }; - struct alc_spec *spec = codec->spec;
+ alc_fixup_hp_gpio_led(codec, action, 0, 0x04); if (action == HDA_FIXUP_ACT_PRE_PROBE) { spec->init_amp = ALC_INIT_DEFAULT; if (alc_register_micmute_input_device(codec) != 0) return;
- snd_hda_add_verbs(codec, gpio_init); snd_hda_jack_detect_enable_callback(codec, 0x1b, gpio2_mic_hotkey_event); - - spec->mute_led_polarity = 0; - spec->gpio_mic_led_mask = 0x04; - snd_hda_gen_add_micmute_led(codec, alc_gpio_micmute_update); return; }
@@ -5306,27 +5270,13 @@ static void alc280_fixup_hp_9480m(struct hda_codec *codec, int action) { struct alc_spec *spec = codec->spec; - static const struct hda_verb gpio_init[] = { - { 0x01, AC_VERB_SET_GPIO_MASK, 0x18 }, - { 0x01, AC_VERB_SET_GPIO_DIRECTION, 0x18 }, - {} - };
+ alc_fixup_hp_gpio_led(codec, action, 0x08, 0); if (action == HDA_FIXUP_ACT_PRE_PROBE) { - /* Set the hooks to turn the headphone amp on/off - * as needed - */ - spec->gen.vmaster_mute.hook = alc_fixup_gpio_mute_hook; + /* amp at GPIO4; toggled via alc280_hp_gpio4_automute_hook() */ + spec->gpio_mask |= 0x10; + spec->gpio_dir |= 0x10; spec->gen.hp_automute_hook = alc280_hp_gpio4_automute_hook; - - /* GPIO3 is connected to the output mute LED, - * high is on, low is off - */ - spec->mute_led_polarity = 0; - spec->gpio_mute_led_mask = 0x08; - - /* Initialize GPIO configuration */ - snd_hda_add_verbs(codec, gpio_init); } }
@@ -7552,17 +7502,10 @@ static void alc662_fixup_led_gpio1(struct hda_codec *codec, const struct hda_fixup *fix, int action) { struct alc_spec *spec = codec->spec; - static const struct hda_verb gpio_init[] = { - { 0x01, AC_VERB_SET_GPIO_MASK, 0x01 }, - { 0x01, AC_VERB_SET_GPIO_DIRECTION, 0x01 }, - {} - };
+ alc_fixup_hp_gpio_led(codec, action, 0x01, 0); if (action == HDA_FIXUP_ACT_PRE_PROBE) { - spec->gen.vmaster_mute.hook = alc_fixup_gpio_mute_hook; spec->mute_led_polarity = 1; - spec->gpio_mute_led_mask = 0x01; - snd_hda_add_verbs(codec, gpio_init); codec->power_filter = gpio_led_power_filter; } }
This patch converts the remaining static init verbs for GPIO bits with the common gpio_* fields management. Only the verbs setting the GPIO data bits are targeted in this patch. The rest will be changed in later patches.
Signed-off-by: Takashi Iwai tiwai@suse.de --- sound/pci/hda/patch_realtek.c | 49 +++++++++++++++++++---------------- 1 file changed, 26 insertions(+), 23 deletions(-)
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index a0881ffcd9d7..f5cc506504c0 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -296,6 +296,12 @@ static void alc_fixup_gpio3(struct hda_codec *codec, alc_fixup_gpio(codec, action, 0x03); }
+static void alc_fixup_gpio4(struct hda_codec *codec, + const struct hda_fixup *fix, int action) +{ + alc_fixup_gpio(codec, action, 0x04); +} + /* * Fix hardware PLL issue * On some codecs, the analog PLL gating control must be off while @@ -5172,13 +5178,6 @@ static void alc282_fixup_asus_tx300(struct hda_codec *codec, const struct hda_fixup *fix, int action) { struct alc_spec *spec = codec->spec; - /* TX300 needs to set up GPIO2 for the speaker amp */ - static const struct hda_verb gpio2_verbs[] = { - { 0x01, AC_VERB_SET_GPIO_MASK, 0x04 }, - { 0x01, AC_VERB_SET_GPIO_DIRECTION, 0x04 }, - { 0x01, AC_VERB_SET_GPIO_DATA, 0x04 }, - {} - }; static const struct hda_pintbl dock_pins[] = { { 0x1b, 0x21114000 }, /* dock speaker pin */ {} @@ -5187,7 +5186,8 @@ static void alc282_fixup_asus_tx300(struct hda_codec *codec, switch (action) { case HDA_FIXUP_ACT_PRE_PROBE: spec->init_amp = ALC_INIT_DEFAULT; - snd_hda_add_verbs(codec, gpio2_verbs); + /* TX300 needs to set up GPIO2 for the speaker amp */ + alc_setup_gpio(codec, 0x04); snd_hda_apply_pincfgs(codec, dock_pins); spec->gen.auto_mute_via_amp = 1; spec->gen.automute_hook = asus_tx300_automute; @@ -5280,6 +5280,19 @@ static void alc280_fixup_hp_9480m(struct hda_codec *codec, } }
+static void alc275_fixup_gpio4_off(struct hda_codec *codec, + const struct hda_fixup *fix, + int action) +{ + struct alc_spec *spec = codec->spec; + + if (action == HDA_FIXUP_ACT_PRE_PROBE) { + spec->gpio_mask |= 0x04; + spec->gpio_dir |= 0x04; + /* set data bit low */ + } +} + static void alc233_alc662_fixup_lenovo_dual_codecs(struct hda_codec *codec, const struct hda_fixup *fix, int action) @@ -5468,13 +5481,8 @@ static const struct hda_fixup alc269_fixups[] = { } }, [ALC275_FIXUP_SONY_VAIO_GPIO2] = { - .type = HDA_FIXUP_VERBS, - .v.verbs = (const struct hda_verb[]) { - {0x01, AC_VERB_SET_GPIO_MASK, 0x04}, - {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x04}, - {0x01, AC_VERB_SET_GPIO_DATA, 0x00}, - { } - }, + .type = HDA_FIXUP_FUNC, + .v.func = alc275_fixup_gpio4_off, .chained = true, .chain_id = ALC269_FIXUP_SONY_VAIO }, @@ -6219,14 +6227,9 @@ static const struct hda_fixup alc269_fixups[] = { .chain_id = ALC256_FIXUP_ASUS_HEADSET_MODE }, [ALC256_FIXUP_ASUS_AIO_GPIO2] = { - .type = HDA_FIXUP_VERBS, - .v.verbs = (const struct hda_verb[]) { - /* Set up GPIO2 for the speaker amp */ - { 0x01, AC_VERB_SET_GPIO_MASK, 0x04 }, - { 0x01, AC_VERB_SET_GPIO_DIRECTION, 0x04 }, - { 0x01, AC_VERB_SET_GPIO_DATA, 0x04 }, - {} - }, + .type = HDA_FIXUP_FUNC, + /* Set up GPIO2 for the speaker amp */ + .v.func = alc_fixup_gpio4, }, [ALC233_FIXUP_ASUS_MIC_NO_PRESENCE] = { .type = HDA_FIXUP_PINS,
Dell XPS13 has multi-step fixups, and one of them (ALC288_FIXUP_DELL_XPS_13_GPIO6) corresponds to the management of GPIO bit6 (0x40). It used to be a static init verbs (to turn *off* the bit6).
In this patch, we convert it as the gpio_mask and gpio_dir initializations folded in the existing fixup function. With this change, ALC288_FIXUP_DELL_XPS_13_GPIO6 becomes superfluous, thus it's removed.
Signed-off-by: Takashi Iwai tiwai@suse.de --- sound/pci/hda/patch_realtek.c | 24 ++++++------------------ 1 file changed, 6 insertions(+), 18 deletions(-)
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index f5cc506504c0..2cda4a614435 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -4881,13 +4881,10 @@ static void alc288_update_headset_jack_cb(struct hda_codec *codec, struct hda_jack_callback *jack) { struct alc_spec *spec = codec->spec; - int present;
alc_update_headset_jack_cb(codec, jack); /* Headset Mic enable or disable, only for Dell Dino */ - present = spec->gen.hp_jack_present ? 0x40 : 0; - snd_hda_codec_write(codec, 0x01, 0, AC_VERB_SET_GPIO_DATA, - present); + alc_update_gpio_data(codec, 0x40, spec->gen.hp_jack_present); }
static void alc_fixup_headset_mode_dell_alc288(struct hda_codec *codec, @@ -4896,6 +4893,9 @@ static void alc_fixup_headset_mode_dell_alc288(struct hda_codec *codec, alc_fixup_headset_mode(codec, fix, action); if (action == HDA_FIXUP_ACT_PROBE) { struct alc_spec *spec = codec->spec; + /* toggled via hp_automute_hook */ + spec->gpio_mask |= 0x40; + spec->gpio_dir |= 0x40; spec->gen.hp_automute_hook = alc288_update_headset_jack_cb; } } @@ -5433,7 +5433,6 @@ enum { ALC280_FIXUP_HP_9480M, ALC288_FIXUP_DELL_HEADSET_MODE, ALC288_FIXUP_DELL1_MIC_NO_PRESENCE, - ALC288_FIXUP_DELL_XPS_13_GPIO6, ALC288_FIXUP_DELL_XPS_13, ALC288_FIXUP_DISABLE_AAMIX, ALC292_FIXUP_DELL_E7X, @@ -6049,22 +6048,11 @@ static const struct hda_fixup alc269_fixups[] = { .chained = true, .chain_id = ALC288_FIXUP_DELL_HEADSET_MODE }, - [ALC288_FIXUP_DELL_XPS_13_GPIO6] = { - .type = HDA_FIXUP_VERBS, - .v.verbs = (const struct hda_verb[]) { - {0x01, AC_VERB_SET_GPIO_MASK, 0x40}, - {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x40}, - {0x01, AC_VERB_SET_GPIO_DATA, 0x00}, - { } - }, - .chained = true, - .chain_id = ALC288_FIXUP_DELL1_MIC_NO_PRESENCE - }, [ALC288_FIXUP_DISABLE_AAMIX] = { .type = HDA_FIXUP_FUNC, .v.func = alc_fixup_disable_aamix, .chained = true, - .chain_id = ALC288_FIXUP_DELL_XPS_13_GPIO6 + .chain_id = ALC288_FIXUP_DELL1_MIC_NO_PRESENCE }, [ALC288_FIXUP_DELL_XPS_13] = { .type = HDA_FIXUP_FUNC, @@ -6902,7 +6890,7 @@ static const struct snd_hda_pin_quirk alc269_pin_fixup_tbl[] = { {0x12, 0x90a60130}, {0x19, 0x03a11020}, {0x21, 0x0321101f}), - SND_HDA_PIN_QUIRK(0x10ec0288, 0x1028, "Dell", ALC288_FIXUP_DELL_XPS_13_GPIO6, + SND_HDA_PIN_QUIRK(0x10ec0288, 0x1028, "Dell", ALC288_FIXUP_DELL1_MIC_NO_PRESENCE, {0x12, 0x90a60120}, {0x14, 0x90170110}, {0x21, 0x0321101f}),
The ALC660VD_FIX_ASUS_GPIO1 quirk requires to set up GPIO bit0 ON while bit 1 OFF. Implement the fixup function and convert from the static init verbs.
Signed-off-by: Takashi Iwai tiwai@suse.de --- sound/pci/hda/patch_realtek.c | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-)
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 2cda4a614435..1ee086bcefcf 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -7354,16 +7354,21 @@ static void alc861vd_fixup_dallas(struct hda_codec *codec, } }
+/* reset GPIO1 */ +static void alc660vd_fixup_asus_gpio1(struct hda_codec *codec, + const struct hda_fixup *fix, int action) +{ + struct alc_spec *spec = codec->spec; + + if (action == HDA_FIXUP_ACT_PRE_PROBE) + spec->gpio_mask |= 0x02; + alc_fixup_gpio(codec, action, 0x01); +} + static const struct hda_fixup alc861vd_fixups[] = { [ALC660VD_FIX_ASUS_GPIO1] = { - .type = HDA_FIXUP_VERBS, - .v.verbs = (const struct hda_verb[]) { - /* reset GPIO1 */ - {0x01, AC_VERB_SET_GPIO_MASK, 0x03}, - {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x01}, - {0x01, AC_VERB_SET_GPIO_DATA, 0x01}, - { } - } + .type = HDA_FIXUP_FUNC, + .v.func = alc660vd_fixup_asus_gpio1, }, [ALC861VD_FIX_DALLAS] = { .type = HDA_FIXUP_FUNC,
The beep mixer controls are the only remaining stuff that uses spec->mixers[] array, and they can be well converted to the standard helper in the generic parser, snd_hda_gen_add_kctl().
This simplifies the code, especially the superfluous mixers and num_mixers fields can be now removed from alc_spec.
Signed-off-by: Takashi Iwai tiwai@suse.de --- sound/pci/hda/patch_realtek.c | 33 +++++++++------------------------ 1 file changed, 9 insertions(+), 24 deletions(-)
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 1ee086bcefcf..42d3b0f77577 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -83,8 +83,6 @@ struct alc_spec { struct hda_gen_spec gen; /* must be at head */
/* codec parameterization */ - const struct snd_kcontrol_new *mixers[5]; /* mixer arrays */ - unsigned int num_mixers; unsigned int beep_amp; /* beep amp value, set via set_beep_amp() */
struct alc_customize_define cdefine; @@ -207,18 +205,6 @@ static void alc_process_coef_fw(struct hda_codec *codec, } }
-/* - * Append the given mixer and verb elements for the later use - * The mixer array is referred in build_controls(), and init_verbs are - * called in init(). - */ -static void add_mixer(struct alc_spec *spec, const struct snd_kcontrol_new *mix) -{ - if (snd_BUG_ON(spec->num_mixers >= ARRAY_SIZE(spec->mixers))) - return; - spec->mixers[spec->num_mixers++] = mix; -} - /* * GPIO setup tables, used in initialization */ @@ -789,18 +775,12 @@ static const struct snd_kcontrol_new alc_beep_mixer[] = { static int alc_build_controls(struct hda_codec *codec) { struct alc_spec *spec = codec->spec; - int i, err; + int err;
err = snd_hda_gen_build_controls(codec); if (err < 0) return err;
- for (i = 0; i < spec->num_mixers; i++) { - err = snd_hda_add_new_ctls(codec, spec->mixers[i]); - if (err < 0) - return err; - } - #ifdef CONFIG_SND_HDA_INPUT_BEEP /* create beep controls if needed */ if (spec->beep_amp) { @@ -2663,7 +2643,6 @@ static const struct snd_kcontrol_new alc268_beep_mixer[] = { .put = alc268_beep_switch_put, .private_value = HDA_COMPOSE_AMP_VAL(0x0f, 3, 1, HDA_INPUT) }, - { } };
/* set PCBEEP vol = 0, mute connections */ @@ -2731,7 +2710,7 @@ static int alc268_parse_auto_config(struct hda_codec *codec) static int patch_alc268(struct hda_codec *codec) { struct alc_spec *spec; - int err; + int i, err;
/* ALC268 has no aa-loopback mixer */ err = alc_alloc_spec(codec, 0); @@ -2753,7 +2732,13 @@ static int patch_alc268(struct hda_codec *codec)
if (err > 0 && !spec->gen.no_analog && spec->gen.autocfg.speaker_pins[0] != 0x1d) { - add_mixer(spec, alc268_beep_mixer); + for (i = 0; i < ARRAY_SIZE(alc268_beep_mixer); i++) { + if (!snd_hda_gen_add_kctl(&spec->gen, NULL, + &alc268_beep_mixer[i])) { + err = -ENOMEM; + goto error; + } + } snd_hda_add_verbs(codec, alc268_beep_init_verbs); if (!query_amp_caps(codec, 0x1d, HDA_INPUT)) /* override the amp caps for beep generator */
In the Realtek codec driver, we used to build kctl elements for beep mixer in the own build_controls callback. This is an open-code and can be covered by the standard feature of the generic parser with snd_hda_gen_add_kctl() instead.
Also, after the conversion, spec->beep_amp becomes superfluous; hence it's removed along with the conversion.
Signed-off-by: Takashi Iwai tiwai@suse.de --- sound/pci/hda/patch_realtek.c | 114 +++++++++++++++++++--------------- 1 file changed, 65 insertions(+), 49 deletions(-)
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 42d3b0f77577..0e84d9cdd42d 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -83,8 +83,6 @@ struct alc_spec { struct hda_gen_spec gen; /* must be at head */
/* codec parameterization */ - unsigned int beep_amp; /* beep amp value, set via set_beep_amp() */ - struct alc_customize_define cdefine; unsigned int parse_flags; /* flag for snd_hda_parse_pin_defcfg() */
@@ -763,41 +761,14 @@ static void alc_fixup_inv_dmic(struct hda_codec *codec, }
-#ifdef CONFIG_SND_HDA_INPUT_BEEP -/* additional beep mixers; the actual parameters are overwritten at build */ -static const struct snd_kcontrol_new alc_beep_mixer[] = { - HDA_CODEC_VOLUME("Beep Playback Volume", 0, 0, HDA_INPUT), - HDA_CODEC_MUTE_BEEP("Beep Playback Switch", 0, 0, HDA_INPUT), - { } /* end */ -}; -#endif - static int alc_build_controls(struct hda_codec *codec) { - struct alc_spec *spec = codec->spec; int err;
err = snd_hda_gen_build_controls(codec); if (err < 0) return err;
-#ifdef CONFIG_SND_HDA_INPUT_BEEP - /* create beep controls if needed */ - if (spec->beep_amp) { - const struct snd_kcontrol_new *knew; - for (knew = alc_beep_mixer; knew->name; knew++) { - struct snd_kcontrol *kctl; - kctl = snd_ctl_new1(knew, codec); - if (!kctl) - return -ENOMEM; - kctl->private_value = spec->beep_amp; - err = snd_hda_ctl_add(codec, 0, kctl); - if (err < 0) - return err; - } - } -#endif - snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_BUILD); return 0; } @@ -1008,8 +979,30 @@ static int alc_codec_rename_from_preset(struct hda_codec *codec) * Digital-beep handlers */ #ifdef CONFIG_SND_HDA_INPUT_BEEP -#define set_beep_amp(spec, nid, idx, dir) \ - ((spec)->beep_amp = HDA_COMPOSE_AMP_VAL(nid, 3, idx, dir)) + +/* additional beep mixers; private_value will be overwritten */ +static const struct snd_kcontrol_new alc_beep_mixer[] = { + HDA_CODEC_VOLUME("Beep Playback Volume", 0, 0, HDA_INPUT), + HDA_CODEC_MUTE_BEEP("Beep Playback Switch", 0, 0, HDA_INPUT), +}; + +/* set up and create beep controls */ +static int set_beep_amp(struct alc_spec *spec, hda_nid_t nid, + int idx, int dir) +{ + struct snd_kcontrol_new *knew; + unsigned int beep_amp = HDA_COMPOSE_AMP_VAL(nid, 3, idx, dir); + int i; + + for (i = 0; i < ARRAY_SIZE(alc_beep_mixer); i++) { + knew = snd_hda_gen_add_kctl(&spec->gen, NULL, + &alc_beep_mixer[i]); + if (!knew) + return -ENOMEM; + knew->private_value = beep_amp; + } + return 0; +}
static const struct snd_pci_quirk beep_white_list[] = { SND_PCI_QUIRK(0x1043, 0x103c, "ASUS", 1), @@ -1034,7 +1027,7 @@ static inline int has_cdefine_beep(struct hda_codec *codec) return spec->cdefine.enable_pcbeep; } #else -#define set_beep_amp(spec, nid, idx, dir) /* NOP */ +#define set_beep_amp(spec, nid, idx, dir) 0 #define has_cdefine_beep(codec) 0 #endif
@@ -1536,8 +1529,11 @@ static int patch_alc880(struct hda_codec *codec) if (err < 0) goto error;
- if (!spec->gen.no_analog) - set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT); + if (!spec->gen.no_analog) { + err = set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT); + if (err < 0) + goto error; + }
snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PROBE);
@@ -1784,8 +1780,11 @@ static int patch_alc260(struct hda_codec *codec) if (err < 0) goto error;
- if (!spec->gen.no_analog) - set_beep_amp(spec, 0x07, 0x05, HDA_INPUT); + if (!spec->gen.no_analog) { + err = set_beep_amp(spec, 0x07, 0x05, HDA_INPUT); + if (err < 0) + goto error; + }
snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PROBE);
@@ -2434,8 +2433,11 @@ static int patch_alc882(struct hda_codec *codec) if (err < 0) goto error;
- if (!spec->gen.no_analog && spec->gen.beep_nid) - set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT); + if (!spec->gen.no_analog && spec->gen.beep_nid) { + err = set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT); + if (err < 0) + goto error; + }
snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PROBE);
@@ -2596,8 +2598,11 @@ static int patch_alc262(struct hda_codec *codec) if (err < 0) goto error;
- if (!spec->gen.no_analog && spec->gen.beep_nid) - set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT); + if (!spec->gen.no_analog && spec->gen.beep_nid) { + err = set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT); + if (err < 0) + goto error; + }
snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PROBE);
@@ -7168,8 +7173,11 @@ static int patch_alc269(struct hda_codec *codec) if (err < 0) goto error;
- if (!spec->gen.no_analog && spec->gen.beep_nid && spec->gen.mixer_nid) - set_beep_amp(spec, spec->gen.mixer_nid, 0x04, HDA_INPUT); + if (!spec->gen.no_analog && spec->gen.beep_nid && spec->gen.mixer_nid) { + err = set_beep_amp(spec, spec->gen.mixer_nid, 0x04, HDA_INPUT); + if (err < 0) + goto error; + }
snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PROBE);
@@ -7298,8 +7306,11 @@ static int patch_alc861(struct hda_codec *codec) if (err < 0) goto error;
- if (!spec->gen.no_analog) - set_beep_amp(spec, 0x23, 0, HDA_OUTPUT); + if (!spec->gen.no_analog) { + err = set_beep_amp(spec, 0x23, 0, HDA_OUTPUT); + if (err < 0) + goto error; + }
snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PROBE);
@@ -7392,8 +7403,11 @@ static int patch_alc861vd(struct hda_codec *codec) if (err < 0) goto error;
- if (!spec->gen.no_analog) - set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT); + if (!spec->gen.no_analog) { + err = set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT); + if (err < 0) + goto error; + }
snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PROBE);
@@ -8103,18 +8117,20 @@ static int patch_alc662(struct hda_codec *codec) if (!spec->gen.no_analog && spec->gen.beep_nid) { switch (codec->core.vendor_id) { case 0x10ec0662: - set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT); + err = set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT); break; case 0x10ec0272: case 0x10ec0663: case 0x10ec0665: case 0x10ec0668: - set_beep_amp(spec, 0x0b, 0x04, HDA_INPUT); + err = set_beep_amp(spec, 0x0b, 0x04, HDA_INPUT); break; case 0x10ec0273: - set_beep_amp(spec, 0x0b, 0x03, HDA_INPUT); + err = set_beep_amp(spec, 0x0b, 0x03, HDA_INPUT); break; } + if (err < 0) + goto error; }
snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PROBE);
Like the previous commit for Realtek codec, the similar cleanup work can be applied to Conexant codec, too. A slight difference is that the call of cx_auto_parse_beep() is moved after snd_hda_gen_parse_auto_config(). It's not strictly needed, but it'd be good to make the creation of such beep mixers at the end, which matches with the former situation.
Along with this conversion, cx_auto_build_controls() becomes just calling snd_hda_gen_build_controls(), so it's simply replaced with snd_hda_gen_build_controls.
Signed-off-by: Takashi Iwai tiwai@suse.de --- sound/pci/hda/patch_conexant.c | 85 +++++++++++----------------------- 1 file changed, 27 insertions(+), 58 deletions(-)
diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c index b7339cb5c45b..75ba66eb4ccd 100644 --- a/sound/pci/hda/patch_conexant.c +++ b/sound/pci/hda/patch_conexant.c @@ -37,8 +37,6 @@ struct conexant_spec { struct hda_gen_spec gen;
- unsigned int beep_amp; - /* extra EAPD pins */ unsigned int num_eapds; hda_nid_t eapds[4]; @@ -62,65 +60,48 @@ struct conexant_spec {
#ifdef CONFIG_SND_HDA_INPUT_BEEP -static inline void set_beep_amp(struct conexant_spec *spec, hda_nid_t nid, - int idx, int dir) -{ - spec->gen.beep_nid = nid; - spec->beep_amp = HDA_COMPOSE_AMP_VAL(nid, 1, idx, dir); -} -/* additional beep mixers; the actual parameters are overwritten at build */ +/* additional beep mixers; private_value will be overwritten */ static const struct snd_kcontrol_new cxt_beep_mixer[] = { HDA_CODEC_VOLUME_MONO("Beep Playback Volume", 0, 1, 0, HDA_OUTPUT), HDA_CODEC_MUTE_BEEP_MONO("Beep Playback Switch", 0, 1, 0, HDA_OUTPUT), - { } /* end */ };
-/* create beep controls if needed */ -static int add_beep_ctls(struct hda_codec *codec) +static int set_beep_amp(struct conexant_spec *spec, hda_nid_t nid, + int idx, int dir) { - struct conexant_spec *spec = codec->spec; - int err; + struct snd_kcontrol_new *knew; + unsigned int beep_amp = HDA_COMPOSE_AMP_VAL(nid, 1, idx, dir); + int i;
- if (spec->beep_amp) { - const struct snd_kcontrol_new *knew; - for (knew = cxt_beep_mixer; knew->name; knew++) { - struct snd_kcontrol *kctl; - kctl = snd_ctl_new1(knew, codec); - if (!kctl) - return -ENOMEM; - kctl->private_value = spec->beep_amp; - err = snd_hda_ctl_add(codec, 0, kctl); - if (err < 0) - return err; - } + spec->gen.beep_nid = nid; + for (i = 0; i < ARRAY_SIZE(cxt_beep_mixer); i++) { + knew = snd_hda_gen_add_kctl(&spec->gen, NULL, + &cxt_beep_mixer[i]); + if (!knew) + return -ENOMEM; + knew->private_value = beep_amp; } return 0; } -#else -#define set_beep_amp(spec, nid, idx, dir) /* NOP */ -#define add_beep_ctls(codec) 0 -#endif
-/* - * Automatic parser for CX20641 & co - */ - -#ifdef CONFIG_SND_HDA_INPUT_BEEP -static void cx_auto_parse_beep(struct hda_codec *codec) +static int cx_auto_parse_beep(struct hda_codec *codec) { struct conexant_spec *spec = codec->spec; hda_nid_t nid;
for_each_hda_codec_node(nid, codec) - if (get_wcaps_type(get_wcaps(codec, nid)) == AC_WID_BEEP) { - set_beep_amp(spec, nid, 0, HDA_OUTPUT); - break; - } + if (get_wcaps_type(get_wcaps(codec, nid)) == AC_WID_BEEP) + return set_beep_amp(spec, nid, 0, HDA_OUTPUT); + return 0; } #else -#define cx_auto_parse_beep(codec) +#define cx_auto_parse_beep(codec) 0 #endif
+/* + * Automatic parser for CX20641 & co + */ + /* parse EAPDs */ static void cx_auto_parse_eapd(struct hda_codec *codec) { @@ -179,21 +160,6 @@ static void cx_auto_vmaster_hook_mute_led(void *private_data, int enabled) enabled ? 0x00 : 0x02); }
-static int cx_auto_build_controls(struct hda_codec *codec) -{ - int err; - - err = snd_hda_gen_build_controls(codec); - if (err < 0) - return err; - - err = add_beep_ctls(codec); - if (err < 0) - return err; - - return 0; -} - static int cx_auto_init(struct hda_codec *codec) { struct conexant_spec *spec = codec->spec; @@ -234,7 +200,7 @@ static void cx_auto_free(struct hda_codec *codec) }
static const struct hda_codec_ops cx_auto_patch_ops = { - .build_controls = cx_auto_build_controls, + .build_controls = snd_hda_gen_build_controls, .build_pcms = snd_hda_gen_build_pcms, .init = cx_auto_init, .reboot_notify = cx_auto_reboot_notify, @@ -1033,7 +999,6 @@ static int patch_conexant_auto(struct hda_codec *codec) codec->spec = spec; codec->patch_ops = cx_auto_patch_ops;
- cx_auto_parse_beep(codec); cx_auto_parse_eapd(codec); spec->gen.own_eapd_ctl = 1; if (spec->dynamic_eapd) @@ -1093,6 +1058,10 @@ static int patch_conexant_auto(struct hda_codec *codec) if (err < 0) goto error;
+ err = cx_auto_parse_beep(codec); + if (err < 0) + goto error; + /* Some laptops with Conexant chips show stalls in S3 resume, * which falls into the single-cmd mode. * Better to make reset, then.
This patch moves the mixer creation code in Cirrus codec driver from its own build_controls callback to snd_hda_gen_add_kctl() for simplification.
As a bonus, this allows us to remove the cs421x_build_controls as it becomes identical with snd_hda_gen_build_controls().
Signed-off-by: Takashi Iwai tiwai@suse.de --- sound/pci/hda/patch_cirrus.c | 29 +++++++++-------------------- 1 file changed, 9 insertions(+), 20 deletions(-)
diff --git a/sound/pci/hda/patch_cirrus.c b/sound/pci/hda/patch_cirrus.c index d6e079f4ec09..a7f91be45194 100644 --- a/sound/pci/hda/patch_cirrus.c +++ b/sound/pci/hda/patch_cirrus.c @@ -1096,25 +1096,6 @@ static int cs421x_init(struct hda_codec *codec) return 0; }
-static int cs421x_build_controls(struct hda_codec *codec) -{ - struct cs_spec *spec = codec->spec; - int err; - - err = snd_hda_gen_build_controls(codec); - if (err < 0) - return err; - - if (spec->gen.autocfg.speaker_outs && - spec->vendor_nid == CS4210_VENDOR_NID) { - err = snd_hda_ctl_add(codec, 0, - snd_ctl_new1(&cs421x_speaker_boost_ctl, codec)); - if (err < 0) - return err; - } - return 0; -} - static void fix_volume_caps(struct hda_codec *codec, hda_nid_t dac) { unsigned int caps; @@ -1144,6 +1125,14 @@ static int cs421x_parse_auto_config(struct hda_codec *codec) return err;
parse_cs421x_digital(codec); + + if (spec->gen.autocfg.speaker_outs && + spec->vendor_nid == CS4210_VENDOR_NID) { + if (!snd_hda_gen_add_kctl(&spec->gen, NULL, + &cs421x_speaker_boost_ctl)) + return -ENOMEM; + } + return 0; }
@@ -1175,7 +1164,7 @@ static int cs421x_suspend(struct hda_codec *codec) #endif
static const struct hda_codec_ops cs421x_patch_ops = { - .build_controls = cs421x_build_controls, + .build_controls = snd_hda_gen_build_controls, .build_pcms = snd_hda_gen_build_pcms, .init = cs421x_init, .free = cs_free,
Currently VIA codec driver invokes via_free() at each place of the error path. Move the error handling to the end of each function commonly and do goto-error as a standard idiom.
This is a preliminary patch for the further cleanups, and no functional changes.
Signed-off-by: Takashi Iwai tiwai@suse.de --- sound/pci/hda/patch_via.c | 100 +++++++++++++++++++++++--------------- 1 file changed, 60 insertions(+), 40 deletions(-)
diff --git a/sound/pci/hda/patch_via.c b/sound/pci/hda/patch_via.c index fc30d1e8aa76..76e47d088a41 100644 --- a/sound/pci/hda/patch_via.c +++ b/sound/pci/hda/patch_via.c @@ -686,10 +686,8 @@ static int patch_vt1708(struct hda_codec *codec)
/* automatic parse from the BIOS config */ err = via_parse_auto_config(codec); - if (err < 0) { - via_free(codec); - return err; - } + if (err < 0) + goto error;
/* add jack detect on/off control */ spec->mixers[spec->num_mixers++] = vt1708_jack_detect_ctl; @@ -700,6 +698,10 @@ static int patch_vt1708(struct hda_codec *codec) codec->jackpoll_interval = 0;
return 0; + + error: + via_free(codec); + return err; }
static int patch_vt1709(struct hda_codec *codec) @@ -715,12 +717,14 @@ static int patch_vt1709(struct hda_codec *codec) spec->gen.mixer_nid = 0x18;
err = via_parse_auto_config(codec); - if (err < 0) { - via_free(codec); - return err; - } + if (err < 0) + goto error;
return 0; + + error: + via_free(codec); + return err; }
static int patch_vt1708S(struct hda_codec *codec); @@ -741,12 +745,14 @@ static int patch_vt1708B(struct hda_codec *codec)
/* automatic parse from the BIOS config */ err = via_parse_auto_config(codec); - if (err < 0) { - via_free(codec); - return err; - } + if (err < 0) + goto error;
return 0; + + error: + via_free(codec); + return err; }
/* Patch for VT1708S */ @@ -793,14 +799,16 @@ static int patch_vt1708S(struct hda_codec *codec)
/* automatic parse from the BIOS config */ err = via_parse_auto_config(codec); - if (err < 0) { - via_free(codec); - return err; - } + if (err < 0) + goto error;
spec->init_verbs[spec->num_iverbs++] = vt1708S_init_verbs;
return 0; + + error: + via_free(codec); + return err; }
/* Patch for VT1702 */ @@ -834,14 +842,16 @@ static int patch_vt1702(struct hda_codec *codec)
/* automatic parse from the BIOS config */ err = via_parse_auto_config(codec); - if (err < 0) { - via_free(codec); - return err; - } + if (err < 0) + goto error;
spec->init_verbs[spec->num_iverbs++] = vt1702_init_verbs;
return 0; + + error: + via_free(codec); + return err; }
/* Patch for VT1718S */ @@ -906,14 +916,16 @@ static int patch_vt1718S(struct hda_codec *codec)
/* automatic parse from the BIOS config */ err = via_parse_auto_config(codec); - if (err < 0) { - via_free(codec); - return err; - } + if (err < 0) + goto error;
spec->init_verbs[spec->num_iverbs++] = vt1718S_init_verbs;
return 0; + + error: + via_free(codec); + return err; }
/* Patch for VT1716S */ @@ -1002,10 +1014,8 @@ static int patch_vt1716S(struct hda_codec *codec)
/* automatic parse from the BIOS config */ err = via_parse_auto_config(codec); - if (err < 0) { - via_free(codec); - return err; - } + if (err < 0) + goto error;
spec->init_verbs[spec->num_iverbs++] = vt1716S_init_verbs;
@@ -1013,6 +1023,10 @@ static int patch_vt1716S(struct hda_codec *codec) spec->mixers[spec->num_mixers++] = vt1716S_mono_out_mixer;
return 0; + + error: + via_free(codec); + return err; }
/* for vt2002P */ @@ -1109,10 +1123,8 @@ static int patch_vt2002P(struct hda_codec *codec)
/* automatic parse from the BIOS config */ err = via_parse_auto_config(codec); - if (err < 0) { - via_free(codec); - return err; - } + if (err < 0) + goto error;
if (spec->codec_type == VT1802) spec->init_verbs[spec->num_iverbs++] = vt1802_init_verbs; @@ -1120,6 +1132,10 @@ static int patch_vt2002P(struct hda_codec *codec) spec->init_verbs[spec->num_iverbs++] = vt2002P_init_verbs;
return 0; + + error: + via_free(codec); + return err; }
/* for vt1812 */ @@ -1150,14 +1166,16 @@ static int patch_vt1812(struct hda_codec *codec)
/* automatic parse from the BIOS config */ err = via_parse_auto_config(codec); - if (err < 0) { - via_free(codec); - return err; - } + if (err < 0) + goto error;
spec->init_verbs[spec->num_iverbs++] = vt1812_init_verbs;
return 0; + + error: + via_free(codec); + return err; }
/* patch for vt3476 */ @@ -1187,14 +1205,16 @@ static int patch_vt3476(struct hda_codec *codec)
/* automatic parse from the BIOS config */ err = via_parse_auto_config(codec); - if (err < 0) { - via_free(codec); - return err; - } + if (err < 0) + goto error;
spec->init_verbs[spec->num_iverbs++] = vt3476_init_verbs;
return 0; + + error: + via_free(codec); + return err; }
/*
This patch replaces the control element creations in VIA codec driver with the standard snd_hda_gen_add_kctl() calls as a cleanup. There are two major fields targeted by this patch: the beep controls and static init controls.
The former is converted just like other codec drivers do. The spec->beep_amp field can be eliminated by this change as well.
The latter, static init controls, are replaced simply with explicit snd_hda_gen_add_kctl() calls.
After these conversions, via_build_controls() becomes superfluous and replaced with snd_hda_gen_build_controls(), too.
Signed-off-by: Takashi Iwai tiwai@suse.de --- sound/pci/hda/patch_via.c | 130 +++++++++++++------------------------- 1 file changed, 44 insertions(+), 86 deletions(-)
diff --git a/sound/pci/hda/patch_via.c b/sound/pci/hda/patch_via.c index 76e47d088a41..dc4961f0dfd1 100644 --- a/sound/pci/hda/patch_via.c +++ b/sound/pci/hda/patch_via.c @@ -91,9 +91,6 @@ struct via_spec { struct hda_gen_spec gen;
/* codec parameterization */ - const struct snd_kcontrol_new *mixers[6]; - unsigned int num_mixers; - const struct hda_verb *init_verbs[5]; unsigned int num_iverbs;
@@ -107,8 +104,6 @@ struct via_spec { /* work to check hp jack state */ int hp_work_active; int vt1708_jack_detect; - - unsigned int beep_amp; };
static enum VIA_HDA_CODEC get_codec_type(struct hda_codec *codec); @@ -262,69 +257,51 @@ static int via_pin_power_ctl_put(struct snd_kcontrol *kcontrol, return 1; }
-static const struct snd_kcontrol_new via_pin_power_ctl_enum[] = { - { +static const struct snd_kcontrol_new via_pin_power_ctl_enum = { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "Dynamic Power-Control", .info = via_pin_power_ctl_info, .get = via_pin_power_ctl_get, .put = via_pin_power_ctl_put, - }, - {} /* terminator */ };
#ifdef CONFIG_SND_HDA_INPUT_BEEP -static inline void set_beep_amp(struct via_spec *spec, hda_nid_t nid, - int idx, int dir) -{ - spec->gen.beep_nid = nid; - spec->beep_amp = HDA_COMPOSE_AMP_VAL(nid, 1, idx, dir); -} - /* additional beep mixers; the actual parameters are overwritten at build */ -static const struct snd_kcontrol_new cxt_beep_mixer[] = { +static const struct snd_kcontrol_new via_beep_mixer[] = { HDA_CODEC_VOLUME_MONO("Beep Playback Volume", 0, 1, 0, HDA_OUTPUT), HDA_CODEC_MUTE_BEEP_MONO("Beep Playback Switch", 0, 1, 0, HDA_OUTPUT), - { } /* end */ };
-/* create beep controls if needed */ -static int add_beep_ctls(struct hda_codec *codec) +static int set_beep_amp(struct via_spec *spec, hda_nid_t nid, + int idx, int dir) { - struct via_spec *spec = codec->spec; - int err; + struct snd_kcontrol_new *knew; + unsigned int beep_amp = HDA_COMPOSE_AMP_VAL(nid, 1, idx, dir); + int i;
- if (spec->beep_amp) { - const struct snd_kcontrol_new *knew; - for (knew = cxt_beep_mixer; knew->name; knew++) { - struct snd_kcontrol *kctl; - kctl = snd_ctl_new1(knew, codec); - if (!kctl) - return -ENOMEM; - kctl->private_value = spec->beep_amp; - err = snd_hda_ctl_add(codec, 0, kctl); - if (err < 0) - return err; - } + spec->gen.beep_nid = nid; + for (i = 0; i < ARRAY_SIZE(via_beep_mixer); i++) { + knew = snd_hda_gen_add_kctl(&spec->gen, NULL, + &via_beep_mixer[i]); + if (!knew) + return -ENOMEM; + knew->private_value = beep_amp; } return 0; }
-static void auto_parse_beep(struct hda_codec *codec) +static int auto_parse_beep(struct hda_codec *codec) { struct via_spec *spec = codec->spec; hda_nid_t nid;
for_each_hda_codec_node(nid, codec) - if (get_wcaps_type(get_wcaps(codec, nid)) == AC_WID_BEEP) { - set_beep_amp(spec, nid, 0, HDA_OUTPUT); - break; - } + if (get_wcaps_type(get_wcaps(codec, nid)) == AC_WID_BEEP) + return set_beep_amp(spec, nid, 0, HDA_OUTPUT); + return 0; } #else -#define set_beep_amp(spec, nid, idx, dir) /* NOP */ -#define add_beep_ctls(codec) 0 -#define auto_parse_beep(codec) +#define auto_parse_beep(codec) 0 #endif
/* check AA path's mute status */ @@ -403,30 +380,6 @@ static void analog_low_current_mode(struct hda_codec *codec) return __analog_low_current_mode(codec, false); }
-static int via_build_controls(struct hda_codec *codec) -{ - struct via_spec *spec = codec->spec; - int err, i; - - err = snd_hda_gen_build_controls(codec); - if (err < 0) - return err; - - err = add_beep_ctls(codec); - if (err < 0) - return err; - - spec->mixers[spec->num_mixers++] = via_pin_power_ctl_enum; - - for (i = 0; i < spec->num_mixers; i++) { - err = snd_hda_add_new_ctls(codec, spec->mixers[i]); - if (err < 0) - return err; - } - - return 0; -} - static void via_playback_pcm_hook(struct hda_pcm_stream *hinfo, struct hda_codec *codec, struct snd_pcm_substream *substream, @@ -481,7 +434,7 @@ static int via_check_power_status(struct hda_codec *codec, hda_nid_t nid) static int via_init(struct hda_codec *codec);
static const struct hda_codec_ops via_patch_ops = { - .build_controls = via_build_controls, + .build_controls = snd_hda_gen_build_controls, .build_pcms = snd_hda_gen_build_pcms, .init = via_init, .free = via_free, @@ -545,16 +498,13 @@ static int vt1708_jack_detect_put(struct snd_kcontrol *kcontrol, return 1; }
-static const struct snd_kcontrol_new vt1708_jack_detect_ctl[] = { - { +static const struct snd_kcontrol_new vt1708_jack_detect_ctl = { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "Jack Detect", .count = 1, .info = snd_ctl_boolean_mono_info, .get = vt1708_jack_detect_get, .put = vt1708_jack_detect_put, - }, - {} /* terminator */ };
static const struct badness_table via_main_out_badness = { @@ -586,12 +536,17 @@ static int via_parse_auto_config(struct hda_codec *codec) if (err < 0) return err;
- auto_parse_beep(codec); - err = snd_hda_gen_parse_auto_config(codec, &spec->gen.autocfg); if (err < 0) return err;
+ err = auto_parse_beep(codec); + if (err < 0) + return err; + + if (!snd_hda_gen_add_kctl(&spec->gen, NULL, &via_pin_power_ctl_enum)) + return -ENOMEM; + /* disable widget PM at start for compatibility */ codec->power_save_node = 0; spec->gen.power_down_unused = 0; @@ -623,7 +578,7 @@ static int vt1708_build_controls(struct hda_codec *codec) int err; int old_interval = codec->jackpoll_interval; codec->jackpoll_interval = msecs_to_jiffies(100); - err = via_build_controls(codec); + err = snd_hda_gen_build_controls(codec); codec->jackpoll_interval = old_interval; return err; } @@ -690,7 +645,10 @@ static int patch_vt1708(struct hda_codec *codec) goto error;
/* add jack detect on/off control */ - spec->mixers[spec->num_mixers++] = vt1708_jack_detect_ctl; + if (!snd_hda_gen_add_kctl(&spec->gen, NULL, &vt1708_jack_detect_ctl)) { + err = -ENOMEM; + goto error; + }
spec->init_verbs[spec->num_iverbs++] = vt1708_init_verbs;
@@ -967,9 +925,9 @@ static int vt1716s_dmic_put(struct snd_kcontrol *kcontrol, return 1; }
-static const struct snd_kcontrol_new vt1716s_dmic_mixer[] = { - HDA_CODEC_VOLUME("Digital Mic Capture Volume", 0x22, 0x0, HDA_INPUT), - { +static const struct snd_kcontrol_new vt1716s_dmic_mixer_vol = + HDA_CODEC_VOLUME("Digital Mic Capture Volume", 0x22, 0x0, HDA_INPUT); +static const struct snd_kcontrol_new vt1716s_dmic_mixer_sw = { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "Digital Mic Capture Switch", .subdevice = HDA_SUBDEV_NID_FLAG | 0x26, @@ -977,16 +935,12 @@ static const struct snd_kcontrol_new vt1716s_dmic_mixer[] = { .info = vt1716s_dmic_info, .get = vt1716s_dmic_get, .put = vt1716s_dmic_put, - }, - {} /* end */ };
/* mono-out mixer elements */ -static const struct snd_kcontrol_new vt1716S_mono_out_mixer[] = { - HDA_CODEC_MUTE("Mono Playback Switch", 0x2a, 0x0, HDA_OUTPUT), - { } /* end */ -}; +static const struct snd_kcontrol_new vt1716S_mono_out_mixer = + HDA_CODEC_MUTE("Mono Playback Switch", 0x2a, 0x0, HDA_OUTPUT);
static const struct hda_verb vt1716S_init_verbs[] = { /* Enable Boost Volume backdoor */ @@ -1019,8 +973,12 @@ static int patch_vt1716S(struct hda_codec *codec)
spec->init_verbs[spec->num_iverbs++] = vt1716S_init_verbs;
- spec->mixers[spec->num_mixers++] = vt1716s_dmic_mixer; - spec->mixers[spec->num_mixers++] = vt1716S_mono_out_mixer; + if (!snd_hda_gen_add_kctl(&spec->gen, NULL, &vt1716s_dmic_mixer_vol) || + !snd_hda_gen_add_kctl(&spec->gen, NULL, &vt1716s_dmic_mixer_sw) || + !snd_hda_gen_add_kctl(&spec->gen, NULL, &vt1716S_mono_out_mixer)) { + err = -ENOMEM; + goto error; + }
return 0;
In this patch, the remaining static init verbs in VIA codec driver are converted to the standard snd_hda_add_verbs() calls. The conversion is straightforward, but one change to be noted is the place of calls: since these verbs are supposed to be executed at the beginning of the init / resume procedure, we need to add snd_hda_add_verbs() calls before calling the other parsers.
This is merely a cleanup, no functional changes.
Signed-off-by: Takashi Iwai tiwai@suse.de --- sound/pci/hda/patch_via.c | 64 +++++++++++++++++++++------------------ 1 file changed, 35 insertions(+), 29 deletions(-)
diff --git a/sound/pci/hda/patch_via.c b/sound/pci/hda/patch_via.c index dc4961f0dfd1..6b9617aee0e6 100644 --- a/sound/pci/hda/patch_via.c +++ b/sound/pci/hda/patch_via.c @@ -90,10 +90,6 @@ enum VIA_HDA_CODEC { struct via_spec { struct hda_gen_spec gen;
- /* codec parameterization */ - const struct hda_verb *init_verbs[5]; - unsigned int num_iverbs; - /* HP mode source */ unsigned int dmic_enabled; enum VIA_HDA_CODEC codec_type; @@ -555,12 +551,6 @@ static int via_parse_auto_config(struct hda_codec *codec)
static int via_init(struct hda_codec *codec) { - struct via_spec *spec = codec->spec; - int i; - - for (i = 0; i < spec->num_iverbs; i++) - snd_hda_sequence_write(codec, spec->init_verbs[i]); - /* init power states */ __analog_low_current_mode(codec, true);
@@ -639,6 +629,10 @@ static int patch_vt1708(struct hda_codec *codec) vt1708_set_pinconfig_connect(codec, VT1708_HP_PIN_NID); vt1708_set_pinconfig_connect(codec, VT1708_CD_PIN_NID);
+ err = snd_hda_add_verbs(codec, vt1708_init_verbs); + if (err < 0) + goto error; + /* automatic parse from the BIOS config */ err = via_parse_auto_config(codec); if (err < 0) @@ -650,8 +644,6 @@ static int patch_vt1708(struct hda_codec *codec) goto error; }
- spec->init_verbs[spec->num_iverbs++] = vt1708_init_verbs; - /* clear jackpoll_interval again; it's set dynamically */ codec->jackpoll_interval = 0;
@@ -755,13 +747,15 @@ static int patch_vt1708S(struct hda_codec *codec) if (codec->core.vendor_id == 0x11064397) snd_hda_codec_set_name(codec, "VT1705");
+ err = snd_hda_add_verbs(codec, vt1708S_init_verbs); + if (err < 0) + goto error; + /* automatic parse from the BIOS config */ err = via_parse_auto_config(codec); if (err < 0) goto error;
- spec->init_verbs[spec->num_iverbs++] = vt1708S_init_verbs; - return 0;
error: @@ -798,13 +792,15 @@ static int patch_vt1702(struct hda_codec *codec) (0x5 << AC_AMPCAP_STEP_SIZE_SHIFT) | (1 << AC_AMPCAP_MUTE_SHIFT));
+ err = snd_hda_add_verbs(codec, vt1702_init_verbs); + if (err < 0) + goto error; + /* automatic parse from the BIOS config */ err = via_parse_auto_config(codec); if (err < 0) goto error;
- spec->init_verbs[spec->num_iverbs++] = vt1702_init_verbs; - return 0;
error: @@ -872,13 +868,15 @@ static int patch_vt1718S(struct hda_codec *codec) override_mic_boost(codec, 0x29, 0, 3, 40); add_secret_dac_path(codec);
+ err = snd_hda_add_verbs(codec, vt1718S_init_verbs); + if (err < 0) + goto error; + /* automatic parse from the BIOS config */ err = via_parse_auto_config(codec); if (err < 0) goto error;
- spec->init_verbs[spec->num_iverbs++] = vt1718S_init_verbs; - return 0;
error: @@ -966,13 +964,15 @@ static int patch_vt1716S(struct hda_codec *codec) override_mic_boost(codec, 0x1a, 0, 3, 40); override_mic_boost(codec, 0x1e, 0, 3, 40);
+ err = snd_hda_add_verbs(codec, vt1716S_init_verbs); + if (err < 0) + goto error; + /* automatic parse from the BIOS config */ err = via_parse_auto_config(codec); if (err < 0) goto error;
- spec->init_verbs[spec->num_iverbs++] = vt1716S_init_verbs; - if (!snd_hda_gen_add_kctl(&spec->gen, NULL, &vt1716s_dmic_mixer_vol) || !snd_hda_gen_add_kctl(&spec->gen, NULL, &vt1716s_dmic_mixer_sw) || !snd_hda_gen_add_kctl(&spec->gen, NULL, &vt1716S_mono_out_mixer)) { @@ -1079,16 +1079,18 @@ static int patch_vt2002P(struct hda_codec *codec) snd_hda_pick_fixup(codec, NULL, vt2002p_fixups, via_fixups); snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE);
+ if (spec->codec_type == VT1802) + err = snd_hda_add_verbs(codec, vt1802_init_verbs); + else + err = snd_hda_add_verbs(codec, vt2002P_init_verbs); + if (err < 0) + goto error; + /* automatic parse from the BIOS config */ err = via_parse_auto_config(codec); if (err < 0) goto error;
- if (spec->codec_type == VT1802) - spec->init_verbs[spec->num_iverbs++] = vt1802_init_verbs; - else - spec->init_verbs[spec->num_iverbs++] = vt2002P_init_verbs; - return 0;
error: @@ -1122,13 +1124,15 @@ static int patch_vt1812(struct hda_codec *codec) override_mic_boost(codec, 0x29, 0, 3, 40); add_secret_dac_path(codec);
+ err = snd_hda_add_verbs(codec, vt1812_init_verbs); + if (err < 0) + goto error; + /* automatic parse from the BIOS config */ err = via_parse_auto_config(codec); if (err < 0) goto error;
- spec->init_verbs[spec->num_iverbs++] = vt1812_init_verbs; - return 0;
error: @@ -1161,13 +1165,15 @@ static int patch_vt3476(struct hda_codec *codec) spec->gen.mixer_nid = 0x3f; add_secret_dac_path(codec);
+ err = snd_hda_add_verbs(codec, vt3476_init_verbs); + if (err < 0) + goto error; + /* automatic parse from the BIOS config */ err = via_parse_auto_config(codec); if (err < 0) goto error;
- spec->init_verbs[spec->num_iverbs++] = vt3476_init_verbs; - return 0;
error:
participants (1)
-
Takashi Iwai