summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sound/firewire/motu/motu-protocol-v2.c64
-rw-r--r--sound/firewire/motu/motu-protocol-v3.c19
-rw-r--r--sound/firewire/motu/motu.c19
-rw-r--r--sound/firewire/motu/motu.h5
-rw-r--r--sound/pci/ctxfi/ctmixer.c15
-rw-r--r--sound/pci/hda/dell_wmi_helper.c116
-rw-r--r--sound/pci/hda/hda_generic.c136
-rw-r--r--sound/pci/hda/hda_generic.h16
-rw-r--r--sound/pci/hda/patch_ca0132.c62
-rw-r--r--sound/pci/hda/patch_conexant.c13
-rw-r--r--sound/pci/hda/patch_realtek.c66
-rw-r--r--sound/pci/hda/patch_sigmatel.c31
-rw-r--r--sound/pci/hda/thinkpad_helper.c27
-rw-r--r--sound/pci/ice1712/prodigy_hifi.c21
-rw-r--r--sound/usb/line6/toneport.c5
15 files changed, 326 insertions, 289 deletions
diff --git a/sound/firewire/motu/motu-protocol-v2.c b/sound/firewire/motu/motu-protocol-v2.c
index 525b746330be..453fc29fade7 100644
--- a/sound/firewire/motu/motu-protocol-v2.c
+++ b/sound/firewire/motu/motu-protocol-v2.c
@@ -13,6 +13,8 @@
#define V2_CLOCK_RATE_SHIFT 3
#define V2_CLOCK_SRC_MASK 0x00000007
#define V2_CLOCK_SRC_SHIFT 0
+#define V2_CLOCK_TRAVELER_FETCH_DISABLE 0x04000000
+#define V2_CLOCK_TRAVELER_FETCH_ENABLE 0x03000000
#define V2_IN_OUT_CONF_OFFSET 0x0c04
#define V2_OPT_OUT_IFACE_MASK 0x00000c00
@@ -66,6 +68,11 @@ static int v2_set_clock_rate(struct snd_motu *motu, unsigned int rate)
data &= ~V2_CLOCK_RATE_MASK;
data |= i << V2_CLOCK_RATE_SHIFT;
+ if (motu->spec == &snd_motu_spec_traveler) {
+ data &= ~V2_CLOCK_TRAVELER_FETCH_ENABLE;
+ data |= V2_CLOCK_TRAVELER_FETCH_DISABLE;
+ }
+
reg = cpu_to_be32(data);
return snd_motu_transaction_write(motu, V2_CLOCK_STATUS_OFFSET, &reg,
sizeof(reg));
@@ -121,8 +128,31 @@ static int v2_get_clock_source(struct snd_motu *motu,
static int v2_switch_fetching_mode(struct snd_motu *motu, bool enable)
{
- /* V2 protocol doesn't have this feature. */
- return 0;
+ __be32 reg;
+ u32 data;
+ int err = 0;
+
+ if (motu->spec == &snd_motu_spec_traveler) {
+ err = snd_motu_transaction_read(motu, V2_CLOCK_STATUS_OFFSET,
+ &reg, sizeof(reg));
+ if (err < 0)
+ return err;
+ data = be32_to_cpu(reg);
+
+ data &= ~(V2_CLOCK_TRAVELER_FETCH_DISABLE |
+ V2_CLOCK_TRAVELER_FETCH_ENABLE);
+
+ if (enable)
+ data |= V2_CLOCK_TRAVELER_FETCH_ENABLE;
+ else
+ data |= V2_CLOCK_TRAVELER_FETCH_DISABLE;
+
+ reg = cpu_to_be32(data);
+ err = snd_motu_transaction_write(motu, V2_CLOCK_STATUS_OFFSET,
+ &reg, sizeof(reg));
+ }
+
+ return err;
}
static void calculate_fixed_part(struct snd_motu_packet_format *formats,
@@ -149,11 +179,20 @@ static void calculate_fixed_part(struct snd_motu_packet_format *formats,
pcm_chunks[1] += 2;
}
} else {
- /*
- * Packets to v2 units transfer main-out-1/2 and phone-out-1/2.
- */
- pcm_chunks[0] += 4;
- pcm_chunks[1] += 4;
+ if (flags & SND_MOTU_SPEC_RX_SEPARETED_MAIN) {
+ pcm_chunks[0] += 2;
+ pcm_chunks[1] += 2;
+ }
+
+ // Packets to v2 units include 2 chunks for phone 1/2, except
+ // for 176.4/192.0 kHz.
+ pcm_chunks[0] += 2;
+ pcm_chunks[1] += 2;
+ }
+
+ if (flags & SND_MOTU_SPEC_HAS_AESEBU_IFACE) {
+ pcm_chunks[0] += 2;
+ pcm_chunks[1] += 2;
}
/*
@@ -164,19 +203,16 @@ static void calculate_fixed_part(struct snd_motu_packet_format *formats,
pcm_chunks[0] += 2;
pcm_chunks[1] += 2;
- /* This part should be multiples of 4. */
- formats->fixed_part_pcm_chunks[0] = round_up(2 + pcm_chunks[0], 4) - 2;
- formats->fixed_part_pcm_chunks[1] = round_up(2 + pcm_chunks[1], 4) - 2;
- if (flags & SND_MOTU_SPEC_SUPPORT_CLOCK_X4)
- formats->fixed_part_pcm_chunks[2] =
- round_up(2 + pcm_chunks[2], 4) - 2;
+ formats->fixed_part_pcm_chunks[0] = pcm_chunks[0];
+ formats->fixed_part_pcm_chunks[1] = pcm_chunks[1];
+ formats->fixed_part_pcm_chunks[2] = pcm_chunks[2];
}
static void calculate_differed_part(struct snd_motu_packet_format *formats,
enum snd_motu_spec_flags flags,
u32 data, u32 mask, u32 shift)
{
- unsigned char pcm_chunks[3] = {0, 0};
+ unsigned char pcm_chunks[2] = {0, 0};
/*
* When optical interfaces are configured for S/PDIF (TOSLINK),
diff --git a/sound/firewire/motu/motu-protocol-v3.c b/sound/firewire/motu/motu-protocol-v3.c
index c7cd9864dc4d..7cc80a05e91f 100644
--- a/sound/firewire/motu/motu-protocol-v3.c
+++ b/sound/firewire/motu/motu-protocol-v3.c
@@ -188,11 +188,20 @@ static void calculate_fixed_part(struct snd_motu_packet_format *formats,
pcm_chunks[1] += 2;
}
} else {
- /*
- * Packets to v2 units transfer main-out-1/2 and phone-out-1/2.
- */
- pcm_chunks[0] += 4;
- pcm_chunks[1] += 4;
+ if (flags & SND_MOTU_SPEC_RX_SEPARETED_MAIN) {
+ pcm_chunks[0] += 2;
+ pcm_chunks[1] += 2;
+ }
+
+ // Packets to v3 units include 2 chunks for phone 1/2, except
+ // for 176.4/192.0 kHz.
+ pcm_chunks[0] += 2;
+ pcm_chunks[1] += 2;
+ }
+
+ if (flags & SND_MOTU_SPEC_HAS_AESEBU_IFACE) {
+ pcm_chunks[0] += 2;
+ pcm_chunks[1] += 2;
}
/*
diff --git a/sound/firewire/motu/motu.c b/sound/firewire/motu/motu.c
index 0d6b526105ab..300d31b6f191 100644
--- a/sound/firewire/motu/motu.c
+++ b/sound/firewire/motu/motu.c
@@ -200,6 +200,22 @@ static const struct snd_motu_spec motu_828mk2 = {
.flags = SND_MOTU_SPEC_SUPPORT_CLOCK_X2 |
SND_MOTU_SPEC_TX_MICINST_CHUNK |
SND_MOTU_SPEC_TX_RETURN_CHUNK |
+ SND_MOTU_SPEC_RX_SEPARETED_MAIN |
+ SND_MOTU_SPEC_HAS_OPT_IFACE_A |
+ SND_MOTU_SPEC_RX_MIDI_2ND_Q |
+ SND_MOTU_SPEC_TX_MIDI_2ND_Q,
+
+ .analog_in_ports = 8,
+ .analog_out_ports = 8,
+};
+
+const struct snd_motu_spec snd_motu_spec_traveler = {
+ .name = "Traveler",
+ .protocol = &snd_motu_protocol_v2,
+ .flags = SND_MOTU_SPEC_SUPPORT_CLOCK_X2 |
+ SND_MOTU_SPEC_SUPPORT_CLOCK_X4 |
+ SND_MOTU_SPEC_TX_RETURN_CHUNK |
+ SND_MOTU_SPEC_HAS_AESEBU_IFACE |
SND_MOTU_SPEC_HAS_OPT_IFACE_A |
SND_MOTU_SPEC_RX_MIDI_2ND_Q |
SND_MOTU_SPEC_TX_MIDI_2ND_Q,
@@ -216,6 +232,7 @@ static const struct snd_motu_spec motu_828mk3 = {
SND_MOTU_SPEC_TX_MICINST_CHUNK |
SND_MOTU_SPEC_TX_RETURN_CHUNK |
SND_MOTU_SPEC_TX_REVERB_CHUNK |
+ SND_MOTU_SPEC_RX_SEPARETED_MAIN |
SND_MOTU_SPEC_HAS_OPT_IFACE_A |
SND_MOTU_SPEC_HAS_OPT_IFACE_B |
SND_MOTU_SPEC_RX_MIDI_3RD_Q |
@@ -231,6 +248,7 @@ static const struct snd_motu_spec motu_audio_express = {
.flags = SND_MOTU_SPEC_SUPPORT_CLOCK_X2 |
SND_MOTU_SPEC_TX_MICINST_CHUNK |
SND_MOTU_SPEC_TX_RETURN_CHUNK |
+ SND_MOTU_SPEC_RX_SEPARETED_MAIN |
SND_MOTU_SPEC_RX_MIDI_2ND_Q |
SND_MOTU_SPEC_TX_MIDI_3RD_Q,
.analog_in_ports = 2,
@@ -250,6 +268,7 @@ static const struct snd_motu_spec motu_audio_express = {
static const struct ieee1394_device_id motu_id_table[] = {
SND_MOTU_DEV_ENTRY(0x101800, &motu_828mk2),
+ SND_MOTU_DEV_ENTRY(0x107800, &snd_motu_spec_traveler),
SND_MOTU_DEV_ENTRY(0x106800, &motu_828mk3), /* FireWire only. */
SND_MOTU_DEV_ENTRY(0x100800, &motu_828mk3), /* Hybrid. */
SND_MOTU_DEV_ENTRY(0x104800, &motu_audio_express),
diff --git a/sound/firewire/motu/motu.h b/sound/firewire/motu/motu.h
index 4b23cf337c4b..fd5327d30ab1 100644
--- a/sound/firewire/motu/motu.h
+++ b/sound/firewire/motu/motu.h
@@ -79,13 +79,14 @@ enum snd_motu_spec_flags {
SND_MOTU_SPEC_TX_MICINST_CHUNK = 0x0004,
SND_MOTU_SPEC_TX_RETURN_CHUNK = 0x0008,
SND_MOTU_SPEC_TX_REVERB_CHUNK = 0x0010,
- SND_MOTU_SPEC_TX_AESEBU_CHUNK = 0x0020,
+ SND_MOTU_SPEC_HAS_AESEBU_IFACE = 0x0020,
SND_MOTU_SPEC_HAS_OPT_IFACE_A = 0x0040,
SND_MOTU_SPEC_HAS_OPT_IFACE_B = 0x0080,
SND_MOTU_SPEC_RX_MIDI_2ND_Q = 0x0100,
SND_MOTU_SPEC_RX_MIDI_3RD_Q = 0x0200,
SND_MOTU_SPEC_TX_MIDI_2ND_Q = 0x0400,
SND_MOTU_SPEC_TX_MIDI_3RD_Q = 0x0800,
+ SND_MOTU_SPEC_RX_SEPARETED_MAIN = 0x1000,
};
#define SND_MOTU_CLOCK_RATE_COUNT 6
@@ -128,6 +129,8 @@ struct snd_motu_spec {
extern const struct snd_motu_protocol snd_motu_protocol_v2;
extern const struct snd_motu_protocol snd_motu_protocol_v3;
+extern const struct snd_motu_spec snd_motu_spec_traveler;
+
int amdtp_motu_init(struct amdtp_stream *s, struct fw_unit *unit,
enum amdtp_stream_direction dir,
const struct snd_motu_protocol *const protocol);
diff --git a/sound/pci/ctxfi/ctmixer.c b/sound/pci/ctxfi/ctmixer.c
index db710d0a609f..4777d50fbbf8 100644
--- a/sound/pci/ctxfi/ctmixer.c
+++ b/sound/pci/ctxfi/ctmixer.c
@@ -938,17 +938,18 @@ static int ct_mixer_topology_build(struct ct_mixer *mixer)
struct sum *sum;
struct amixer *amix_d, *amix_s;
enum CT_AMIXER_CTL i, j;
+ enum CT_SUM_CTL k;
/* Build topology from destination to source */
/* Set up Master mixer */
- for (i = AMIXER_MASTER_F, j = SUM_IN_F;
- i <= AMIXER_MASTER_S; i++, j++) {
+ for (i = AMIXER_MASTER_F, k = SUM_IN_F;
+ i <= AMIXER_MASTER_S; i++, k++) {
amix_d = mixer->amixers[i*CHN_NUM];
- sum = mixer->sums[j*CHN_NUM];
+ sum = mixer->sums[k*CHN_NUM];
amix_d->ops->setup(amix_d, &sum->rsc, INIT_VOL, NULL);
amix_d = mixer->amixers[i*CHN_NUM+1];
- sum = mixer->sums[j*CHN_NUM+1];
+ sum = mixer->sums[k*CHN_NUM+1];
amix_d->ops->setup(amix_d, &sum->rsc, INIT_VOL, NULL);
}
@@ -972,12 +973,12 @@ static int ct_mixer_topology_build(struct ct_mixer *mixer)
amix_d->ops->setup(amix_d, &amix_s->rsc, INIT_VOL, NULL);
/* Set up PCM-in mixer */
- for (i = AMIXER_PCM_F, j = SUM_IN_F; i <= AMIXER_PCM_S; i++, j++) {
+ for (i = AMIXER_PCM_F, k = SUM_IN_F; i <= AMIXER_PCM_S; i++, k++) {
amix_d = mixer->amixers[i*CHN_NUM];
- sum = mixer->sums[j*CHN_NUM];
+ sum = mixer->sums[k*CHN_NUM];
amix_d->ops->setup(amix_d, NULL, INIT_VOL, sum);
amix_d = mixer->amixers[i*CHN_NUM+1];
- sum = mixer->sums[j*CHN_NUM+1];
+ sum = mixer->sums[k*CHN_NUM+1];
amix_d->ops->setup(amix_d, NULL, INIT_VOL, sum);
}
diff --git a/sound/pci/hda/dell_wmi_helper.c b/sound/pci/hda/dell_wmi_helper.c
index 1b48a8c19d28..8a7dbd1a7fbf 100644
--- a/sound/pci/hda/dell_wmi_helper.c
+++ b/sound/pci/hda/dell_wmi_helper.c
@@ -6,111 +6,18 @@
#if IS_ENABLED(CONFIG_DELL_LAPTOP)
#include <linux/dell-led.h>
-enum {
- MICMUTE_LED_ON,
- MICMUTE_LED_OFF,
- MICMUTE_LED_FOLLOW_CAPTURE,
- MICMUTE_LED_FOLLOW_MUTE,
-};
-
-static int dell_led_mode = MICMUTE_LED_FOLLOW_MUTE;
-static int dell_capture;
-static int dell_led_value;
static int (*dell_micmute_led_set_func)(int);
-static void (*dell_old_cap_hook)(struct hda_codec *,
- struct snd_kcontrol *,
- struct snd_ctl_elem_value *);
-
-static void call_micmute_led_update(void)
-{
- int val;
-
- switch (dell_led_mode) {
- case MICMUTE_LED_ON:
- val = 1;
- break;
- case MICMUTE_LED_OFF:
- val = 0;
- break;
- case MICMUTE_LED_FOLLOW_CAPTURE:
- val = dell_capture;
- break;
- case MICMUTE_LED_FOLLOW_MUTE:
- default:
- val = !dell_capture;
- break;
- }
-
- if (val == dell_led_value)
- return;
- dell_led_value = val;
- dell_micmute_led_set_func(dell_led_value);
-}
-
-static void update_dell_wmi_micmute_led(struct hda_codec *codec,
- struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- if (dell_old_cap_hook)
- dell_old_cap_hook(codec, kcontrol, ucontrol);
-
- if (!ucontrol || !dell_micmute_led_set_func)
- return;
- if (strcmp("Capture Switch", ucontrol->id.name) == 0 && ucontrol->id.index == 0) {
- /* TODO: How do I verify if it's a mono or stereo here? */
- dell_capture = (ucontrol->value.integer.value[0] ||
- ucontrol->value.integer.value[1]);
- call_micmute_led_update();
- }
-}
-static int dell_mic_mute_led_mode_info(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_info *uinfo)
+static void dell_micmute_update(struct hda_codec *codec)
{
- static const char * const texts[] = {
- "On", "Off", "Follow Capture", "Follow Mute",
- };
-
- return snd_ctl_enum_info(uinfo, 1, ARRAY_SIZE(texts), texts);
-}
+ struct hda_gen_spec *spec = codec->spec;
-static int dell_mic_mute_led_mode_get(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- ucontrol->value.enumerated.item[0] = dell_led_mode;
- return 0;
+ dell_micmute_led_set_func(spec->micmute_led.led_value);
}
-static int dell_mic_mute_led_mode_put(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- unsigned int mode;
-
- mode = ucontrol->value.enumerated.item[0];
- if (mode > MICMUTE_LED_FOLLOW_MUTE)
- mode = MICMUTE_LED_FOLLOW_MUTE;
- if (mode == dell_led_mode)
- return 0;
- dell_led_mode = mode;
- call_micmute_led_update();
- return 1;
-}
-
-static const struct snd_kcontrol_new dell_mic_mute_mode_ctls[] = {
- {
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "Mic Mute-LED Mode",
- .info = dell_mic_mute_led_mode_info,
- .get = dell_mic_mute_led_mode_get,
- .put = dell_mic_mute_led_mode_put,
- },
- {}
-};
-
static void alc_fixup_dell_wmi(struct hda_codec *codec,
const struct hda_fixup *fix, int action)
{
- struct alc_spec *spec = codec->spec;
bool removefunc = false;
if (action == HDA_FIXUP_ACT_PROBE) {
@@ -121,25 +28,14 @@ static void alc_fixup_dell_wmi(struct hda_codec *codec,
return;
}
- removefunc = true;
- if (dell_micmute_led_set_func(false) >= 0) {
- dell_led_value = 0;
- if (spec->gen.num_adc_nids > 1 && !spec->gen.dyn_adc_switch)
- codec_dbg(codec, "Skipping micmute LED control due to several ADCs");
- else {
- dell_old_cap_hook = spec->gen.cap_sync_hook;
- spec->gen.cap_sync_hook = update_dell_wmi_micmute_led;
- removefunc = false;
- add_mixer(spec, dell_mic_mute_mode_ctls);
- }
- }
-
+ removefunc = (dell_micmute_led_set_func(false) < 0) ||
+ (snd_hda_gen_add_micmute_led(codec,
+ dell_micmute_update) <= 0);
}
if (dell_micmute_led_set_func && (action == HDA_FIXUP_ACT_FREE || removefunc)) {
symbol_put(dell_micmute_led_set);
dell_micmute_led_set_func = NULL;
- dell_old_cap_hook = NULL;
}
}
diff --git a/sound/pci/hda/hda_generic.c b/sound/pci/hda/hda_generic.c
index db773e219aaa..942f96e184b6 100644
--- a/sound/pci/hda/hda_generic.c
+++ b/sound/pci/hda/hda_generic.c
@@ -3900,6 +3900,142 @@ static int parse_mic_boost(struct hda_codec *codec)
}
/*
+ * mic mute LED hook helpers
+ */
+enum {
+ MICMUTE_LED_ON,
+ MICMUTE_LED_OFF,
+ MICMUTE_LED_FOLLOW_CAPTURE,
+ MICMUTE_LED_FOLLOW_MUTE,
+};
+
+static void call_micmute_led_update(struct hda_codec *codec)
+{
+ struct hda_gen_spec *spec = codec->spec;
+ unsigned int val;
+
+ switch (spec->micmute_led.led_mode) {
+ case MICMUTE_LED_ON:
+ val = 1;
+ break;
+ case MICMUTE_LED_OFF:
+ val = 0;
+ break;
+ case MICMUTE_LED_FOLLOW_CAPTURE:
+ val = !!spec->micmute_led.capture;
+ break;
+ case MICMUTE_LED_FOLLOW_MUTE:
+ default:
+ val = !spec->micmute_led.capture;
+ break;
+ }
+
+ if (val == spec->micmute_led.led_value)
+ return;
+ spec->micmute_led.led_value = val;
+ if (spec->micmute_led.update)
+ spec->micmute_led.update(codec);
+}
+
+static void update_micmute_led(struct hda_codec *codec,
+ struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct hda_gen_spec *spec = codec->spec;
+ unsigned int mask;
+
+ if (spec->micmute_led.old_hook)
+ spec->micmute_led.old_hook(codec, kcontrol, ucontrol);
+
+ if (!ucontrol)
+ return;
+ mask = 1U << snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
+ if (!strcmp("Capture Switch", ucontrol->id.name)) {
+ /* TODO: How do I verify if it's a mono or stereo here? */
+ if (ucontrol->value.integer.value[0] ||
+ ucontrol->value.integer.value[1])
+ spec->micmute_led.capture |= mask;
+ else
+ spec->micmute_led.capture &= ~mask;
+ call_micmute_led_update(codec);
+ }
+}
+
+static int micmute_led_mode_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
+{
+ static const char * const texts[] = {
+ "On", "Off", "Follow Capture", "Follow Mute",
+ };
+
+ return snd_ctl_enum_info(uinfo, 1, ARRAY_SIZE(texts), texts);
+}
+
+static int micmute_led_mode_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct hda_gen_spec *spec = codec->spec;
+
+ ucontrol->value.enumerated.item[0] = spec->micmute_led.led_mode;
+ return 0;
+}
+
+static int micmute_led_mode_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct hda_gen_spec *spec = codec->spec;
+ unsigned int mode;
+
+ mode = ucontrol->value.enumerated.item[0];
+ if (mode > MICMUTE_LED_FOLLOW_MUTE)
+ mode = MICMUTE_LED_FOLLOW_MUTE;
+ if (mode == spec->micmute_led.led_mode)
+ return 0;
+ spec->micmute_led.led_mode = mode;
+ call_micmute_led_update(codec);
+ return 1;
+}
+
+static const struct snd_kcontrol_new micmute_led_mode_ctl = {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "Mic Mute-LED Mode",
+ .info = micmute_led_mode_info,
+ .get = micmute_led_mode_get,
+ .put = micmute_led_mode_put,
+};
+
+/**
+ * snd_hda_gen_add_micmute_led - helper for setting up mic mute LED hook
+ * @codec: the HDA codec
+ * @hook: the callback for updating LED
+ *
+ * Called from the codec drivers for offering the mic mute LED controls.
+ * When established, it sets up cap_sync_hook and triggers the callback at
+ * each time when the capture mixer switch changes. The callback is supposed
+ * to update the LED accordingly.
+ *
+ * Returns 0 if the hook is established or a negative error code.
+ */
+int snd_hda_gen_add_micmute_led(struct hda_codec *codec,
+ void (*hook)(struct hda_codec *))
+{
+ struct hda_gen_spec *spec = codec->spec;
+
+ spec->micmute_led.led_mode = MICMUTE_LED_FOLLOW_MUTE;
+ spec->micmute_led.capture = 0;
+ spec->micmute_led.led_value = 0;
+ spec->micmute_led.old_hook = spec->cap_sync_hook;
+ spec->micmute_led.update = hook;
+ spec->cap_sync_hook = update_micmute_led;
+ if (!snd_hda_gen_add_kctl(spec, NULL, &micmute_led_mode_ctl))
+ return -ENOMEM;
+ return 0;
+}
+EXPORT_SYMBOL_GPL(snd_hda_gen_add_micmute_led);
+
+/*
* parse digital I/Os and set up NIDs in BIOS auto-parse mode
*/
static void parse_digital(struct hda_codec *codec)
diff --git a/sound/pci/hda/hda_generic.h b/sound/pci/hda/hda_generic.h
index 61772317de46..10123664fa61 100644
--- a/sound/pci/hda/hda_generic.h
+++ b/sound/pci/hda/hda_generic.h
@@ -86,6 +86,16 @@ struct badness_table {
extern const struct badness_table hda_main_out_badness;
extern const struct badness_table hda_extra_out_badness;
+struct hda_micmute_hook {
+ unsigned int led_mode;
+ unsigned int capture;
+ unsigned int led_value;
+ void (*update)(struct hda_codec *codec);
+ void (*old_hook)(struct hda_codec *codec,
+ struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol);
+};
+
struct hda_gen_spec {
char stream_name_analog[32]; /* analog PCM stream */
const struct hda_pcm_stream *stream_analog_playback;
@@ -276,6 +286,9 @@ struct hda_gen_spec {
struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol);
+ /* mic mute LED hook; called via cap_sync_hook */
+ struct hda_micmute_hook micmute_led;
+
/* PCM hooks */
void (*pcm_playback_hook)(struct hda_pcm_stream *hinfo,
struct hda_codec *codec,
@@ -342,4 +355,7 @@ unsigned int snd_hda_gen_path_power_filter(struct hda_codec *codec,
void snd_hda_gen_stream_pm(struct hda_codec *codec, hda_nid_t nid, bool on);
int snd_hda_gen_fix_pin_power(struct hda_codec *codec, hda_nid_t pin);
+int snd_hda_gen_add_micmute_led(struct hda_codec *codec,
+ void (*hook)(struct hda_codec *));
+
#endif /* __SOUND_HDA_GENERIC_H */
diff --git a/sound/pci/hda/patch_ca0132.c b/sound/pci/hda/patch_ca0132.c
index 04e949aa01ad..d62c56feaf7d 100644
--- a/sound/pci/hda/patch_ca0132.c
+++ b/sound/pci/hda/patch_ca0132.c
@@ -991,6 +991,7 @@ struct ca0132_spec {
enum {
QUIRK_NONE,
QUIRK_ALIENWARE,
+ QUIRK_ALIENWARE_M17XR4,
QUIRK_SBZ,
QUIRK_R3DI,
};
@@ -1040,6 +1041,7 @@ static const struct hda_pintbl r3di_pincfgs[] = {
};
static const struct snd_pci_quirk ca0132_quirks[] = {
+ SND_PCI_QUIRK(0x1028, 0x057b, "Alienware M17x R4", QUIRK_ALIENWARE_M17XR4),
SND_PCI_QUIRK(0x1028, 0x0685, "Alienware 15 2015", QUIRK_ALIENWARE),
SND_PCI_QUIRK(0x1028, 0x0688, "Alienware 17 2015", QUIRK_ALIENWARE),
SND_PCI_QUIRK(0x1028, 0x0708, "Alienware 15 R2 2016", QUIRK_ALIENWARE),
@@ -5966,7 +5968,7 @@ static int ca0132_build_pcms(struct hda_codec *codec)
info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->adcs[0];
/* With the DSP enabled, desktops don't use this ADC. */
- if (spec->use_alt_functions) {
+ if (!spec->use_alt_functions) {
info = snd_hda_codec_pcm_new(codec, "CA0132 Analog Mic-In2");
if (!info)
return -ENOMEM;
@@ -6130,7 +6132,10 @@ static void ca0132_init_dmic(struct hda_codec *codec)
* Bit 6: set to select Data2, clear for Data1
* Bit 7: set to enable DMic, clear for AMic
*/
- val = 0x23;
+ if (spec->quirk == QUIRK_ALIENWARE_M17XR4)
+ val = 0x33;
+ else
+ val = 0x23;
/* keep a copy of dmic ctl val for enable/disable dmic purpuse */
spec->dmic_ctl = val;
snd_hda_codec_write(codec, spec->input_pins[0], 0,
@@ -7223,7 +7228,7 @@ static int ca0132_init(struct hda_codec *codec)
snd_hda_sequence_write(codec, spec->base_init_verbs);
- if (spec->quirk != QUIRK_NONE)
+ if (spec->use_alt_functions)
ca0132_alt_init(codec);
ca0132_download_dsp(codec);
@@ -7237,8 +7242,9 @@ static int ca0132_init(struct hda_codec *codec)
case QUIRK_R3DI:
r3di_setup_defaults(codec);
break;
- case QUIRK_NONE:
- case QUIRK_ALIENWARE:
+ case QUIRK_SBZ:
+ break;
+ default:
ca0132_setup_defaults(codec);
ca0132_init_analog_mic2(codec);
ca0132_init_dmic(codec);
@@ -7343,7 +7349,6 @@ static const struct hda_codec_ops ca0132_patch_ops = {
static void ca0132_config(struct hda_codec *codec)
{
struct ca0132_spec *spec = codec->spec;
- struct auto_pin_cfg *cfg = &spec->autocfg;
spec->dacs[0] = 0x2;
spec->dacs[1] = 0x3;
@@ -7405,12 +7410,7 @@ static void ca0132_config(struct hda_codec *codec)
/* SPDIF I/O */
spec->dig_out = 0x05;
spec->multiout.dig_out_nid = spec->dig_out;
- cfg->dig_out_pins[0] = 0x0c;
- cfg->dig_outs = 1;
- cfg->dig_out_type[0] = HDA_PCM_TYPE_SPDIF;
spec->dig_in = 0x09;
- cfg->dig_in_pin = 0x0e;
- cfg->dig_in_type = HDA_PCM_TYPE_SPDIF;
break;
case QUIRK_R3DI:
codec_dbg(codec, "%s: QUIRK_R3DI applied.\n", __func__);
@@ -7438,9 +7438,6 @@ static void ca0132_config(struct hda_codec *codec)
/* SPDIF I/O */
spec->dig_out = 0x05;
spec->multiout.dig_out_nid = spec->dig_out;
- cfg->dig_out_pins[0] = 0x0c;
- cfg->dig_outs = 1;
- cfg->dig_out_type[0] = HDA_PCM_TYPE_SPDIF;
break;
default:
spec->num_outputs = 2;
@@ -7463,12 +7460,7 @@ static void ca0132_config(struct hda_codec *codec)
/* SPDIF I/O */
spec->dig_out = 0x05;
spec->multiout.dig_out_nid = spec->dig_out;
- cfg->dig_out_pins[0] = 0x0c;
- cfg->dig_outs = 1;
- cfg->dig_out_type[0] = HDA_PCM_TYPE_SPDIF;
spec->dig_in = 0x09;
- cfg->dig_in_pin = 0x0e;
- cfg->dig_in_type = HDA_PCM_TYPE_SPDIF;
break;
}
}
@@ -7476,7 +7468,7 @@ static void ca0132_config(struct hda_codec *codec)
static int ca0132_prepare_verbs(struct hda_codec *codec)
{
/* Verbs + terminator (an empty element) */
-#define NUM_SPEC_VERBS 4
+#define NUM_SPEC_VERBS 2
struct ca0132_spec *spec = codec->spec;
spec->chip_init_verbs = ca0132_init_verbs0;
@@ -7488,34 +7480,24 @@ static int ca0132_prepare_verbs(struct hda_codec *codec)
if (!spec->spec_init_verbs)
return -ENOMEM;
- /* HP jack autodetection */
- spec->spec_init_verbs[0].nid = spec->unsol_tag_hp;
- spec->spec_init_verbs[0].param = AC_VERB_SET_UNSOLICITED_ENABLE;
- spec->spec_init_verbs[0].verb = AC_USRSP_EN | spec->unsol_tag_hp;
-
- /* MIC1 jack autodetection */
- spec->spec_init_verbs[1].nid = spec->unsol_tag_amic1;
- spec->spec_init_verbs[1].param = AC_VERB_SET_UNSOLICITED_ENABLE;
- spec->spec_init_verbs[1].verb = AC_USRSP_EN | spec->unsol_tag_amic1;
-
/* config EAPD */
- spec->spec_init_verbs[2].nid = 0x0b;
- spec->spec_init_verbs[2].param = 0x78D;
- spec->spec_init_verbs[2].verb = 0x00;
+ spec->spec_init_verbs[0].nid = 0x0b;
+ spec->spec_init_verbs[0].param = 0x78D;
+ spec->spec_init_verbs[0].verb = 0x00;
/* Previously commented configuration */
/*
- spec->spec_init_verbs[3].nid = 0x0b;
- spec->spec_init_verbs[3].param = AC_VERB_SET_EAPD_BTLENABLE;
+ spec->spec_init_verbs[2].nid = 0x0b;
+ spec->spec_init_verbs[2].param = AC_VERB_SET_EAPD_BTLENABLE;
+ spec->spec_init_verbs[2].verb = 0x02;
+
+ spec->spec_init_verbs[3].nid = 0x10;
+ spec->spec_init_verbs[3].param = 0x78D;
spec->spec_init_verbs[3].verb = 0x02;
spec->spec_init_verbs[4].nid = 0x10;
- spec->spec_init_verbs[4].param = 0x78D;
+ spec->spec_init_verbs[4].param = AC_VERB_SET_EAPD_BTLENABLE;
spec->spec_init_verbs[4].verb = 0x02;
-
- spec->spec_init_verbs[5].nid = 0x10;
- spec->spec_init_verbs[5].param = AC_VERB_SET_EAPD_BTLENABLE;
- spec->spec_init_verbs[5].verb = 0x02;
*/
/* Terminator: spec->spec_init_verbs[NUM_SPEC_VERBS-1] */
diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c
index e7fcfc3b8885..b7339cb5c45b 100644
--- a/sound/pci/hda/patch_conexant.c
+++ b/sound/pci/hda/patch_conexant.c
@@ -343,6 +343,7 @@ static void cxt_fixup_headphone_mic(struct hda_codec *codec,
snd_hdac_regmap_add_vendor_verb(&codec->core, 0x410);
break;
case HDA_FIXUP_ACT_PROBE:
+ WARN_ON(spec->gen.cap_sync_hook);
spec->gen.cap_sync_hook = cxt_update_headset_mode_hook;
spec->gen.automute_hook = cxt_update_headset_mode;
break;
@@ -695,16 +696,12 @@ static void cxt_fixup_gpio_mute_hook(void *private_data, int enabled)
}
/* turn on/off mic-mute LED via GPIO per capture hook */
-static void cxt_fixup_gpio_mic_mute_hook(struct hda_codec *codec,
- struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
+static void cxt_gpio_micmute_update(struct hda_codec *codec)
{
struct conexant_spec *spec = codec->spec;
- if (ucontrol)
- cxt_update_gpio_led(codec, spec->gpio_mic_led_mask,
- ucontrol->value.integer.value[0] ||
- ucontrol->value.integer.value[1]);
+ cxt_update_gpio_led(codec, spec->gpio_mic_led_mask,
+ spec->gen.micmute_led.led_value);
}
@@ -721,11 +718,11 @@ static void cxt_fixup_mute_led_gpio(struct hda_codec *codec,
if (action == HDA_FIXUP_ACT_PRE_PROBE) {
spec->gen.vmaster_mute.hook = cxt_fixup_gpio_mute_hook;
- spec->gen.cap_sync_hook = cxt_fixup_gpio_mic_mute_hook;
spec->gpio_led = 0;
spec->mute_led_polarity = 0;
spec->gpio_mute_led_mask = 0x01;
spec->gpio_mic_led_mask = 0x02;
+ snd_hda_gen_add_micmute_led(codec, cxt_gpio_micmute_update);
}
snd_hda_add_verbs(codec, gpio_init);
if (spec->gpio_led)
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index e9bd33ea538f..7934c5df4d80 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -3718,16 +3718,12 @@ static void alc_fixup_gpio_mute_hook(void *private_data, int enabled)
}
/* turn on/off mic-mute LED via GPIO per capture hook */
-static void alc_fixup_gpio_mic_mute_hook(struct hda_codec *codec,
- struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
+static void alc_gpio_micmute_update(struct hda_codec *codec)
{
struct alc_spec *spec = codec->spec;
- if (ucontrol)
- alc_update_gpio_led(codec, spec->gpio_mic_led_mask,
- ucontrol->value.integer.value[0] ||
- ucontrol->value.integer.value[1]);
+ alc_update_gpio_led(codec, spec->gpio_mic_led_mask,
+ spec->gen.micmute_led.led_value);
}
static void alc269_fixup_hp_gpio_led(struct hda_codec *codec,
@@ -3742,12 +3738,12 @@ 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->gen.cap_sync_hook = alc_fixup_gpio_mic_mute_hook;
spec->gpio_led = 0;
spec->mute_led_polarity = 0;
spec->gpio_mute_led_mask = 0x08;
spec->gpio_mic_led_mask = 0x10;
snd_hda_add_verbs(codec, gpio_init);
+ snd_hda_gen_add_micmute_led(codec, alc_gpio_micmute_update);
}
}
@@ -3763,39 +3759,30 @@ 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->gen.cap_sync_hook = alc_fixup_gpio_mic_mute_hook;
spec->gpio_led = 0;
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);
}
}
/* turn on/off mic-mute LED per capture hook */
-static void alc269_fixup_hp_cap_mic_mute_hook(struct hda_codec *codec,
- struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
+static void alc_cap_micmute_update(struct hda_codec *codec)
{
struct alc_spec *spec = codec->spec;
- unsigned int pinval, enable, disable;
+ unsigned int pinval;
+ if (!spec->cap_mute_led_nid)
+ return;
pinval = snd_hda_codec_get_pin_target(codec, spec->cap_mute_led_nid);
pinval &= ~AC_PINCTL_VREFEN;
- enable = pinval | AC_PINCTL_VREF_80;
- disable = pinval | AC_PINCTL_VREF_HIZ;
-
- if (!ucontrol)
- return;
-
- if (ucontrol->value.integer.value[0] ||
- ucontrol->value.integer.value[1])
- pinval = disable;
+ if (spec->gen.micmute_led.led_value)
+ pinval |= AC_PINCTL_VREF_80;
else
- pinval = enable;
-
- if (spec->cap_mute_led_nid)
- snd_hda_set_pin_ctl_cache(codec, spec->cap_mute_led_nid, pinval);
+ pinval |= AC_PINCTL_VREF_HIZ;
+ snd_hda_set_pin_ctl_cache(codec, spec->cap_mute_led_nid, pinval);
}
static void alc269_fixup_hp_gpio_mic1_led(struct hda_codec *codec,
@@ -3810,12 +3797,12 @@ 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->gen.cap_sync_hook = alc269_fixup_hp_cap_mic_mute_hook;
spec->gpio_led = 0;
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;
}
}
@@ -3833,12 +3820,12 @@ 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->gen.cap_sync_hook = alc269_fixup_hp_cap_mic_mute_hook;
spec->gpio_led = 0;
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;
}
}
@@ -3915,11 +3902,11 @@ 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->gen.cap_sync_hook = alc_fixup_gpio_mic_mute_hook;
spec->gpio_led = 0;
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;
}
@@ -3957,10 +3944,10 @@ 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->gen.cap_sync_hook = alc_fixup_gpio_mic_mute_hook;
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);
return;
}
@@ -3986,14 +3973,10 @@ static void alc269_fixup_hp_line1_mic1_led(struct hda_codec *codec,
{
struct alc_spec *spec = codec->spec;
+ alc269_fixup_hp_mute_led_micx(codec, fix, action, 0x1a);
if (action == HDA_FIXUP_ACT_PRE_PROBE) {
- spec->gen.vmaster_mute.hook = alc269_fixup_mic_mute_hook;
- spec->gen.cap_sync_hook = alc269_fixup_hp_cap_mic_mute_hook;
- spec->mute_led_polarity = 0;
- spec->mute_led_nid = 0x1a;
spec->cap_mute_led_nid = 0x18;
- spec->gen.vmaster_mute_enum = 1;
- codec->power_filter = led_power_filter;
+ snd_hda_gen_add_micmute_led(codec, alc_cap_micmute_update);
}
}
@@ -4841,6 +4824,7 @@ static void alc_probe_headset_mode(struct hda_codec *codec)
spec->headphone_mic_pin = cfg->inputs[i].pin;
}
+ WARN_ON(spec->gen.cap_sync_hook);
spec->gen.cap_sync_hook = alc_update_headset_mode_hook;
spec->gen.automute_hook = alc_update_headset_mode;
spec->gen.hp_automute_hook = alc_update_headset_jack_cb;
@@ -4995,7 +4979,6 @@ static void alc_fixup_tpt440_dock(struct hda_codec *codec,
struct alc_spec *spec = codec->spec;
if (action == HDA_FIXUP_ACT_PRE_PROBE) {
- spec->shutup = alc_no_shutup; /* reduce click noise */
spec->reboot_notify = alc_d3_at_reboot; /* reduce noise */
spec->parse_flags = HDA_PINCFG_NO_HP_FIXUP;
codec->power_save_node = 0; /* avoid click noises */
@@ -5394,6 +5377,13 @@ static void alc274_fixup_bind_dacs(struct hda_codec *codec,
/* for hda_fixup_thinkpad_acpi() */
#include "thinkpad_helper.c"
+static void alc_fixup_thinkpad_acpi(struct hda_codec *codec,
+ const struct hda_fixup *fix, int action)
+{
+ alc_fixup_no_shutup(codec, fix, action); /* reduce click noise */
+ hda_fixup_thinkpad_acpi(codec, fix, action);
+}
+
/* for dell wmi mic mute led */
#include "dell_wmi_helper.c"
@@ -5946,7 +5936,7 @@ static const struct hda_fixup alc269_fixups[] = {
},
[ALC269_FIXUP_THINKPAD_ACPI] = {
.type = HDA_FIXUP_FUNC,
- .v.func = hda_fixup_thinkpad_acpi,
+ .v.func = alc_fixup_thinkpad_acpi,
.chained = true,
.chain_id = ALC269_FIXUP_SKU_IGNORE,
},
diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c
index 63d15b545b33..046705b4691a 100644
--- a/sound/pci/hda/patch_sigmatel.c
+++ b/sound/pci/hda/patch_sigmatel.c
@@ -332,33 +332,15 @@ 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_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
+static void stac_capture_led_update(struct hda_codec *codec)
{
struct sigmatel_spec *spec = codec->spec;
- unsigned int mask;
- bool cur_mute, prev_mute;
- if (!kcontrol || !ucontrol)
- return;
-
- 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;
+ if (spec->gen.micmute_led.led_value)
+ spec->gpio_data |= spec->mic_mute_led_gpio;
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;
- stac_gpio_set(codec, spec->gpio_mask,
- spec->gpio_dir, spec->gpio_data);
- }
+ spec->gpio_data &= ~spec->mic_mute_led_gpio;
+ stac_gpio_set(codec, spec->gpio_mask, spec->gpio_dir, spec->gpio_data);
}
static int stac_vrefout_set(struct hda_codec *codec,
@@ -4656,8 +4638,7 @@ static void stac_setup_gpio(struct hda_codec *codec)
spec->gpio_dir |= spec->mic_mute_led_gpio;
spec->mic_enabled = 0;
spec->gpio_data |= spec->mic_mute_led_gpio;
-
- spec->gen.cap_sync_hook = stac_capture_led_hook;
+ snd_hda_gen_add_micmute_led(codec, stac_capture_led_update);
}
}
diff --git a/sound/pci/hda/thinkpad_helper.c b/sound/pci/hda/thinkpad_helper.c
index 65bb3ac6af4c..97f49b751e6e 100644
--- a/sound/pci/hda/thinkpad_helper.c
+++ b/sound/pci/hda/thinkpad_helper.c
@@ -27,17 +27,11 @@ static void update_tpacpi_mute_led(void *private_data, int enabled)
led_set_func(TPACPI_LED_MUTE, !enabled);
}
-static void update_tpacpi_micmute_led(struct hda_codec *codec,
- struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
+static void update_tpacpi_micmute(struct hda_codec *codec)
{
- if (!ucontrol || !led_set_func)
- return;
- if (strcmp("Capture Switch", ucontrol->id.name) == 0 && ucontrol->id.index == 0) {
- /* TODO: How do I verify if it's a mono or stereo here? */
- bool val = ucontrol->value.integer.value[0] || ucontrol->value.integer.value[1];
- led_set_func(TPACPI_LED_MICMUTE, !val);
- }
+ struct hda_gen_spec *spec = codec->spec;
+
+ led_set_func(TPACPI_LED_MICMUTE, spec->micmute_led.led_value);
}
static void hda_fixup_thinkpad_acpi(struct hda_codec *codec,
@@ -63,15 +57,10 @@ static void hda_fixup_thinkpad_acpi(struct hda_codec *codec,
spec->vmaster_mute.hook = update_tpacpi_mute_led;
removefunc = false;
}
- if (led_set_func(TPACPI_LED_MICMUTE, false) >= 0) {
- if (spec->num_adc_nids > 1 && !spec->dyn_adc_switch)
- codec_dbg(codec,
- "Skipping micmute LED control due to several ADCs");
- else {
- spec->cap_sync_hook = update_tpacpi_micmute_led;
- removefunc = false;
- }
- }
+ if (led_set_func(TPACPI_LED_MICMUTE, false) >= 0 &&
+ snd_hda_gen_add_micmute_led(codec,
+ update_tpacpi_micmute) > 0)
+ removefunc = false;
}
if (led_set_func && (action == HDA_FIXUP_ACT_FREE || removefunc)) {
diff --git a/sound/pci/ice1712/prodigy_hifi.c b/sound/pci/ice1712/prodigy_hifi.c
index d7366ade5a25..c97b5528e4b8 100644
--- a/sound/pci/ice1712/prodigy_hifi.c
+++ b/sound/pci/ice1712/prodigy_hifi.c
@@ -314,26 +314,7 @@ static struct snd_kcontrol_new prodigy_hd2_controls[] = {
/* --------------- */
-/*
- * Logarithmic volume values for WM87*6
- * Computed as 20 * Log10(255 / x)
- */
-static const unsigned char wm_vol[256] = {
- 127, 48, 42, 39, 36, 34, 33, 31, 30, 29, 28, 27, 27, 26, 25, 25, 24, 24, 23,
- 23, 22, 22, 21, 21, 21, 20, 20, 20, 19, 19, 19, 18, 18, 18, 18, 17, 17, 17,
- 17, 16, 16, 16, 16, 15, 15, 15, 15, 15, 15, 14, 14, 14, 14, 14, 13, 13, 13,
- 13, 13, 13, 13, 12, 12, 12, 12, 12, 12, 12, 11, 11, 11, 11, 11, 11, 11, 11,
- 11, 10, 10, 10, 10, 10, 10, 10, 10, 10, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 6, 6, 6,
- 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
- 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 3, 3, 3, 3, 3,
- 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0
-};
-
-#define WM_VOL_MAX (sizeof(wm_vol) - 1)
+#define WM_VOL_MAX 255
#define WM_VOL_MUTE 0x8000
diff --git a/sound/usb/line6/toneport.c b/sound/usb/line6/toneport.c
index 750467fb95db..f47ba94e6f4a 100644
--- a/sound/usb/line6/toneport.c
+++ b/sound/usb/line6/toneport.c
@@ -367,12 +367,13 @@ static bool toneport_has_source_select(struct usb_line6_toneport *toneport)
*/
static void toneport_setup(struct usb_line6_toneport *toneport)
{
- int ticks;
+ u32 ticks;
struct usb_line6 *line6 = &toneport->line6;
struct usb_device *usbdev = line6->usbdev;
/* sync time on device with host: */
- ticks = (int)get_seconds();
+ /* note: 32-bit timestamps overflow in year 2106 */
+ ticks = (u32)ktime_get_real_seconds();
line6_write_data(line6, 0x80c6, &ticks, 4);
/* enable device: */