Skip to content

Commit

Permalink
ALSA: hda - Fix inconsistent Mic mute LED
Browse files Browse the repository at this point in the history
The current code for controlling mic mute LED in patch_sigmatel.c
blindly assumes that there is a single capture switch.  But, there can
be multiple multiple ones, and each of them flips the state, ended up
in an inconsistent state.

For fixing this problem, this patch adds kcontrol to be passed to the
hook function so that the callee can check which switch is being
accessed.  In stac_capture_led_hook(), the state is checked as a
bitmask, and turns on the LED when all capture switches are off.

Signed-off-by: Takashi Iwai <tiwai@suse.de>
  • Loading branch information
Takashi Iwai committed Feb 7, 2014
1 parent f8f1bec commit 7fe3071
Show file tree
Hide file tree
Showing 6 changed files with 31 additions and 18 deletions.
8 changes: 4 additions & 4 deletions sound/pci/hda/hda_generic.c
Original file line number Diff line number Diff line change
Expand Up @@ -3269,7 +3269,7 @@ static int cap_put_caller(struct snd_kcontrol *kcontrol,
mutex_unlock(&codec->control_mutex);
snd_hda_codec_flush_cache(codec); /* flush the updates */
if (err >= 0 && spec->cap_sync_hook)
spec->cap_sync_hook(codec, ucontrol);
spec->cap_sync_hook(codec, kcontrol, ucontrol);
return err;
}

Expand Down Expand Up @@ -3390,7 +3390,7 @@ static int cap_single_sw_put(struct snd_kcontrol *kcontrol,
return ret;

if (spec->cap_sync_hook)
spec->cap_sync_hook(codec, ucontrol);
spec->cap_sync_hook(codec, kcontrol, ucontrol);

return ret;
}
Expand Down Expand Up @@ -3795,7 +3795,7 @@ static int mux_select(struct hda_codec *codec, unsigned int adc_idx,
return 0;
snd_hda_activate_path(codec, path, true, false);
if (spec->cap_sync_hook)
spec->cap_sync_hook(codec, NULL);
spec->cap_sync_hook(codec, NULL, NULL);
path_power_down_sync(codec, old_path);
return 1;
}
Expand Down Expand Up @@ -5270,7 +5270,7 @@ static void init_input_src(struct hda_codec *codec)
}

if (spec->cap_sync_hook)
spec->cap_sync_hook(codec, NULL);
spec->cap_sync_hook(codec, NULL, NULL);
}

/* set right pin controls for digital I/O */
Expand Down
1 change: 1 addition & 0 deletions sound/pci/hda/hda_generic.h
Original file line number Diff line number Diff line change
Expand Up @@ -274,6 +274,7 @@ struct hda_gen_spec {
void (*init_hook)(struct hda_codec *codec);
void (*automute_hook)(struct hda_codec *codec);
void (*cap_sync_hook)(struct hda_codec *codec,
struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol);

/* PCM hooks */
Expand Down
3 changes: 2 additions & 1 deletion sound/pci/hda/patch_conexant.c
Original file line number Diff line number Diff line change
Expand Up @@ -3291,7 +3291,8 @@ static void cxt_update_headset_mode(struct hda_codec *codec)
}

static void cxt_update_headset_mode_hook(struct hda_codec *codec,
struct snd_ctl_elem_value *ucontrol)
struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
cxt_update_headset_mode(codec);
}
Expand Down
9 changes: 6 additions & 3 deletions sound/pci/hda/patch_realtek.c
Original file line number Diff line number Diff line change
Expand Up @@ -708,7 +708,8 @@ static void alc_inv_dmic_sync(struct hda_codec *codec, bool force)
}

static void alc_inv_dmic_hook(struct hda_codec *codec,
struct snd_ctl_elem_value *ucontrol)
struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
alc_inv_dmic_sync(codec, false);
}
Expand Down Expand Up @@ -3218,7 +3219,8 @@ static void alc269_fixup_hp_gpio_mute_hook(void *private_data, int enabled)

/* turn on/off mic-mute LED per capture hook */
static void alc269_fixup_hp_gpio_mic_mute_hook(struct hda_codec *codec,
struct snd_ctl_elem_value *ucontrol)
struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct alc_spec *spec = codec->spec;
unsigned int oldval = spec->gpio_led;
Expand Down Expand Up @@ -3528,7 +3530,8 @@ static void alc_update_headset_mode(struct hda_codec *codec)
}

static void alc_update_headset_mode_hook(struct hda_codec *codec,
struct snd_ctl_elem_value *ucontrol)
struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
alc_update_headset_mode(codec);
}
Expand Down
27 changes: 17 additions & 10 deletions sound/pci/hda/patch_sigmatel.c
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,7 @@ struct sigmatel_spec {
int default_polarity;

unsigned int mic_mute_led_gpio; /* capture mute LED GPIO */
bool mic_mute_led_on; /* current mic mute state */
unsigned int mic_enabled; /* current mic mute state (bitmask) */

/* stream */
unsigned int stream_delay;
Expand Down Expand Up @@ -324,19 +324,26 @@ static void stac_gpio_set(struct hda_codec *codec, unsigned int mask,

/* hook for controlling mic-mute LED GPIO */
static void stac_capture_led_hook(struct hda_codec *codec,
struct snd_ctl_elem_value *ucontrol)
struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct sigmatel_spec *spec = codec->spec;
bool mute;
unsigned int mask;
bool cur_mute, prev_mute;

if (!ucontrol)
if (!kcontrol || !ucontrol)
return;

mute = !(ucontrol->value.integer.value[0] ||
ucontrol->value.integer.value[1]);
if (spec->mic_mute_led_on != mute) {
spec->mic_mute_led_on = mute;
if (mute)
mask = 1U << snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
prev_mute = !spec->mic_enabled;
if (ucontrol->value.integer.value[0] ||
ucontrol->value.integer.value[1])
spec->mic_enabled |= mask;
else
spec->mic_enabled &= ~mask;
cur_mute = !spec->mic_enabled;
if (cur_mute != prev_mute) {
if (cur_mute)
spec->gpio_data |= spec->mic_mute_led_gpio;
else
spec->gpio_data &= ~spec->mic_mute_led_gpio;
Expand Down Expand Up @@ -4462,7 +4469,7 @@ static void stac_setup_gpio(struct hda_codec *codec)
if (spec->mic_mute_led_gpio) {
spec->gpio_mask |= spec->mic_mute_led_gpio;
spec->gpio_dir |= spec->mic_mute_led_gpio;
spec->mic_mute_led_on = true;
spec->mic_enabled = 0;
spec->gpio_data |= spec->mic_mute_led_gpio;

spec->gen.cap_sync_hook = stac_capture_led_hook;
Expand Down
1 change: 1 addition & 0 deletions sound/pci/hda/thinkpad_helper.c
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ static void update_tpacpi_mute_led(void *private_data, int enabled)
}

static void update_tpacpi_micmute_led(struct hda_codec *codec,
struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
if (!ucontrol || !led_set_func)
Expand Down

0 comments on commit 7fe3071

Please sign in to comment.