diff options
Diffstat (limited to 'sound/pci/hda')
-rw-r--r-- | sound/pci/hda/Kconfig | 11 | ||||
-rw-r--r-- | sound/pci/hda/hda_bind.c | 4 | ||||
-rw-r--r-- | sound/pci/hda/hda_controller.c | 3 | ||||
-rw-r--r-- | sound/pci/hda/hda_intel.c | 176 | ||||
-rw-r--r-- | sound/pci/hda/hda_jack.c | 151 | ||||
-rw-r--r-- | sound/pci/hda/hda_jack.h | 107 | ||||
-rw-r--r-- | sound/pci/hda/patch_ca0132.c | 23 | ||||
-rw-r--r-- | sound/pci/hda/patch_conexant.c | 1 | ||||
-rw-r--r-- | sound/pci/hda/patch_hdmi.c | 366 | ||||
-rw-r--r-- | sound/pci/hda/patch_realtek.c | 202 |
10 files changed, 707 insertions, 337 deletions
diff --git a/sound/pci/hda/Kconfig b/sound/pci/hda/Kconfig index dae47a45b2b8..bd48335d09d7 100644 --- a/sound/pci/hda/Kconfig +++ b/sound/pci/hda/Kconfig @@ -12,7 +12,7 @@ config SND_HDA_INTEL tristate "HD Audio PCI" depends on SND_PCI select SND_HDA - select SND_INTEL_NHLT if ACPI + select SND_INTEL_DSP_CONFIG help Say Y here to include support for Intel "High Definition Audio" (Azalia) and its compatible devices. @@ -23,15 +23,6 @@ config SND_HDA_INTEL To compile this driver as a module, choose M here: the module will be called snd-hda-intel. -config SND_HDA_INTEL_DETECT_DMIC - bool "DMIC detection and probe abort" - depends on SND_HDA_INTEL - help - Say Y to detect digital microphones on SKL+ devices. DMICs - cannot be handled by the HDaudio legacy driver and are - currently only supported by the SOF driver. - If unsure say N. - config SND_HDA_TEGRA tristate "NVIDIA Tegra HD Audio" depends on ARCH_TEGRA diff --git a/sound/pci/hda/hda_bind.c b/sound/pci/hda/hda_bind.c index 8272b50b8349..6a8564566375 100644 --- a/sound/pci/hda/hda_bind.c +++ b/sound/pci/hda/hda_bind.c @@ -43,6 +43,10 @@ static void hda_codec_unsol_event(struct hdac_device *dev, unsigned int ev) { struct hda_codec *codec = container_of(dev, struct hda_codec, core); + /* ignore unsol events during shutdown */ + if (codec->bus->shutdown) + return; + if (codec->patch_ops.unsol_event) codec->patch_ops.unsol_event(codec, ev); } diff --git a/sound/pci/hda/hda_controller.c b/sound/pci/hda/hda_controller.c index 6387c7e90918..ba56b59b3e17 100644 --- a/sound/pci/hda/hda_controller.c +++ b/sound/pci/hda/hda_controller.c @@ -701,7 +701,6 @@ static const struct snd_pcm_ops azx_pcm_ops = { .pointer = azx_pcm_pointer, .get_time_info = azx_get_time_info, .mmap = azx_pcm_mmap, - .page = snd_pcm_sgbuf_ops_page, }; static void azx_pcm_free(struct snd_pcm *pcm) @@ -884,7 +883,7 @@ static int azx_rirb_get_response(struct hdac_bus *bus, unsigned int addr, return -EAGAIN; /* give a chance to retry */ } - dev_WARN(chip->card->dev, + dev_err(chip->card->dev, "azx_get_response timeout, switching to single_cmd mode: last cmd=0x%08x\n", bus->last_cmd[addr]); chip->single_cmd = 1; diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index 240f4ca76391..8ef223aa1e37 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c @@ -35,6 +35,7 @@ #include <linux/clocksource.h> #include <linux/time.h> #include <linux/completion.h> +#include <linux/acpi.h> #ifdef CONFIG_X86 /* for snoop control */ @@ -46,7 +47,7 @@ #include <sound/initval.h> #include <sound/hdaudio.h> #include <sound/hda_i915.h> -#include <sound/intel-nhlt.h> +#include <sound/intel-dsp-config.h> #include <linux/vgaarb.h> #include <linux/vga_switcheroo.h> #include <linux/firmware.h> @@ -124,7 +125,7 @@ static char *patch[SNDRV_CARDS]; static bool beep_mode[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS-1)] = CONFIG_SND_HDA_INPUT_BEEP_MODE}; #endif -static bool dmic_detect = IS_ENABLED(CONFIG_SND_HDA_INTEL_DETECT_DMIC); +static bool dmic_detect = 1; module_param_array(index, int, NULL, 0444); MODULE_PARM_DESC(index, "Index value for Intel HD audio interface."); @@ -160,7 +161,9 @@ MODULE_PARM_DESC(beep_mode, "Select HDA Beep registration mode " "(0=off, 1=on) (default=1)."); #endif module_param(dmic_detect, bool, 0444); -MODULE_PARM_DESC(dmic_detect, "DMIC detect on SKL+ platforms"); +MODULE_PARM_DESC(dmic_detect, "Allow DSP driver selection (bypass this driver) " + "(0=off, 1=on) (default=1); " + "deprecated, use snd-intel-dspcfg.dsp_driver option instead"); #ifdef CONFIG_PM static int param_set_xint(const char *val, const struct kernel_param *kp); @@ -280,12 +283,13 @@ enum { /* quirks for old Intel chipsets */ #define AZX_DCAPS_INTEL_ICH \ - (AZX_DCAPS_OLD_SSYNC | AZX_DCAPS_NO_ALIGN_BUFSIZE) + (AZX_DCAPS_OLD_SSYNC | AZX_DCAPS_NO_ALIGN_BUFSIZE |\ + AZX_DCAPS_SYNC_WRITE) /* quirks for Intel PCH */ #define AZX_DCAPS_INTEL_PCH_BASE \ (AZX_DCAPS_NO_ALIGN_BUFSIZE | AZX_DCAPS_COUNT_LPIB_DELAY |\ - AZX_DCAPS_SNOOP_TYPE(SCH)) + AZX_DCAPS_SNOOP_TYPE(SCH) | AZX_DCAPS_SYNC_WRITE) /* PCH up to IVB; no runtime PM; bind with i915 gfx */ #define AZX_DCAPS_INTEL_PCH_NOPM \ @@ -300,13 +304,13 @@ 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_SNOOP_TYPE(SCH)) + AZX_DCAPS_SNOOP_TYPE(SCH) | AZX_DCAPS_SYNC_WRITE) /* 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_SNOOP_TYPE(SCH)) + AZX_DCAPS_SNOOP_TYPE(SCH) | AZX_DCAPS_SYNC_WRITE) #define AZX_DCAPS_INTEL_BAYTRAIL \ (AZX_DCAPS_INTEL_PCH_BASE | AZX_DCAPS_I915_COMPONENT) @@ -368,8 +372,6 @@ enum { ((pci)->device == 0x160c)) #define IS_BXT(pci) ((pci)->vendor == 0x8086 && (pci)->device == 0x5a98) -#define IS_CFL(pci) ((pci)->vendor == 0x8086 && (pci)->device == 0xa348) -#define IS_CNL(pci) ((pci)->vendor == 0x8086 && (pci)->device == 0x9dc8) static char *driver_short_names[] = { [AZX_DRIVER_ICH] = "HDA Intel", @@ -1280,11 +1282,17 @@ static void init_vga_switcheroo(struct azx *chip) { struct hda_intel *hda = container_of(chip, struct hda_intel, chip); struct pci_dev *p = get_bound_vga(chip->pci); + struct pci_dev *parent; if (p) { dev_info(chip->card->dev, "Handle vga_switcheroo audio client\n"); hda->use_vga_switcheroo = 1; - chip->bus.keep_power = 1; /* cleared in either gpu_bound op or codec probe */ + + /* cleared in either gpu_bound op or codec probe, or when its + * upstream port has _PR3 (i.e. dGPU). + */ + parent = pci_upstream_bridge(p); + chip->bus.keep_power = parent ? !pci_pr3_present(parent) : 1; chip->driver_caps |= AZX_DCAPS_PM_RUNTIME; pci_dev_put(p); } @@ -1348,9 +1356,9 @@ static int azx_free(struct azx *chip) } if (bus->chip_init) { - azx_stop_chip(chip); azx_clear_irq_pending(chip); azx_stop_all_streams(chip); + azx_stop_chip(chip); } if (bus->irq >= 0) @@ -1382,8 +1390,11 @@ static int azx_free(struct azx *chip) static int azx_dev_disconnect(struct snd_device *device) { struct azx *chip = device->device_data; + struct hdac_bus *bus = azx_bus(chip); chip->bus.shutdown = 1; + cancel_work_sync(&bus->unsol_work); + return 0; } @@ -1393,6 +1404,43 @@ static int azx_dev_free(struct snd_device *device) } #ifdef SUPPORT_VGA_SWITCHEROO +#ifdef CONFIG_ACPI +/* ATPX is in the integrated GPU's namespace */ +static bool atpx_present(void) +{ + struct pci_dev *pdev = NULL; + acpi_handle dhandle, atpx_handle; + acpi_status status; + + while ((pdev = pci_get_class(PCI_CLASS_DISPLAY_VGA << 8, pdev)) != NULL) { + dhandle = ACPI_HANDLE(&pdev->dev); + if (dhandle) { + status = acpi_get_handle(dhandle, "ATPX", &atpx_handle); + if (!ACPI_FAILURE(status)) { + pci_dev_put(pdev); + return true; + } + } + } + while ((pdev = pci_get_class(PCI_CLASS_DISPLAY_OTHER << 8, pdev)) != NULL) { + dhandle = ACPI_HANDLE(&pdev->dev); + if (dhandle) { + status = acpi_get_handle(dhandle, "ATPX", &atpx_handle); + if (!ACPI_FAILURE(status)) { + pci_dev_put(pdev); + return true; + } + } + } + return false; +} +#else +static bool atpx_present(void) +{ + return false; +} +#endif + /* * Check of disabled HDMI controller by vga_switcheroo */ @@ -1404,6 +1452,22 @@ static struct pci_dev *get_bound_vga(struct pci_dev *pci) switch (pci->vendor) { case PCI_VENDOR_ID_ATI: case PCI_VENDOR_ID_AMD: + if (pci->devfn == 1) { + p = pci_get_domain_bus_and_slot(pci_domain_nr(pci->bus), + pci->bus->number, 0); + if (p) { + /* ATPX is in the integrated GPU's ACPI namespace + * rather than the dGPU's namespace. However, + * the dGPU is the one who is involved in + * vgaswitcheroo. + */ + if (((p->class >> 16) == PCI_BASE_CLASS_DISPLAY) && + atpx_present()) + return p; + pci_dev_put(p); + } + } + break; case PCI_VENDOR_ID_NVIDIA: if (pci->devfn == 1) { p = pci_get_domain_bus_and_slot(pci_domain_nr(pci->bus), @@ -1753,10 +1817,6 @@ static int azx_create(struct snd_card *card, struct pci_dev *pci, if (!azx_snoop(chip)) azx_bus(chip)->dma_type = SNDRV_DMA_TYPE_DEV_UC; - /* Workaround for a communication error on CFL (bko#199007) and CNL */ - if (IS_CFL(pci) || IS_CNL(pci)) - azx_bus(chip)->polling_mode = 1; - if (chip->driver_type == AZX_DRIVER_NVIDIA) { dev_dbg(chip->card->dev, "Enable delay in RIRB handling\n"); chip->bus.needs_damn_long_delay = 1; @@ -2020,25 +2080,6 @@ static const struct hda_controller_ops pci_hda_ops = { .position_check = azx_position_check, }; -static int azx_check_dmic(struct pci_dev *pci, struct azx *chip) -{ - struct nhlt_acpi_table *nhlt; - int ret = 0; - - if (chip->driver_type == AZX_DRIVER_SKL && - pci->class != 0x040300) { - nhlt = intel_nhlt_init(&pci->dev); - if (nhlt) { - if (intel_nhlt_get_dmic_geo(&pci->dev, nhlt)) { - ret = -ENODEV; - dev_info(&pci->dev, "Digital mics found on Skylake+ platform, aborting probe\n"); - } - intel_nhlt_free(nhlt); - } - } - return ret; -} - static int azx_probe(struct pci_dev *pci, const struct pci_device_id *pci_id) { @@ -2056,6 +2097,18 @@ static int azx_probe(struct pci_dev *pci, return -ENOENT; } + /* + * stop probe if another Intel's DSP driver should be activated + */ + if (dmic_detect) { + err = snd_intel_dsp_driver_probe(pci); + if (err != SND_INTEL_DSP_DRIVER_ANY && + err != SND_INTEL_DSP_DRIVER_LEGACY) + return -ENODEV; + } else { + dev_warn(&pci->dev, "dmic_detect option is deprecated, pass snd-intel-dspcfg.dsp_driver=1 option instead\n"); + } + err = snd_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE, 0, &card); if (err < 0) { @@ -2069,17 +2122,6 @@ static int azx_probe(struct pci_dev *pci, card->private_data = chip; hda = container_of(chip, struct hda_intel, chip); - /* - * stop probe if digital microphones detected on Skylake+ platform - * with the DSP enabled. This is an opt-in behavior defined at build - * time or at run-time with a module parameter - */ - if (dmic_detect) { - err = azx_check_dmic(pci, chip); - if (err < 0) - goto out_free; - } - pci_set_drvdata(pci, card); err = register_vga_switcheroo(chip); @@ -2396,9 +2438,18 @@ static const struct pci_device_id azx_ids[] = { /* CometLake-H */ { PCI_DEVICE(0x8086, 0x06C8), .driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE}, + /* CometLake-S */ + { PCI_DEVICE(0x8086, 0xa3f0), + .driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE}, /* Icelake */ { PCI_DEVICE(0x8086, 0x34c8), .driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE}, + /* Jasperlake */ + { PCI_DEVICE(0x8086, 0x38c8), + .driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE}, + /* Tigerlake */ + { PCI_DEVICE(0x8086, 0xa0c8), + .driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE}, /* Elkhart Lake */ { PCI_DEVICE(0x8086, 0x4b55), .driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE}, @@ -2554,13 +2605,38 @@ static const struct pci_device_id azx_ids[] = { { PCI_DEVICE(0x1002, 0xaac8), .driver_data = AZX_DRIVER_ATIHDMI_NS | AZX_DCAPS_PRESET_ATI_HDMI_NS }, { PCI_DEVICE(0x1002, 0xaad8), - .driver_data = AZX_DRIVER_ATIHDMI_NS | AZX_DCAPS_PRESET_ATI_HDMI_NS }, - { PCI_DEVICE(0x1002, 0xaae8), - .driver_data = AZX_DRIVER_ATIHDMI_NS | AZX_DCAPS_PRESET_ATI_HDMI_NS }, + .driver_data = AZX_DRIVER_ATIHDMI_NS | AZX_DCAPS_PRESET_ATI_HDMI_NS | + AZX_DCAPS_PM_RUNTIME }, { PCI_DEVICE(0x1002, 0xaae0), - .driver_data = AZX_DRIVER_ATIHDMI_NS | AZX_DCAPS_PRESET_ATI_HDMI_NS }, + .driver_data = AZX_DRIVER_ATIHDMI_NS | AZX_DCAPS_PRESET_ATI_HDMI_NS | + AZX_DCAPS_PM_RUNTIME }, + { PCI_DEVICE(0x1002, 0xaae8), + .driver_data = AZX_DRIVER_ATIHDMI_NS | AZX_DCAPS_PRESET_ATI_HDMI_NS | + AZX_DCAPS_PM_RUNTIME }, { PCI_DEVICE(0x1002, 0xaaf0), - .driver_data = AZX_DRIVER_ATIHDMI_NS | AZX_DCAPS_PRESET_ATI_HDMI_NS }, + .driver_data = AZX_DRIVER_ATIHDMI_NS | AZX_DCAPS_PRESET_ATI_HDMI_NS | + AZX_DCAPS_PM_RUNTIME }, + { PCI_DEVICE(0x1002, 0xaaf8), + .driver_data = AZX_DRIVER_ATIHDMI_NS | AZX_DCAPS_PRESET_ATI_HDMI_NS | + AZX_DCAPS_PM_RUNTIME }, + { PCI_DEVICE(0x1002, 0xab00), + .driver_data = AZX_DRIVER_ATIHDMI_NS | AZX_DCAPS_PRESET_ATI_HDMI_NS | + AZX_DCAPS_PM_RUNTIME }, + { PCI_DEVICE(0x1002, 0xab08), + .driver_data = AZX_DRIVER_ATIHDMI_NS | AZX_DCAPS_PRESET_ATI_HDMI_NS | + AZX_DCAPS_PM_RUNTIME }, + { PCI_DEVICE(0x1002, 0xab10), + .driver_data = AZX_DRIVER_ATIHDMI_NS | AZX_DCAPS_PRESET_ATI_HDMI_NS | + AZX_DCAPS_PM_RUNTIME }, + { PCI_DEVICE(0x1002, 0xab18), + .driver_data = AZX_DRIVER_ATIHDMI_NS | AZX_DCAPS_PRESET_ATI_HDMI_NS | + AZX_DCAPS_PM_RUNTIME }, + { PCI_DEVICE(0x1002, 0xab20), + .driver_data = AZX_DRIVER_ATIHDMI_NS | AZX_DCAPS_PRESET_ATI_HDMI_NS | + AZX_DCAPS_PM_RUNTIME }, + { PCI_DEVICE(0x1002, 0xab38), + .driver_data = AZX_DRIVER_ATIHDMI_NS | AZX_DCAPS_PRESET_ATI_HDMI_NS | + AZX_DCAPS_PM_RUNTIME }, /* VIA VT8251/VT8237A */ { PCI_DEVICE(0x1106, 0x3288), .driver_data = AZX_DRIVER_VIA }, /* VIA GFX VT7122/VX900 */ diff --git a/sound/pci/hda/hda_jack.c b/sound/pci/hda/hda_jack.c index 1fb7b06457ae..bf0255cb0515 100644 --- a/sound/pci/hda/hda_jack.c +++ b/sound/pci/hda/hda_jack.c @@ -43,7 +43,7 @@ bool is_jack_detectable(struct hda_codec *codec, hda_nid_t nid) EXPORT_SYMBOL_GPL(is_jack_detectable); /* execute pin sense measurement */ -static u32 read_pin_sense(struct hda_codec *codec, hda_nid_t nid) +static u32 read_pin_sense(struct hda_codec *codec, hda_nid_t nid, int dev_id) { u32 pincap; u32 val; @@ -55,19 +55,20 @@ static u32 read_pin_sense(struct hda_codec *codec, hda_nid_t nid) AC_VERB_SET_PIN_SENSE, 0); } val = snd_hda_codec_read(codec, nid, 0, - AC_VERB_GET_PIN_SENSE, 0); + AC_VERB_GET_PIN_SENSE, dev_id); if (codec->inv_jack_detect) val ^= AC_PINSENSE_PRESENCE; return val; } /** - * snd_hda_jack_tbl_get - query the jack-table entry for the given NID + * snd_hda_jack_tbl_get_mst - query the jack-table entry for the given NID * @codec: the HDA codec * @nid: pin NID to refer to + * @dev_id: pin device entry id */ struct hda_jack_tbl * -snd_hda_jack_tbl_get(struct hda_codec *codec, hda_nid_t nid) +snd_hda_jack_tbl_get_mst(struct hda_codec *codec, hda_nid_t nid, int dev_id) { struct hda_jack_tbl *jack = codec->jacktbl.list; int i; @@ -75,19 +76,21 @@ snd_hda_jack_tbl_get(struct hda_codec *codec, hda_nid_t nid) if (!nid || !jack) return NULL; for (i = 0; i < codec->jacktbl.used; i++, jack++) - if (jack->nid == nid) + if (jack->nid == nid && jack->dev_id == dev_id) return jack; return NULL; } -EXPORT_SYMBOL_GPL(snd_hda_jack_tbl_get); +EXPORT_SYMBOL_GPL(snd_hda_jack_tbl_get_mst); /** * snd_hda_jack_tbl_get_from_tag - query the jack-table entry for the given tag * @codec: the HDA codec * @tag: tag value to refer to + * @dev_id: pin device entry id */ struct hda_jack_tbl * -snd_hda_jack_tbl_get_from_tag(struct hda_codec *codec, unsigned char tag) +snd_hda_jack_tbl_get_from_tag(struct hda_codec *codec, + unsigned char tag, int dev_id) { struct hda_jack_tbl *jack = codec->jacktbl.list; int i; @@ -95,29 +98,62 @@ snd_hda_jack_tbl_get_from_tag(struct hda_codec *codec, unsigned char tag) if (!tag || !jack) return NULL; for (i = 0; i < codec->jacktbl.used; i++, jack++) - if (jack->tag == tag) + if (jack->tag == tag && jack->dev_id == dev_id) return jack; return NULL; } EXPORT_SYMBOL_GPL(snd_hda_jack_tbl_get_from_tag); +static struct hda_jack_tbl * +any_jack_tbl_get_from_nid(struct hda_codec *codec, hda_nid_t nid) +{ + struct hda_jack_tbl *jack = codec->jacktbl.list; + int i; + + if (!nid || !jack) + return NULL; + for (i = 0; i < codec->jacktbl.used; i++, jack++) + if (jack->nid == nid) + return jack; + return NULL; +} + /** * snd_hda_jack_tbl_new - create a jack-table entry for the given NID * @codec: the HDA codec * @nid: pin NID to assign */ static struct hda_jack_tbl * -snd_hda_jack_tbl_new(struct hda_codec *codec, hda_nid_t nid) +snd_hda_jack_tbl_new(struct hda_codec *codec, hda_nid_t nid, int dev_id) { - struct hda_jack_tbl *jack = snd_hda_jack_tbl_get(codec, nid); + struct hda_jack_tbl *jack = + snd_hda_jack_tbl_get_mst(codec, nid, dev_id); + struct hda_jack_tbl *existing_nid_jack = + any_jack_tbl_get_from_nid(codec, nid); + + WARN_ON(dev_id != 0 && !codec->dp_mst); + if (jack) return jack; jack = snd_array_new(&codec->jacktbl); if (!jack) return NULL; jack->nid = nid; + jack->dev_id = dev_id; jack->jack_dirty = 1; - jack->tag = codec->jacktbl.used; + if (existing_nid_jack) { + jack->tag = existing_nid_jack->tag; + + /* + * Copy jack_detect from existing_nid_jack to avoid + * snd_hda_jack_detect_enable_callback_mst() making multiple + * SET_UNSOLICITED_ENABLE calls on the same pin. + */ + jack->jack_detect = existing_nid_jack->jack_detect; + } else { + jack->tag = codec->jacktbl.used; + } + return jack; } @@ -153,10 +189,12 @@ static void jack_detect_update(struct hda_codec *codec, if (jack->phantom_jack) jack->pin_sense = AC_PINSENSE_PRESENCE; else - jack->pin_sense = read_pin_sense(codec, jack->nid); + jack->pin_sense = read_pin_sense(codec, jack->nid, + jack->dev_id); /* A gating jack indicates the jack is invalid if gating is unplugged */ - if (jack->gating_jack && !snd_hda_jack_detect(codec, jack->gating_jack)) + if (jack->gating_jack && + !snd_hda_jack_detect_mst(codec, jack->gating_jack, jack->dev_id)) jack->pin_sense &= ~AC_PINSENSE_PRESENCE; jack->jack_dirty = 0; @@ -164,7 +202,8 @@ static void jack_detect_update(struct hda_codec *codec, /* If a jack is gated by this one update it. */ if (jack->gated_jack) { struct hda_jack_tbl *gated = - snd_hda_jack_tbl_get(codec, jack->gated_jack); + snd_hda_jack_tbl_get_mst(codec, jack->gated_jack, + jack->dev_id); if (gated) { gated->jack_dirty = 1; jack_detect_update(codec, gated); @@ -191,63 +230,69 @@ void snd_hda_jack_set_dirty_all(struct hda_codec *codec) EXPORT_SYMBOL_GPL(snd_hda_jack_set_dirty_all); /** - * snd_hda_pin_sense - execute pin sense measurement + * snd_hda_jack_pin_sense - execute pin sense measurement * @codec: the CODEC to sense * @nid: the pin NID to sense * * Execute necessary pin sense measurement and return its Presence Detect, * Impedance, ELD Valid etc. status bits. */ -u32 snd_hda_pin_sense(struct hda_codec *codec, hda_nid_t nid) +u32 snd_hda_jack_pin_sense(struct hda_codec *codec, hda_nid_t nid, int dev_id) { - struct hda_jack_tbl *jack = snd_hda_jack_tbl_get(codec, nid); + struct hda_jack_tbl *jack = + snd_hda_jack_tbl_get_mst(codec, nid, dev_id); if (jack) { jack_detect_update(codec, jack); return jack->pin_sense; } - return read_pin_sense(codec, nid); + return read_pin_sense(codec, nid, dev_id); } -EXPORT_SYMBOL_GPL(snd_hda_pin_sense); +EXPORT_SYMBOL_GPL(snd_hda_jack_pin_sense); /** - * snd_hda_jack_detect_state - query pin Presence Detect status + * snd_hda_jack_detect_state_mst - query pin Presence Detect status * @codec: the CODEC to sense * @nid: the pin NID to sense + * @dev_id: pin device entry id * * Query and return the pin's Presence Detect status, as either * HDA_JACK_NOT_PRESENT, HDA_JACK_PRESENT or HDA_JACK_PHANTOM. */ -int snd_hda_jack_detect_state(struct hda_codec *codec, hda_nid_t nid) +int snd_hda_jack_detect_state_mst(struct hda_codec *codec, + hda_nid_t nid, int dev_id) { - struct hda_jack_tbl *jack = snd_hda_jack_tbl_get(codec, nid); + struct hda_jack_tbl *jack = + snd_hda_jack_tbl_get_mst(codec, nid, dev_id); if (jack && jack->phantom_jack) return HDA_JACK_PHANTOM; - else if (snd_hda_pin_sense(codec, nid) & AC_PINSENSE_PRESENCE) + else if (snd_hda_jack_pin_sense(codec, nid, dev_id) & + AC_PINSENSE_PRESENCE) return HDA_JACK_PRESENT; else return HDA_JACK_NOT_PRESENT; } -EXPORT_SYMBOL_GPL(snd_hda_jack_detect_state); +EXPORT_SYMBOL_GPL(snd_hda_jack_detect_state_mst); /** - * snd_hda_jack_detect_enable - enable the jack-detection + * snd_hda_jack_detect_enable_mst - enable the jack-detection * @codec: the HDA codec * @nid: pin NID to enable * @func: callback function to register + * @dev_id: pin device entry id * * In the case of error, the return value will be a pointer embedded with * errno. Check and handle the return value appropriately with standard * macros such as @IS_ERR() and @PTR_ERR(). */ struct hda_jack_callback * -snd_hda_jack_detect_enable_callback(struct hda_codec *codec, hda_nid_t nid, - hda_jack_callback_fn func) +snd_hda_jack_detect_enable_callback_mst(struct hda_codec *codec, hda_nid_t nid, + int dev_id, hda_jack_callback_fn func) { struct hda_jack_tbl *jack; struct hda_jack_callback *callback = NULL; int err; - jack = snd_hda_jack_tbl_new(codec, nid); + jack = snd_hda_jack_tbl_new(codec, nid, dev_id); if (!jack) return ERR_PTR(-ENOMEM); if (func) { @@ -256,6 +301,7 @@ snd_hda_jack_detect_enable_callback(struct hda_codec *codec, hda_nid_t nid, return ERR_PTR(-ENOMEM); callback->func = func; callback->nid = jack->nid; + callback->dev_id = jack->dev_id; callback->next = jack->callback; jack->callback = callback; } @@ -272,19 +318,24 @@ snd_hda_jack_detect_enable_callback(struct hda_codec *codec, hda_nid_t nid, return ERR_PTR(err); return callback; } -EXPORT_SYMBOL_GPL(snd_hda_jack_detect_enable_callback); +EXPORT_SYMBOL_GPL(snd_hda_jack_detect_enable_callback_mst); /** * snd_hda_jack_detect_enable - Enable the jack detection on the given pin * @codec: the HDA codec * @nid: pin NID to enable jack detection + * @dev_id: pin device entry id * * Enable the jack detection with the default callback. Returns zero if * successful or a negative error code. */ -int snd_hda_jack_detect_enable(struct hda_codec *codec, hda_nid_t nid) +int snd_hda_jack_detect_enable(struct hda_codec *codec, hda_nid_t nid, + int dev_id) { - return PTR_ERR_OR_ZERO(snd_hda_jack_detect_enable_callback(codec, nid, NULL)); + return PTR_ERR_OR_ZERO(snd_hda_jack_detect_enable_callback_mst(codec, + nid, + dev_id, + NULL)); } EXPORT_SYMBOL_GPL(snd_hda_jack_detect_enable); @@ -299,8 +350,11 @@ EXPORT_SYMBOL_GPL(snd_hda_jack_detect_enable); int snd_hda_jack_set_gating_jack(struct hda_codec *codec, hda_nid_t gated_nid, hda_nid_t gating_nid) { - struct hda_jack_tbl *gated = snd_hda_jack_tbl_new(codec, gated_nid); - struct hda_jack_tbl *gating = snd_hda_jack_tbl_new(codec, gating_nid); + struct hda_jack_tbl *gated = snd_hda_jack_tbl_new(codec, gated_nid, 0); + struct hda_jack_tbl *gating = + snd_hda_jack_tbl_new(codec, gating_nid, 0); + + WARN_ON(codec->dp_mst); if (!gated || !gating) return -EINVAL; @@ -376,9 +430,10 @@ static void hda_free_jack_priv(struct snd_jack *jack) } /** - * snd_hda_jack_add_kctl - Add a kctl for the given pin + * snd_hda_jack_add_kctl_mst - Add a kctl for the given pin * @codec: the HDA codec * @nid: pin NID to assign + * @dev_id : pin device entry id * @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 @@ -387,15 +442,15 @@ static void hda_free_jack_priv(struct snd_jack *jack) * 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, - int type, const struct hda_jack_keymap *keymap) +int snd_hda_jack_add_kctl_mst(struct hda_codec *codec, hda_nid_t nid, + int dev_id, const char *name, bool phantom_jack, + int type, const struct hda_jack_keymap *keymap) { struct hda_jack_tbl *jack; const struct hda_jack_keymap *map; int err, state, buttons; - jack = snd_hda_jack_tbl_new(codec, nid); + jack = snd_hda_jack_tbl_new(codec, nid, dev_id); if (!jack) return 0; if (jack->jack) @@ -425,12 +480,12 @@ int snd_hda_jack_add_kctl(struct hda_codec *codec, hda_nid_t nid, snd_jack_set_key(jack->jack, map->type, map->key); } - state = snd_hda_jack_detect(codec, nid); + state = snd_hda_jack_detect_mst(codec, nid, dev_id); snd_jack_report(jack->jack, state ? jack->type : 0); return 0; } -EXPORT_SYMBOL_GPL(snd_hda_jack_add_kctl); +EXPORT_SYMBOL_GPL(snd_hda_jack_add_kctl_mst); static int add_jack_kctl(struct hda_codec *codec, hda_nid_t nid, const struct auto_pin_cfg *cfg, @@ -441,6 +496,8 @@ static int add_jack_kctl(struct hda_codec *codec, hda_nid_t nid, int err; bool phantom_jack; + WARN_ON(codec->dp_mst); + if (!nid) return 0; def_conf = snd_hda_codec_get_pincfg(codec, nid); @@ -462,7 +519,7 @@ static int add_jack_kctl(struct hda_codec *codec, hda_nid_t nid, return err; if (!phantom_jack) - return snd_hda_jack_detect_enable(codec, nid); + return snd_hda_jack_detect_enable(codec, nid, 0); return 0; } @@ -540,7 +597,8 @@ static void call_jack_callback(struct hda_codec *codec, unsigned int res, } if (jack->gated_jack) { struct hda_jack_tbl *gated = - snd_hda_jack_tbl_get(codec, jack->gated_jack); + snd_hda_jack_tbl_get_mst(codec, jack->gated_jack, + jack->dev_id); if (gated) { for (cb = gated->callback; cb; cb = cb->next) { cb->jack = gated; @@ -561,7 +619,14 @@ void snd_hda_jack_unsol_event(struct hda_codec *codec, unsigned int res) struct hda_jack_tbl *event; int tag = (res & AC_UNSOL_RES_TAG) >> AC_UNSOL_RES_TAG_SHIFT; - event = snd_hda_jack_tbl_get_from_tag(codec, tag); + if (codec->dp_mst) { + int dev_entry = + (res & AC_UNSOL_RES_DE) >> AC_UNSOL_RES_DE_SHIFT; + + event = snd_hda_jack_tbl_get_from_tag(codec, tag, dev_entry); + } else { + event = snd_hda_jack_tbl_get_from_tag(codec, tag, 0); + } if (!event) return; event->jack_dirty = 1; diff --git a/sound/pci/hda/hda_jack.h b/sound/pci/hda/hda_jack.h index 22fe7ee43e82..727b6d3ba454 100644 --- a/sound/pci/hda/hda_jack.h +++ b/sound/pci/hda/hda_jack.h @@ -19,6 +19,7 @@ typedef void (*hda_jack_callback_fn) (struct hda_codec *, struct hda_jack_callba struct hda_jack_callback { hda_nid_t nid; + int dev_id; hda_jack_callback_fn func; unsigned int private_data; /* arbitrary data */ unsigned int unsol_res; /* unsolicited event bits */ @@ -28,6 +29,7 @@ struct hda_jack_callback { struct hda_jack_tbl { hda_nid_t nid; + int dev_id; unsigned char tag; /* unsol event tag */ struct hda_jack_callback *callback; /* jack-detection stuff */ @@ -49,46 +51,129 @@ struct hda_jack_keymap { }; struct hda_jack_tbl * -snd_hda_jack_tbl_get(struct hda_codec *codec, hda_nid_t nid); +snd_hda_jack_tbl_get_mst(struct hda_codec *codec, hda_nid_t nid, int dev_id); + +/** + * snd_hda_jack_tbl_get - query the jack-table entry for the given NID + * @codec: the HDA codec + * @nid: pin NID to refer to + */ +static inline struct hda_jack_tbl * +snd_hda_jack_tbl_get(struct hda_codec *codec, hda_nid_t nid) +{ + return snd_hda_jack_tbl_get_mst(codec, nid, 0); +} + struct hda_jack_tbl * -snd_hda_jack_tbl_get_from_tag(struct hda_codec *codec, unsigned char tag); +snd_hda_jack_tbl_get_from_tag(struct hda_codec *codec, + unsigned char tag, int dev_id); void snd_hda_jack_tbl_clear(struct hda_codec *codec); void snd_hda_jack_set_dirty_all(struct hda_codec *codec); -int snd_hda_jack_detect_enable(struct hda_codec *codec, hda_nid_t nid); +int snd_hda_jack_detect_enable(struct hda_codec *codec, hda_nid_t nid, + int dev_id); + struct hda_jack_callback * +snd_hda_jack_detect_enable_callback_mst(struct hda_codec *codec, hda_nid_t nid, + int dev_id, hda_jack_callback_fn cb); + +/** + * snd_hda_jack_detect_enable - enable the jack-detection + * @codec: the HDA codec + * @nid: pin NID to enable + * @func: callback function to register + * + * In the case of error, the return value will be a pointer embedded with + * errno. Check and handle the return value appropriately with standard + * macros such as @IS_ERR() and @PTR_ERR(). + */ +static inline struct hda_jack_callback * snd_hda_jack_detect_enable_callback(struct hda_codec *codec, hda_nid_t nid, - hda_jack_callback_fn cb); + hda_jack_callback_fn cb) +{ + return snd_hda_jack_detect_enable_callback_mst(codec, nid, 0, cb); +} int snd_hda_jack_set_gating_jack(struct hda_codec *codec, hda_nid_t gated_nid, hda_nid_t gating_nid); -u32 snd_hda_pin_sense(struct hda_codec *codec, hda_nid_t nid); +u32 snd_hda_jack_pin_sense(struct hda_codec *codec, hda_nid_t nid, int dev_id); /* the jack state returned from snd_hda_jack_detect_state() */ enum { HDA_JACK_NOT_PRESENT, HDA_JACK_PRESENT, HDA_JACK_PHANTOM, }; -int snd_hda_jack_detect_state(struct hda_codec *codec, hda_nid_t nid); +int snd_hda_jack_detect_state_mst(struct hda_codec *codec, hda_nid_t nid, + int dev_id); + +/** + * snd_hda_jack_detect_state - query pin Presence Detect status + * @codec: the CODEC to sense + * @nid: the pin NID to sense + * + * Query and return the pin's Presence Detect status, as either + * HDA_JACK_NOT_PRESENT, HDA_JACK_PRESENT or HDA_JACK_PHANTOM. + */ +static inline int +snd_hda_jack_detect_state(struct hda_codec *codec, hda_nid_t nid) +{ + return snd_hda_jack_detect_state_mst(codec, nid, 0); +} + +/** + * snd_hda_jack_detect_mst - Detect the jack + * @codec: the HDA codec + * @nid: pin NID to check jack detection + * @dev_id: pin device entry id + */ +static inline bool +snd_hda_jack_detect_mst(struct hda_codec *codec, hda_nid_t nid, int dev_id) +{ + return snd_hda_jack_detect_state_mst(codec, nid, dev_id) != + HDA_JACK_NOT_PRESENT; +} /** * snd_hda_jack_detect - Detect the jack * @codec: the HDA codec * @nid: pin NID to check jack detection */ -static inline bool snd_hda_jack_detect(struct hda_codec *codec, hda_nid_t nid) +static inline bool +snd_hda_jack_detect(struct hda_codec *codec, hda_nid_t nid) { - return snd_hda_jack_detect_state(codec, nid) != HDA_JACK_NOT_PRESENT; + return snd_hda_jack_detect_mst(codec, nid, 0); } 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, - int type, const struct hda_jack_keymap *keymap); +int snd_hda_jack_add_kctl_mst(struct hda_codec *codec, hda_nid_t nid, + int dev_id, const char *name, bool phantom_jack, + int type, const struct hda_jack_keymap *keymap); + +/** + * snd_hda_jack_add_kctl - Add a kctl for the given pin + * @codec: the HDA codec + * @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. + */ +static inline int +snd_hda_jack_add_kctl(struct hda_codec *codec, hda_nid_t nid, + const char *name, bool phantom_jack, + int type, const struct hda_jack_keymap *keymap) +{ + return snd_hda_jack_add_kctl_mst(codec, nid, 0, + name, phantom_jack, type, keymap); +} + int snd_hda_jack_add_kctls(struct hda_codec *codec, const struct auto_pin_cfg *cfg); diff --git a/sound/pci/hda/patch_ca0132.c b/sound/pci/hda/patch_ca0132.c index 6d1fb7c11f17..32ed46464af7 100644 --- a/sound/pci/hda/patch_ca0132.c +++ b/sound/pci/hda/patch_ca0132.c @@ -1809,13 +1809,14 @@ struct scp_msg { static void dspio_clear_response_queue(struct hda_codec *codec) { + unsigned long timeout = jiffies + msecs_to_jiffies(1000); unsigned int dummy = 0; - int status = -1; + int status; /* clear all from the response queue */ do { status = dspio_read(codec, &dummy); - } while (status == 0); + } while (status == 0 && time_before(jiffies, timeout)); } static int dspio_get_response_data(struct hda_codec *codec) @@ -7588,12 +7589,14 @@ static void ca0132_process_dsp_response(struct hda_codec *codec, struct ca0132_spec *spec = codec->spec; codec_dbg(codec, "ca0132_process_dsp_response\n"); + snd_hda_power_up_pm(codec); if (spec->wait_scp) { if (dspio_get_response_data(codec) >= 0) spec->wait_scp = 0; } dspio_clear_response_queue(codec); + snd_hda_power_down_pm(codec); } static void hp_callback(struct hda_codec *codec, struct hda_jack_callback *cb) @@ -7604,11 +7607,10 @@ static void hp_callback(struct hda_codec *codec, struct hda_jack_callback *cb) /* Delay enabling the HP amp, to let the mic-detection * state machine run. */ - cancel_delayed_work_sync(&spec->unsol_hp_work); - schedule_delayed_work(&spec->unsol_hp_work, msecs_to_jiffies(500)); tbl = snd_hda_jack_tbl_get(codec, cb->nid); if (tbl) tbl->block_report = 1; + schedule_delayed_work(&spec->unsol_hp_work, msecs_to_jiffies(500)); } static void amic_callback(struct hda_codec *codec, struct hda_jack_callback *cb) @@ -8454,12 +8456,25 @@ static void ca0132_reboot_notify(struct hda_codec *codec) codec->patch_ops.free(codec); } +#ifdef CONFIG_PM +static int ca0132_suspend(struct hda_codec *codec) +{ + struct ca0132_spec *spec = codec->spec; + + cancel_delayed_work_sync(&spec->unsol_hp_work); + return 0; +} +#endif + static const struct hda_codec_ops ca0132_patch_ops = { .build_controls = ca0132_build_controls, .build_pcms = ca0132_build_pcms, .init = ca0132_init, .free = ca0132_free, .unsol_event = snd_hda_jack_unsol_event, +#ifdef CONFIG_PM + .suspend = ca0132_suspend, +#endif .reboot_notify = ca0132_reboot_notify, }; diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c index 968d3caab6ac..90aa0f400a57 100644 --- a/sound/pci/hda/patch_conexant.c +++ b/sound/pci/hda/patch_conexant.c @@ -910,6 +910,7 @@ static const struct snd_pci_quirk cxt5066_fixups[] = { SND_PCI_QUIRK(0x103c, 0x837f, "HP ProBook 470 G5", CXT_FIXUP_MUTE_LED_GPIO), SND_PCI_QUIRK(0x103c, 0x8299, "HP 800 G3 SFF", CXT_FIXUP_HP_MIC_NO_PRESENCE), SND_PCI_QUIRK(0x103c, 0x829a, "HP 800 G3 DM", CXT_FIXUP_HP_MIC_NO_PRESENCE), + SND_PCI_QUIRK(0x103c, 0x8402, "HP ProBook 645 G4", CXT_FIXUP_MUTE_LED_GPIO), SND_PCI_QUIRK(0x103c, 0x8455, "HP Z2 G4", CXT_FIXUP_HP_MIC_NO_PRESENCE), SND_PCI_QUIRK(0x103c, 0x8456, "HP Z2 G4 SFF", CXT_FIXUP_HP_MIC_NO_PRESENCE), SND_PCI_QUIRK(0x103c, 0x8457, "HP Z2 G4 mini", CXT_FIXUP_HP_MIC_NO_PRESENCE), diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c index 59aaee4a40fd..630b1f5c276d 100644 --- a/sound/pci/hda/patch_hdmi.c +++ b/sound/pci/hda/patch_hdmi.c @@ -32,28 +32,12 @@ #include <sound/hda_codec.h> #include "hda_local.h" #include "hda_jack.h" +#include "hda_controller.h" static bool static_hdmi_pcm; module_param(static_hdmi_pcm, bool, 0644); MODULE_PARM_DESC(static_hdmi_pcm, "Don't restrict PCM parameters per ELD info"); -#define is_haswell(codec) ((codec)->core.vendor_id == 0x80862807) -#define is_broadwell(codec) ((codec)->core.vendor_id == 0x80862808) -#define is_skylake(codec) ((codec)->core.vendor_id == 0x80862809) -#define is_broxton(codec) ((codec)->core.vendor_id == 0x8086280a) -#define is_kabylake(codec) ((codec)->core.vendor_id == 0x8086280b) -#define is_geminilake(codec) (((codec)->core.vendor_id == 0x8086280d) || \ - ((codec)->core.vendor_id == 0x80862800)) -#define is_cannonlake(codec) ((codec)->core.vendor_id == 0x8086280c) -#define is_icelake(codec) ((codec)->core.vendor_id == 0x8086280f) -#define is_haswell_plus(codec) (is_haswell(codec) || is_broadwell(codec) \ - || is_skylake(codec) || is_broxton(codec) \ - || is_kabylake(codec) || is_geminilake(codec) \ - || is_cannonlake(codec) || is_icelake(codec)) -#define is_valleyview(codec) ((codec)->core.vendor_id == 0x80862882) -#define is_cherryview(codec) ((codec)->core.vendor_id == 0x80862883) -#define is_valleyview_plus(codec) (is_valleyview(codec) || is_cherryview(codec)) - struct hdmi_spec_per_cvt { hda_nid_t cvt_nid; int assigned; @@ -97,16 +81,19 @@ struct hdmi_spec_per_pin { /* operations used by generic code that can be overridden by patches */ struct hdmi_ops { int (*pin_get_eld)(struct hda_codec *codec, hda_nid_t pin_nid, - unsigned char *buf, int *eld_size); + int dev_id, unsigned char *buf, int *eld_size); void (*pin_setup_infoframe)(struct hda_codec *codec, hda_nid_t pin_nid, + int dev_id, int ca, int active_channels, int conn_type); /* enable/disable HBR (HD passthrough) */ - int (*pin_hbr_setup)(struct hda_codec *codec, hda_nid_t pin_nid, bool hbr); + int (*pin_hbr_setup)(struct hda_codec *codec, hda_nid_t pin_nid, + int dev_id, bool hbr); int (*setup_stream)(struct hda_codec *codec, hda_nid_t cvt_nid, - hda_nid_t pin_nid, u32 stream_tag, int format); + hda_nid_t pin_nid, int dev_id, u32 stream_tag, + int format); void (*pin_cvt_fixup)(struct hda_codec *codec, struct hdmi_spec_per_pin *per_pin, @@ -145,6 +132,7 @@ struct hdmi_spec { struct snd_array pins; /* struct hdmi_spec_per_pin */ struct hdmi_pcm pcm_rec[16]; struct mutex pcm_lock; + struct mutex bind_lock; /* for audio component binding */ /* pcm_bitmap means which pcms have been assigned to pins*/ unsigned long pcm_bitmap; int pcm_used; /* counter of pcm_rec[] */ @@ -159,6 +147,7 @@ struct hdmi_spec { bool dyn_pin_out; bool dyn_pcm_assign; + bool intel_hsw_fixup; /* apply Intel platform-specific fixups */ /* * Non-generic VIA/NVIDIA specific */ @@ -651,8 +640,16 @@ static bool hdmi_infoframe_uptodate(struct hda_codec *codec, hda_nid_t pin_nid, return true; } +static int hdmi_pin_get_eld(struct hda_codec *codec, hda_nid_t nid, + int dev_id, unsigned char *buf, int *eld_size) +{ + snd_hda_set_dev_select(codec, nid, dev_id); + + return snd_hdmi_get_eld(codec, nid, buf, eld_size); +} + static void hdmi_pin_setup_infoframe(struct hda_codec *codec, - hda_nid_t pin_nid, + hda_nid_t pin_nid, int dev_id, int ca, int active_channels, int conn_type) { @@ -682,6 +679,8 @@ static void hdmi_pin_setup_infoframe(struct hda_codec *codec, return; } + snd_hda_set_dev_select(codec, pin_nid, dev_id); + /* * sizeof(ai) is used instead of sizeof(*hdmi_ai) or * sizeof(*dp_ai) to avoid partial match/update problems when @@ -707,6 +706,7 @@ static void hdmi_setup_audio_infoframe(struct hda_codec *codec, struct hdmi_spec *spec = codec->spec; struct hdac_chmap *chmap = &spec->chmap; hda_nid_t pin_nid = per_pin->pin_nid; + int dev_id = per_pin->dev_id; int channels = per_pin->channels; int active_channels; struct hdmi_eld *eld; @@ -715,6 +715,8 @@ static void hdmi_setup_audio_infoframe(struct hda_codec *codec, if (!channels) return; + snd_hda_set_dev_select(codec, pin_nid, dev_id); + /* some HW (e.g. HSW+) needs reprogramming the amp at each time */ if (get_wcaps(codec, pin_nid) & AC_WCAP_OUT_AMP) snd_hda_codec_write(codec, pin_nid, 0, @@ -740,8 +742,8 @@ static void hdmi_setup_audio_infoframe(struct hda_codec *codec, pin_nid, non_pcm, ca, channels, per_pin->chmap, per_pin->chmap_set); - spec->ops.pin_setup_infoframe(codec, pin_nid, ca, active_channels, - eld->info.conn_type); + spec->ops.pin_setup_infoframe(codec, pin_nid, dev_id, + ca, active_channels, eld->info.conn_type); per_pin->non_pcm = non_pcm; } @@ -773,34 +775,32 @@ static void jack_callback(struct hda_codec *codec, if (codec_has_acomp(codec)) return; - /* hda_jack don't support DP MST */ - check_presence_and_report(codec, jack->nid, 0); + check_presence_and_report(codec, jack->nid, jack->dev_id); } static void hdmi_intrinsic_event(struct hda_codec *codec, unsigned int res) { int tag = res >> AC_UNSOL_RES_TAG_SHIFT; struct hda_jack_tbl *jack; - int dev_entry = (res & AC_UNSOL_RES_DE) >> AC_UNSOL_RES_DE_SHIFT; - /* - * assume DP MST uses dyn_pcm_assign and acomp and - * never comes here - * if DP MST supports unsol event, below code need - * consider dev_entry - */ - jack = snd_hda_jack_tbl_get_from_tag(codec, tag); + if (codec->dp_mst) { + int dev_entry = + (res & AC_UNSOL_RES_DE) >> AC_UNSOL_RES_DE_SHIFT; + + jack = snd_hda_jack_tbl_get_from_tag(codec, tag, dev_entry); + } else { + jack = snd_hda_jack_tbl_get_from_tag(codec, tag, 0); + } if (!jack) return; jack->jack_dirty = 1; codec_dbg(codec, "HDMI hot plug event: Codec=%d Pin=%d Device=%d Inactive=%d Presence_Detect=%d ELD_Valid=%d\n", - codec->addr, jack->nid, dev_entry, !!(res & AC_UNSOL_RES_IA), + codec->addr, jack->nid, jack->dev_id, !!(res & AC_UNSOL_RES_IA), !!(res & AC_UNSOL_RES_PD), !!(res & AC_UNSOL_RES_ELDV)); - /* hda_jack don't support DP MST */ - check_presence_and_report(codec, jack->nid, 0); + check_presence_and_report(codec, jack->nid, jack->dev_id); } static void hdmi_non_intrinsic_event(struct hda_codec *codec, unsigned int res) @@ -830,11 +830,21 @@ static void hdmi_unsol_event(struct hda_codec *codec, unsigned int res) { int tag = res >> AC_UNSOL_RES_TAG_SHIFT; int subtag = (res & AC_UNSOL_RES_SUBTAG) >> AC_UNSOL_RES_SUBTAG_SHIFT; + struct hda_jack_tbl *jack; if (codec_has_acomp(codec)) return; - if (!snd_hda_jack_tbl_get_from_tag(codec, tag)) { + if (codec->dp_mst) { + int dev_entry = + (res & AC_UNSOL_RES_DE) >> AC_UNSOL_RES_DE_SHIFT; + + jack = snd_hda_jack_tbl_get_from_tag(codec, tag, dev_entry); + } else { + jack = snd_hda_jack_tbl_get_from_tag(codec, tag, 0); + } + + if (!jack) { codec_dbg(codec, "Unexpected HDMI event tag 0x%x\n", tag); return; } @@ -875,11 +885,12 @@ static void haswell_verify_D0(struct hda_codec *codec, ((format & AC_FMT_TYPE_NON_PCM) && (format & AC_FMT_CHAN_MASK) == 7) static int hdmi_pin_hbr_setup(struct hda_codec *codec, hda_nid_t pin_nid, - bool hbr) + int dev_id, bool hbr) { int pinctl, new_pinctl; if (snd_hda_query_pin_caps(codec, pin_nid) & AC_PINCAP_HBR) { + snd_hda_set_dev_select(codec, pin_nid, dev_id); pinctl = snd_hda_codec_read(codec, pin_nid, 0, AC_VERB_GET_PIN_WIDGET_CONTROL, 0); @@ -909,20 +920,22 @@ static int hdmi_pin_hbr_setup(struct hda_codec *codec, hda_nid_t pin_nid, } static int hdmi_setup_stream(struct hda_codec *codec, hda_nid_t cvt_nid, - hda_nid_t pin_nid, u32 stream_tag, int format) + hda_nid_t pin_nid, int dev_id, + u32 stream_tag, int format) { struct hdmi_spec *spec = codec->spec; unsigned int param; int err; - err = spec->ops.pin_hbr_setup(codec, pin_nid, is_hbr_format(format)); + err = spec->ops.pin_hbr_setup(codec, pin_nid, dev_id, + is_hbr_format(format)); if (err) { codec_dbg(codec, "hdmi_setup_stream: HBR is not supported\n"); return err; } - if (is_haswell_plus(codec)) { + if (spec->intel_hsw_fixup) { /* * on recent platforms IEC Coding Type is required for HBR @@ -1237,6 +1250,10 @@ static int hdmi_pcm_open(struct hda_pcm_stream *hinfo, per_pin->cvt_nid = per_cvt->cvt_nid; hinfo->nid = per_cvt->cvt_nid; + /* flip stripe flag for the assigned stream if supported */ + if (get_wcaps(codec, per_cvt->cvt_nid) & AC_WCAP_STRIPE) + azx_stream(get_azx_dev(substream))->stripe = 1; + snd_hda_set_dev_select(codec, per_pin->pin_nid, per_pin->dev_id); snd_hda_codec_write_cache(codec, per_pin->pin_nid, 0, AC_VERB_SET_CONNECT_SEL, @@ -1289,6 +1306,8 @@ static int hdmi_read_pin_conn(struct hda_codec *codec, int pin_idx) struct hdmi_spec *spec = codec->spec; struct hdmi_spec_per_pin *per_pin = get_pin(spec, pin_idx); hda_nid_t pin_nid = per_pin->pin_nid; + int dev_id = per_pin->dev_id; + int conns; if (!(get_wcaps(codec, pin_nid) & AC_WCAP_CONN_LIST)) { codec_warn(codec, @@ -1297,24 +1316,53 @@ static int hdmi_read_pin_conn(struct hda_codec *codec, int pin_idx) return -EINVAL; } + snd_hda_set_dev_select(codec, pin_nid, dev_id); + + if (spec->intel_hsw_fixup) { + conns = spec->num_cvts; + memcpy(per_pin->mux_nids, spec->cvt_nids, + sizeof(hda_nid_t) * conns); + } else { + conns = snd_hda_get_raw_connections(codec, pin_nid, + per_pin->mux_nids, + HDA_MAX_CONNECTIONS); + } + /* all the device entries on the same pin have the same conn list */ - per_pin->num_mux_nids = snd_hda_get_connections(codec, pin_nid, - per_pin->mux_nids, - HDA_MAX_CONNECTIONS); + per_pin->num_mux_nids = conns; return 0; } static int hdmi_find_pcm_slot(struct hdmi_spec *spec, - struct hdmi_spec_per_pin *per_pin) + struct hdmi_spec_per_pin *per_pin) { int i; - /* try the prefer PCM */ - if (!test_bit(per_pin->pin_nid_idx, &spec->pcm_bitmap)) - return per_pin->pin_nid_idx; + /* + * generic_hdmi_build_pcms() may allocate extra PCMs on some + * platforms (with maximum of 'num_nids + dev_num - 1') + * + * The per_pin of pin_nid_idx=n and dev_id=m prefers to get pcm-n + * if m==0. This guarantees that dynamic pcm assignments are compatible + * with the legacy static per_pin-pcm assignment that existed in the + * days before DP-MST. + * + * Intel DP-MST prefers this legacy behavior for compatibility, too. + * + * per_pin of m!=0 prefers to get pcm=(num_nids + (m - 1)). + */ + + if (per_pin->dev_id == 0 || spec->intel_hsw_fixup) { + if (!test_bit(per_pin->pin_nid_idx, &spec->pcm_bitmap)) + return per_pin->pin_nid_idx; + } else { + i = spec->num_nids + (per_pin->dev_id - 1); + if (i < spec->pcm_used && !(test_bit(i, &spec->pcm_bitmap))) + return i; + } - /* have a second try; check the "reserved area" over num_pins */ + /* have a second try; check the area over num_nids */ for (i = spec->num_nids; i < spec->pcm_used; i++) { if (!test_bit(i, &spec->pcm_bitmap)) return i; @@ -1508,6 +1556,7 @@ static bool hdmi_present_sense_via_verbs(struct hdmi_spec_per_pin *per_pin, struct hdmi_spec *spec = codec->spec; struct hdmi_eld *eld = &spec->temp_eld; hda_nid_t pin_nid = per_pin->pin_nid; + int dev_id = per_pin->dev_id; /* * Always execute a GetPinSense verb here, even when called from * hdmi_intrinsic_event; for some NVIDIA HW, the unsolicited @@ -1520,7 +1569,7 @@ static bool hdmi_present_sense_via_verbs(struct hdmi_spec_per_pin *per_pin, bool ret; bool do_repoll = false; - present = snd_hda_pin_sense(codec, pin_nid); + present = snd_hda_jack_pin_sense(codec, pin_nid, dev_id); mutex_lock(&per_pin->lock); eld->monitor_present = !!(present & AC_PINSENSE_PRESENCE); @@ -1534,8 +1583,8 @@ static bool hdmi_present_sense_via_verbs(struct hdmi_spec_per_pin *per_pin, codec->addr, pin_nid, eld->monitor_present, eld->eld_valid); if (eld->eld_valid) { - if (spec->ops.pin_get_eld(codec, pin_nid, eld->eld_buffer, - &eld->eld_size) < 0) + if (spec->ops.pin_get_eld(codec, pin_nid, dev_id, + eld->eld_buffer, &eld->eld_size) < 0) eld->eld_valid = false; else { if (snd_hdmi_parse_eld(codec, &eld->info, eld->eld_buffer, @@ -1553,7 +1602,7 @@ static bool hdmi_present_sense_via_verbs(struct hdmi_spec_per_pin *per_pin, ret = !repoll || !eld->monitor_present || eld->eld_valid; - jack = snd_hda_jack_tbl_get(codec, pin_nid); + jack = snd_hda_jack_tbl_get_mst(codec, pin_nid, per_pin->dev_id); if (jack) { jack->block_report = !ret; jack->pin_sense = (eld->monitor_present && eld->eld_valid) ? @@ -1584,7 +1633,8 @@ static struct snd_jack *pin_idx_to_jack(struct hda_codec *codec, * DP MST will use dyn_pcm_assign, * so DP MST will never come here */ - jack_tbl = snd_hda_jack_tbl_get(codec, per_pin->pin_nid); + jack_tbl = snd_hda_jack_tbl_get_mst(codec, per_pin->pin_nid, + per_pin->dev_id); if (jack_tbl) jack = jack_tbl->jack; } @@ -1665,7 +1715,8 @@ static void hdmi_repoll_eld(struct work_struct *work) struct hdmi_spec *spec = codec->spec; struct hda_jack_tbl *jack; - jack = snd_hda_jack_tbl_get(codec, per_pin->pin_nid); + jack = snd_hda_jack_tbl_get_mst(codec, per_pin->pin_nid, + per_pin->dev_id); if (jack) jack->jack_dirty = 1; @@ -1678,9 +1729,6 @@ static void hdmi_repoll_eld(struct work_struct *work) mutex_unlock(&spec->pcm_lock); } -static void intel_haswell_fixup_connect_list(struct hda_codec *codec, - hda_nid_t nid); - static int hdmi_add_pin(struct hda_codec *codec, hda_nid_t pin_nid) { struct hdmi_spec *spec = codec->spec; @@ -1706,7 +1754,7 @@ static int hdmi_add_pin(struct hda_codec *codec, hda_nid_t pin_nid) * To simplify the implementation, malloc all * the virtual pins in the initialization statically */ - if (is_haswell_plus(codec)) { + if (spec->intel_hsw_fixup) { /* * On Intel platforms, device entries number is * changed dynamically. If there is a DP MST @@ -1755,8 +1803,6 @@ static int hdmi_add_pin(struct hda_codec *codec, hda_nid_t pin_nid) per_pin->dev_id = i; per_pin->non_pcm = false; snd_hda_set_dev_select(codec, pin_nid, i); - if (is_haswell_plus(codec)) - intel_haswell_fixup_connect_list(codec, pin_nid); err = hdmi_read_pin_conn(codec, pin_idx); if (err < 0) return err; @@ -1870,7 +1916,6 @@ static int generic_hdmi_playback_pcm_prepare(struct hda_pcm_stream *hinfo, struct hdmi_spec *spec = codec->spec; int pin_idx; struct hdmi_spec_per_pin *per_pin; - hda_nid_t pin_nid; struct snd_pcm_runtime *runtime = substream->runtime; bool non_pcm; int pinctl, stripe; @@ -1894,7 +1939,6 @@ static int generic_hdmi_playback_pcm_prepare(struct hda_pcm_stream *hinfo, goto unlock; } per_pin = get_pin(spec, pin_idx); - pin_nid = per_pin->pin_nid; /* Verify pin:cvt selections to avoid silent audio after S3. * After S3, the audio driver restores pin:cvt selections @@ -1909,8 +1953,8 @@ static int generic_hdmi_playback_pcm_prepare(struct hda_pcm_stream *hinfo, /* Call sync_audio_rate to set the N/CTS/M manually if necessary */ /* Todo: add DP1.2 MST audio support later */ if (codec_has_acomp(codec)) - snd_hdac_sync_audio_rate(&codec->core, pin_nid, per_pin->dev_id, - runtime->rate); + snd_hdac_sync_audio_rate(&codec->core, per_pin->pin_nid, + per_pin->dev_id, runtime->rate); non_pcm = check_non_pcm_per_cvt(codec, cvt_nid); mutex_lock(&per_pin->lock); @@ -1928,16 +1972,18 @@ static int generic_hdmi_playback_pcm_prepare(struct hda_pcm_stream *hinfo, hdmi_setup_audio_infoframe(codec, per_pin, non_pcm); mutex_unlock(&per_pin->lock); if (spec->dyn_pin_out) { - pinctl = snd_hda_codec_read(codec, pin_nid, 0, + snd_hda_set_dev_select(codec, per_pin->pin_nid, + per_pin->dev_id); + pinctl = snd_hda_codec_read(codec, per_pin->pin_nid, 0, AC_VERB_GET_PIN_WIDGET_CONTROL, 0); - snd_hda_codec_write(codec, pin_nid, 0, + snd_hda_codec_write(codec, per_pin->pin_nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, pinctl | PIN_OUT); } /* snd_hda_set_dev_select() has been called before */ - err = spec->ops.setup_stream(codec, cvt_nid, pin_nid, - stream_tag, format); + err = spec->ops.setup_stream(codec, cvt_nid, per_pin->pin_nid, + per_pin->dev_id, stream_tag, format); unlock: mutex_unlock(&spec->pcm_lock); return err; @@ -1975,6 +2021,8 @@ static int hdmi_pcm_close(struct hda_pcm_stream *hinfo, per_cvt->assigned = 0; hinfo->nid = 0; + azx_stream(get_azx_dev(substream))->stripe = 0; + mutex_lock(&spec->pcm_lock); snd_hda_spdif_ctls_unassign(codec, pcm_idx); clear_bit(pcm_idx, &spec->pcm_in_use); @@ -1989,6 +2037,8 @@ static int hdmi_pcm_close(struct hda_pcm_stream *hinfo, per_pin = get_pin(spec, pin_idx); if (spec->dyn_pin_out) { + snd_hda_set_dev_select(codec, per_pin->pin_nid, + per_pin->dev_id); pinctl = snd_hda_codec_read(codec, per_pin->pin_nid, 0, AC_VERB_GET_PIN_WIDGET_CONTROL, 0); snd_hda_codec_write(codec, per_pin->pin_nid, 0, @@ -2166,11 +2216,13 @@ static int generic_hdmi_build_jack(struct hda_codec *codec, int pcm_idx) if (phantom_jack) 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, 0, NULL); + ret = snd_hda_jack_add_kctl_mst(codec, per_pin->pin_nid, + per_pin->dev_id, hdmi_str, phantom_jack, + 0, NULL); if (ret < 0) return ret; - jack = snd_hda_jack_tbl_get(codec, per_pin->pin_nid); + jack = snd_hda_jack_tbl_get_mst(codec, per_pin->pin_nid, + per_pin->dev_id); if (jack == NULL) return 0; /* assign jack->jack to pcm_rec[].jack to @@ -2267,7 +2319,7 @@ static int generic_hdmi_init(struct hda_codec *codec) struct hdmi_spec *spec = codec->spec; int pin_idx; - mutex_lock(&spec->pcm_lock); + mutex_lock(&spec->bind_lock); spec->use_jack_detect = !codec->jackpoll_interval; for (pin_idx = 0; pin_idx < spec->num_pins; pin_idx++) { struct hdmi_spec_per_pin *per_pin = get_pin(spec, pin_idx); @@ -2279,12 +2331,13 @@ static int generic_hdmi_init(struct hda_codec *codec) if (codec_has_acomp(codec)) continue; if (spec->use_jack_detect) - snd_hda_jack_detect_enable(codec, pin_nid); + snd_hda_jack_detect_enable(codec, pin_nid, dev_id); else - snd_hda_jack_detect_enable_callback(codec, pin_nid, - jack_callback); + snd_hda_jack_detect_enable_callback_mst(codec, pin_nid, + dev_id, + jack_callback); } - mutex_unlock(&spec->pcm_lock); + mutex_unlock(&spec->bind_lock); return 0; } @@ -2321,8 +2374,8 @@ static void generic_hdmi_free(struct hda_codec *codec) snd_hdac_acomp_exit(&codec->bus->core); } else if (codec_has_acomp(codec)) { snd_hdac_acomp_register_notifier(&codec->bus->core, NULL); - codec->relaxed_resume = 0; } + codec->relaxed_resume = 0; for (pin_idx = 0; pin_idx < spec->num_pins; pin_idx++) { struct hdmi_spec_per_pin *per_pin = get_pin(spec, pin_idx); @@ -2372,7 +2425,7 @@ static const struct hda_codec_ops generic_hdmi_patch_ops = { }; static const struct hdmi_ops generic_standard_hdmi_ops = { - .pin_get_eld = snd_hdmi_get_eld, + .pin_get_eld = hdmi_pin_get_eld, .pin_setup_infoframe = hdmi_pin_setup_infoframe, .pin_hbr_setup = hdmi_pin_hbr_setup, .setup_stream = hdmi_setup_stream, @@ -2391,6 +2444,7 @@ static int alloc_generic_hdmi(struct hda_codec *codec) spec->ops = generic_standard_hdmi_ops; spec->dev_num = 1; /* initialize to 1 */ mutex_init(&spec->pcm_lock); + mutex_init(&spec->bind_lock); snd_hdac_register_chmap_ops(&codec->core, &spec->chmap); spec->chmap.ops.get_chmap = hdmi_get_chmap; @@ -2431,11 +2485,11 @@ static int patch_generic_hdmi(struct hda_codec *codec) /* turn on / off the unsol event jack detection dynamically */ static void reprogram_jack_detect(struct hda_codec *codec, hda_nid_t nid, - bool use_acomp) + int dev_id, bool use_acomp) { struct hda_jack_tbl *tbl; - tbl = snd_hda_jack_tbl_get(codec, nid); + tbl = snd_hda_jack_tbl_get_mst(codec, nid, dev_id); if (tbl) { /* clear unsol even if component notifier is used, or re-enable * if notifier is cleared @@ -2448,7 +2502,7 @@ static void reprogram_jack_detect(struct hda_codec *codec, hda_nid_t nid, * at need (i.e. only when notifier is cleared) */ if (!use_acomp) - snd_hda_jack_detect_enable(codec, nid); + snd_hda_jack_detect_enable(codec, nid, dev_id); } } @@ -2460,7 +2514,7 @@ static void generic_acomp_notifier_set(struct drm_audio_component *acomp, int i; spec = container_of(acomp->audio_ops, struct hdmi_spec, drm_audio_ops); - mutex_lock(&spec->pcm_lock); + mutex_lock(&spec->bind_lock); spec->use_acomp_notifier = use_acomp; spec->codec->relaxed_resume = use_acomp; /* reprogram each jack detection logic depending on the notifier */ @@ -2468,9 +2522,10 @@ static void generic_acomp_notifier_set(struct drm_audio_component *acomp, for (i = 0; i < spec->num_pins; i++) reprogram_jack_detect(spec->codec, get_pin(spec, i)->pin_nid, + get_pin(spec, i)->dev_id, use_acomp); } - mutex_unlock(&spec->pcm_lock); + mutex_unlock(&spec->bind_lock); } /* enable / disable the notifier via master bind / unbind */ @@ -2561,23 +2616,6 @@ static void generic_acomp_init(struct hda_codec *codec, * Intel codec parsers and helpers */ -static void intel_haswell_fixup_connect_list(struct hda_codec *codec, - hda_nid_t nid) -{ - struct hdmi_spec *spec = codec->spec; - hda_nid_t conns[4]; - int nconns; - - nconns = snd_hda_get_connections(codec, nid, conns, ARRAY_SIZE(conns)); - if (nconns == spec->num_cvts && - !memcmp(conns, spec->cvt_nids, spec->num_cvts * sizeof(hda_nid_t))) - return; - - /* override pins connection list */ - codec_dbg(codec, "hdmi: haswell: override pin connection 0x%x\n", nid); - snd_hda_override_conn_list(codec, nid, spec->num_cvts, spec->cvt_nids); -} - #define INTEL_GET_VENDOR_VERB 0xf81 #define INTEL_SET_VENDOR_VERB 0x781 #define INTEL_EN_DP12 0x02 /* enable DP 1.2 features */ @@ -2669,7 +2707,7 @@ static int intel_pin2port(void *audio_ptr, int pin_nid) base_nid = intel_base_nid(codec); if (WARN_ON(pin_nid < base_nid || pin_nid >= base_nid + 3)) return -1; - return pin_nid - base_nid + 1; /* intel port is 1-based */ + return pin_nid - base_nid + 1; } /* @@ -2678,10 +2716,9 @@ static int intel_pin2port(void *audio_ptr, int pin_nid) */ for (i = 0; i < spec->port_num; i++) { if (pin_nid == spec->port_map[i]) - return i + 1; + return i; } - /* return -1 if pin number exceeds our expectation */ codec_info(codec, "Can't find the HDMI/DP port for pin %d\n", pin_nid); return -1; } @@ -2694,13 +2731,12 @@ static int intel_port2pin(struct hda_codec *codec, int port) /* we assume only from port-B to port-D */ if (port < 1 || port > 3) return 0; - /* intel port is 1-based */ return port + intel_base_nid(codec) - 1; } - if (port < 1 || port > spec->port_num) + if (port < 0 || port >= spec->port_num) return 0; - return spec->port_map[port - 1]; + return spec->port_map[port]; } static void intel_pin_eld_notify(void *audio_ptr, int port, int pipe) @@ -2746,10 +2782,12 @@ static void register_i915_notifier(struct hda_codec *codec) /* setup_stream ops override for HSW+ */ static int i915_hsw_setup_stream(struct hda_codec *codec, hda_nid_t cvt_nid, - hda_nid_t pin_nid, u32 stream_tag, int format) + hda_nid_t pin_nid, int dev_id, u32 stream_tag, + int format) { haswell_verify_D0(codec, cvt_nid, pin_nid); - return hdmi_setup_stream(codec, cvt_nid, pin_nid, stream_tag, format); + return hdmi_setup_stream(codec, cvt_nid, pin_nid, dev_id, + stream_tag, format); } /* pin_cvt_fixup ops override for HSW+ and VLV+ */ @@ -2821,6 +2859,7 @@ static int intel_hsw_common_init(struct hda_codec *codec, hda_nid_t vendor_nid, spec->vendor_nid = vendor_nid; spec->port_map = port_map; spec->port_num = port_num; + spec->intel_hsw_fixup = true; intel_haswell_enable_all_pins(codec, true); intel_haswell_fixup_enable_dp12(codec); @@ -2851,9 +2890,20 @@ static int patch_i915_icl_hdmi(struct hda_codec *codec) { /* * pin to port mapping table where the value indicate the pin number and - * the index indicate the port number with 1 base. + * the index indicate the port number. + */ + static const int map[] = {0x0, 0x4, 0x6, 0x8, 0xa, 0xb}; + + return intel_hsw_common_init(codec, 0x02, map, ARRAY_SIZE(map)); +} + +static int patch_i915_tgl_hdmi(struct hda_codec *codec) +{ + /* + * pin to port mapping table where the value indicate the pin number and + * the index indicate the port number. */ - static const int map[] = {0x4, 0x6, 0x8, 0xa, 0xb}; + static const int map[] = {0x4, 0x6, 0x8, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf}; return intel_hsw_common_init(codec, 0x02, map, ARRAY_SIZE(map)); } @@ -2963,7 +3013,7 @@ static int simple_playback_init(struct hda_codec *codec) if (get_wcaps(codec, pin) & AC_WCAP_OUT_AMP) snd_hda_codec_write(codec, pin, 0, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE); - snd_hda_jack_detect_enable(codec, pin); + snd_hda_jack_detect_enable(codec, pin, per_pin->dev_id); return 0; } @@ -3472,6 +3522,40 @@ static int patch_nvhdmi(struct hda_codec *codec) struct hdmi_spec *spec; int err; + err = alloc_generic_hdmi(codec); + if (err < 0) + return err; + codec->dp_mst = true; + + spec = codec->spec; + spec->dyn_pcm_assign = true; + + err = hdmi_parse_codec(codec); + if (err < 0) { + generic_spec_free(codec); + return err; + } + + generic_hdmi_init_per_pins(codec); + + spec->dyn_pin_out = true; + + spec->chmap.ops.chmap_cea_alloc_validate_get_type = + nvhdmi_chmap_cea_alloc_validate_get_type; + spec->chmap.ops.chmap_validate = nvhdmi_chmap_validate; + + codec->link_down_at_suspend = 1; + + generic_acomp_init(codec, &nvhdmi_audio_ops, nvhdmi_port2pin); + + return 0; +} + +static int patch_nvhdmi_legacy(struct hda_codec *codec) +{ + struct hdmi_spec *spec; + int err; + err = patch_generic_hdmi(codec); if (err) return err; @@ -3483,7 +3567,7 @@ static int patch_nvhdmi(struct hda_codec *codec) nvhdmi_chmap_cea_alloc_validate_get_type; spec->chmap.ops.chmap_validate = nvhdmi_chmap_validate; - generic_acomp_init(codec, &nvhdmi_audio_ops, nvhdmi_port2pin); + codec->link_down_at_suspend = 1; return 0; } @@ -3701,16 +3785,19 @@ static int patch_tegra_hdmi(struct hda_codec *codec) #define ATI_HBR_ENABLE 0x10 static int atihdmi_pin_get_eld(struct hda_codec *codec, hda_nid_t nid, - unsigned char *buf, int *eld_size) + int dev_id, unsigned char *buf, int *eld_size) { + WARN_ON(dev_id != 0); /* call hda_eld.c ATI/AMD-specific function */ return snd_hdmi_get_eld_ati(codec, nid, buf, eld_size, is_amdhdmi_rev3_or_later(codec)); } -static void atihdmi_pin_setup_infoframe(struct hda_codec *codec, hda_nid_t pin_nid, int ca, +static void atihdmi_pin_setup_infoframe(struct hda_codec *codec, + hda_nid_t pin_nid, int dev_id, int ca, int active_channels, int conn_type) { + WARN_ON(dev_id != 0); snd_hda_codec_write(codec, pin_nid, 0, ATI_VERB_SET_CHANNEL_ALLOCATION, ca); } @@ -3901,10 +3988,12 @@ static void atihdmi_paired_cea_alloc_to_tlv_chmap(struct hdac_chmap *hchmap, } static int atihdmi_pin_hbr_setup(struct hda_codec *codec, hda_nid_t pin_nid, - bool hbr) + int dev_id, bool hbr) { int hbr_ctl, hbr_ctl_new; + WARN_ON(dev_id != 0); + hbr_ctl = snd_hda_codec_read(codec, pin_nid, 0, ATI_VERB_GET_HBR_CONTROL, 0); if (hbr_ctl >= 0 && (hbr_ctl & ATI_HBR_CAPABLE)) { if (hbr) @@ -3930,9 +4019,9 @@ static int atihdmi_pin_hbr_setup(struct hda_codec *codec, hda_nid_t pin_nid, } static int atihdmi_setup_stream(struct hda_codec *codec, hda_nid_t cvt_nid, - hda_nid_t pin_nid, u32 stream_tag, int format) + hda_nid_t pin_nid, int dev_id, + u32 stream_tag, int format) { - if (is_amdhdmi_rev3_or_later(codec)) { int ramp_rate = 180; /* default as per AMD spec */ /* disable ramp-up/down for non-pcm as per AMD spec */ @@ -3942,7 +4031,8 @@ static int atihdmi_setup_stream(struct hda_codec *codec, hda_nid_t cvt_nid, snd_hda_codec_write(codec, cvt_nid, 0, ATI_VERB_SET_RAMP_RATE, ramp_rate); } - return hdmi_setup_stream(codec, cvt_nid, pin_nid, stream_tag, format); + return hdmi_setup_stream(codec, cvt_nid, pin_nid, dev_id, + stream_tag, format); } @@ -3968,6 +4058,7 @@ static int atihdmi_init(struct hda_codec *codec) ATI_VERB_SET_MULTICHANNEL_MODE, ATI_MULTICHANNEL_MODE_SINGLE); } + codec->auto_runtime_pm = 1; return 0; } @@ -4072,25 +4163,25 @@ HDA_CODEC_ENTRY(0x10de0004, "GPU 04 HDMI", patch_nvhdmi_8ch_7x), HDA_CODEC_ENTRY(0x10de0005, "MCP77/78 HDMI", patch_nvhdmi_8ch_7x), HDA_CODEC_ENTRY(0x10de0006, "MCP77/78 HDMI", patch_nvhdmi_8ch_7x), HDA_CODEC_ENTRY(0x10de0007, "MCP79/7A HDMI", patch_nvhdmi_8ch_7x), -HDA_CODEC_ENTRY(0x10de0008, "GPU 08 HDMI/DP", patch_nvhdmi), -HDA_CODEC_ENTRY(0x10de0009, "GPU 09 HDMI/DP", patch_nvhdmi), -HDA_CODEC_ENTRY(0x10de000a, "GPU 0a HDMI/DP", patch_nvhdmi), -HDA_CODEC_ENTRY(0x10de000b, "GPU 0b HDMI/DP", patch_nvhdmi), -HDA_CODEC_ENTRY(0x10de000c, "MCP89 HDMI", patch_nvhdmi), -HDA_CODEC_ENTRY(0x10de000d, "GPU 0d HDMI/DP", patch_nvhdmi), -HDA_CODEC_ENTRY(0x10de0010, "GPU 10 HDMI/DP", patch_nvhdmi), -HDA_CODEC_ENTRY(0x10de0011, "GPU 11 HDMI/DP", patch_nvhdmi), -HDA_CODEC_ENTRY(0x10de0012, "GPU 12 HDMI/DP", patch_nvhdmi), -HDA_CODEC_ENTRY(0x10de0013, "GPU 13 HDMI/DP", patch_nvhdmi), -HDA_CODEC_ENTRY(0x10de0014, "GPU 14 HDMI/DP", patch_nvhdmi), -HDA_CODEC_ENTRY(0x10de0015, "GPU 15 HDMI/DP", patch_nvhdmi), -HDA_CODEC_ENTRY(0x10de0016, "GPU 16 HDMI/DP", patch_nvhdmi), +HDA_CODEC_ENTRY(0x10de0008, "GPU 08 HDMI/DP", patch_nvhdmi_legacy), +HDA_CODEC_ENTRY(0x10de0009, "GPU 09 HDMI/DP", patch_nvhdmi_legacy), +HDA_CODEC_ENTRY(0x10de000a, "GPU 0a HDMI/DP", patch_nvhdmi_legacy), +HDA_CODEC_ENTRY(0x10de000b, "GPU 0b HDMI/DP", patch_nvhdmi_legacy), +HDA_CODEC_ENTRY(0x10de000c, "MCP89 HDMI", patch_nvhdmi_legacy), +HDA_CODEC_ENTRY(0x10de000d, "GPU 0d HDMI/DP", patch_nvhdmi_legacy), +HDA_CODEC_ENTRY(0x10de0010, "GPU 10 HDMI/DP", patch_nvhdmi_legacy), +HDA_CODEC_ENTRY(0x10de0011, "GPU 11 HDMI/DP", patch_nvhdmi_legacy), +HDA_CODEC_ENTRY(0x10de0012, "GPU 12 HDMI/DP", patch_nvhdmi_legacy), +HDA_CODEC_ENTRY(0x10de0013, "GPU 13 HDMI/DP", patch_nvhdmi_legacy), +HDA_CODEC_ENTRY(0x10de0014, "GPU 14 HDMI/DP", patch_nvhdmi_legacy), +HDA_CODEC_ENTRY(0x10de0015, "GPU 15 HDMI/DP", patch_nvhdmi_legacy), +HDA_CODEC_ENTRY(0x10de0016, "GPU 16 HDMI/DP", patch_nvhdmi_legacy), /* 17 is known to be absent */ -HDA_CODEC_ENTRY(0x10de0018, "GPU 18 HDMI/DP", patch_nvhdmi), -HDA_CODEC_ENTRY(0x10de0019, "GPU 19 HDMI/DP", patch_nvhdmi), -HDA_CODEC_ENTRY(0x10de001a, "GPU 1a HDMI/DP", patch_nvhdmi), -HDA_CODEC_ENTRY(0x10de001b, "GPU 1b HDMI/DP", patch_nvhdmi), -HDA_CODEC_ENTRY(0x10de001c, "GPU 1c HDMI/DP", patch_nvhdmi), +HDA_CODEC_ENTRY(0x10de0018, "GPU 18 HDMI/DP", patch_nvhdmi_legacy), +HDA_CODEC_ENTRY(0x10de0019, "GPU 19 HDMI/DP", patch_nvhdmi_legacy), +HDA_CODEC_ENTRY(0x10de001a, "GPU 1a HDMI/DP", patch_nvhdmi_legacy), +HDA_CODEC_ENTRY(0x10de001b, "GPU 1b HDMI/DP", patch_nvhdmi_legacy), +HDA_CODEC_ENTRY(0x10de001c, "GPU 1c HDMI/DP", patch_nvhdmi_legacy), 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), @@ -4158,6 +4249,7 @@ HDA_CODEC_ENTRY(0x8086280b, "Kabylake HDMI", patch_i915_hsw_hdmi), HDA_CODEC_ENTRY(0x8086280c, "Cannonlake HDMI", patch_i915_glk_hdmi), HDA_CODEC_ENTRY(0x8086280d, "Geminilake HDMI", patch_i915_glk_hdmi), HDA_CODEC_ENTRY(0x8086280f, "Icelake HDMI", patch_i915_icl_hdmi), +HDA_CODEC_ENTRY(0x80862812, "Tigerlake HDMI", patch_i915_tgl_hdmi), HDA_CODEC_ENTRY(0x80862880, "CedarTrail HDMI", patch_generic_hdmi), HDA_CODEC_ENTRY(0x80862882, "Valleyview2 HDMI", patch_i915_byt_hdmi), HDA_CODEC_ENTRY(0x80862883, "Braswell HDMI", patch_i915_byt_hdmi), diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index b000b36ac3c6..f2ea3528bfb1 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -367,9 +367,7 @@ static void alc_fill_eapd_coef(struct hda_codec *codec) case 0x10ec0215: case 0x10ec0233: case 0x10ec0235: - case 0x10ec0236: case 0x10ec0255: - case 0x10ec0256: case 0x10ec0257: case 0x10ec0282: case 0x10ec0283: @@ -381,6 +379,11 @@ static void alc_fill_eapd_coef(struct hda_codec *codec) case 0x10ec0300: alc_update_coef_idx(codec, 0x10, 1<<9, 0); break; + case 0x10ec0236: + case 0x10ec0256: + alc_write_coef_idx(codec, 0x36, 0x5757); + alc_update_coef_idx(codec, 0x10, 1<<9, 0); + break; case 0x10ec0275: alc_update_coef_idx(codec, 0xe, 0, 1<<0); break; @@ -393,6 +396,7 @@ static void alc_fill_eapd_coef(struct hda_codec *codec) case 0x10ec0700: case 0x10ec0701: case 0x10ec0703: + case 0x10ec0711: alc_update_coef_idx(codec, 0x10, 1<<15, 0); break; case 0x10ec0662: @@ -408,6 +412,10 @@ static void alc_fill_eapd_coef(struct hda_codec *codec) case 0x10ec0672: alc_update_coef_idx(codec, 0xd, 0, 1<<14); /* EAPD Ctrl */ break; + case 0x10ec0222: + case 0x10ec0623: + alc_update_coef_idx(codec, 0x19, 1<<13, 0); + break; case 0x10ec0668: alc_update_coef_idx(codec, 0x7, 3<<13, 0); break; @@ -423,6 +431,7 @@ static void alc_fill_eapd_coef(struct hda_codec *codec) break; case 0x10ec0899: case 0x10ec0900: + case 0x10ec0b00: case 0x10ec1168: case 0x10ec1220: alc_update_coef_idx(codec, 0x7, 1<<1, 0); @@ -494,6 +503,7 @@ static void alc_shutup_pins(struct hda_codec *codec) struct alc_spec *spec = codec->spec; switch (codec->core.vendor_id) { + case 0x10ec0283: case 0x10ec0286: case 0x10ec0288: case 0x10ec0298: @@ -2518,6 +2528,7 @@ static int patch_alc882(struct hda_codec *codec) case 0x10ec0882: case 0x10ec0885: case 0x10ec0900: + case 0x10ec0b00: case 0x10ec1220: break; default: @@ -2919,6 +2930,7 @@ enum { ALC269_TYPE_ALC225, ALC269_TYPE_ALC294, ALC269_TYPE_ALC300, + ALC269_TYPE_ALC623, ALC269_TYPE_ALC700, }; @@ -2954,6 +2966,7 @@ static int alc269_parse_auto_config(struct hda_codec *codec) case ALC269_TYPE_ALC225: case ALC269_TYPE_ALC294: case ALC269_TYPE_ALC300: + case ALC269_TYPE_ALC623: case ALC269_TYPE_ALC700: ssids = alc269_ssids; break; @@ -5358,6 +5371,17 @@ static void alc271_hp_gate_mic_jack(struct hda_codec *codec, } } +static void alc256_fixup_dell_xps_13_headphone_noise2(struct hda_codec *codec, + const struct hda_fixup *fix, + int action) +{ + if (action != HDA_FIXUP_ACT_PRE_PROBE) + return; + + snd_hda_codec_amp_stereo(codec, 0x1a, HDA_INPUT, 0, HDA_AMP_VOLMASK, 1); + snd_hda_override_wcaps(codec, 0x1a, get_wcaps(codec, 0x1a) & ~AC_WCAP_IN_AMP); +} + static void alc269_fixup_limit_int_mic_boost(struct hda_codec *codec, const struct hda_fixup *fix, int action) @@ -5527,6 +5551,16 @@ static void alc295_fixup_disable_dac3(struct hda_codec *codec, } } +/* force NID 0x17 (Bass Speaker) to DAC1 to share it with the main speaker */ +static void alc285_fixup_speaker2_to_dac1(struct hda_codec *codec, + const struct hda_fixup *fix, int action) +{ + if (action == HDA_FIXUP_ACT_PRE_PROBE) { + hda_nid_t conn[1] = { 0x02 }; + snd_hda_override_conn_list(codec, 0x17, 1, conn); + } +} + /* Hook to update amp GPIO4 for automute */ static void alc280_hp_gpio4_automute_hook(struct hda_codec *codec, struct hda_jack_callback *jack) @@ -5822,12 +5856,14 @@ enum { ALC298_FIXUP_DELL_AIO_MIC_NO_PRESENCE, ALC275_FIXUP_DELL_XPS, ALC256_FIXUP_DELL_XPS_13_HEADPHONE_NOISE, + ALC256_FIXUP_DELL_XPS_13_HEADPHONE_NOISE2, ALC293_FIXUP_LENOVO_SPK_NOISE, ALC233_FIXUP_LENOVO_LINE2_MIC_HOTKEY, ALC255_FIXUP_DELL_SPK_NOISE, ALC225_FIXUP_DISABLE_MIC_VREF, ALC225_FIXUP_DELL1_MIC_NO_PRESENCE, ALC295_FIXUP_DISABLE_DAC3, + ALC285_FIXUP_SPEAKER2_TO_DAC1, ALC280_FIXUP_HP_HEADSET_MIC, ALC221_FIXUP_HP_FRONT_MIC, ALC292_FIXUP_TPT460, @@ -5869,10 +5905,15 @@ enum { ALC225_FIXUP_WYSE_AUTO_MUTE, ALC225_FIXUP_WYSE_DISABLE_MIC_VREF, ALC286_FIXUP_ACER_AIO_HEADSET_MIC, + ALC256_FIXUP_ASUS_HEADSET_MIC, ALC256_FIXUP_ASUS_MIC_NO_PRESENCE, ALC299_FIXUP_PREDATOR_SPK, - ALC294_FIXUP_ASUS_INTSPK_HEADSET_MIC, ALC256_FIXUP_MEDION_HEADSET_NO_PRESENCE, + ALC289_FIXUP_DELL_SPK2, + ALC289_FIXUP_DUAL_SPK, + ALC294_FIXUP_SPK2_TO_DAC1, + ALC294_FIXUP_ASUS_DUAL_SPK, + }; static const struct hda_fixup alc269_fixups[] = { @@ -6558,6 +6599,12 @@ static const struct hda_fixup alc269_fixups[] = { .chained = true, .chain_id = ALC255_FIXUP_DELL1_MIC_NO_PRESENCE }, + [ALC256_FIXUP_DELL_XPS_13_HEADPHONE_NOISE2] = { + .type = HDA_FIXUP_FUNC, + .v.func = alc256_fixup_dell_xps_13_headphone_noise2, + .chained = true, + .chain_id = ALC256_FIXUP_DELL_XPS_13_HEADPHONE_NOISE + }, [ALC293_FIXUP_LENOVO_SPK_NOISE] = { .type = HDA_FIXUP_FUNC, .v.func = alc_fixup_disable_aamix, @@ -6620,6 +6667,10 @@ static const struct hda_fixup alc269_fixups[] = { .type = HDA_FIXUP_FUNC, .v.func = alc295_fixup_disable_dac3, }, + [ALC285_FIXUP_SPEAKER2_TO_DAC1] = { + .type = HDA_FIXUP_FUNC, + .v.func = alc285_fixup_speaker2_to_dac1, + }, [ALC256_FIXUP_DELL_INSPIRON_7559_SUBWOOFER] = { .type = HDA_FIXUP_PINS, .v.pins = (const struct hda_pintbl[]) { @@ -6912,6 +6963,15 @@ static const struct hda_fixup alc269_fixups[] = { .chained = true, .chain_id = ALC286_FIXUP_ACER_AIO_MIC_NO_PRESENCE }, + [ALC256_FIXUP_ASUS_HEADSET_MIC] = { + .type = HDA_FIXUP_PINS, + .v.pins = (const struct hda_pintbl[]) { + { 0x19, 0x03a11020 }, /* headset mic with jack detect */ + { } + }, + .chained = true, + .chain_id = ALC256_FIXUP_ASUS_HEADSET_MODE + }, [ALC256_FIXUP_ASUS_MIC_NO_PRESENCE] = { .type = HDA_FIXUP_PINS, .v.pins = (const struct hda_pintbl[]) { @@ -6928,26 +6988,45 @@ static const struct hda_fixup alc269_fixups[] = { { } } }, - [ALC294_FIXUP_ASUS_INTSPK_HEADSET_MIC] = { + [ALC256_FIXUP_MEDION_HEADSET_NO_PRESENCE] = { .type = HDA_FIXUP_PINS, .v.pins = (const struct hda_pintbl[]) { - { 0x14, 0x411111f0 }, /* disable confusing internal speaker */ - { 0x19, 0x04a11150 }, /* use as headset mic, without its own jack detect */ + { 0x19, 0x04a11040 }, + { 0x21, 0x04211020 }, { } }, .chained = true, - .chain_id = ALC269_FIXUP_HEADSET_MODE_NO_HP_MIC + .chain_id = ALC256_FIXUP_ASUS_HEADSET_MODE }, - [ALC256_FIXUP_MEDION_HEADSET_NO_PRESENCE] = { + [ALC289_FIXUP_DELL_SPK2] = { .type = HDA_FIXUP_PINS, .v.pins = (const struct hda_pintbl[]) { - { 0x19, 0x04a11040 }, - { 0x21, 0x04211020 }, + { 0x17, 0x90170130 }, /* bass spk */ { } }, .chained = true, - .chain_id = ALC256_FIXUP_ASUS_HEADSET_MODE + .chain_id = ALC269_FIXUP_DELL4_MIC_NO_PRESENCE + }, + [ALC289_FIXUP_DUAL_SPK] = { + .type = HDA_FIXUP_FUNC, + .v.func = alc285_fixup_speaker2_to_dac1, + .chained = true, + .chain_id = ALC289_FIXUP_DELL_SPK2 }, + [ALC294_FIXUP_SPK2_TO_DAC1] = { + .type = HDA_FIXUP_FUNC, + .v.func = alc285_fixup_speaker2_to_dac1, + .chained = true, + .chain_id = ALC294_FIXUP_ASUS_HEADSET_MIC + }, + [ALC294_FIXUP_ASUS_DUAL_SPK] = { + .type = HDA_FIXUP_FUNC, + /* The GPIO must be pulled to initialize the AMP */ + .v.func = alc_fixup_gpio4, + .chained = true, + .chain_id = ALC294_FIXUP_SPK2_TO_DAC1 + }, + }; static const struct snd_pci_quirk alc269_fixup_tbl[] = { @@ -7001,17 +7080,17 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { SND_PCI_QUIRK(0x1028, 0x06de, "Dell", ALC293_FIXUP_DISABLE_AAMIX_MULTIJACK), SND_PCI_QUIRK(0x1028, 0x06df, "Dell", ALC293_FIXUP_DISABLE_AAMIX_MULTIJACK), SND_PCI_QUIRK(0x1028, 0x06e0, "Dell", ALC293_FIXUP_DISABLE_AAMIX_MULTIJACK), - SND_PCI_QUIRK(0x1028, 0x0704, "Dell XPS 13 9350", ALC256_FIXUP_DELL_XPS_13_HEADPHONE_NOISE), + SND_PCI_QUIRK(0x1028, 0x0704, "Dell XPS 13 9350", ALC256_FIXUP_DELL_XPS_13_HEADPHONE_NOISE2), SND_PCI_QUIRK(0x1028, 0x0706, "Dell Inspiron 7559", ALC256_FIXUP_DELL_INSPIRON_7559_SUBWOOFER), SND_PCI_QUIRK(0x1028, 0x0725, "Dell Inspiron 3162", ALC255_FIXUP_DELL_SPK_NOISE), SND_PCI_QUIRK(0x1028, 0x0738, "Dell Precision 5820", ALC269_FIXUP_NO_SHUTUP), - SND_PCI_QUIRK(0x1028, 0x075b, "Dell XPS 13 9360", ALC256_FIXUP_DELL_XPS_13_HEADPHONE_NOISE), + SND_PCI_QUIRK(0x1028, 0x075b, "Dell XPS 13 9360", ALC256_FIXUP_DELL_XPS_13_HEADPHONE_NOISE2), SND_PCI_QUIRK(0x1028, 0x075c, "Dell XPS 27 7760", ALC298_FIXUP_SPK_VOLUME), SND_PCI_QUIRK(0x1028, 0x075d, "Dell AIO", ALC298_FIXUP_SPK_VOLUME), SND_PCI_QUIRK(0x1028, 0x07b0, "Dell Precision 7520", ALC295_FIXUP_DISABLE_DAC3), SND_PCI_QUIRK(0x1028, 0x0798, "Dell Inspiron 17 7000 Gaming", ALC256_FIXUP_DELL_INSPIRON_7559_SUBWOOFER), SND_PCI_QUIRK(0x1028, 0x080c, "Dell WYSE", ALC225_FIXUP_DELL_WYSE_MIC_NO_PRESENCE), - SND_PCI_QUIRK(0x1028, 0x082a, "Dell XPS 13 9360", ALC256_FIXUP_DELL_XPS_13_HEADPHONE_NOISE), + SND_PCI_QUIRK(0x1028, 0x082a, "Dell XPS 13 9360", ALC256_FIXUP_DELL_XPS_13_HEADPHONE_NOISE2), SND_PCI_QUIRK(0x1028, 0x084b, "Dell", ALC274_FIXUP_DELL_AIO_LINEOUT_VERB), SND_PCI_QUIRK(0x1028, 0x084e, "Dell", ALC274_FIXUP_DELL_AIO_LINEOUT_VERB), SND_PCI_QUIRK(0x1028, 0x0871, "Dell Precision 3630", ALC255_FIXUP_DELL_HEADSET_MIC), @@ -7020,6 +7099,8 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { SND_PCI_QUIRK(0x1028, 0x08ad, "Dell WYSE AIO", ALC225_FIXUP_DELL_WYSE_AIO_MIC_NO_PRESENCE), SND_PCI_QUIRK(0x1028, 0x08ae, "Dell WYSE NB", ALC225_FIXUP_DELL1_MIC_NO_PRESENCE), SND_PCI_QUIRK(0x1028, 0x0935, "Dell", ALC274_FIXUP_DELL_AIO_LINEOUT_VERB), + SND_PCI_QUIRK(0x1028, 0x097e, "Dell Precision", ALC289_FIXUP_DUAL_SPK), + SND_PCI_QUIRK(0x1028, 0x097d, "Dell Precision", ALC289_FIXUP_DUAL_SPK), SND_PCI_QUIRK(0x1028, 0x164a, "Dell", ALC293_FIXUP_DELL1_MIC_NO_PRESENCE), SND_PCI_QUIRK(0x1028, 0x164b, "Dell", ALC293_FIXUP_DELL1_MIC_NO_PRESENCE), SND_PCI_QUIRK(0x103c, 0x1586, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC2), @@ -7107,7 +7188,8 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { SND_PCI_QUIRK(0x1043, 0x1427, "Asus Zenbook UX31E", ALC269VB_FIXUP_ASUS_ZENBOOK), 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, 0x17d1, "ASUS UX431FL", ALC294_FIXUP_ASUS_INTSPK_HEADSET_MIC), + SND_PCI_QUIRK(0x1043, 0x17d1, "ASUS UX431FL", ALC294_FIXUP_ASUS_DUAL_SPK), + SND_PCI_QUIRK(0x1043, 0x18b1, "Asus MJ401TA", ALC256_FIXUP_ASUS_HEADSET_MIC), SND_PCI_QUIRK(0x1043, 0x1a13, "Asus G73Jw", ALC269_FIXUP_ASUS_G73JW), SND_PCI_QUIRK(0x1043, 0x1a30, "ASUS X705UD", ALC256_FIXUP_ASUS_MIC), SND_PCI_QUIRK(0x1043, 0x1b13, "Asus U41SV", ALC269_FIXUP_INV_DMIC), @@ -7178,6 +7260,8 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { SND_PCI_QUIRK(0x17aa, 0x224c, "Thinkpad", ALC298_FIXUP_TPT470_DOCK), SND_PCI_QUIRK(0x17aa, 0x224d, "Thinkpad", ALC298_FIXUP_TPT470_DOCK), SND_PCI_QUIRK(0x17aa, 0x225d, "Thinkpad T480", ALC269_FIXUP_LIMIT_INT_MIC_BOOST), + SND_PCI_QUIRK(0x17aa, 0x2292, "Thinkpad X1 Yoga 7th", ALC285_FIXUP_SPEAKER2_TO_DAC1), + SND_PCI_QUIRK(0x17aa, 0x2293, "Thinkpad X1 Carbon 7th", ALC285_FIXUP_SPEAKER2_TO_DAC1), SND_PCI_QUIRK(0x17aa, 0x30bb, "ThinkCentre AIO", ALC233_FIXUP_LENOVO_LINE2_MIC_HOTKEY), SND_PCI_QUIRK(0x17aa, 0x30e2, "ThinkCentre AIO", ALC233_FIXUP_LENOVO_LINE2_MIC_HOTKEY), SND_PCI_QUIRK(0x17aa, 0x310c, "ThinkCentre Station", ALC294_FIXUP_LENOVO_MIC_LOCATION), @@ -7186,6 +7270,8 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { SND_PCI_QUIRK(0x17aa, 0x312f, "ThinkCentre Station", ALC294_FIXUP_LENOVO_MIC_LOCATION), SND_PCI_QUIRK(0x17aa, 0x313c, "ThinkCentre Station", ALC294_FIXUP_LENOVO_MIC_LOCATION), SND_PCI_QUIRK(0x17aa, 0x3151, "ThinkCentre Station", ALC283_FIXUP_HEADSET_MIC), + SND_PCI_QUIRK(0x17aa, 0x3176, "ThinkCentre Station", ALC283_FIXUP_HEADSET_MIC), + SND_PCI_QUIRK(0x17aa, 0x3178, "ThinkCentre Station", ALC283_FIXUP_HEADSET_MIC), SND_PCI_QUIRK(0x17aa, 0x3902, "Lenovo E50-80", ALC269_FIXUP_DMIC_THINKPAD_ACPI), SND_PCI_QUIRK(0x17aa, 0x3977, "IdeaPad S210", ALC283_FIXUP_INT_MIC), SND_PCI_QUIRK(0x17aa, 0x3978, "Lenovo B50-70", ALC269_FIXUP_DMIC_THINKPAD_ACPI), @@ -7211,6 +7297,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { SND_PCI_QUIRK(0x17aa, 0x9e54, "LENOVO NB", ALC269_FIXUP_LENOVO_EAPD), SND_PCI_QUIRK(0x19e5, 0x3204, "Huawei MACH-WX9", ALC256_FIXUP_HUAWEI_MACH_WX9_PINS), SND_PCI_QUIRK(0x1b7d, 0xa831, "Ordissimo EVE2 ", ALC269VB_FIXUP_ORDISSIMO_EVE2), /* Also known as Malata PC-B1303 */ + SND_PCI_QUIRK(0x1d72, 0x1901, "RedmiBook 14", ALC256_FIXUP_ASUS_HEADSET_MIC), SND_PCI_QUIRK(0x10ec, 0x118c, "Medion EE4254 MD62100", ALC256_FIXUP_MEDION_HEADSET_NO_PRESENCE), #if 0 @@ -7359,6 +7446,7 @@ static const struct hda_model_fixup alc269_fixup_models[] = { {.id = ALC255_FIXUP_DELL_SPK_NOISE, .name = "dell-spk-noise"}, {.id = ALC225_FIXUP_DELL1_MIC_NO_PRESENCE, .name = "alc225-dell1"}, {.id = ALC295_FIXUP_DISABLE_DAC3, .name = "alc295-disable-dac3"}, + {.id = ALC285_FIXUP_SPEAKER2_TO_DAC1, .name = "alc285-speaker2-to-dac1"}, {.id = ALC280_FIXUP_HP_HEADSET_MIC, .name = "alc280-hp-headset"}, {.id = ALC221_FIXUP_HP_FRONT_MIC, .name = "alc221-hp-mic"}, {.id = ALC298_FIXUP_SPK_VOLUME, .name = "alc298-spk-volume"}, @@ -7475,20 +7563,6 @@ static const struct snd_hda_pin_quirk alc269_pin_fixup_tbl[] = { {0x19, 0x02a11020}, {0x1a, 0x02a11030}, {0x21, 0x0221101f}), - SND_HDA_PIN_QUIRK(0x10ec0236, 0x1028, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE, - {0x12, 0x90a60140}, - {0x14, 0x90170110}, - {0x21, 0x02211020}), - SND_HDA_PIN_QUIRK(0x10ec0236, 0x1028, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE, - {0x12, 0x90a60140}, - {0x14, 0x90170150}, - {0x21, 0x02211020}), - SND_HDA_PIN_QUIRK(0x10ec0236, 0x1028, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE, - {0x21, 0x02211020}), - SND_HDA_PIN_QUIRK(0x10ec0236, 0x1028, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE, - {0x12, 0x40000000}, - {0x14, 0x90170110}, - {0x21, 0x02211020}), SND_HDA_PIN_QUIRK(0x10ec0255, 0x1028, "Dell", ALC255_FIXUP_DELL2_MIC_NO_PRESENCE, {0x14, 0x90170110}, {0x21, 0x02211020}), @@ -7571,38 +7645,6 @@ static const struct snd_hda_pin_quirk alc269_pin_fixup_tbl[] = { SND_HDA_PIN_QUIRK(0x10ec0255, 0x1028, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE, {0x1b, 0x01011020}, {0x21, 0x02211010}), - SND_HDA_PIN_QUIRK(0x10ec0256, 0x1028, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE, - {0x12, 0x90a60130}, - {0x14, 0x90170110}, - {0x1b, 0x01011020}, - {0x21, 0x0221101f}), - SND_HDA_PIN_QUIRK(0x10ec0256, 0x1028, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE, - {0x12, 0x90a60160}, - {0x14, 0x90170120}, - {0x21, 0x02211030}), - SND_HDA_PIN_QUIRK(0x10ec0256, 0x1028, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE, - {0x12, 0x90a60170}, - {0x14, 0x90170120}, - {0x21, 0x02211030}), - SND_HDA_PIN_QUIRK(0x10ec0256, 0x1028, "Dell Inspiron 5468", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE, - {0x12, 0x90a60180}, - {0x14, 0x90170120}, - {0x21, 0x02211030}), - SND_HDA_PIN_QUIRK(0x10ec0256, 0x1028, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE, - {0x12, 0xb7a60130}, - {0x14, 0x90170110}, - {0x21, 0x02211020}), - SND_HDA_PIN_QUIRK(0x10ec0256, 0x1028, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE, - {0x12, 0x90a60130}, - {0x14, 0x90170110}, - {0x14, 0x01011020}, - {0x21, 0x0221101f}), - SND_HDA_PIN_QUIRK(0x10ec0256, 0x1028, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE, - ALC256_STANDARD_PINS), - SND_HDA_PIN_QUIRK(0x10ec0256, 0x1028, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE, - {0x14, 0x90170110}, - {0x1b, 0x01011020}, - {0x21, 0x0221101f}), SND_HDA_PIN_QUIRK(0x10ec0256, 0x1043, "ASUS", ALC256_FIXUP_ASUS_MIC, {0x14, 0x90170110}, {0x1b, 0x90a70130}, @@ -7623,11 +7665,6 @@ static const struct snd_hda_pin_quirk alc269_pin_fixup_tbl[] = { {0x1a, 0x90a70130}, {0x1b, 0x90170110}, {0x21, 0x03211020}), - SND_HDA_PIN_QUIRK(0x10ec0274, 0x1028, "Dell", ALC274_FIXUP_DELL_AIO_LINEOUT_VERB, - {0x12, 0xb7a60130}, - {0x13, 0xb8a61140}, - {0x16, 0x90170110}, - {0x21, 0x04211020}), SND_HDA_PIN_QUIRK(0x10ec0280, 0x103c, "HP", ALC280_FIXUP_HP_GPIO4, {0x12, 0x90a60130}, {0x14, 0x90170110}, @@ -7815,6 +7852,15 @@ static const struct snd_hda_pin_quirk alc269_fallback_pin_fixup_tbl[] = { SND_HDA_PIN_QUIRK(0x10ec0289, 0x1028, "Dell", ALC269_FIXUP_DELL4_MIC_NO_PRESENCE, {0x19, 0x40000000}, {0x1b, 0x40000000}), + SND_HDA_PIN_QUIRK(0x10ec0256, 0x1028, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE, + {0x19, 0x40000000}, + {0x1a, 0x40000000}), + SND_HDA_PIN_QUIRK(0x10ec0236, 0x1028, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE, + {0x19, 0x40000000}, + {0x1a, 0x40000000}), + SND_HDA_PIN_QUIRK(0x10ec0274, 0x1028, "Dell", ALC274_FIXUP_DELL_AIO_LINEOUT_VERB, + {0x19, 0x40000000}, + {0x1a, 0x40000000}), {} }; @@ -7987,9 +8033,13 @@ static int patch_alc269(struct hda_codec *codec) spec->codec_variant = ALC269_TYPE_ALC300; spec->gen.mixer_nid = 0; /* no loopback on ALC300 */ break; + case 0x10ec0623: + spec->codec_variant = ALC269_TYPE_ALC623; + break; case 0x10ec0700: case 0x10ec0701: case 0x10ec0703: + case 0x10ec0711: 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 */ @@ -8414,6 +8464,8 @@ static void alc662_fixup_aspire_ethos_hp(struct hda_codec *codec, case HDA_FIXUP_ACT_PRE_PROBE: snd_hda_jack_detect_enable_callback(codec, 0x1b, alc662_aspire_ethos_mute_speakers); + /* subwoofer needs an extra GPIO setting to become audible */ + alc_setup_gpio(codec, 0x02); break; case HDA_FIXUP_ACT_INIT: /* Make sure to start in a correct state, i.e. if @@ -8496,7 +8548,6 @@ enum { ALC662_FIXUP_USI_HEADSET_MODE, ALC662_FIXUP_LENOVO_MULTI_CODECS, ALC669_FIXUP_ACER_ASPIRE_ETHOS, - ALC669_FIXUP_ACER_ASPIRE_ETHOS_SUBWOOFER, ALC669_FIXUP_ACER_ASPIRE_ETHOS_HEADSET, }; @@ -8828,18 +8879,6 @@ static const struct hda_fixup alc662_fixups[] = { .type = HDA_FIXUP_FUNC, .v.func = alc662_fixup_aspire_ethos_hp, }, - [ALC669_FIXUP_ACER_ASPIRE_ETHOS_SUBWOOFER] = { - .type = HDA_FIXUP_VERBS, - /* subwoofer needs an extra GPIO setting to become audible */ - .v.verbs = (const struct hda_verb[]) { - {0x01, AC_VERB_SET_GPIO_MASK, 0x02}, - {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x02}, - {0x01, AC_VERB_SET_GPIO_DATA, 0x00}, - { } - }, - .chained = true, - .chain_id = ALC669_FIXUP_ACER_ASPIRE_ETHOS_HEADSET - }, [ALC669_FIXUP_ACER_ASPIRE_ETHOS] = { .type = HDA_FIXUP_PINS, .v.pins = (const struct hda_pintbl[]) { @@ -8849,7 +8888,7 @@ static const struct hda_fixup alc662_fixups[] = { { } }, .chained = true, - .chain_id = ALC669_FIXUP_ACER_ASPIRE_ETHOS_SUBWOOFER + .chain_id = ALC669_FIXUP_ACER_ASPIRE_ETHOS_HEADSET }, }; @@ -9187,6 +9226,7 @@ static const struct hda_device_id snd_hda_id_realtek[] = { HDA_CODEC_ENTRY(0x10ec0298, "ALC298", patch_alc269), HDA_CODEC_ENTRY(0x10ec0299, "ALC299", patch_alc269), HDA_CODEC_ENTRY(0x10ec0300, "ALC300", patch_alc269), + HDA_CODEC_ENTRY(0x10ec0623, "ALC623", patch_alc269), HDA_CODEC_REV_ENTRY(0x10ec0861, 0x100340, "ALC660", patch_alc861), HDA_CODEC_ENTRY(0x10ec0660, "ALC660-VD", patch_alc861vd), HDA_CODEC_ENTRY(0x10ec0861, "ALC861", patch_alc861), @@ -9204,6 +9244,7 @@ static const struct hda_device_id snd_hda_id_realtek[] = { HDA_CODEC_ENTRY(0x10ec0700, "ALC700", patch_alc269), HDA_CODEC_ENTRY(0x10ec0701, "ALC701", patch_alc269), HDA_CODEC_ENTRY(0x10ec0703, "ALC703", patch_alc269), + HDA_CODEC_ENTRY(0x10ec0711, "ALC711", patch_alc269), HDA_CODEC_ENTRY(0x10ec0867, "ALC891", patch_alc662), HDA_CODEC_ENTRY(0x10ec0880, "ALC880", patch_alc880), HDA_CODEC_ENTRY(0x10ec0882, "ALC882", patch_alc882), @@ -9218,6 +9259,7 @@ static const struct hda_device_id snd_hda_id_realtek[] = { HDA_CODEC_ENTRY(0x10ec0892, "ALC892", patch_alc662), HDA_CODEC_ENTRY(0x10ec0899, "ALC898", patch_alc882), HDA_CODEC_ENTRY(0x10ec0900, "ALC1150", patch_alc882), + HDA_CODEC_ENTRY(0x10ec0b00, "ALCS1200A", patch_alc882), HDA_CODEC_ENTRY(0x10ec1168, "ALC1220", patch_alc882), HDA_CODEC_ENTRY(0x10ec1220, "ALC1220", patch_alc882), {} /* terminator */ |