diff options
Diffstat (limited to 'sound/pci/hda')
-rw-r--r-- | sound/pci/hda/Kconfig | 14 | ||||
-rw-r--r-- | sound/pci/hda/cs35l41_hda.c | 109 | ||||
-rw-r--r-- | sound/pci/hda/hda_codec.c | 13 | ||||
-rw-r--r-- | sound/pci/hda/hda_controller.c | 3 | ||||
-rw-r--r-- | sound/pci/hda/hda_controller.h | 1 | ||||
-rw-r--r-- | sound/pci/hda/hda_cs_dsp_ctl.c | 4 | ||||
-rw-r--r-- | sound/pci/hda/hda_intel.c | 8 | ||||
-rw-r--r-- | sound/pci/hda/hda_tegra.c | 6 | ||||
-rw-r--r-- | sound/pci/hda/patch_ca0132.c | 2 |
9 files changed, 93 insertions, 67 deletions
diff --git a/sound/pci/hda/Kconfig b/sound/pci/hda/Kconfig index 06d304db4183..886255a03e8b 100644 --- a/sound/pci/hda/Kconfig +++ b/sound/pci/hda/Kconfig @@ -302,6 +302,20 @@ config SND_HDA_INTEL_HDMI_SILENT_STREAM This feature can impact power consumption as resources are kept reserved both at transmitter and receiver. +config SND_HDA_CTL_DEV_ID + bool "Use the device identifier field for controls" + depends on SND_HDA_INTEL + help + Say Y to use the device identifier field for (mixer) + controls (old behaviour until this option is available). + + When enabled, the multiple HDA codecs may set the device + field in control (mixer) element identifiers. The use + of this field is not recommended and defined for mixer controls. + + The old behaviour (Y) is obsolete and will be removed. Consider + to not enable this option. + endif endmenu diff --git a/sound/pci/hda/cs35l41_hda.c b/sound/pci/hda/cs35l41_hda.c index f7815ee24f83..75020edd39e7 100644 --- a/sound/pci/hda/cs35l41_hda.c +++ b/sound/pci/hda/cs35l41_hda.c @@ -58,7 +58,7 @@ static const struct reg_sequence cs35l41_hda_config[] = { { CS35L41_DSP1_RX3_SRC, 0x00000018 }, // DSP1RX3 SRC = VMON { CS35L41_DSP1_RX4_SRC, 0x00000019 }, // DSP1RX4 SRC = IMON { CS35L41_DSP1_RX5_SRC, 0x00000020 }, // DSP1RX5 SRC = ERRVOL - { CS35L41_AMP_DIG_VOL_CTRL, 0x00000000 }, // AMP_VOL_PCM 0.0 dB + { CS35L41_AMP_DIG_VOL_CTRL, 0x00008000 }, // AMP_HPF_PCM_EN = 1, AMP_VOL_PCM 0.0 dB { CS35L41_AMP_GAIN_CTRL, 0x00000084 }, // AMP_GAIN_PCM 4.5 dB }; @@ -82,13 +82,13 @@ static const struct reg_sequence cs35l41_hda_config_dsp[] = { { CS35L41_DSP1_RX3_SRC, 0x00000018 }, // DSP1RX3 SRC = VMON { CS35L41_DSP1_RX4_SRC, 0x00000019 }, // DSP1RX4 SRC = IMON { CS35L41_DSP1_RX5_SRC, 0x00000029 }, // DSP1RX5 SRC = VBSTMON - { CS35L41_AMP_DIG_VOL_CTRL, 0x00000000 }, // AMP_VOL_PCM 0.0 dB + { CS35L41_AMP_DIG_VOL_CTRL, 0x00008000 }, // AMP_HPF_PCM_EN = 1, AMP_VOL_PCM 0.0 dB { CS35L41_AMP_GAIN_CTRL, 0x00000233 }, // AMP_GAIN_PCM = 17.5dB AMP_GAIN_PDM = 19.5dB }; static const struct reg_sequence cs35l41_hda_mute[] = { { CS35L41_AMP_GAIN_CTRL, 0x00000000 }, // AMP_GAIN_PCM 0.5 dB - { CS35L41_AMP_DIG_VOL_CTRL, 0x0000A678 }, // AMP_VOL_PCM Mute + { CS35L41_AMP_DIG_VOL_CTRL, 0x0000A678 }, // AMP_HPF_PCM_EN = 1, AMP_VOL_PCM Mute }; static void cs35l41_add_controls(struct cs35l41_hda *cs35l41) @@ -178,11 +178,10 @@ static int cs35l41_request_firmware_files_spkid(struct cs35l41_hda *cs35l41, cs35l41->speaker_id, "wmfw"); if (!ret) { /* try cirrus/part-dspN-fwtype-sub<-spkidN><-ampname>.bin */ - cs35l41_request_firmware_file(cs35l41, coeff_firmware, coeff_filename, - CS35L41_FIRMWARE_ROOT, - cs35l41->acpi_subsystem_id, cs35l41->amp_name, - cs35l41->speaker_id, "bin"); - return 0; + return cs35l41_request_firmware_file(cs35l41, coeff_firmware, coeff_filename, + CS35L41_FIRMWARE_ROOT, + cs35l41->acpi_subsystem_id, cs35l41->amp_name, + cs35l41->speaker_id, "bin"); } /* try cirrus/part-dspN-fwtype-sub<-ampname>.wmfw */ @@ -191,10 +190,10 @@ static int cs35l41_request_firmware_files_spkid(struct cs35l41_hda *cs35l41, cs35l41->amp_name, -1, "wmfw"); if (!ret) { /* try cirrus/part-dspN-fwtype-sub<-spkidN><-ampname>.bin */ - cs35l41_request_firmware_file(cs35l41, coeff_firmware, coeff_filename, - CS35L41_FIRMWARE_ROOT, cs35l41->acpi_subsystem_id, - cs35l41->amp_name, cs35l41->speaker_id, "bin"); - return 0; + return cs35l41_request_firmware_file(cs35l41, coeff_firmware, coeff_filename, + CS35L41_FIRMWARE_ROOT, + cs35l41->acpi_subsystem_id, cs35l41->amp_name, + cs35l41->speaker_id, "bin"); } /* try cirrus/part-dspN-fwtype-sub<-spkidN>.wmfw */ @@ -209,11 +208,10 @@ static int cs35l41_request_firmware_files_spkid(struct cs35l41_hda *cs35l41, cs35l41->amp_name, cs35l41->speaker_id, "bin"); if (ret) /* try cirrus/part-dspN-fwtype-sub<-spkidN>.bin */ - cs35l41_request_firmware_file(cs35l41, coeff_firmware, coeff_filename, - CS35L41_FIRMWARE_ROOT, - cs35l41->acpi_subsystem_id, - NULL, cs35l41->speaker_id, "bin"); - return 0; + return cs35l41_request_firmware_file(cs35l41, coeff_firmware, + coeff_filename, CS35L41_FIRMWARE_ROOT, + cs35l41->acpi_subsystem_id, NULL, + cs35l41->speaker_id, "bin"); } /* try cirrus/part-dspN-fwtype-sub.wmfw */ @@ -224,29 +222,16 @@ static int cs35l41_request_firmware_files_spkid(struct cs35l41_hda *cs35l41, /* try cirrus/part-dspN-fwtype-sub<-spkidN><-ampname>.bin */ ret = cs35l41_request_firmware_file(cs35l41, coeff_firmware, coeff_filename, CS35L41_FIRMWARE_ROOT, - cs35l41->acpi_subsystem_id, - cs35l41->amp_name, cs35l41->speaker_id, "bin"); + cs35l41->acpi_subsystem_id, cs35l41->amp_name, + cs35l41->speaker_id, "bin"); if (ret) /* try cirrus/part-dspN-fwtype-sub<-spkidN>.bin */ - cs35l41_request_firmware_file(cs35l41, coeff_firmware, coeff_filename, - CS35L41_FIRMWARE_ROOT, - cs35l41->acpi_subsystem_id, - NULL, cs35l41->speaker_id, "bin"); - return 0; - } - - /* fallback try cirrus/part-dspN-fwtype.wmfw */ - ret = cs35l41_request_firmware_file(cs35l41, wmfw_firmware, wmfw_filename, - CS35L41_FIRMWARE_ROOT, NULL, NULL, -1, "wmfw"); - if (!ret) { - /* fallback try cirrus/part-dspN-fwtype.bin */ - cs35l41_request_firmware_file(cs35l41, coeff_firmware, coeff_filename, - CS35L41_FIRMWARE_ROOT, NULL, NULL, -1, "bin"); - return 0; + return cs35l41_request_firmware_file(cs35l41, coeff_firmware, + coeff_filename, CS35L41_FIRMWARE_ROOT, + cs35l41->acpi_subsystem_id, NULL, + cs35l41->speaker_id, "bin"); } - dev_warn(cs35l41->dev, "Failed to request firmware\n"); - return ret; } @@ -258,9 +243,12 @@ static int cs35l41_request_firmware_files(struct cs35l41_hda *cs35l41, { int ret; - if (cs35l41->speaker_id > -1) - return cs35l41_request_firmware_files_spkid(cs35l41, wmfw_firmware, wmfw_filename, - coeff_firmware, coeff_filename); + if (cs35l41->speaker_id > -1) { + ret = cs35l41_request_firmware_files_spkid(cs35l41, wmfw_firmware, wmfw_filename, + coeff_firmware, coeff_filename); + goto out; + + } /* try cirrus/part-dspN-fwtype-sub<-ampname>.wmfw */ ret = cs35l41_request_firmware_file(cs35l41, wmfw_firmware, wmfw_filename, @@ -268,10 +256,11 @@ static int cs35l41_request_firmware_files(struct cs35l41_hda *cs35l41, cs35l41->amp_name, -1, "wmfw"); if (!ret) { /* try cirrus/part-dspN-fwtype-sub<-ampname>.bin */ - cs35l41_request_firmware_file(cs35l41, coeff_firmware, coeff_filename, - CS35L41_FIRMWARE_ROOT, cs35l41->acpi_subsystem_id, - cs35l41->amp_name, -1, "bin"); - return 0; + ret = cs35l41_request_firmware_file(cs35l41, coeff_firmware, coeff_filename, + CS35L41_FIRMWARE_ROOT, + cs35l41->acpi_subsystem_id, cs35l41->amp_name, + -1, "bin"); + goto out; } /* try cirrus/part-dspN-fwtype-sub.wmfw */ @@ -286,25 +275,35 @@ static int cs35l41_request_firmware_files(struct cs35l41_hda *cs35l41, cs35l41->amp_name, -1, "bin"); if (ret) /* try cirrus/part-dspN-fwtype-sub.bin */ - cs35l41_request_firmware_file(cs35l41, coeff_firmware, coeff_filename, - CS35L41_FIRMWARE_ROOT, - cs35l41->acpi_subsystem_id, - NULL, -1, "bin"); - return 0; + ret = cs35l41_request_firmware_file(cs35l41, coeff_firmware, coeff_filename, + CS35L41_FIRMWARE_ROOT, + cs35l41->acpi_subsystem_id, NULL, -1, + "bin"); } +out: + if (!ret) + return 0; + + /* Handle fallback */ + dev_warn(cs35l41->dev, "Falling back to default firmware.\n"); + + release_firmware(*wmfw_firmware); + kfree(*wmfw_filename); + /* fallback try cirrus/part-dspN-fwtype.wmfw */ ret = cs35l41_request_firmware_file(cs35l41, wmfw_firmware, wmfw_filename, CS35L41_FIRMWARE_ROOT, NULL, NULL, -1, "wmfw"); - if (!ret) { + if (!ret) /* fallback try cirrus/part-dspN-fwtype.bin */ - cs35l41_request_firmware_file(cs35l41, coeff_firmware, coeff_filename, - CS35L41_FIRMWARE_ROOT, NULL, NULL, -1, "bin"); - return 0; - } - - dev_warn(cs35l41->dev, "Failed to request firmware\n"); + ret = cs35l41_request_firmware_file(cs35l41, coeff_firmware, coeff_filename, + CS35L41_FIRMWARE_ROOT, NULL, NULL, -1, "bin"); + if (ret) { + release_firmware(*wmfw_firmware); + kfree(*wmfw_filename); + dev_warn(cs35l41->dev, "Unable to find firmware and tuning\n"); + } return ret; } diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index 2e728aad6771..9f79c0ac2bda 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c @@ -3389,7 +3389,12 @@ int snd_hda_add_new_ctls(struct hda_codec *codec, kctl = snd_ctl_new1(knew, codec); if (!kctl) return -ENOMEM; - if (addr > 0) + /* Do not use the id.device field for MIXER elements. + * This field is for real device numbers (like PCM) but codecs + * are hidden components from the user space view (unrelated + * to the mixer element identification). + */ + if (addr > 0 && codec->ctl_dev_id) kctl->id.device = addr; if (idx > 0) kctl->id.index = idx; @@ -3400,9 +3405,11 @@ int snd_hda_add_new_ctls(struct hda_codec *codec, * the codec addr; if it still fails (or it's the * primary codec), then try another control index */ - if (!addr && codec->core.addr) + if (!addr && codec->core.addr) { addr = codec->core.addr; - else if (!idx && !knew->index) { + if (!codec->ctl_dev_id) + idx += 10 * addr; + } else if (!idx && !knew->index) { idx = find_empty_mixer_ctl_idx(codec, knew->name, 0); if (idx <= 0) diff --git a/sound/pci/hda/hda_controller.c b/sound/pci/hda/hda_controller.c index 0ff286b7b66b..406779625fb5 100644 --- a/sound/pci/hda/hda_controller.c +++ b/sound/pci/hda/hda_controller.c @@ -257,7 +257,7 @@ static int azx_pcm_trigger(struct snd_pcm_substream *substream, int cmd) azx_dev = get_azx_dev(s); if (start) { azx_dev->insufficient = 1; - snd_hdac_stream_start(azx_stream(azx_dev), true); + snd_hdac_stream_start(azx_stream(azx_dev)); } else { snd_hdac_stream_stop(azx_stream(azx_dev)); } @@ -1231,6 +1231,7 @@ int azx_probe_codecs(struct azx *chip, unsigned int max_slots) continue; codec->jackpoll_interval = chip->jackpoll_interval; codec->beep_mode = chip->beep_mode; + codec->ctl_dev_id = chip->ctl_dev_id; codecs++; } } diff --git a/sound/pci/hda/hda_controller.h b/sound/pci/hda/hda_controller.h index f5bf295eb830..8556031bcd68 100644 --- a/sound/pci/hda/hda_controller.h +++ b/sound/pci/hda/hda_controller.h @@ -124,6 +124,7 @@ struct azx { /* HD codec */ int codec_probe_mask; /* copied from probe_mask option */ unsigned int beep_mode; + bool ctl_dev_id; #ifdef CONFIG_SND_HDA_PATCH_LOADER const struct firmware *fw; diff --git a/sound/pci/hda/hda_cs_dsp_ctl.c b/sound/pci/hda/hda_cs_dsp_ctl.c index 5433f6227ac9..463ca06036bf 100644 --- a/sound/pci/hda/hda_cs_dsp_ctl.c +++ b/sound/pci/hda/hda_cs_dsp_ctl.c @@ -218,10 +218,10 @@ int hda_cs_dsp_write_ctl(struct cs_dsp *dsp, const char *name, int type, cs_ctl = cs_dsp_get_ctl(dsp, name, type, alg); ret = cs_dsp_coeff_write_ctrl(cs_ctl, 0, buf, len); mutex_unlock(&dsp->pwr_lock); - if (ret) + if (ret < 0) return ret; - if (cs_ctl->flags & WMFW_CTL_FLAG_SYS) + if (ret == 0 || (cs_ctl->flags & WMFW_CTL_FLAG_SYS)) return 0; ctl = cs_ctl->priv; diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index 87002670c0c9..81c4a45254ff 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c @@ -50,6 +50,7 @@ #include <sound/intel-dsp-config.h> #include <linux/vgaarb.h> #include <linux/vga_switcheroo.h> +#include <linux/apple-gmux.h> #include <linux/firmware.h> #include <sound/hda_codec.h> #include "hda_controller.h" @@ -119,6 +120,7 @@ static bool beep_mode[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS-1)] = CONFIG_SND_HDA_INPUT_BEEP_MODE}; #endif static bool dmic_detect = 1; +static bool ctl_dev_id = IS_ENABLED(CONFIG_SND_HDA_CTL_DEV_ID) ? 1 : 0; module_param_array(index, int, NULL, 0444); MODULE_PARM_DESC(index, "Index value for Intel HD audio interface."); @@ -157,6 +159,8 @@ module_param(dmic_detect, bool, 0444); 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"); +module_param(ctl_dev_id, bool, 0444); +MODULE_PARM_DESC(ctl_dev_id, "Use control device identifier (based on codec address)."); #ifdef CONFIG_PM static int param_set_xint(const char *val, const struct kernel_param *kp); @@ -1463,7 +1467,7 @@ static struct pci_dev *get_bound_vga(struct pci_dev *pci) * vgaswitcheroo. */ if (((p->class >> 16) == PCI_BASE_CLASS_DISPLAY) && - atpx_present()) + (atpx_present() || apple_gmux_detect(NULL, NULL))) return p; pci_dev_put(p); } @@ -2278,6 +2282,8 @@ static int azx_probe_continue(struct azx *chip) chip->beep_mode = beep_mode[dev]; #endif + chip->ctl_dev_id = ctl_dev_id; + /* create codec instances */ if (bus->codec_mask) { err = azx_probe_codecs(chip, azx_max_codecs[chip->driver_type]); diff --git a/sound/pci/hda/hda_tegra.c b/sound/pci/hda/hda_tegra.c index 976a112c7d00..c2bf86781894 100644 --- a/sound/pci/hda/hda_tegra.c +++ b/sound/pci/hda/hda_tegra.c @@ -582,12 +582,10 @@ static void hda_tegra_probe_work(struct work_struct *work) static int hda_tegra_remove(struct platform_device *pdev) { - int ret; - - ret = snd_card_free(dev_get_drvdata(&pdev->dev)); + snd_card_free(dev_get_drvdata(&pdev->dev)); pm_runtime_disable(&pdev->dev); - return ret; + return 0; } static void hda_tegra_shutdown(struct platform_device *pdev) diff --git a/sound/pci/hda/patch_ca0132.c b/sound/pci/hda/patch_ca0132.c index 0a292bf271f2..acde4cd58785 100644 --- a/sound/pci/hda/patch_ca0132.c +++ b/sound/pci/hda/patch_ca0132.c @@ -2455,7 +2455,7 @@ static int dspio_set_uint_param(struct hda_codec *codec, int mod_id, static int dspio_alloc_dma_chan(struct hda_codec *codec, unsigned int *dma_chan) { int status = 0; - unsigned int size = sizeof(dma_chan); + unsigned int size = sizeof(*dma_chan); codec_dbg(codec, " dspio_alloc_dma_chan() -- begin\n"); status = dspio_scp(codec, MASTERCONTROL, 0x20, |