diff options
Diffstat (limited to 'sound/pci/hda')
-rw-r--r-- | sound/pci/hda/Kconfig | 62 | ||||
-rw-r--r-- | sound/pci/hda/dell_wmi_helper.c | 48 | ||||
-rw-r--r-- | sound/pci/hda/hda_codec.c | 16 | ||||
-rw-r--r-- | sound/pci/hda/hda_controller.c | 11 | ||||
-rw-r--r-- | sound/pci/hda/hda_controller.h | 8 | ||||
-rw-r--r-- | sound/pci/hda/hda_generic.c | 31 | ||||
-rw-r--r-- | sound/pci/hda/hda_generic.h | 2 | ||||
-rw-r--r-- | sound/pci/hda/hda_intel.c | 274 | ||||
-rw-r--r-- | sound/pci/hda/hda_jack.c | 56 | ||||
-rw-r--r-- | sound/pci/hda/hda_jack.h | 12 | ||||
-rw-r--r-- | sound/pci/hda/hda_tegra.c | 22 | ||||
-rw-r--r-- | sound/pci/hda/patch_ca0132.c | 207 | ||||
-rw-r--r-- | sound/pci/hda/patch_conexant.c | 1 | ||||
-rw-r--r-- | sound/pci/hda/patch_hdmi.c | 14 | ||||
-rw-r--r-- | sound/pci/hda/patch_realtek.c | 183 | ||||
-rw-r--r-- | sound/pci/hda/thinkpad_helper.c | 43 |
16 files changed, 624 insertions, 366 deletions
diff --git a/sound/pci/hda/Kconfig b/sound/pci/hda/Kconfig index 4235907b7858..0d38c006e182 100644 --- a/sound/pci/hda/Kconfig +++ b/sound/pci/hda/Kconfig @@ -226,6 +226,68 @@ config SND_HDA_POWER_SAVE_DEFAULT The default time-out value in seconds for HD-audio automatic power-save mode. 0 means to disable the power-save mode. +if SND_HDA_INTEL + +# The options below should not be enabled by distributions or +# users. They are selected by Intel/Skylake or SOF drivers when they +# register for a PCI ID which is also handled by the HDAudio legacy +# driver. When this option is selected and the DSP is detected based on +# the PCI class/subclass/prog-if, the probe of the HDAudio legacy +# aborts. This mechanism removes the need for distributions to use +# blacklists. It can be bypassed with module parameters should the +# Intel/Skylake or SOF drivers fail to handle a specific platform. + +config SND_HDA_INTEL_DSP_DETECTION_SKL + bool + help + This option is selected by SOF or SST drivers, not users or distros. + It enables DSP detection based on PCI class information for + Skylake machines. + +config SND_HDA_INTEL_DSP_DETECTION_APL + bool + help + This option is selected by SOF or SST drivers, not users or distros. + It enables DSP detection based on PCI class information for + Broxton/ApolloLake machines + +config SND_HDA_INTEL_DSP_DETECTION_KBL + bool + help + This option is selected by SOF or SST drivers, not users or distros. + It enables DSP detection based on PCI class information for + KabyLake machines + +config SND_HDA_INTEL_DSP_DETECTION_GLK + bool + help + This option is selected by SOF or SST drivers, not users or distros. + It enables DSP detection based on PCI class information for + GeminiLake machines + +config SND_HDA_INTEL_DSP_DETECTION_CNL + bool + help + This option is selected by SOF or SST drivers, not users or distros. + It enables DSP detection based on PCI class information for + CannonLake machines + +config SND_HDA_INTEL_DSP_DETECTION_CFL + bool + help + This option is selected by SOF or SST drivers, not users or distros. + It enables DSP detection based on PCI class information for + CoffeeLake machines + +config SND_HDA_INTEL_DSP_DETECTION_ICL + bool + help + This option is selected by SOF or SST drivers, not users or distros. + It enables DSP detection based on PCI class information for + IceLake machines + +endif ## SND_HDA_INTEL + endif endmenu diff --git a/sound/pci/hda/dell_wmi_helper.c b/sound/pci/hda/dell_wmi_helper.c deleted file mode 100644 index bbd6c87a4ed6..000000000000 --- a/sound/pci/hda/dell_wmi_helper.c +++ /dev/null @@ -1,48 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* Helper functions for Dell Mic Mute LED control; - * to be included from codec driver - */ - -#if IS_ENABLED(CONFIG_DELL_LAPTOP) -#include <linux/dell-led.h> - -static int (*dell_micmute_led_set_func)(int); - -static void dell_micmute_update(struct hda_codec *codec) -{ - struct hda_gen_spec *spec = codec->spec; - - dell_micmute_led_set_func(spec->micmute_led.led_value); -} - -static void alc_fixup_dell_wmi(struct hda_codec *codec, - const struct hda_fixup *fix, int action) -{ - bool removefunc = false; - - if (action == HDA_FIXUP_ACT_PROBE) { - if (!dell_micmute_led_set_func) - dell_micmute_led_set_func = symbol_request(dell_micmute_led_set); - if (!dell_micmute_led_set_func) { - codec_warn(codec, "Failed to find dell wmi symbol dell_micmute_led_set\n"); - return; - } - - 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; - } -} - -#else /* CONFIG_DELL_LAPTOP */ -static void alc_fixup_dell_wmi(struct hda_codec *codec, - const struct hda_fixup *fix, int action) -{ -} - -#endif /* CONFIG_DELL_LAPTOP */ diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index 0957813939e5..9f8d59e7e89f 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c @@ -36,6 +36,7 @@ #include "hda_beep.h" #include "hda_jack.h" #include <sound/hda_hwdep.h> +#include <sound/hda_component.h> #define codec_in_pm(codec) snd_hdac_is_in_pm(&codec->core) #define hda_codec_is_power_on(codec) snd_hdac_is_power_on(&codec->core) @@ -799,6 +800,13 @@ void snd_hda_codec_cleanup_for_unbind(struct hda_codec *codec) static unsigned int hda_set_power_state(struct hda_codec *codec, unsigned int power_state); +/* enable/disable display power per codec */ +static void codec_display_power(struct hda_codec *codec, bool enable) +{ + if (codec->display_power_control) + snd_hdac_display_power(&codec->bus->core, codec->addr, enable); +} + /* also called from hda_bind.c */ void snd_hda_codec_register(struct hda_codec *codec) { @@ -806,7 +814,7 @@ void snd_hda_codec_register(struct hda_codec *codec) return; if (device_is_registered(hda_codec_dev(codec))) { snd_hda_register_beep_device(codec); - snd_hdac_link_power(&codec->core, true); + codec_display_power(codec, true); pm_runtime_enable(hda_codec_dev(codec)); /* it was powered up in snd_hda_codec_new(), now all done */ snd_hda_power_down(codec); @@ -834,7 +842,7 @@ static int snd_hda_codec_dev_free(struct snd_device *device) codec->in_freeing = 1; snd_hdac_device_unregister(&codec->core); - snd_hdac_link_power(&codec->core, false); + codec_display_power(codec, false); put_device(hda_codec_dev(codec)); return 0; } @@ -2926,7 +2934,7 @@ static int hda_codec_runtime_suspend(struct device *dev) (codec_has_clkstop(codec) && codec_has_epss(codec) && (state & AC_PWRST_CLK_STOP_OK))) snd_hdac_codec_link_down(&codec->core); - snd_hdac_link_power(&codec->core, false); + codec_display_power(codec, false); return 0; } @@ -2934,7 +2942,7 @@ static int hda_codec_runtime_resume(struct device *dev) { struct hda_codec *codec = dev_to_hda_codec(dev); - snd_hdac_link_power(&codec->core, true); + codec_display_power(codec, true); snd_hdac_codec_link_up(&codec->core); hda_call_codec_resume(codec); pm_runtime_mark_last_busy(dev); diff --git a/sound/pci/hda/hda_controller.c b/sound/pci/hda/hda_controller.c index fe2506672a72..532e081f8b8a 100644 --- a/sound/pci/hda/hda_controller.c +++ b/sound/pci/hda/hda_controller.c @@ -989,20 +989,9 @@ static int azx_get_response(struct hdac_bus *bus, unsigned int addr, return azx_rirb_get_response(bus, addr, res); } -static int azx_link_power(struct hdac_bus *bus, bool enable) -{ - struct azx *chip = bus_to_azx(bus); - - if (chip->ops->link_power) - return chip->ops->link_power(chip, enable); - else - return -EINVAL; -} - static const struct hdac_bus_ops bus_core_ops = { .command = azx_send_cmd, .get_response = azx_get_response, - .link_power = azx_link_power, }; #ifdef CONFIG_SND_HDA_DSP_LOADER diff --git a/sound/pci/hda/hda_controller.h b/sound/pci/hda/hda_controller.h index c95097bb5a0c..e0c3fcbaa028 100644 --- a/sound/pci/hda/hda_controller.h +++ b/sound/pci/hda/hda_controller.h @@ -37,7 +37,7 @@ #else #define AZX_DCAPS_I915_COMPONENT 0 /* NOP */ #endif -/* 14 unused */ +#define AZX_DCAPS_INTEL_SHARED (1 << 14) /* shared with ASoC */ #define AZX_DCAPS_CTX_WORKAROUND (1 << 15) /* X-Fi workaround */ #define AZX_DCAPS_POSFIX_LPIB (1 << 16) /* Use LPIB as default */ /* 17 unused */ @@ -50,11 +50,7 @@ /* 24 unused */ #define AZX_DCAPS_COUNT_LPIB_DELAY (1 << 25) /* Take LPIB as delay */ #define AZX_DCAPS_PM_RUNTIME (1 << 26) /* runtime PM support */ -#ifdef CONFIG_SND_HDA_I915 -#define AZX_DCAPS_I915_POWERWELL (1 << 27) /* HSW i915 powerwell support */ -#else -#define AZX_DCAPS_I915_POWERWELL 0 /* NOP */ -#endif +/* 27 unused */ #define AZX_DCAPS_CORBRP_SELF_CLEAR (1 << 28) /* CORBRP clears itself after reset */ #define AZX_DCAPS_NO_MSI64 (1 << 29) /* Stick to 32-bit MSIs */ #define AZX_DCAPS_SEPARATE_STREAM_TAG (1 << 30) /* capture and playback use separate stream tag */ diff --git a/sound/pci/hda/hda_generic.c b/sound/pci/hda/hda_generic.c index 276150f29cda..4095cd7c56c6 100644 --- a/sound/pci/hda/hda_generic.c +++ b/sound/pci/hda/hda_generic.c @@ -29,6 +29,7 @@ #include <linux/string.h> #include <linux/bitops.h> #include <linux/module.h> +#include <linux/leds.h> #include <sound/core.h> #include <sound/jack.h> #include <sound/tlv.h> @@ -4035,6 +4036,36 @@ int snd_hda_gen_add_micmute_led(struct hda_codec *codec, } EXPORT_SYMBOL_GPL(snd_hda_gen_add_micmute_led); +#if IS_REACHABLE(CONFIG_LEDS_TRIGGER_AUDIO) +static void call_ledtrig_micmute(struct hda_codec *codec) +{ + struct hda_gen_spec *spec = codec->spec; + + ledtrig_audio_set(LED_AUDIO_MICMUTE, + spec->micmute_led.led_value ? LED_ON : LED_OFF); +} +#endif + +/** + * snd_hda_gen_fixup_micmute_led - A fixup for mic-mute LED trigger + * + * Pass this function to the quirk entry if another driver supports the + * audio mic-mute LED trigger. Then this will bind the mixer capture switch + * change with the LED. + * + * Note that this fixup has to be called after other fixup that sets + * cap_sync_hook. Otherwise the chaining wouldn't work. + */ +void snd_hda_gen_fixup_micmute_led(struct hda_codec *codec, + const struct hda_fixup *fix, int action) +{ +#if IS_REACHABLE(CONFIG_LEDS_TRIGGER_AUDIO) + if (action == HDA_FIXUP_ACT_PROBE) + snd_hda_gen_add_micmute_led(codec, call_ledtrig_micmute); +#endif +} +EXPORT_SYMBOL_GPL(snd_hda_gen_fixup_micmute_led); + /* * parse digital I/Os and set up NIDs in BIOS auto-parse mode */ diff --git a/sound/pci/hda/hda_generic.h b/sound/pci/hda/hda_generic.h index 10123664fa61..78d77042b05a 100644 --- a/sound/pci/hda/hda_generic.h +++ b/sound/pci/hda/hda_generic.h @@ -357,5 +357,7 @@ 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 *)); +void snd_hda_gen_fixup_micmute_led(struct hda_codec *codec, + const struct hda_fixup *fix, int action); #endif /* __SOUND_HDA_GENERIC_H */ diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index 76f03abd15ab..e42cc2230977 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c @@ -172,6 +172,9 @@ module_param_array(beep_mode, bool, NULL, 0444); MODULE_PARM_DESC(beep_mode, "Select HDA Beep registration mode " "(0=off, 1=on) (default=1)."); #endif +static int skl_pci_binding; +module_param_named(pci_binding, skl_pci_binding, int, 0444); +MODULE_PARM_DESC(pci_binding, "PCI binding (0=auto, 1=only legacy, 2=only asoc"); #ifdef CONFIG_PM static int param_set_xint(const char *val, const struct kernel_param *kp); @@ -310,31 +313,28 @@ enum { #define AZX_DCAPS_INTEL_HASWELL \ (/*AZX_DCAPS_ALIGN_BUFSIZE |*/ AZX_DCAPS_COUNT_LPIB_DELAY |\ AZX_DCAPS_PM_RUNTIME | AZX_DCAPS_I915_COMPONENT |\ - AZX_DCAPS_I915_POWERWELL | AZX_DCAPS_SNOOP_TYPE(SCH)) + AZX_DCAPS_SNOOP_TYPE(SCH)) /* Broadwell HDMI can't use position buffer reliably, force to use LPIB */ #define AZX_DCAPS_INTEL_BROADWELL \ (/*AZX_DCAPS_ALIGN_BUFSIZE |*/ AZX_DCAPS_POSFIX_LPIB |\ AZX_DCAPS_PM_RUNTIME | AZX_DCAPS_I915_COMPONENT |\ - AZX_DCAPS_I915_POWERWELL | AZX_DCAPS_SNOOP_TYPE(SCH)) + AZX_DCAPS_SNOOP_TYPE(SCH)) #define AZX_DCAPS_INTEL_BAYTRAIL \ - (AZX_DCAPS_INTEL_PCH_BASE | AZX_DCAPS_I915_COMPONENT |\ - AZX_DCAPS_I915_POWERWELL) + (AZX_DCAPS_INTEL_PCH_BASE | AZX_DCAPS_I915_COMPONENT) #define AZX_DCAPS_INTEL_BRASWELL \ (AZX_DCAPS_INTEL_PCH_BASE | AZX_DCAPS_PM_RUNTIME |\ - AZX_DCAPS_I915_COMPONENT | AZX_DCAPS_I915_POWERWELL) + AZX_DCAPS_I915_COMPONENT) #define AZX_DCAPS_INTEL_SKYLAKE \ (AZX_DCAPS_INTEL_PCH_BASE | AZX_DCAPS_PM_RUNTIME |\ - AZX_DCAPS_SEPARATE_STREAM_TAG | AZX_DCAPS_I915_COMPONENT |\ - AZX_DCAPS_I915_POWERWELL) + AZX_DCAPS_SEPARATE_STREAM_TAG | AZX_DCAPS_I915_COMPONENT) #define AZX_DCAPS_INTEL_BROXTON \ (AZX_DCAPS_INTEL_PCH_BASE | AZX_DCAPS_PM_RUNTIME |\ - AZX_DCAPS_SEPARATE_STREAM_TAG | AZX_DCAPS_I915_COMPONENT |\ - AZX_DCAPS_I915_POWERWELL) + AZX_DCAPS_SEPARATE_STREAM_TAG | AZX_DCAPS_I915_COMPONENT) /* quirks for ATI SB / AMD Hudson */ #define AZX_DCAPS_PRESET_ATI_SB \ @@ -360,6 +360,7 @@ enum { AZX_DCAPS_NO_64BIT |\ AZX_DCAPS_4K_BDLE_BOUNDARY | AZX_DCAPS_SNOOP_OFF) +#define AZX_DCAPS_INTEL_DSP_DETECTION(conf) (IS_ENABLED(CONFIG_SND_HDA_INTEL_DSP_DETECTION_##conf) ? AZX_DCAPS_INTEL_SHARED : 0) /* * vga_switcheroo support */ @@ -591,8 +592,7 @@ static void hda_intel_init_chip(struct azx *chip, bool full_reset) struct pci_dev *pci = chip->pci; u32 val; - if (chip->driver_caps & AZX_DCAPS_I915_POWERWELL) - snd_hdac_set_codec_wakeup(bus, true); + snd_hdac_set_codec_wakeup(bus, true); if (chip->driver_type == AZX_DRIVER_SKL) { pci_read_config_dword(pci, INTEL_HDA_CGCTL, &val); val = val & ~INTEL_HDA_CGCTL_MISCBDCGE; @@ -604,8 +604,8 @@ static void hda_intel_init_chip(struct azx *chip, bool full_reset) val = val | INTEL_HDA_CGCTL_MISCBDCGE; pci_write_config_dword(pci, INTEL_HDA_CGCTL, val); } - if (chip->driver_caps & AZX_DCAPS_I915_POWERWELL) - snd_hdac_set_codec_wakeup(bus, false); + + snd_hdac_set_codec_wakeup(bus, false); /* reduce dma latency to avoid noise */ if (IS_BXT(pci)) @@ -667,13 +667,8 @@ static int azx_position_check(struct azx *chip, struct azx_dev *azx_dev) return 0; } -/* Enable/disable i915 display power for the link */ -static int azx_intel_link_power(struct azx *chip, bool enable) -{ - struct hdac_bus *bus = azx_bus(chip); - - return snd_hdac_display_power(bus, enable); -} +#define display_power(chip, enable) \ + snd_hdac_display_power(azx_bus(chip), HDA_CODEC_IDX_CONTROLLER, enable) /* * Check whether the current DMA position is acceptable for updating @@ -930,35 +925,75 @@ static int param_set_xint(const char *val, const struct kernel_param *kp) mutex_unlock(&card_list_lock); return 0; } -#else -#define azx_add_card_list(chip) /* NOP */ -#define azx_del_card_list(chip) /* NOP */ -#endif /* CONFIG_PM */ -#ifdef CONFIG_PM_SLEEP /* * power management */ -static int azx_suspend(struct device *dev) +static bool azx_is_pm_ready(struct snd_card *card) { - struct snd_card *card = dev_get_drvdata(dev); struct azx *chip; struct hda_intel *hda; - struct hdac_bus *bus; if (!card) - return 0; - + return false; chip = card->private_data; hda = container_of(chip, struct hda_intel, chip); if (chip->disabled || hda->init_failed || !chip->running) + return false; + return true; +} + +static void __azx_runtime_suspend(struct azx *chip) +{ + azx_stop_chip(chip); + azx_enter_link_reset(chip); + azx_clear_irq_pending(chip); + display_power(chip, false); +} + +static void __azx_runtime_resume(struct azx *chip) +{ + struct hda_intel *hda = container_of(chip, struct hda_intel, chip); + struct hdac_bus *bus = azx_bus(chip); + struct hda_codec *codec; + int status; + + display_power(chip, true); + if (hda->need_i915_power) + snd_hdac_i915_set_bclk(bus); + + /* Read STATESTS before controller reset */ + status = azx_readw(chip, STATESTS); + + azx_init_pci(chip); + hda_intel_init_chip(chip, true); + + if (status) { + list_for_each_codec(codec, &chip->bus) + if (status & (1 << codec->addr)) + schedule_delayed_work(&codec->jackpoll_work, + codec->jackpoll_interval); + } + + /* power down again for link-controlled chips */ + if (!hda->need_i915_power) + display_power(chip, false); +} + +#ifdef CONFIG_PM_SLEEP +static int azx_suspend(struct device *dev) +{ + struct snd_card *card = dev_get_drvdata(dev); + struct azx *chip; + struct hdac_bus *bus; + + if (!azx_is_pm_ready(card)) return 0; + chip = card->private_data; bus = azx_bus(chip); snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); - azx_clear_irq_pending(chip); - azx_stop_chip(chip); - azx_enter_link_reset(chip); + __azx_runtime_suspend(chip); if (bus->irq >= 0) { free_irq(bus->irq, chip); bus->irq = -1; @@ -966,9 +1001,6 @@ static int azx_suspend(struct device *dev) if (chip->msi) pci_disable_msi(chip->pci); - if ((chip->driver_caps & AZX_DCAPS_I915_POWERWELL) - && hda->need_i915_power) - snd_hdac_display_power(bus, false); trace_azx_suspend(chip); return 0; @@ -976,41 +1008,19 @@ static int azx_suspend(struct device *dev) static int azx_resume(struct device *dev) { - struct pci_dev *pci = to_pci_dev(dev); struct snd_card *card = dev_get_drvdata(dev); struct azx *chip; - struct hda_intel *hda; - struct hdac_bus *bus; - if (!card) + if (!azx_is_pm_ready(card)) return 0; chip = card->private_data; - hda = container_of(chip, struct hda_intel, chip); - bus = azx_bus(chip); - if (chip->disabled || hda->init_failed || !chip->running) - return 0; - - if (chip->driver_caps & AZX_DCAPS_I915_POWERWELL) { - snd_hdac_display_power(bus, true); - if (hda->need_i915_power) - snd_hdac_i915_set_bclk(bus); - } - if (chip->msi) - if (pci_enable_msi(pci) < 0) + if (pci_enable_msi(chip->pci) < 0) chip->msi = 0; if (azx_acquire_irq(chip, 1) < 0) return -EIO; - azx_init_pci(chip); - - hda_intel_init_chip(chip, true); - - /* power down again for link-controlled chips */ - if ((chip->driver_caps & AZX_DCAPS_I915_POWERWELL) && - !hda->need_i915_power) - snd_hdac_display_power(bus, false); - + __azx_runtime_resume(chip); snd_power_change_state(card, SNDRV_CTL_POWER_D0); trace_azx_resume(chip); @@ -1045,21 +1055,14 @@ static int azx_thaw_noirq(struct device *dev) } #endif /* CONFIG_PM_SLEEP */ -#ifdef CONFIG_PM static int azx_runtime_suspend(struct device *dev) { struct snd_card *card = dev_get_drvdata(dev); struct azx *chip; - struct hda_intel *hda; - if (!card) + if (!azx_is_pm_ready(card)) return 0; - chip = card->private_data; - hda = container_of(chip, struct hda_intel, chip); - if (chip->disabled || hda->init_failed) - return 0; - if (!azx_has_pm_runtime(chip)) return 0; @@ -1067,13 +1070,7 @@ static int azx_runtime_suspend(struct device *dev) azx_writew(chip, WAKEEN, azx_readw(chip, WAKEEN) | STATESTS_INT_MASK); - azx_stop_chip(chip); - azx_enter_link_reset(chip); - azx_clear_irq_pending(chip); - if ((chip->driver_caps & AZX_DCAPS_I915_POWERWELL) - && hda->need_i915_power) - snd_hdac_display_power(azx_bus(chip), false); - + __azx_runtime_suspend(chip); trace_azx_runtime_suspend(chip); return 0; } @@ -1082,51 +1079,18 @@ static int azx_runtime_resume(struct device *dev) { struct snd_card *card = dev_get_drvdata(dev); struct azx *chip; - struct hda_intel *hda; - struct hdac_bus *bus; - struct hda_codec *codec; - int status; - if (!card) + if (!azx_is_pm_ready(card)) return 0; - chip = card->private_data; - hda = container_of(chip, struct hda_intel, chip); - bus = azx_bus(chip); - if (chip->disabled || hda->init_failed) - return 0; - if (!azx_has_pm_runtime(chip)) return 0; - - if (chip->driver_caps & AZX_DCAPS_I915_POWERWELL) { - snd_hdac_display_power(bus, true); - if (hda->need_i915_power) - snd_hdac_i915_set_bclk(bus); - } - - /* Read STATESTS before controller reset */ - status = azx_readw(chip, STATESTS); - - azx_init_pci(chip); - hda_intel_init_chip(chip, true); - - if (status) { - list_for_each_codec(codec, &chip->bus) - if (status & (1 << codec->addr)) - schedule_delayed_work(&codec->jackpoll_work, - codec->jackpoll_interval); - } + __azx_runtime_resume(chip); /* disable controller Wake Up event*/ azx_writew(chip, WAKEEN, azx_readw(chip, WAKEEN) & ~STATESTS_INT_MASK); - /* power down again for link-controlled chips */ - if ((chip->driver_caps & AZX_DCAPS_I915_POWERWELL) && - !hda->need_i915_power) - snd_hdac_display_power(bus, false); - trace_azx_runtime_resume(chip); return 0; } @@ -1167,6 +1131,8 @@ static const struct dev_pm_ops azx_pm = { #define AZX_PM_OPS &azx_pm #else +#define azx_add_card_list(chip) /* NOP */ +#define azx_del_card_list(chip) /* NOP */ #define AZX_PM_OPS NULL #endif /* CONFIG_PM */ @@ -1374,11 +1340,8 @@ static int azx_free(struct azx *chip) #ifdef CONFIG_SND_HDA_PATCH_LOADER release_firmware(chip->fw); #endif + display_power(chip, false); - if (chip->driver_caps & AZX_DCAPS_I915_POWERWELL) { - if (hda->need_i915_power) - snd_hdac_display_power(bus, false); - } if (chip->driver_caps & AZX_DCAPS_I915_COMPONENT) snd_hdac_i915_exit(bus); kfree(hda); @@ -1935,8 +1898,7 @@ static int azx_first_init(struct azx *chip) /* initialize chip */ azx_init_pci(chip); - if (chip->driver_caps & AZX_DCAPS_I915_POWERWELL) - snd_hdac_i915_set_bclk(bus); + snd_hdac_i915_set_bclk(bus); hda_intel_init_chip(chip, (probe_only[dev] & 2) == 0); @@ -2078,7 +2040,6 @@ static const struct hda_controller_ops pci_hda_ops = { .disable_msi_reset_irq = disable_msi_reset_irq, .pcm_mmap_prepare = pcm_mmap_prepare, .position_check = azx_position_check, - .link_power = azx_intel_link_power, }; static int azx_probe(struct pci_dev *pci, @@ -2091,6 +2052,28 @@ static int azx_probe(struct pci_dev *pci, bool schedule_probe; int err; + /* check if this driver can be used on SKL+ Intel platforms */ + if (pci_id->driver_data & AZX_DCAPS_INTEL_SHARED) { + switch (skl_pci_binding) { + case SND_SKL_PCI_BIND_AUTO: + if (pci->class != 0x040300) { + dev_info(&pci->dev, "The DSP is enabled on this platform, aborting probe\n"); + return -ENODEV; + } + dev_info(&pci->dev, "No DSP detected, continuing HDaudio legacy probe\n"); + break; + case SND_SKL_PCI_BIND_LEGACY: + dev_info(&pci->dev, "Module parameter forced binding with HDaudio legacy, bypassed detection logic\n"); + break; + case SND_SKL_PCI_BIND_ASOC: + dev_info(&pci->dev, "Module parameter forced binding with SKL+ ASoC driver, aborting probe\n"); + return -ENODEV; + default: + dev_err(&pci->dev, "invalid value for skl_pci_binding module parameter, ignored\n"); + break; + } + } + if (dev >= SNDRV_CARDS) return -ENODEV; if (!enable[dev]) { @@ -2245,10 +2228,13 @@ static int azx_probe_continue(struct azx *chip) goto out_free; } else { /* don't bother any longer */ - chip->driver_caps &= - ~(AZX_DCAPS_I915_COMPONENT | AZX_DCAPS_I915_POWERWELL); + chip->driver_caps &= ~AZX_DCAPS_I915_COMPONENT; } } + + /* HSW/BDW controllers need this power */ + if (CONTROLLER_IN_GPU(pci)) + hda->need_i915_power = 1; } /* Request display power well for the HDA controller or codec. For @@ -2256,18 +2242,7 @@ static int azx_probe_continue(struct azx *chip) * this power. For other platforms, like Baytrail/Braswell, only the * display codec needs the power and it can be released after probe. */ - if (chip->driver_caps & AZX_DCAPS_I915_POWERWELL) { - /* HSW/BDW controllers need this power */ - if (CONTROLLER_IN_GPU(pci)) - hda->need_i915_power = 1; - - err = snd_hdac_display_power(bus, true); - if (err < 0) { - dev_err(chip->card->dev, - "Cannot turn on display power on i915\n"); - goto i915_power_fail; - } - } + display_power(chip, true); err = azx_first_init(chip); if (err < 0) @@ -2315,11 +2290,8 @@ static int azx_probe_continue(struct azx *chip) pm_runtime_put_autosuspend(&pci->dev); out_free: - if ((chip->driver_caps & AZX_DCAPS_I915_POWERWELL) - && !hda->need_i915_power) - snd_hdac_display_power(bus, false); - -i915_power_fail: + if (err < 0 || !hda->need_i915_power) + display_power(chip, false); if (err < 0) hda->init_failed = 1; complete_all(&hda->probe_wait); @@ -2408,34 +2380,48 @@ static const struct pci_device_id azx_ids[] = { .driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE }, /* Sunrise Point-LP */ { PCI_DEVICE(0x8086, 0x9d70), - .driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE }, + .driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE | + AZX_DCAPS_INTEL_DSP_DETECTION(SKL) + }, /* Kabylake */ { PCI_DEVICE(0x8086, 0xa171), .driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE }, /* Kabylake-LP */ { PCI_DEVICE(0x8086, 0x9d71), - .driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE }, + .driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE | + AZX_DCAPS_INTEL_DSP_DETECTION(KBL) + }, /* Kabylake-H */ { PCI_DEVICE(0x8086, 0xa2f0), .driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE }, /* Coffelake */ { PCI_DEVICE(0x8086, 0xa348), - .driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE}, + .driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE | + AZX_DCAPS_INTEL_DSP_DETECTION(CFL) + }, /* Cannonlake */ { PCI_DEVICE(0x8086, 0x9dc8), - .driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE}, + .driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE | + AZX_DCAPS_INTEL_DSP_DETECTION(CNL) + }, /* Icelake */ { PCI_DEVICE(0x8086, 0x34c8), - .driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE}, + .driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE | + AZX_DCAPS_INTEL_DSP_DETECTION(ICL) + }, /* Broxton-P(Apollolake) */ { PCI_DEVICE(0x8086, 0x5a98), - .driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_BROXTON }, + .driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_BROXTON | + AZX_DCAPS_INTEL_DSP_DETECTION(APL) + }, /* Broxton-T */ { PCI_DEVICE(0x8086, 0x1a98), .driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_BROXTON }, /* Gemini-Lake */ { PCI_DEVICE(0x8086, 0x3198), - .driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_BROXTON }, + .driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_BROXTON | + AZX_DCAPS_INTEL_DSP_DETECTION(GLK) + }, /* Haswell */ { PCI_DEVICE(0x8086, 0x0a0c), .driver_data = AZX_DRIVER_HDMI | AZX_DCAPS_INTEL_HASWELL }, diff --git a/sound/pci/hda/hda_jack.c b/sound/pci/hda/hda_jack.c index c499727920e6..74b46952fc98 100644 --- a/sound/pci/hda/hda_jack.c +++ b/sound/pci/hda/hda_jack.c @@ -339,9 +339,15 @@ void snd_hda_jack_report_sync(struct hda_codec *codec) if (jack->nid) { if (!jack->jack || jack->block_report) continue; - state = get_jack_plug_state(jack->pin_sense); - snd_jack_report(jack->jack, - state ? jack->type : 0); + state = jack->button_state; + if (get_jack_plug_state(jack->pin_sense)) + state |= jack->type; + snd_jack_report(jack->jack, state); + if (jack->button_state) { + snd_jack_report(jack->jack, + state & ~jack->button_state); + jack->button_state = 0; /* button released */ + } } } EXPORT_SYMBOL_GPL(snd_hda_jack_report_sync); @@ -379,15 +385,19 @@ static void hda_free_jack_priv(struct snd_jack *jack) * @nid: pin NID to assign * @name: string name for the jack * @phantom_jack: flag to deal as a phantom jack + * @type: jack type bits to be reported, 0 for guessing from pincfg + * @keymap: optional jack / key mapping * * This assigns a jack-detection kctl to the given pin. The kcontrol * will have the given name and index. */ int snd_hda_jack_add_kctl(struct hda_codec *codec, hda_nid_t nid, - const char *name, bool phantom_jack) + const char *name, bool phantom_jack, + int type, const struct hda_jack_keymap *keymap) { struct hda_jack_tbl *jack; - int err, state, type; + const struct hda_jack_keymap *map; + int err, state, buttons; jack = snd_hda_jack_tbl_new(codec, nid); if (!jack) @@ -395,16 +405,30 @@ int snd_hda_jack_add_kctl(struct hda_codec *codec, hda_nid_t nid, if (jack->jack) return 0; /* already created */ - type = get_input_jack_type(codec, nid); - err = snd_jack_new(codec->card, name, type, + if (!type) + type = get_input_jack_type(codec, nid); + + buttons = 0; + if (keymap) { + for (map = keymap; map->type; map++) + buttons |= map->type; + } + + err = snd_jack_new(codec->card, name, type | buttons, &jack->jack, true, phantom_jack); if (err < 0) return err; jack->phantom_jack = !!phantom_jack; jack->type = type; + jack->button_state = 0; jack->jack->private_data = jack; jack->jack->private_free = hda_free_jack_priv; + if (keymap) { + for (map = keymap; map->type; map++) + snd_jack_set_key(jack->jack, map->type, map->key); + } + state = snd_hda_jack_detect(codec, nid); snd_jack_report(jack->jack, state ? jack->type : 0); @@ -437,7 +461,7 @@ static int add_jack_kctl(struct hda_codec *codec, hda_nid_t nid, if (phantom_jack) /* Example final name: "Internal Mic Phantom Jack" */ strncat(name, " Phantom", sizeof(name) - strlen(name) - 1); - err = snd_hda_jack_add_kctl(codec, nid, name, phantom_jack); + err = snd_hda_jack_add_kctl(codec, nid, name, phantom_jack, 0, NULL); if (err < 0) return err; @@ -508,19 +532,25 @@ int snd_hda_jack_add_kctls(struct hda_codec *codec, } EXPORT_SYMBOL_GPL(snd_hda_jack_add_kctls); -static void call_jack_callback(struct hda_codec *codec, +static void call_jack_callback(struct hda_codec *codec, unsigned int res, struct hda_jack_tbl *jack) { struct hda_jack_callback *cb; - for (cb = jack->callback; cb; cb = cb->next) + for (cb = jack->callback; cb; cb = cb->next) { + cb->jack = jack; + cb->unsol_res = res; cb->func(codec, cb); + } if (jack->gated_jack) { struct hda_jack_tbl *gated = snd_hda_jack_tbl_get(codec, jack->gated_jack); if (gated) { - for (cb = gated->callback; cb; cb = cb->next) + for (cb = gated->callback; cb; cb = cb->next) { + cb->jack = gated; + cb->unsol_res = res; cb->func(codec, cb); + } } } } @@ -540,7 +570,7 @@ void snd_hda_jack_unsol_event(struct hda_codec *codec, unsigned int res) return; event->jack_dirty = 1; - call_jack_callback(codec, event); + call_jack_callback(codec, res, event); snd_hda_jack_report_sync(codec); } EXPORT_SYMBOL_GPL(snd_hda_jack_unsol_event); @@ -566,7 +596,7 @@ void snd_hda_jack_poll_all(struct hda_codec *codec) if (old_sense == get_jack_plug_state(jack->pin_sense)) continue; changes = 1; - call_jack_callback(codec, jack); + call_jack_callback(codec, 0, jack); } if (changes) snd_hda_jack_report_sync(codec); diff --git a/sound/pci/hda/hda_jack.h b/sound/pci/hda/hda_jack.h index e9814c0168ea..1d713201c160 100644 --- a/sound/pci/hda/hda_jack.h +++ b/sound/pci/hda/hda_jack.h @@ -13,6 +13,7 @@ #define __SOUND_HDA_JACK_H #include <linux/err.h> +#include <sound/jack.h> struct auto_pin_cfg; struct hda_jack_tbl; @@ -24,6 +25,8 @@ struct hda_jack_callback { hda_nid_t nid; hda_jack_callback_fn func; unsigned int private_data; /* arbitrary data */ + unsigned int unsol_res; /* unsolicited event bits */ + struct hda_jack_tbl *jack; /* associated jack entry */ struct hda_jack_callback *next; }; @@ -40,9 +43,15 @@ struct hda_jack_tbl { hda_nid_t gating_jack; /* valid when gating jack plugged */ hda_nid_t gated_jack; /* gated is dependent on this jack */ int type; + int button_state; struct snd_jack *jack; }; +struct hda_jack_keymap { + enum snd_jack_types type; + int key; +}; + struct hda_jack_tbl * snd_hda_jack_tbl_get(struct hda_codec *codec, hda_nid_t nid); struct hda_jack_tbl * @@ -82,7 +91,8 @@ static inline bool snd_hda_jack_detect(struct hda_codec *codec, hda_nid_t nid) bool is_jack_detectable(struct hda_codec *codec, hda_nid_t nid); int snd_hda_jack_add_kctl(struct hda_codec *codec, hda_nid_t nid, - const char *name, bool phantom_jack); + const char *name, bool phantom_jack, + int type, const struct hda_jack_keymap *keymap); int snd_hda_jack_add_kctls(struct hda_codec *codec, const struct auto_pin_cfg *cfg); diff --git a/sound/pci/hda/hda_tegra.c b/sound/pci/hda/hda_tegra.c index dd7d4242d6d2..83befd8d43e8 100644 --- a/sound/pci/hda/hda_tegra.c +++ b/sound/pci/hda/hda_tegra.c @@ -31,6 +31,7 @@ #include <linux/of_device.h> #include <linux/slab.h> #include <linux/time.h> +#include <linux/string.h> #include <sound/core.h> #include <sound/initval.h> @@ -344,6 +345,8 @@ static int hda_tegra_first_init(struct azx *chip, struct platform_device *pdev) int err; unsigned short gcap; int irq_id = platform_get_irq(pdev, 0); + const char *sname; + struct device_node *root; err = hda_tegra_init_chip(chip, pdev); if (err) @@ -401,8 +404,23 @@ static int hda_tegra_first_init(struct azx *chip, struct platform_device *pdev) return -ENODEV; } + /* driver name */ strcpy(card->driver, "tegra-hda"); - strcpy(card->shortname, "tegra-hda"); + + root = of_find_node_by_path("/"); + sname = of_get_property(root, "compatible", NULL); + of_node_put(root); + if (!sname) { + dev_err(card->dev, + "failed to get compatible property from root node\n"); + return -ENODEV; + } + /* shortname for card */ + if (strlen(sname) > sizeof(card->shortname)) + dev_info(card->dev, "truncating shortname for card\n"); + strncpy(card->shortname, sname, sizeof(card->shortname)); + + /* longname for card */ snprintf(card->longname, sizeof(card->longname), "%s at 0x%lx irq %i", card->shortname, bus->addr, bus->irq); @@ -513,7 +531,7 @@ static void hda_tegra_probe_work(struct work_struct *work) goto out_free; /* create codec instances */ - err = azx_probe_codecs(chip, 0); + err = azx_probe_codecs(chip, 8); if (err < 0) goto out_free; diff --git a/sound/pci/hda/patch_ca0132.c b/sound/pci/hda/patch_ca0132.c index 0a567634e5fa..e5bdbc245682 100644 --- a/sound/pci/hda/patch_ca0132.c +++ b/sound/pci/hda/patch_ca0132.c @@ -1081,6 +1081,18 @@ enum { QUIRK_AE5, }; +#ifdef CONFIG_PCI +#define ca0132_quirk(spec) ((spec)->quirk) +#define ca0132_use_pci_mmio(spec) ((spec)->use_pci_mmio) +#define ca0132_use_alt_functions(spec) ((spec)->use_alt_functions) +#define ca0132_use_alt_controls(spec) ((spec)->use_alt_controls) +#else +#define ca0132_quirk(spec) ({ (void)(spec); QUIRK_NONE; }) +#define ca0132_use_alt_functions(spec) ({ (void)(spec); false; }) +#define ca0132_use_pci_mmio(spec) ({ (void)(spec); false; }) +#define ca0132_use_alt_controls(spec) ({ (void)(spec); false; }) +#endif + static const struct hda_pintbl alienware_pincfgs[] = { { 0x0b, 0x90170110 }, /* Builtin Speaker */ { 0x0c, 0x411111f0 }, /* N/A */ @@ -3101,7 +3113,7 @@ static void dspload_post_setup(struct hda_codec *codec) { struct ca0132_spec *spec = codec->spec; codec_dbg(codec, "---- dspload_post_setup ------\n"); - if (!spec->use_alt_functions) { + if (!ca0132_use_alt_functions(spec)) { /*set DSP speaker to 2.0 configuration*/ chipio_write(codec, XRAM_XRAM_INST_OFFSET(0x18), 0x08080080); chipio_write(codec, XRAM_XRAM_INST_OFFSET(0x19), 0x3f800000); @@ -3333,7 +3345,7 @@ static void ca0132_gpio_init(struct hda_codec *codec) { struct ca0132_spec *spec = codec->spec; - switch (spec->quirk) { + switch (ca0132_quirk(spec)) { case QUIRK_SBZ: case QUIRK_AE5: snd_hda_codec_write(codec, 0x01, 0, 0x793, 0x00); @@ -3344,6 +3356,8 @@ static void ca0132_gpio_init(struct hda_codec *codec) snd_hda_codec_write(codec, 0x01, 0, 0x793, 0x00); snd_hda_codec_write(codec, 0x01, 0, 0x794, 0x5B); break; + default: + break; } } @@ -3353,7 +3367,7 @@ static void ca0132_gpio_setup(struct hda_codec *codec) { struct ca0132_spec *spec = codec->spec; - switch (spec->quirk) { + switch (ca0132_quirk(spec)) { case QUIRK_SBZ: snd_hda_codec_write(codec, 0x01, 0, AC_VERB_SET_GPIO_DIRECTION, 0x07); @@ -3372,6 +3386,8 @@ static void ca0132_gpio_setup(struct hda_codec *codec) snd_hda_codec_write(codec, 0x01, 0, AC_VERB_SET_GPIO_DATA, 0x0C); break; + default: + break; } } @@ -4172,7 +4188,7 @@ static void ca0132_alt_select_out_quirk_handler(struct hda_codec *codec) switch (spec->cur_out_type) { case SPEAKER_OUT: - switch (spec->quirk) { + switch (ca0132_quirk(spec)) { case QUIRK_SBZ: ca0113_mmio_gpio_set(codec, 7, false); ca0113_mmio_gpio_set(codec, 4, true); @@ -4203,10 +4219,12 @@ static void ca0132_alt_select_out_quirk_handler(struct hda_codec *codec) chipio_set_control_param(codec, 0x0d, 0xa4); chipio_write(codec, 0x18b03c, 0x00000012); break; + default: + break; } break; case HEADPHONE_OUT: - switch (spec->quirk) { + switch (ca0132_quirk(spec)) { case QUIRK_SBZ: ca0113_mmio_gpio_set(codec, 7, true); ca0113_mmio_gpio_set(codec, 4, true); @@ -4238,10 +4256,12 @@ static void ca0132_alt_select_out_quirk_handler(struct hda_codec *codec) chipio_set_control_param(codec, 0x0d, 0xa1); chipio_write(codec, 0x18b03c, 0x00000012); break; + default: + break; } break; case SURROUND_OUT: - switch (spec->quirk) { + switch (ca0132_quirk(spec)) { case QUIRK_SBZ: ca0113_mmio_gpio_set(codec, 7, false); ca0113_mmio_gpio_set(codec, 4, true); @@ -4272,6 +4292,8 @@ static void ca0132_alt_select_out_quirk_handler(struct hda_codec *codec) chipio_set_control_param(codec, 0x0d, 0xa4); chipio_write(codec, 0x18b03c, 0x00000012); break; + default: + break; } break; } @@ -4446,7 +4468,7 @@ static void ca0132_unsol_hp_delayed(struct work_struct *work) to_delayed_work(work), struct ca0132_spec, unsol_hp_work); struct hda_jack_tbl *jack; - if (spec->use_alt_functions) + if (ca0132_use_alt_functions(spec)) ca0132_alt_select_out(spec->codec); else ca0132_select_out(spec->codec); @@ -4530,14 +4552,14 @@ static int ca0132_alt_set_vipsource(struct hda_codec *codec, int val) chipio_set_conn_rate(codec, MEM_CONNID_MICIN1, SR_96_000); chipio_set_conn_rate(codec, MEM_CONNID_MICOUT1, SR_96_000); - if (spec->quirk == QUIRK_R3DI) + if (ca0132_quirk(spec) == QUIRK_R3DI) chipio_set_conn_rate(codec, 0x0F, SR_96_000); if (spec->in_enum_val == REAR_LINE_IN) tmp = FLOAT_ZERO; else { - if (spec->quirk == QUIRK_SBZ) + if (ca0132_quirk(spec) == QUIRK_SBZ) tmp = FLOAT_THREE; else tmp = FLOAT_ONE; @@ -4549,7 +4571,7 @@ static int ca0132_alt_set_vipsource(struct hda_codec *codec, int val) codec_dbg(codec, "%s: on.", __func__); chipio_set_conn_rate(codec, MEM_CONNID_MICIN1, SR_16_000); chipio_set_conn_rate(codec, MEM_CONNID_MICOUT1, SR_16_000); - if (spec->quirk == QUIRK_R3DI) + if (ca0132_quirk(spec) == QUIRK_R3DI) chipio_set_conn_rate(codec, 0x0F, SR_16_000); if (spec->effects_switch[VOICE_FOCUS - EFFECT_START_NID]) @@ -4645,7 +4667,7 @@ static int ca0132_alt_select_in(struct hda_codec *codec) switch (spec->cur_mic_type) { case REAR_MIC: - switch (spec->quirk) { + switch (ca0132_quirk(spec)) { case QUIRK_SBZ: case QUIRK_R3D: ca0113_mmio_gpio_set(codec, 0, false); @@ -4669,14 +4691,14 @@ static int ca0132_alt_select_in(struct hda_codec *codec) chipio_set_conn_rate(codec, MEM_CONNID_MICIN1, SR_96_000); chipio_set_conn_rate(codec, MEM_CONNID_MICOUT1, SR_96_000); - if (spec->quirk == QUIRK_R3DI) + if (ca0132_quirk(spec) == QUIRK_R3DI) chipio_set_conn_rate(codec, 0x0F, SR_96_000); dspio_set_uint_param(codec, 0x80, 0x00, tmp); chipio_set_stream_control(codec, 0x03, 1); chipio_set_stream_control(codec, 0x04, 1); - switch (spec->quirk) { + switch (ca0132_quirk(spec)) { case QUIRK_SBZ: chipio_write(codec, 0x18B098, 0x0000000C); chipio_write(codec, 0x18B09C, 0x0000000C); @@ -4689,12 +4711,14 @@ static int ca0132_alt_select_in(struct hda_codec *codec) chipio_write(codec, 0x18B098, 0x0000000C); chipio_write(codec, 0x18B09C, 0x0000004C); break; + default: + break; } ca0132_alt_mic_boost_set(codec, spec->mic_boost_enum_val); break; case REAR_LINE_IN: ca0132_mic_boost_set(codec, 0); - switch (spec->quirk) { + switch (ca0132_quirk(spec)) { case QUIRK_SBZ: case QUIRK_R3D: ca0113_mmio_gpio_set(codec, 0, false); @@ -4705,28 +4729,32 @@ static int ca0132_alt_select_in(struct hda_codec *codec) case QUIRK_AE5: ca0113_mmio_command_set(codec, 0x48, 0x28, 0x00); break; + default: + break; } chipio_set_conn_rate(codec, MEM_CONNID_MICIN1, SR_96_000); chipio_set_conn_rate(codec, MEM_CONNID_MICOUT1, SR_96_000); - if (spec->quirk == QUIRK_R3DI) + if (ca0132_quirk(spec) == QUIRK_R3DI) chipio_set_conn_rate(codec, 0x0F, SR_96_000); tmp = FLOAT_ZERO; dspio_set_uint_param(codec, 0x80, 0x00, tmp); - switch (spec->quirk) { + switch (ca0132_quirk(spec)) { case QUIRK_SBZ: case QUIRK_AE5: chipio_write(codec, 0x18B098, 0x00000000); chipio_write(codec, 0x18B09C, 0x00000000); break; + default: + break; } chipio_set_stream_control(codec, 0x03, 1); chipio_set_stream_control(codec, 0x04, 1); break; case FRONT_MIC: - switch (spec->quirk) { + switch (ca0132_quirk(spec)) { case QUIRK_SBZ: case QUIRK_R3D: ca0113_mmio_gpio_set(codec, 0, true); @@ -4748,7 +4776,7 @@ static int ca0132_alt_select_in(struct hda_codec *codec) chipio_set_conn_rate(codec, MEM_CONNID_MICIN1, SR_96_000); chipio_set_conn_rate(codec, MEM_CONNID_MICOUT1, SR_96_000); - if (spec->quirk == QUIRK_R3DI) + if (ca0132_quirk(spec) == QUIRK_R3DI) chipio_set_conn_rate(codec, 0x0F, SR_96_000); dspio_set_uint_param(codec, 0x80, 0x00, tmp); @@ -4756,7 +4784,7 @@ static int ca0132_alt_select_in(struct hda_codec *codec) chipio_set_stream_control(codec, 0x03, 1); chipio_set_stream_control(codec, 0x04, 1); - switch (spec->quirk) { + switch (ca0132_quirk(spec)) { case QUIRK_SBZ: chipio_write(codec, 0x18B098, 0x0000000C); chipio_write(codec, 0x18B09C, 0x000000CC); @@ -4765,6 +4793,8 @@ static int ca0132_alt_select_in(struct hda_codec *codec) chipio_write(codec, 0x18B098, 0x0000000C); chipio_write(codec, 0x18B09C, 0x0000004C); break; + default: + break; } ca0132_alt_mic_boost_set(codec, spec->mic_boost_enum_val); break; @@ -4859,7 +4889,7 @@ static int ca0132_effects_set(struct hda_codec *codec, hda_nid_t nid, long val) val = 0; /* If Voice Focus on SBZ, set to two channel. */ - if ((nid == VOICE_FOCUS) && (spec->use_pci_mmio) + if ((nid == VOICE_FOCUS) && ca0132_use_pci_mmio(spec) && (spec->cur_mic_type != REAR_LINE_IN)) { if (spec->effects_switch[CRYSTAL_VOICE - EFFECT_START_NID]) { @@ -4878,7 +4908,7 @@ static int ca0132_effects_set(struct hda_codec *codec, hda_nid_t nid, long val) * For SBZ noise reduction, there's an extra command * to module ID 0x47. No clue why. */ - if ((nid == NOISE_REDUCTION) && (spec->use_pci_mmio) + if ((nid == NOISE_REDUCTION) && ca0132_use_pci_mmio(spec) && (spec->cur_mic_type != REAR_LINE_IN)) { if (spec->effects_switch[CRYSTAL_VOICE - EFFECT_START_NID]) { @@ -4894,7 +4924,7 @@ static int ca0132_effects_set(struct hda_codec *codec, hda_nid_t nid, long val) } /* If rear line in disable effects. */ - if (spec->use_alt_functions && + if (ca0132_use_alt_functions(spec) && spec->in_enum_val == REAR_LINE_IN) val = 0; } @@ -4924,7 +4954,7 @@ static int ca0132_pe_switch_set(struct hda_codec *codec) codec_dbg(codec, "ca0132_pe_switch_set: val=%ld\n", spec->effects_switch[PLAY_ENHANCEMENT - EFFECT_START_NID]); - if (spec->use_alt_functions) + if (ca0132_use_alt_functions(spec)) ca0132_alt_select_out(codec); i = OUT_EFFECT_START_NID - EFFECT_START_NID; @@ -4984,7 +5014,7 @@ static int ca0132_cvoice_switch_set(struct hda_codec *codec) /* set correct vipsource */ oldval = stop_mic1(codec); - if (spec->use_alt_functions) + if (ca0132_use_alt_functions(spec)) ret |= ca0132_alt_set_vipsource(codec, 1); else ret |= ca0132_set_vipsource(codec, 1); @@ -5053,7 +5083,7 @@ static int ca0132_vnode_switch_set(struct snd_kcontrol *kcontrol, auto_jack = spec->vnode_lswitch[VNID_HP_ASEL - VNODE_START_NID]; if (!auto_jack) { - if (spec->use_alt_functions) + if (ca0132_use_alt_functions(spec)) ca0132_alt_select_out(codec); else ca0132_select_out(codec); @@ -5070,7 +5100,7 @@ static int ca0132_vnode_switch_set(struct snd_kcontrol *kcontrol, } if (nid == VNID_HP_ASEL) { - if (spec->use_alt_functions) + if (ca0132_use_alt_functions(spec)) ca0132_alt_select_out(codec); else ca0132_select_out(codec); @@ -5784,7 +5814,7 @@ static int ca0132_switch_put(struct snd_kcontrol *kcontrol, /* mic boost */ if (nid == spec->input_pins[0]) { spec->cur_mic_boost = *valp; - if (spec->use_alt_functions) { + if (ca0132_use_alt_functions(spec)) { if (spec->in_enum_val != REAR_LINE_IN) changed = ca0132_mic_boost_set(codec, *valp); } else { @@ -6080,7 +6110,7 @@ static int add_fx_switch(struct hda_codec *codec, hda_nid_t nid, /* If using alt_controls, add FX: prefix. But, don't add FX: * prefix to OutFX or InFX enable controls. */ - if ((spec->use_alt_controls) && (nid <= IN_EFFECT_END_NID)) + if (ca0132_use_alt_controls(spec) && (nid <= IN_EFFECT_END_NID)) sprintf(namestr, "FX: %s %s Switch", pfx, dirstr[dir]); else sprintf(namestr, "%s %s Switch", pfx, dirstr[dir]); @@ -6357,7 +6387,7 @@ static int ca0132_build_controls(struct hda_codec *codec) return err; } /* Setup vmaster with surround slaves for desktop ca0132 devices */ - if (spec->use_alt_functions) { + if (ca0132_use_alt_functions(spec)) { snd_hda_set_vmaster_tlv(codec, spec->dacs[0], HDA_OUTPUT, spec->tlv); snd_hda_add_vmaster(codec, "Master Playback Volume", @@ -6377,7 +6407,7 @@ static int ca0132_build_controls(struct hda_codec *codec) num_fx = OUT_EFFECTS_COUNT + IN_EFFECTS_COUNT; for (i = 0; i < num_fx; i++) { /* Desktop cards break if Echo Cancellation is used. */ - if (spec->use_pci_mmio) { + if (ca0132_use_pci_mmio(spec)) { if (i == (ECHO_CANCELLATION - IN_EFFECT_START_NID + OUT_EFFECTS_COUNT)) continue; @@ -6394,7 +6424,7 @@ static int ca0132_build_controls(struct hda_codec *codec) * EQ presets, and Smart Volume presets. Also, change names to add FX * prefix, and change PlayEnhancement and CrystalVoice to match. */ - if (spec->use_alt_controls) { + if (ca0132_use_alt_controls(spec)) { err = ca0132_alt_add_svm_enum(codec); if (err < 0) return err; @@ -6448,7 +6478,7 @@ static int ca0132_build_controls(struct hda_codec *codec) * to select the new outputs and inputs, plus add the new mic boost * setting control. */ - if (spec->use_alt_functions) { + if (ca0132_use_alt_functions(spec)) { err = ca0132_alt_add_output_enum(codec); if (err < 0) return err; @@ -6459,14 +6489,14 @@ static int ca0132_build_controls(struct hda_codec *codec) * ZxR only has microphone input, there is no front panel * header on the card, and aux-in is handled by the DBPro board. */ - if (spec->quirk != QUIRK_ZXR) { + if (ca0132_quirk(spec) != QUIRK_ZXR) { err = ca0132_alt_add_input_enum(codec); if (err < 0) return err; } } - if (spec->quirk == QUIRK_AE5) { + if (ca0132_quirk(spec) == QUIRK_AE5) { err = ae5_add_headphone_gain_enum(codec); if (err < 0) return err; @@ -6475,7 +6505,7 @@ static int ca0132_build_controls(struct hda_codec *codec) return err; } - if (spec->quirk == QUIRK_ZXR) { + if (ca0132_quirk(spec) == QUIRK_ZXR) { err = zxr_add_headphone_gain_switch(codec); if (err < 0) return err; @@ -6505,7 +6535,7 @@ static int ca0132_build_controls(struct hda_codec *codec) return err; } - if (spec->use_alt_functions) + if (ca0132_use_alt_functions(spec)) ca0132_alt_add_chmap_ctls(codec); return 0; @@ -6583,7 +6613,7 @@ static int ca0132_build_pcms(struct hda_codec *codec) info = snd_hda_codec_pcm_new(codec, "CA0132 Analog"); if (!info) return -ENOMEM; - if (spec->use_alt_functions) { + if (ca0132_use_alt_functions(spec)) { info->own_chmap = true; info->stream[SNDRV_PCM_STREAM_PLAYBACK].chmap = ca0132_alt_chmaps; @@ -6597,7 +6627,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 (!ca0132_use_alt_functions(spec)) { info = snd_hda_codec_pcm_new(codec, "CA0132 Analog Mic-In2"); if (!info) return -ENOMEM; @@ -6795,7 +6825,7 @@ 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 */ - if (spec->quirk == QUIRK_ALIENWARE_M17XR4) + if (ca0132_quirk(spec) == QUIRK_ALIENWARE_M17XR4) val = 0x33; else val = 0x23; @@ -6877,7 +6907,7 @@ static void ca0132_alt_init_analog_mics(struct hda_codec *codec) /* Mic 1 Setup */ chipio_set_conn_rate(codec, MEM_CONNID_MICIN1, SR_96_000); chipio_set_conn_rate(codec, MEM_CONNID_MICOUT1, SR_96_000); - if (spec->quirk == QUIRK_R3DI) { + if (ca0132_quirk(spec) == QUIRK_R3DI) { chipio_set_conn_rate(codec, 0x0F, SR_96_000); tmp = FLOAT_ONE; } else @@ -6887,7 +6917,7 @@ static void ca0132_alt_init_analog_mics(struct hda_codec *codec) /* Mic 2 setup (not present on desktop cards) */ chipio_set_conn_rate(codec, MEM_CONNID_MICIN2, SR_96_000); chipio_set_conn_rate(codec, MEM_CONNID_MICOUT2, SR_96_000); - if (spec->quirk == QUIRK_R3DI) + if (ca0132_quirk(spec) == QUIRK_R3DI) chipio_set_conn_rate(codec, 0x0F, SR_96_000); tmp = FLOAT_ZERO; dspio_set_uint_param(codec, 0x80, 0x01, tmp); @@ -6949,7 +6979,7 @@ static void sbz_chipio_startup_data(struct hda_codec *codec) chipio_set_stream_channels(codec, 0x0C, 6); chipio_set_stream_control(codec, 0x0C, 1); /* No clue what these control */ - if (spec->quirk == QUIRK_SBZ) { + if (ca0132_quirk(spec) == QUIRK_SBZ) { chipio_write_no_mutex(codec, 0x190030, 0x0001e0c0); chipio_write_no_mutex(codec, 0x190034, 0x0001e1c1); chipio_write_no_mutex(codec, 0x190038, 0x0001e4c2); @@ -6962,7 +6992,7 @@ static void sbz_chipio_startup_data(struct hda_codec *codec) chipio_write_no_mutex(codec, 0x190054, 0x0001edc9); chipio_write_no_mutex(codec, 0x190058, 0x0001eaca); chipio_write_no_mutex(codec, 0x19005c, 0x0001ebcb); - } else if (spec->quirk == QUIRK_ZXR) { + } else if (ca0132_quirk(spec) == QUIRK_ZXR) { chipio_write_no_mutex(codec, 0x190038, 0x000140c2); chipio_write_no_mutex(codec, 0x19003c, 0x000141c3); chipio_write_no_mutex(codec, 0x190040, 0x000150c4); @@ -6992,7 +7022,7 @@ static void ca0132_alt_dsp_scp_startup(struct hda_codec *codec) * why this is, but multiple tests have confirmed it. */ for (i = 0; i < 2; i++) { - switch (spec->quirk) { + switch (ca0132_quirk(spec)) { case QUIRK_SBZ: case QUIRK_AE5: tmp = 0x00000003; @@ -7021,6 +7051,8 @@ static void ca0132_alt_dsp_scp_startup(struct hda_codec *codec) tmp = 0x00000000; dspio_set_uint_param_no_source(codec, 0x80, 0x0C, tmp); break; + default: + break; } msleep(100); } @@ -7043,7 +7075,7 @@ static void ca0132_alt_dsp_initial_mic_setup(struct hda_codec *codec) chipio_set_stream_control(codec, 0x03, 1); chipio_set_stream_control(codec, 0x04, 1); - switch (spec->quirk) { + switch (ca0132_quirk(spec)) { case QUIRK_SBZ: chipio_write(codec, 0x18b098, 0x0000000c); chipio_write(codec, 0x18b09C, 0x0000000c); @@ -7052,6 +7084,8 @@ static void ca0132_alt_dsp_initial_mic_setup(struct hda_codec *codec) chipio_write(codec, 0x18b098, 0x0000000c); chipio_write(codec, 0x18b09c, 0x0000004c); break; + default: + break; } } @@ -7273,7 +7307,7 @@ static void r3d_setup_defaults(struct hda_codec *codec) /* Set speaker source? */ dspio_set_uint_param(codec, 0x32, 0x00, tmp); - if (spec->quirk == QUIRK_R3DI) + if (ca0132_quirk(spec) == QUIRK_R3DI) r3di_gpio_dsp_status_set(codec, R3DI_DSP_DOWNLOADED); /* Setup effect defaults */ @@ -7420,7 +7454,7 @@ static void ca0132_init_flags(struct hda_codec *codec) { struct ca0132_spec *spec = codec->spec; - if (spec->use_alt_functions) { + if (ca0132_use_alt_functions(spec)) { chipio_set_control_flag(codec, CONTROL_FLAG_DSP_96KHZ, 1); chipio_set_control_flag(codec, CONTROL_FLAG_DAC_96KHZ, 1); chipio_set_control_flag(codec, CONTROL_FLAG_ADC_B_96KHZ, 1); @@ -7453,7 +7487,7 @@ static void ca0132_init_params(struct hda_codec *codec) { struct ca0132_spec *spec = codec->spec; - if (spec->use_alt_functions) { + if (ca0132_use_alt_functions(spec)) { chipio_set_conn_rate(codec, MEM_CONNID_WUH, SR_48_000); chipio_set_conn_rate(codec, 0x0B, SR_48_000); chipio_set_control_param(codec, CONTROL_PARAM_SPDIF1_SOURCE, 0); @@ -7490,7 +7524,7 @@ static bool ca0132_download_dsp_images(struct hda_codec *codec) * can use the default firmware, but I'll leave the option in case * it needs it again. */ - switch (spec->quirk) { + switch (ca0132_quirk(spec)) { case QUIRK_SBZ: case QUIRK_R3D: case QUIRK_AE5: @@ -7564,7 +7598,7 @@ static void ca0132_download_dsp(struct hda_codec *codec) } /* For codecs using alt functions, this is already done earlier */ - if (spec->dsp_state == DSP_DOWNLOADED && (!spec->use_alt_functions)) + if (spec->dsp_state == DSP_DOWNLOADED && !ca0132_use_alt_functions(spec)) ca0132_set_dsp_msr(codec, true); } @@ -7601,7 +7635,7 @@ static void amic_callback(struct hda_codec *codec, struct hda_jack_callback *cb) { struct ca0132_spec *spec = codec->spec; - if (spec->use_alt_functions) + if (ca0132_use_alt_functions(spec)) ca0132_alt_select_in(codec); else ca0132_select_mic(codec); @@ -7616,7 +7650,7 @@ static void ca0132_init_unsol(struct hda_codec *codec) snd_hda_jack_detect_enable_callback(codec, UNSOL_TAG_DSP, ca0132_process_dsp_response); /* Front headphone jack detection */ - if (spec->use_alt_functions) + if (ca0132_use_alt_functions(spec)) snd_hda_jack_detect_enable_callback(codec, spec->unsol_tag_front_hp, hp_callback); } @@ -7706,7 +7740,7 @@ static void ca0132_init_chip(struct hda_codec *codec) mutex_init(&spec->chipio_mutex); spec->cur_out_type = SPEAKER_OUT; - if (!spec->use_alt_functions) + if (!ca0132_use_alt_functions(spec)) spec->cur_mic_type = DIGITAL_MIC; else spec->cur_mic_type = REAR_MIC; @@ -7732,7 +7766,7 @@ static void ca0132_init_chip(struct hda_codec *codec) * Sets defaults for the effect slider controls, only for alternative * ca0132 codecs. Also sets x-bass crossover frequency to 80hz. */ - if (spec->use_alt_controls) { + if (ca0132_use_alt_controls(spec)) { spec->xbass_xover_freq = 8; for (i = 0; i < EFFECT_LEVEL_SLIDERS; i++) spec->fx_ctl_val[i] = effect_slider_defaults[i]; @@ -7747,7 +7781,7 @@ static void ca0132_init_chip(struct hda_codec *codec) * the daughter board. So, there is no input enum control, and we need * to make sure that spec->in_enum_val is set properly. */ - if (spec->quirk == QUIRK_ZXR) + if (ca0132_quirk(spec) == QUIRK_ZXR) spec->in_enum_val = REAR_MIC; #ifdef ENABLE_TUNING_CONTROLS @@ -8088,27 +8122,27 @@ static void ca0132_mmio_init(struct hda_codec *codec) { struct ca0132_spec *spec = codec->spec; - if (spec->quirk == QUIRK_AE5) + if (ca0132_quirk(spec) == QUIRK_AE5) writel(0x00000001, spec->mem_base + 0x400); else writel(0x00000000, spec->mem_base + 0x400); - if (spec->quirk == QUIRK_AE5) + if (ca0132_quirk(spec) == QUIRK_AE5) writel(0x00000001, spec->mem_base + 0x408); else writel(0x00000000, spec->mem_base + 0x408); - if (spec->quirk == QUIRK_AE5) + if (ca0132_quirk(spec) == QUIRK_AE5) writel(0x00000001, spec->mem_base + 0x40c); else writel(0x00000000, spec->mem_base + 0x40C); - if (spec->quirk == QUIRK_ZXR) + if (ca0132_quirk(spec) == QUIRK_ZXR) writel(0x00880640, spec->mem_base + 0x01C); else writel(0x00880680, spec->mem_base + 0x01C); - if (spec->quirk == QUIRK_AE5) + if (ca0132_quirk(spec) == QUIRK_AE5) writel(0x00000080, spec->mem_base + 0xC0C); else writel(0x00000083, spec->mem_base + 0xC0C); @@ -8116,7 +8150,7 @@ static void ca0132_mmio_init(struct hda_codec *codec) writel(0x00000030, spec->mem_base + 0xC00); writel(0x00000000, spec->mem_base + 0xC04); - if (spec->quirk == QUIRK_AE5) + if (ca0132_quirk(spec) == QUIRK_AE5) writel(0x00000000, spec->mem_base + 0xC0C); else writel(0x00000003, spec->mem_base + 0xC0C); @@ -8125,7 +8159,7 @@ static void ca0132_mmio_init(struct hda_codec *codec) writel(0x00000003, spec->mem_base + 0xC0C); writel(0x00000003, spec->mem_base + 0xC0C); - if (spec->quirk == QUIRK_AE5) + if (ca0132_quirk(spec) == QUIRK_AE5) writel(0x00000001, spec->mem_base + 0xC08); else writel(0x000000C1, spec->mem_base + 0xC08); @@ -8136,7 +8170,7 @@ static void ca0132_mmio_init(struct hda_codec *codec) writel(0x000000C1, spec->mem_base + 0xC08); writel(0x00000080, spec->mem_base + 0xC04); - if (spec->quirk == QUIRK_AE5) { + if (ca0132_quirk(spec) == QUIRK_AE5) { writel(0x00000000, spec->mem_base + 0x42c); writel(0x00000000, spec->mem_base + 0x46c); writel(0x00000000, spec->mem_base + 0x4ac); @@ -8211,7 +8245,7 @@ static void ca0132_alt_init(struct hda_codec *codec) ca0132_alt_vol_setup(codec); - switch (spec->quirk) { + switch (ca0132_quirk(spec)) { case QUIRK_SBZ: codec_dbg(codec, "SBZ alt_init"); ca0132_gpio_init(codec); @@ -8248,6 +8282,8 @@ static void ca0132_alt_init(struct hda_codec *codec) snd_hda_sequence_write(codec, spec->chip_init_verbs); snd_hda_sequence_write(codec, spec->desktop_init_verbs); break; + default: + break; } } @@ -8274,7 +8310,7 @@ static int ca0132_init(struct hda_codec *codec) spec->dsp_reload = true; spec->dsp_state = DSP_DOWNLOAD_INIT; } else { - if (spec->quirk == QUIRK_SBZ) + if (ca0132_quirk(spec) == QUIRK_SBZ) sbz_dsp_startup_check(codec); return 0; } @@ -8284,12 +8320,12 @@ static int ca0132_init(struct hda_codec *codec) spec->dsp_state = DSP_DOWNLOAD_INIT; spec->curr_chip_addx = INVALID_CHIP_ADDRESS; - if (spec->use_pci_mmio) + if (ca0132_use_pci_mmio(spec)) ca0132_mmio_init(codec); snd_hda_power_up_pm(codec); - if (spec->quirk == QUIRK_AE5) + if (ca0132_quirk(spec) == QUIRK_AE5) ae5_register_set(codec); ca0132_init_unsol(codec); @@ -8298,14 +8334,14 @@ static int ca0132_init(struct hda_codec *codec) snd_hda_sequence_write(codec, spec->base_init_verbs); - if (spec->use_alt_functions) + if (ca0132_use_alt_functions(spec)) ca0132_alt_init(codec); ca0132_download_dsp(codec); ca0132_refresh_widget_caps(codec); - switch (spec->quirk) { + switch (ca0132_quirk(spec)) { case QUIRK_R3DI: case QUIRK_R3D: r3d_setup_defaults(codec); @@ -8334,7 +8370,7 @@ static int ca0132_init(struct hda_codec *codec) init_input(codec, cfg->dig_in_pin, spec->dig_in); - if (!spec->use_alt_functions) { + if (!ca0132_use_alt_functions(spec)) { snd_hda_sequence_write(codec, spec->chip_init_verbs); snd_hda_codec_write(codec, WIDGET_CHIP_CTRL, 0, VENDOR_CHIPIO_PARAM_EX_ID_SET, 0x0D); @@ -8342,11 +8378,11 @@ static int ca0132_init(struct hda_codec *codec) VENDOR_CHIPIO_PARAM_EX_VALUE_SET, 0x20); } - if (spec->quirk == QUIRK_SBZ) + if (ca0132_quirk(spec) == QUIRK_SBZ) ca0132_gpio_setup(codec); snd_hda_sequence_write(codec, spec->spec_init_verbs); - if (spec->use_alt_functions) { + if (ca0132_use_alt_functions(spec)) { ca0132_alt_select_out(codec); ca0132_alt_select_in(codec); } else { @@ -8391,7 +8427,7 @@ static void ca0132_free(struct hda_codec *codec) cancel_delayed_work_sync(&spec->unsol_hp_work); snd_hda_power_up(codec); - switch (spec->quirk) { + switch (ca0132_quirk(spec)) { case QUIRK_SBZ: sbz_exit_chip(codec); break; @@ -8407,13 +8443,15 @@ static void ca0132_free(struct hda_codec *codec) case QUIRK_R3DI: r3di_gpio_shutdown(codec); break; + default: + break; } snd_hda_sequence_write(codec, spec->base_exit_verbs); ca0132_exit_chip(codec); snd_hda_power_down(codec); - if (spec->mem_base) + if (IS_ENABLED(CONFIG_PCI) && spec->mem_base) pci_iounmap(codec->bus->pci, spec->mem_base); kfree(spec->spec_init_verbs); kfree(codec->spec); @@ -8461,12 +8499,12 @@ static void ca0132_config(struct hda_codec *codec) spec->multiout.dac_nids = spec->dacs; spec->multiout.num_dacs = 3; - if (!spec->use_alt_functions) + if (!ca0132_use_alt_functions(spec)) spec->multiout.max_channels = 2; else spec->multiout.max_channels = 6; - switch (spec->quirk) { + switch (ca0132_quirk(spec)) { case QUIRK_ALIENWARE: codec_dbg(codec, "%s: QUIRK_ALIENWARE applied.\n", __func__); snd_hda_apply_pincfgs(codec, alienware_pincfgs); @@ -8491,9 +8529,11 @@ static void ca0132_config(struct hda_codec *codec) codec_dbg(codec, "%s: QUIRK_AE5 applied.\n", __func__); snd_hda_apply_pincfgs(codec, ae5_pincfgs); break; + default: + break; } - switch (spec->quirk) { + switch (ca0132_quirk(spec)) { case QUIRK_ALIENWARE: spec->num_outputs = 2; spec->out_pins[0] = 0x0b; /* speaker out */ @@ -8654,7 +8694,7 @@ static int ca0132_prepare_verbs(struct hda_codec *codec) * Since desktop cards use pci_mmio, this can be used to determine * whether or not to use these verbs instead of a separate bool. */ - if (spec->use_pci_mmio) + if (ca0132_use_pci_mmio(spec)) spec->desktop_init_verbs = ca0132_init_verbs1; spec->spec_init_verbs = kcalloc(NUM_SPEC_VERBS, sizeof(struct hda_verb), @@ -8729,11 +8769,10 @@ static int patch_ca0132(struct hda_codec *codec) spec->quirk = quirk->value; else spec->quirk = QUIRK_NONE; - - if (spec->quirk == QUIRK_SBZ) + if (ca0132_quirk(spec) == QUIRK_SBZ) sbz_detect_quirk(codec); - if (spec->quirk == QUIRK_ZXR_DBPRO) + if (ca0132_quirk(spec) == QUIRK_ZXR_DBPRO) codec->patch_ops = dbpro_patch_ops; else codec->patch_ops = ca0132_patch_ops; @@ -8746,7 +8785,7 @@ static int patch_ca0132(struct hda_codec *codec) spec->num_mixers = 1; /* Set which mixers each quirk uses. */ - switch (spec->quirk) { + switch (ca0132_quirk(spec)) { case QUIRK_SBZ: spec->mixers[0] = desktop_mixer; snd_hda_codec_set_name(codec, "Sound Blaster Z"); @@ -8775,7 +8814,7 @@ static int patch_ca0132(struct hda_codec *codec) } /* Setup whether or not to use alt functions/controls/pci_mmio */ - switch (spec->quirk) { + switch (ca0132_quirk(spec)) { case QUIRK_SBZ: case QUIRK_R3D: case QUIRK_AE5: @@ -8796,6 +8835,7 @@ static int patch_ca0132(struct hda_codec *codec) break; } +#ifdef CONFIG_PCI if (spec->use_pci_mmio) { spec->mem_base = pci_iomap(codec->bus->pci, 2, 0xC20); if (spec->mem_base == NULL) { @@ -8803,6 +8843,7 @@ static int patch_ca0132(struct hda_codec *codec) spec->quirk = QUIRK_NONE; } } +#endif spec->base_init_verbs = ca0132_base_init_verbs; spec->base_exit_verbs = ca0132_base_exit_verbs; diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c index 950e02e71766..51cc6589443f 100644 --- a/sound/pci/hda/patch_conexant.c +++ b/sound/pci/hda/patch_conexant.c @@ -923,6 +923,7 @@ static const struct snd_pci_quirk cxt5066_fixups[] = { SND_PCI_QUIRK(0x103c, 0x8079, "HP EliteBook 840 G3", CXT_FIXUP_HP_DOCK), SND_PCI_QUIRK(0x103c, 0x807C, "HP EliteBook 820 G3", CXT_FIXUP_HP_DOCK), SND_PCI_QUIRK(0x103c, 0x80FD, "HP ProBook 640 G2", CXT_FIXUP_HP_DOCK), + SND_PCI_QUIRK(0x103c, 0x828c, "HP EliteBook 840 G4", CXT_FIXUP_HP_DOCK), SND_PCI_QUIRK(0x103c, 0x83b3, "HP EliteBook 830 G5", CXT_FIXUP_HP_DOCK), SND_PCI_QUIRK(0x103c, 0x83d3, "HP ProBook 640 G4", CXT_FIXUP_HP_DOCK), SND_PCI_QUIRK(0x103c, 0x8174, "HP Spectre x360", CXT_FIXUP_HP_SPECTRE), diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c index 67099cbb6be2..46f88dc7b7e8 100644 --- a/sound/pci/hda/patch_hdmi.c +++ b/sound/pci/hda/patch_hdmi.c @@ -2142,7 +2142,7 @@ static int generic_hdmi_build_jack(struct hda_codec *codec, int pcm_idx) strncat(hdmi_str, " Phantom", sizeof(hdmi_str) - strlen(hdmi_str) - 1); ret = snd_hda_jack_add_kctl(codec, per_pin->pin_nid, hdmi_str, - phantom_jack); + phantom_jack, 0, NULL); if (ret < 0) return ret; jack = snd_hda_jack_tbl_get(codec, per_pin->pin_nid); @@ -2616,11 +2616,7 @@ static int intel_hsw_common_init(struct hda_codec *codec, hda_nid_t vendor_nid) intel_haswell_enable_all_pins(codec, true); intel_haswell_fixup_enable_dp12(codec); - /* For Haswell/Broadwell, the controller is also in the power well and - * can cover the codec power request, and so need not set this flag. - */ - if (!is_haswell(codec) && !is_broadwell(codec)) - codec->core.link_power_control = 1; + codec->display_power_control = 1; codec->patch_ops.set_power_state = haswell_set_power_state; codec->depop_delay = 0; @@ -2656,7 +2652,7 @@ static int patch_i915_byt_hdmi(struct hda_codec *codec) /* For Valleyview/Cherryview, only the display codec is in the display * power well and can use link_power ops to request/release the power. */ - codec->core.link_power_control = 1; + codec->display_power_control = 1; codec->depop_delay = 0; codec->auto_runtime_pm = 1; @@ -3834,6 +3830,10 @@ HDA_CODEC_ENTRY(0x10de0020, "Tegra30 HDMI", patch_tegra_hdmi), HDA_CODEC_ENTRY(0x10de0022, "Tegra114 HDMI", patch_tegra_hdmi), HDA_CODEC_ENTRY(0x10de0028, "Tegra124 HDMI", patch_tegra_hdmi), HDA_CODEC_ENTRY(0x10de0029, "Tegra210 HDMI/DP", patch_tegra_hdmi), +HDA_CODEC_ENTRY(0x10de002d, "Tegra186 HDMI/DP0", patch_tegra_hdmi), +HDA_CODEC_ENTRY(0x10de002e, "Tegra186 HDMI/DP1", patch_tegra_hdmi), +HDA_CODEC_ENTRY(0x10de002f, "Tegra194 HDMI/DP2", patch_tegra_hdmi), +HDA_CODEC_ENTRY(0x10de0030, "Tegra194 HDMI/DP3", patch_tegra_hdmi), HDA_CODEC_ENTRY(0x10de0040, "GPU 40 HDMI/DP", patch_nvhdmi), HDA_CODEC_ENTRY(0x10de0041, "GPU 41 HDMI/DP", patch_nvhdmi), HDA_CODEC_ENTRY(0x10de0042, "GPU 42 HDMI/DP", patch_nvhdmi), diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 8d75597028ee..a4f4a9dd488d 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -5380,6 +5380,66 @@ static void alc285_fixup_invalidate_dacs(struct hda_codec *codec, snd_hda_override_wcaps(codec, 0x03, 0); } +static const struct hda_jack_keymap alc_headset_btn_keymap[] = { + { SND_JACK_BTN_0, KEY_PLAYPAUSE }, + { SND_JACK_BTN_1, KEY_VOICECOMMAND }, + { SND_JACK_BTN_2, KEY_VOLUMEUP }, + { SND_JACK_BTN_3, KEY_VOLUMEDOWN }, + {} +}; + +static void alc_headset_btn_callback(struct hda_codec *codec, + struct hda_jack_callback *jack) +{ + int report = 0; + + if (jack->unsol_res & (7 << 13)) + report |= SND_JACK_BTN_0; + + if (jack->unsol_res & (1 << 16 | 3 << 8)) + report |= SND_JACK_BTN_1; + + /* Volume up key */ + if (jack->unsol_res & (7 << 23)) + report |= SND_JACK_BTN_2; + + /* Volume down key */ + if (jack->unsol_res & (7 << 10)) + report |= SND_JACK_BTN_3; + + jack->jack->button_state = report; +} + +static void alc_fixup_headset_jack(struct hda_codec *codec, + const struct hda_fixup *fix, int action) +{ + + switch (action) { + case HDA_FIXUP_ACT_PRE_PROBE: + snd_hda_jack_detect_enable_callback(codec, 0x55, + alc_headset_btn_callback); + snd_hda_jack_add_kctl(codec, 0x55, "Headset Jack", false, + SND_JACK_HEADSET, alc_headset_btn_keymap); + break; + case HDA_FIXUP_ACT_INIT: + switch (codec->core.vendor_id) { + case 0x10ec0225: + case 0x10ec0295: + case 0x10ec0299: + alc_write_coef_idx(codec, 0x48, 0xd011); + alc_update_coef_idx(codec, 0x49, 0x007f, 0x0045); + alc_update_coef_idx(codec, 0x44, 0x007f << 8, 0x0045 << 8); + break; + case 0x10ec0236: + case 0x10ec0256: + alc_write_coef_idx(codec, 0x48, 0xd011); + alc_update_coef_idx(codec, 0x49, 0x007f, 0x0045); + break; + } + break; + } +} + /* for hda_fixup_thinkpad_acpi() */ #include "thinkpad_helper.c" @@ -5390,9 +5450,6 @@ static void alc_fixup_thinkpad_acpi(struct hda_codec *codec, hda_fixup_thinkpad_acpi(codec, fix, action); } -/* for dell wmi mic mute led */ -#include "dell_wmi_helper.c" - /* for alc295_fixup_hp_top_speakers */ #include "hp_x360_helper.c" @@ -5470,7 +5527,7 @@ enum { ALC292_FIXUP_TPT440_DOCK, ALC292_FIXUP_TPT440, ALC283_FIXUP_HEADSET_MIC, - ALC255_FIXUP_DELL_WMI_MIC_MUTE_LED, + ALC255_FIXUP_MIC_MUTE_LED, ALC282_FIXUP_ASPIRE_V5_PINS, ALC280_FIXUP_HP_GPIO4, ALC286_FIXUP_HP_GPIO_LED, @@ -5515,11 +5572,16 @@ enum { ALC298_FIXUP_TPT470_DOCK, ALC255_FIXUP_DUMMY_LINEOUT_VERB, ALC255_FIXUP_DELL_HEADSET_MIC, + ALC256_FIXUP_HUAWEI_MBXP_PINS, ALC295_FIXUP_HP_X360, ALC221_FIXUP_HP_HEADSET_MIC, ALC285_FIXUP_LENOVO_HEADPHONE_NOISE, ALC295_FIXUP_HP_AUTO_MUTE, ALC286_FIXUP_ACER_AIO_MIC_NO_PRESENCE, + ALC294_FIXUP_ASUS_MIC, + ALC294_FIXUP_ASUS_HEADSET_MIC, + ALC294_FIXUP_ASUS_SPK, + ALC225_FIXUP_HEADSET_JACK, }; static const struct hda_fixup alc269_fixups[] = { @@ -5767,7 +5829,7 @@ static const struct hda_fixup alc269_fixups[] = { .type = HDA_FIXUP_FUNC, .v.func = alc_fixup_headset_mode, .chained = true, - .chain_id = ALC255_FIXUP_DELL_WMI_MIC_MUTE_LED + .chain_id = ALC255_FIXUP_MIC_MUTE_LED }, [ALC269_FIXUP_HEADSET_MODE_NO_HP_MIC] = { .type = HDA_FIXUP_FUNC, @@ -5791,6 +5853,24 @@ static const struct hda_fixup alc269_fixups[] = { .chained = true, .chain_id = ALC269_FIXUP_HEADSET_MIC }, + [ALC256_FIXUP_HUAWEI_MBXP_PINS] = { + .type = HDA_FIXUP_PINS, + .v.pins = (const struct hda_pintbl[]) { + {0x12, 0x90a60130}, + {0x13, 0x40000000}, + {0x14, 0x90170110}, + {0x18, 0x411111f0}, + {0x19, 0x04a11040}, + {0x1a, 0x411111f0}, + {0x1b, 0x90170112}, + {0x1d, 0x40759a05}, + {0x1e, 0x411111f0}, + {0x21, 0x04211020}, + { } + }, + .chained = true, + .chain_id = ALC255_FIXUP_MIC_MUTE_LED + }, [ALC269_FIXUP_ASUS_X101_FUNC] = { .type = HDA_FIXUP_FUNC, .v.func = alc269_fixup_x101_headset_mic, @@ -5993,7 +6073,7 @@ static const struct hda_fixup alc269_fixups[] = { .type = HDA_FIXUP_FUNC, .v.func = alc_fixup_headset_mode_alc255, .chained = true, - .chain_id = ALC255_FIXUP_DELL_WMI_MIC_MUTE_LED + .chain_id = ALC255_FIXUP_MIC_MUTE_LED }, [ALC255_FIXUP_HEADSET_MODE_NO_HP_MIC] = { .type = HDA_FIXUP_FUNC, @@ -6028,9 +6108,9 @@ static const struct hda_fixup alc269_fixups[] = { { }, }, }, - [ALC255_FIXUP_DELL_WMI_MIC_MUTE_LED] = { + [ALC255_FIXUP_MIC_MUTE_LED] = { .type = HDA_FIXUP_FUNC, - .v.func = alc_fixup_dell_wmi, + .v.func = snd_hda_gen_fixup_micmute_led, }, [ALC282_FIXUP_ASPIRE_V5_PINS] = { .type = HDA_FIXUP_PINS, @@ -6089,7 +6169,7 @@ static const struct hda_fixup alc269_fixups[] = { .type = HDA_FIXUP_FUNC, .v.func = alc_fixup_headset_mode_dell_alc288, .chained = true, - .chain_id = ALC255_FIXUP_DELL_WMI_MIC_MUTE_LED + .chain_id = ALC255_FIXUP_MIC_MUTE_LED }, [ALC288_FIXUP_DELL1_MIC_NO_PRESENCE] = { .type = HDA_FIXUP_PINS, @@ -6392,6 +6472,8 @@ static const struct hda_fixup alc269_fixups[] = { [ALC285_FIXUP_LENOVO_HEADPHONE_NOISE] = { .type = HDA_FIXUP_FUNC, .v.func = alc285_fixup_invalidate_dacs, + .chained = true, + .chain_id = ALC269_FIXUP_THINKPAD_ACPI }, [ALC295_FIXUP_HP_AUTO_MUTE] = { .type = HDA_FIXUP_FUNC, @@ -6406,6 +6488,40 @@ static const struct hda_fixup alc269_fixups[] = { .chained = true, .chain_id = ALC269_FIXUP_HEADSET_MIC }, + [ALC294_FIXUP_ASUS_MIC] = { + .type = HDA_FIXUP_PINS, + .v.pins = (const struct hda_pintbl[]) { + { 0x13, 0x90a60160 }, /* use as internal mic */ + { 0x19, 0x04a11120 }, /* use as headset mic, without its own jack detect */ + { } + }, + .chained = true, + .chain_id = ALC269_FIXUP_HEADSET_MODE_NO_HP_MIC + }, + [ALC294_FIXUP_ASUS_HEADSET_MIC] = { + .type = HDA_FIXUP_PINS, + .v.pins = (const struct hda_pintbl[]) { + { 0x19, 0x01a1113c }, /* use as headset mic, without its own jack detect */ + { } + }, + .chained = true, + .chain_id = ALC269_FIXUP_HEADSET_MODE_NO_HP_MIC + }, + [ALC294_FIXUP_ASUS_SPK] = { + .type = HDA_FIXUP_VERBS, + .v.verbs = (const struct hda_verb[]) { + /* Set EAPD high */ + { 0x20, AC_VERB_SET_COEF_INDEX, 0x40 }, + { 0x20, AC_VERB_SET_PROC_COEF, 0x8800 }, + { } + }, + .chained = true, + .chain_id = ALC294_FIXUP_ASUS_HEADSET_MIC + }, + [ALC225_FIXUP_HEADSET_JACK] = { + .type = HDA_FIXUP_FUNC, + .v.func = alc_fixup_headset_jack, + }, }; static const struct snd_pci_quirk alc269_fixup_tbl[] = { @@ -6538,6 +6654,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { SND_PCI_QUIRK(0x1043, 0x103e, "ASUS X540SA", ALC256_FIXUP_ASUS_MIC), SND_PCI_QUIRK(0x1043, 0x103f, "ASUS TX300", ALC282_FIXUP_ASUS_TX300), SND_PCI_QUIRK(0x1043, 0x106d, "Asus K53BE", ALC269_FIXUP_LIMIT_INT_MIC_BOOST), + SND_PCI_QUIRK(0x1043, 0x10a1, "ASUS UX391UA", ALC294_FIXUP_ASUS_SPK), SND_PCI_QUIRK(0x1043, 0x10c0, "ASUS X540SA", ALC256_FIXUP_ASUS_MIC), SND_PCI_QUIRK(0x1043, 0x10d0, "ASUS X540LA/X540LJ", ALC255_FIXUP_ASUS_MIC_NO_PRESENCE), SND_PCI_QUIRK(0x1043, 0x115d, "Asus 1015E", ALC269_FIXUP_LIMIT_INT_MIC_BOOST), @@ -6548,6 +6665,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { SND_PCI_QUIRK(0x1043, 0x12e0, "ASUS X541SA", ALC256_FIXUP_ASUS_MIC), SND_PCI_QUIRK(0x1043, 0x13b0, "ASUS Z550SA", ALC256_FIXUP_ASUS_MIC), SND_PCI_QUIRK(0x1043, 0x1427, "Asus Zenbook UX31E", ALC269VB_FIXUP_ASUS_ZENBOOK), + SND_PCI_QUIRK(0x1043, 0x14a1, "ASUS UX533FD", ALC294_FIXUP_ASUS_SPK), SND_PCI_QUIRK(0x1043, 0x1517, "Asus Zenbook UX31A", ALC269VB_FIXUP_ASUS_ZENBOOK_UX31A), SND_PCI_QUIRK(0x1043, 0x16e3, "ASUS UX50", ALC269_FIXUP_STEREO_DMIC), SND_PCI_QUIRK(0x1043, 0x1a13, "Asus G73Jw", ALC269_FIXUP_ASUS_G73JW), @@ -6644,6 +6762,9 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { SND_PCI_QUIRK(0x17aa, 0x511f, "Thinkpad", ALC298_FIXUP_TPT470_DOCK), SND_PCI_QUIRK(0x17aa, 0x3bf8, "Quanta FL1", ALC269_FIXUP_PCM_44K), SND_PCI_QUIRK(0x17aa, 0x9e54, "LENOVO NB", ALC269_FIXUP_LENOVO_EAPD), + SND_PCI_QUIRK(0x19e5, 0x3200, "Huawei MBX", ALC255_FIXUP_MIC_MUTE_LED), + SND_PCI_QUIRK(0x19e5, 0x3201, "Huawei MBX", ALC255_FIXUP_MIC_MUTE_LED), + SND_PCI_QUIRK(0x19e5, 0x3204, "Huawei MBXP", ALC256_FIXUP_HUAWEI_MBXP_PINS), SND_PCI_QUIRK(0x1b7d, 0xa831, "Ordissimo EVE2 ", ALC269VB_FIXUP_ORDISSIMO_EVE2), /* Also known as Malata PC-B1303 */ #if 0 @@ -6769,7 +6890,7 @@ static const struct hda_model_fixup alc269_fixup_models[] = { {.id = ALC255_FIXUP_DELL2_MIC_NO_PRESENCE, .name = "alc255-dell2"}, {.id = ALC293_FIXUP_DELL1_MIC_NO_PRESENCE, .name = "alc293-dell1"}, {.id = ALC283_FIXUP_HEADSET_MIC, .name = "alc283-headset"}, - {.id = ALC255_FIXUP_DELL_WMI_MIC_MUTE_LED, .name = "alc255-dell-mute"}, + {.id = ALC255_FIXUP_MIC_MUTE_LED, .name = "alc255-dell-mute"}, {.id = ALC282_FIXUP_ASPIRE_V5_PINS, .name = "aspire-v5"}, {.id = ALC280_FIXUP_HP_GPIO4, .name = "hp-gpio4"}, {.id = ALC286_FIXUP_HP_GPIO_LED, .name = "hp-gpio-led"}, @@ -6808,6 +6929,7 @@ static const struct hda_model_fixup alc269_fixup_models[] = { {.id = ALC255_FIXUP_DUMMY_LINEOUT_VERB, .name = "alc255-dummy-lineout"}, {.id = ALC255_FIXUP_DELL_HEADSET_MIC, .name = "alc255-dell-headset"}, {.id = ALC295_FIXUP_HP_X360, .name = "alc295-hp-x360"}, + {.id = ALC225_FIXUP_HEADSET_JACK, .name = "alc-sense-combo"}, {} }; #define ALC225_STANDARD_PINS \ @@ -7155,6 +7277,14 @@ static const struct snd_hda_pin_quirk alc269_pin_fixup_tbl[] = { SND_HDA_PIN_QUIRK(0x10ec0293, 0x1028, "Dell", ALC293_FIXUP_DELL1_MIC_NO_PRESENCE, ALC292_STANDARD_PINS, {0x13, 0x90a60140}), + SND_HDA_PIN_QUIRK(0x10ec0294, 0x1043, "ASUS", ALC294_FIXUP_ASUS_MIC, + {0x14, 0x90170110}, + {0x1b, 0x90a70130}, + {0x21, 0x04211020}), + SND_HDA_PIN_QUIRK(0x10ec0294, 0x1043, "ASUS", ALC294_FIXUP_ASUS_SPK, + {0x12, 0x90a60130}, + {0x17, 0x90170110}, + {0x21, 0x04211020}), SND_HDA_PIN_QUIRK(0x10ec0295, 0x1028, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE, ALC295_STANDARD_PINS, {0x17, 0x21014020}, @@ -7227,6 +7357,37 @@ static void alc269_fill_coef(struct hda_codec *codec) alc_update_coef_idx(codec, 0x4, 0, 1<<11); } +static void alc294_hp_init(struct hda_codec *codec) +{ + struct alc_spec *spec = codec->spec; + hda_nid_t hp_pin = spec->gen.autocfg.hp_pins[0]; + int i, val; + + if (!hp_pin) + return; + + snd_hda_codec_write(codec, hp_pin, 0, + AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE); + + msleep(100); + + snd_hda_codec_write(codec, hp_pin, 0, + AC_VERB_SET_PIN_WIDGET_CONTROL, 0x0); + + alc_update_coef_idx(codec, 0x6f, 0x000f, 0);/* Set HP depop to manual mode */ + alc_update_coefex_idx(codec, 0x58, 0x00, 0x8000, 0x8000); /* HP depop procedure start */ + + /* Wait for depop procedure finish */ + val = alc_read_coefex_idx(codec, 0x58, 0x01); + for (i = 0; i < 20 && val & 0x0080; i++) { + msleep(50); + val = alc_read_coefex_idx(codec, 0x58, 0x01); + } + /* Set HP depop to auto mode */ + alc_update_coef_idx(codec, 0x6f, 0x000f, 0x000b); + msleep(50); +} + /* */ static int patch_alc269(struct hda_codec *codec) @@ -7352,6 +7513,7 @@ static int patch_alc269(struct hda_codec *codec) spec->codec_variant = ALC269_TYPE_ALC294; spec->gen.mixer_nid = 0; /* ALC2x4 does not have any loopback mixer path */ alc_update_coef_idx(codec, 0x6b, 0x0018, (1<<4) | (1<<3)); /* UAJ MIC Vref control by verb */ + alc294_hp_init(codec); break; case 0x10ec0300: spec->codec_variant = ALC269_TYPE_ALC300; @@ -7363,6 +7525,7 @@ static int patch_alc269(struct hda_codec *codec) spec->codec_variant = ALC269_TYPE_ALC700; spec->gen.mixer_nid = 0; /* ALC700 does not have any loopback mixer path */ alc_update_coef_idx(codec, 0x4a, 1 << 15, 0); /* Combo jack auto trigger control */ + alc294_hp_init(codec); break; } diff --git a/sound/pci/hda/thinkpad_helper.c b/sound/pci/hda/thinkpad_helper.c index 568575b72f2f..4089feb8c68e 100644 --- a/sound/pci/hda/thinkpad_helper.c +++ b/sound/pci/hda/thinkpad_helper.c @@ -3,12 +3,11 @@ * to be included from codec driver */ -#if IS_ENABLED(CONFIG_THINKPAD_ACPI) +#if IS_ENABLED(CONFIG_THINKPAD_ACPI) && IS_REACHABLE(CONFIG_LEDS_TRIGGER_AUDIO) #include <linux/acpi.h> -#include <linux/thinkpad_acpi.h> +#include <linux/leds.h> -static int (*led_set_func)(int, bool); static void (*old_vmaster_hook)(void *, int); static bool is_thinkpad(struct hda_codec *codec) @@ -23,50 +22,20 @@ static void update_tpacpi_mute_led(void *private_data, int enabled) if (old_vmaster_hook) old_vmaster_hook(private_data, enabled); - if (led_set_func) - led_set_func(TPACPI_LED_MUTE, !enabled); -} - -static void update_tpacpi_micmute(struct hda_codec *codec) -{ - struct hda_gen_spec *spec = codec->spec; - - led_set_func(TPACPI_LED_MICMUTE, spec->micmute_led.led_value); + ledtrig_audio_set(LED_AUDIO_MUTE, enabled ? LED_OFF : LED_ON); } static void hda_fixup_thinkpad_acpi(struct hda_codec *codec, const struct hda_fixup *fix, int action) { struct hda_gen_spec *spec = codec->spec; - bool removefunc = false; if (action == HDA_FIXUP_ACT_PROBE) { if (!is_thinkpad(codec)) return; - if (!led_set_func) - led_set_func = symbol_request(tpacpi_led_set); - if (!led_set_func) { - codec_warn(codec, - "Failed to find thinkpad-acpi symbol tpacpi_led_set\n"); - return; - } - - removefunc = true; - if (led_set_func(TPACPI_LED_MUTE, false) >= 0) { - old_vmaster_hook = spec->vmaster_mute.hook; - spec->vmaster_mute.hook = update_tpacpi_mute_led; - removefunc = false; - } - if (led_set_func(TPACPI_LED_MICMUTE, false) >= 0 && - !snd_hda_gen_add_micmute_led(codec, - update_tpacpi_micmute)) - removefunc = false; - } - - if (led_set_func && (action == HDA_FIXUP_ACT_FREE || removefunc)) { - symbol_put(tpacpi_led_set); - led_set_func = NULL; - old_vmaster_hook = NULL; + old_vmaster_hook = spec->vmaster_mute.hook; + spec->vmaster_mute.hook = update_tpacpi_mute_led; + snd_hda_gen_fixup_micmute_led(codec, fix, action); } } |