diff options
Diffstat (limited to 'sound/pci/hda')
-rw-r--r-- | sound/pci/hda/hda_codec.c | 251 | ||||
-rw-r--r-- | sound/pci/hda/hda_controller.c | 3 | ||||
-rw-r--r-- | sound/pci/hda/hda_controller.h | 6 | ||||
-rw-r--r-- | sound/pci/hda/hda_generic.c | 46 | ||||
-rw-r--r-- | sound/pci/hda/hda_intel.c | 112 | ||||
-rw-r--r-- | sound/pci/hda/hda_local.h | 61 | ||||
-rw-r--r-- | sound/pci/hda/hda_sysfs.c | 2 | ||||
-rw-r--r-- | sound/pci/hda/patch_hdmi.c | 104 | ||||
-rw-r--r-- | sound/pci/hda/patch_realtek.c | 281 | ||||
-rw-r--r-- | sound/pci/hda/patch_si3054.c | 4 |
10 files changed, 446 insertions, 424 deletions
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index 70bb365a08d2..821aad374a06 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c @@ -19,13 +19,11 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include <linux/mm.h> #include <linux/init.h> #include <linux/delay.h> #include <linux/slab.h> #include <linux/mutex.h> #include <linux/module.h> -#include <linux/async.h> #include <linux/pm.h> #include <linux/pm_runtime.h> #include <sound/core.h> @@ -1477,18 +1475,8 @@ int snd_hda_mixer_amp_volume_put(struct snd_kcontrol *kcontrol, } EXPORT_SYMBOL_GPL(snd_hda_mixer_amp_volume_put); -/** - * snd_hda_mixer_amp_volume_put - TLV callback for a standard AMP mixer volume - * @kcontrol: ctl element - * @op_flag: operation flag - * @size: byte size of input TLV - * @_tlv: TLV data - * - * The control element is supposed to have the private_value field - * set up via HDA_COMPOSE_AMP_VAL*() or related macros. - */ -int snd_hda_mixer_amp_tlv(struct snd_kcontrol *kcontrol, int op_flag, - unsigned int size, unsigned int __user *_tlv) +/* inquiry the amp caps and convert to TLV */ +static void get_ctl_amp_tlv(struct snd_kcontrol *kcontrol, unsigned int *tlv) { struct hda_codec *codec = snd_kcontrol_chip(kcontrol); hda_nid_t nid = get_amp_nid(kcontrol); @@ -1497,8 +1485,6 @@ int snd_hda_mixer_amp_tlv(struct snd_kcontrol *kcontrol, int op_flag, bool min_mute = get_amp_min_mute(kcontrol); u32 caps, val1, val2; - if (size < 4 * sizeof(unsigned int)) - return -ENOMEM; caps = query_amp_caps(codec, nid, dir); val2 = (caps & AC_AMPCAP_STEP_SIZE) >> AC_AMPCAP_STEP_SIZE_SHIFT; val2 = (val2 + 1) * 25; @@ -1507,13 +1493,31 @@ int snd_hda_mixer_amp_tlv(struct snd_kcontrol *kcontrol, int op_flag, val1 = ((int)val1) * ((int)val2); if (min_mute || (caps & AC_AMPCAP_MIN_MUTE)) val2 |= TLV_DB_SCALE_MUTE; - if (put_user(SNDRV_CTL_TLVT_DB_SCALE, _tlv)) - return -EFAULT; - if (put_user(2 * sizeof(unsigned int), _tlv + 1)) - return -EFAULT; - if (put_user(val1, _tlv + 2)) - return -EFAULT; - if (put_user(val2, _tlv + 3)) + tlv[0] = SNDRV_CTL_TLVT_DB_SCALE; + tlv[1] = 2 * sizeof(unsigned int); + tlv[2] = val1; + tlv[3] = val2; +} + +/** + * snd_hda_mixer_amp_tlv - TLV callback for a standard AMP mixer volume + * @kcontrol: ctl element + * @op_flag: operation flag + * @size: byte size of input TLV + * @_tlv: TLV data + * + * The control element is supposed to have the private_value field + * set up via HDA_COMPOSE_AMP_VAL*() or related macros. + */ +int snd_hda_mixer_amp_tlv(struct snd_kcontrol *kcontrol, int op_flag, + unsigned int size, unsigned int __user *_tlv) +{ + unsigned int tlv[4]; + + if (size < 4 * sizeof(unsigned int)) + return -ENOMEM; + get_ctl_amp_tlv(kcontrol, tlv); + if (copy_to_user(_tlv, tlv, sizeof(tlv))) return -EFAULT; return 0; } @@ -1807,13 +1811,10 @@ static int get_kctl_0dB_offset(struct hda_codec *codec, const int *tlv = NULL; int val = -1; - if (kctl->vd[0].access & SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK) { - /* FIXME: set_fs() hack for obtaining user-space TLV data */ - mm_segment_t fs = get_fs(); - set_fs(get_ds()); - if (!kctl->tlv.c(kctl, 0, sizeof(_tlv), _tlv)) - tlv = _tlv; - set_fs(fs); + if ((kctl->vd[0].access & SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK) && + kctl->tlv.c == snd_hda_mixer_amp_tlv) { + get_ctl_amp_tlv(kctl, _tlv); + tlv = _tlv; } else if (kctl->vd[0].access & SNDRV_CTL_ELEM_ACCESS_TLV_READ) tlv = kctl->tlv.p; if (tlv && tlv[0] == SNDRV_CTL_TLVT_DB_SCALE) { @@ -2118,196 +2119,6 @@ int snd_hda_mixer_amp_switch_put(struct snd_kcontrol *kcontrol, EXPORT_SYMBOL_GPL(snd_hda_mixer_amp_switch_put); /* - * bound volume controls - * - * bind multiple volumes (# indices, from 0) - */ - -#define AMP_VAL_IDX_SHIFT 19 -#define AMP_VAL_IDX_MASK (0x0f<<19) - -/** - * snd_hda_mixer_bind_switch_get - Get callback for a bound volume control - * @kcontrol: ctl element - * @ucontrol: pointer to get/store the data - * - * The control element is supposed to have the private_value field - * set up via HDA_BIND_MUTE*() macros. - */ -int snd_hda_mixer_bind_switch_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct hda_codec *codec = snd_kcontrol_chip(kcontrol); - unsigned long pval; - int err; - - mutex_lock(&codec->control_mutex); - pval = kcontrol->private_value; - kcontrol->private_value = pval & ~AMP_VAL_IDX_MASK; /* index 0 */ - err = snd_hda_mixer_amp_switch_get(kcontrol, ucontrol); - kcontrol->private_value = pval; - mutex_unlock(&codec->control_mutex); - return err; -} -EXPORT_SYMBOL_GPL(snd_hda_mixer_bind_switch_get); - -/** - * snd_hda_mixer_bind_switch_put - Put callback for a bound volume control - * @kcontrol: ctl element - * @ucontrol: pointer to get/store the data - * - * The control element is supposed to have the private_value field - * set up via HDA_BIND_MUTE*() macros. - */ -int snd_hda_mixer_bind_switch_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct hda_codec *codec = snd_kcontrol_chip(kcontrol); - unsigned long pval; - int i, indices, err = 0, change = 0; - - mutex_lock(&codec->control_mutex); - pval = kcontrol->private_value; - indices = (pval & AMP_VAL_IDX_MASK) >> AMP_VAL_IDX_SHIFT; - for (i = 0; i < indices; i++) { - kcontrol->private_value = (pval & ~AMP_VAL_IDX_MASK) | - (i << AMP_VAL_IDX_SHIFT); - err = snd_hda_mixer_amp_switch_put(kcontrol, ucontrol); - if (err < 0) - break; - change |= err; - } - kcontrol->private_value = pval; - mutex_unlock(&codec->control_mutex); - return err < 0 ? err : change; -} -EXPORT_SYMBOL_GPL(snd_hda_mixer_bind_switch_put); - -/** - * snd_hda_mixer_bind_ctls_info - Info callback for a generic bound control - * @kcontrol: referred ctl element - * @uinfo: pointer to get/store the data - * - * The control element is supposed to have the private_value field - * set up via HDA_BIND_VOL() or HDA_BIND_SW() macros. - */ -int snd_hda_mixer_bind_ctls_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - struct hda_codec *codec = snd_kcontrol_chip(kcontrol); - struct hda_bind_ctls *c; - int err; - - mutex_lock(&codec->control_mutex); - c = (struct hda_bind_ctls *)kcontrol->private_value; - kcontrol->private_value = *c->values; - err = c->ops->info(kcontrol, uinfo); - kcontrol->private_value = (long)c; - mutex_unlock(&codec->control_mutex); - return err; -} -EXPORT_SYMBOL_GPL(snd_hda_mixer_bind_ctls_info); - -/** - * snd_hda_mixer_bind_ctls_get - Get callback for a generic bound control - * @kcontrol: ctl element - * @ucontrol: pointer to get/store the data - * - * The control element is supposed to have the private_value field - * set up via HDA_BIND_VOL() or HDA_BIND_SW() macros. - */ -int snd_hda_mixer_bind_ctls_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct hda_codec *codec = snd_kcontrol_chip(kcontrol); - struct hda_bind_ctls *c; - int err; - - mutex_lock(&codec->control_mutex); - c = (struct hda_bind_ctls *)kcontrol->private_value; - kcontrol->private_value = *c->values; - err = c->ops->get(kcontrol, ucontrol); - kcontrol->private_value = (long)c; - mutex_unlock(&codec->control_mutex); - return err; -} -EXPORT_SYMBOL_GPL(snd_hda_mixer_bind_ctls_get); - -/** - * snd_hda_mixer_bind_ctls_put - Put callback for a generic bound control - * @kcontrol: ctl element - * @ucontrol: pointer to get/store the data - * - * The control element is supposed to have the private_value field - * set up via HDA_BIND_VOL() or HDA_BIND_SW() macros. - */ -int snd_hda_mixer_bind_ctls_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct hda_codec *codec = snd_kcontrol_chip(kcontrol); - struct hda_bind_ctls *c; - unsigned long *vals; - int err = 0, change = 0; - - mutex_lock(&codec->control_mutex); - c = (struct hda_bind_ctls *)kcontrol->private_value; - for (vals = c->values; *vals; vals++) { - kcontrol->private_value = *vals; - err = c->ops->put(kcontrol, ucontrol); - if (err < 0) - break; - change |= err; - } - kcontrol->private_value = (long)c; - mutex_unlock(&codec->control_mutex); - return err < 0 ? err : change; -} -EXPORT_SYMBOL_GPL(snd_hda_mixer_bind_ctls_put); - -/** - * snd_hda_mixer_bind_tlv - TLV callback for a generic bound control - * @kcontrol: ctl element - * @op_flag: operation flag - * @size: byte size of input TLV - * @tlv: TLV data - * - * The control element is supposed to have the private_value field - * set up via HDA_BIND_VOL() macro. - */ -int snd_hda_mixer_bind_tlv(struct snd_kcontrol *kcontrol, int op_flag, - unsigned int size, unsigned int __user *tlv) -{ - struct hda_codec *codec = snd_kcontrol_chip(kcontrol); - struct hda_bind_ctls *c; - int err; - - mutex_lock(&codec->control_mutex); - c = (struct hda_bind_ctls *)kcontrol->private_value; - kcontrol->private_value = *c->values; - err = c->ops->tlv(kcontrol, op_flag, size, tlv); - kcontrol->private_value = (long)c; - mutex_unlock(&codec->control_mutex); - return err; -} -EXPORT_SYMBOL_GPL(snd_hda_mixer_bind_tlv); - -struct hda_ctl_ops snd_hda_bind_vol = { - .info = snd_hda_mixer_amp_volume_info, - .get = snd_hda_mixer_amp_volume_get, - .put = snd_hda_mixer_amp_volume_put, - .tlv = snd_hda_mixer_amp_tlv -}; -EXPORT_SYMBOL_GPL(snd_hda_bind_vol); - -struct hda_ctl_ops snd_hda_bind_sw = { - .info = snd_hda_mixer_amp_switch_info, - .get = snd_hda_mixer_amp_switch_get, - .put = snd_hda_mixer_amp_switch_put, - .tlv = snd_hda_mixer_amp_tlv -}; -EXPORT_SYMBOL_GPL(snd_hda_bind_sw); - -/* * SPDIF out controls */ diff --git a/sound/pci/hda/hda_controller.c b/sound/pci/hda/hda_controller.c index 1c60beb5b70a..d1eb14842340 100644 --- a/sound/pci/hda/hda_controller.c +++ b/sound/pci/hda/hda_controller.c @@ -1345,6 +1345,9 @@ int azx_codec_configure(struct azx *chip) list_for_each_codec_safe(codec, next, &chip->bus) { snd_hda_codec_configure(codec); } + + if (!azx_bus(chip)->num_codecs) + return -ENODEV; return 0; } EXPORT_SYMBOL_GPL(azx_codec_configure); diff --git a/sound/pci/hda/hda_controller.h b/sound/pci/hda/hda_controller.h index 35a9ab2cac46..a68e75b00ea3 100644 --- a/sound/pci/hda/hda_controller.h +++ b/sound/pci/hda/hda_controller.h @@ -32,7 +32,11 @@ #define AZX_DCAPS_NO_MSI (1 << 9) /* No MSI support */ #define AZX_DCAPS_SNOOP_MASK (3 << 10) /* snoop type mask */ #define AZX_DCAPS_SNOOP_OFF (1 << 12) /* snoop default off */ -/* 13 unused */ +#ifdef CONFIG_SND_HDA_I915 +#define AZX_DCAPS_I915_COMPONENT (1 << 13) /* bind with i915 gfx */ +#else +#define AZX_DCAPS_I915_COMPONENT 0 /* NOP */ +#endif /* 14 unused */ #define AZX_DCAPS_CTX_WORKAROUND (1 << 15) /* X-Fi workaround */ #define AZX_DCAPS_POSFIX_LPIB (1 << 16) /* Use LPIB as default */ diff --git a/sound/pci/hda/hda_generic.c b/sound/pci/hda/hda_generic.c index 71545b56b4c8..28e265a88383 100644 --- a/sound/pci/hda/hda_generic.c +++ b/sound/pci/hda/hda_generic.c @@ -948,6 +948,8 @@ static void resume_path_from_idx(struct hda_codec *codec, int path_idx) static int hda_gen_mixer_mute_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol); +static int hda_gen_bind_mute_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol); static int hda_gen_bind_mute_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol); @@ -970,7 +972,7 @@ static const struct snd_kcontrol_new control_templates[] = { { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .info = snd_hda_mixer_amp_switch_info, - .get = snd_hda_mixer_bind_switch_get, + .get = hda_gen_bind_mute_get, .put = hda_gen_bind_mute_put, /* replaced */ .private_value = HDA_COMPOSE_AMP_VAL(0, 3, 0, 0), }, @@ -1101,11 +1103,51 @@ static int hda_gen_mixer_mute_put(struct snd_kcontrol *kcontrol, return snd_hda_mixer_amp_switch_put(kcontrol, ucontrol); } +/* + * Bound mute controls + */ +#define AMP_VAL_IDX_SHIFT 19 +#define AMP_VAL_IDX_MASK (0x0f<<19) + +static int hda_gen_bind_mute_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct hda_codec *codec = snd_kcontrol_chip(kcontrol); + unsigned long pval; + int err; + + mutex_lock(&codec->control_mutex); + pval = kcontrol->private_value; + kcontrol->private_value = pval & ~AMP_VAL_IDX_MASK; /* index 0 */ + err = snd_hda_mixer_amp_switch_get(kcontrol, ucontrol); + kcontrol->private_value = pval; + mutex_unlock(&codec->control_mutex); + return err; +} + static int hda_gen_bind_mute_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { + struct hda_codec *codec = snd_kcontrol_chip(kcontrol); + unsigned long pval; + int i, indices, err = 0, change = 0; + sync_auto_mute_bits(kcontrol, ucontrol); - return snd_hda_mixer_bind_switch_put(kcontrol, ucontrol); + + mutex_lock(&codec->control_mutex); + pval = kcontrol->private_value; + indices = (pval & AMP_VAL_IDX_MASK) >> AMP_VAL_IDX_SHIFT; + for (i = 0; i < indices; i++) { + kcontrol->private_value = (pval & ~AMP_VAL_IDX_MASK) | + (i << AMP_VAL_IDX_SHIFT); + err = snd_hda_mixer_amp_switch_put(kcontrol, ucontrol); + if (err < 0) + break; + change |= err; + } + kcontrol->private_value = pval; + mutex_unlock(&codec->control_mutex); + return err < 0 ? err : change; } /* any ctl assigned to the path with the given index? */ diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index 01eb1dc7b5b3..5ae8ddab6412 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c @@ -263,6 +263,7 @@ enum { AZX_DRIVER_ICH, AZX_DRIVER_PCH, AZX_DRIVER_SCH, + AZX_DRIVER_SKL, AZX_DRIVER_HDMI, AZX_DRIVER_ATI, AZX_DRIVER_ATIHDMI, @@ -292,38 +293,43 @@ enum { (AZX_DCAPS_NO_ALIGN_BUFSIZE | AZX_DCAPS_COUNT_LPIB_DELAY |\ AZX_DCAPS_SNOOP_TYPE(SCH)) -/* PCH up to IVB; no runtime PM */ +/* PCH up to IVB; no runtime PM; bind with i915 gfx */ #define AZX_DCAPS_INTEL_PCH_NOPM \ - (AZX_DCAPS_INTEL_PCH_BASE) + (AZX_DCAPS_INTEL_PCH_BASE | AZX_DCAPS_I915_COMPONENT) /* PCH for HSW/BDW; with runtime PM */ +/* no i915 binding for this as HSW/BDW has another controller for HDMI */ #define AZX_DCAPS_INTEL_PCH \ (AZX_DCAPS_INTEL_PCH_BASE | AZX_DCAPS_PM_RUNTIME) /* HSW HDMI */ #define AZX_DCAPS_INTEL_HASWELL \ (/*AZX_DCAPS_ALIGN_BUFSIZE |*/ AZX_DCAPS_COUNT_LPIB_DELAY |\ - AZX_DCAPS_PM_RUNTIME | AZX_DCAPS_I915_POWERWELL |\ - AZX_DCAPS_SNOOP_TYPE(SCH)) + AZX_DCAPS_PM_RUNTIME | AZX_DCAPS_I915_COMPONENT |\ + AZX_DCAPS_I915_POWERWELL | AZX_DCAPS_SNOOP_TYPE(SCH)) /* Broadwell HDMI can't use position buffer reliably, force to use LPIB */ #define AZX_DCAPS_INTEL_BROADWELL \ (/*AZX_DCAPS_ALIGN_BUFSIZE |*/ AZX_DCAPS_POSFIX_LPIB |\ - AZX_DCAPS_PM_RUNTIME | AZX_DCAPS_I915_POWERWELL |\ - AZX_DCAPS_SNOOP_TYPE(SCH)) + AZX_DCAPS_PM_RUNTIME | AZX_DCAPS_I915_COMPONENT |\ + AZX_DCAPS_I915_POWERWELL | AZX_DCAPS_SNOOP_TYPE(SCH)) #define AZX_DCAPS_INTEL_BAYTRAIL \ - (AZX_DCAPS_INTEL_PCH_NOPM | AZX_DCAPS_I915_POWERWELL) + (AZX_DCAPS_INTEL_PCH_BASE | AZX_DCAPS_I915_COMPONENT |\ + AZX_DCAPS_I915_POWERWELL) #define AZX_DCAPS_INTEL_BRASWELL \ - (AZX_DCAPS_INTEL_PCH | AZX_DCAPS_I915_POWERWELL) + (AZX_DCAPS_INTEL_PCH_BASE | AZX_DCAPS_PM_RUNTIME |\ + AZX_DCAPS_I915_COMPONENT | AZX_DCAPS_I915_POWERWELL) #define AZX_DCAPS_INTEL_SKYLAKE \ - (AZX_DCAPS_INTEL_PCH | AZX_DCAPS_SEPARATE_STREAM_TAG |\ + (AZX_DCAPS_INTEL_PCH_BASE | AZX_DCAPS_PM_RUNTIME |\ + AZX_DCAPS_SEPARATE_STREAM_TAG | AZX_DCAPS_I915_COMPONENT |\ AZX_DCAPS_I915_POWERWELL) #define AZX_DCAPS_INTEL_BROXTON \ - (AZX_DCAPS_INTEL_PCH | AZX_DCAPS_SEPARATE_STREAM_TAG |\ + (AZX_DCAPS_INTEL_PCH_BASE | AZX_DCAPS_PM_RUNTIME |\ + AZX_DCAPS_SEPARATE_STREAM_TAG | AZX_DCAPS_I915_COMPONENT |\ AZX_DCAPS_I915_POWERWELL) /* quirks for ATI SB / AMD Hudson */ @@ -364,23 +370,13 @@ enum { ((pci)->device == 0x0d0c) || \ ((pci)->device == 0x160c)) -#define IS_SKL(pci) ((pci)->vendor == 0x8086 && (pci)->device == 0xa170) -#define IS_SKL_LP(pci) ((pci)->vendor == 0x8086 && (pci)->device == 0x9d70) -#define IS_KBL(pci) ((pci)->vendor == 0x8086 && (pci)->device == 0xa171) -#define IS_KBL_LP(pci) ((pci)->vendor == 0x8086 && (pci)->device == 0x9d71) -#define IS_KBL_H(pci) ((pci)->vendor == 0x8086 && (pci)->device == 0xa2f0) #define IS_BXT(pci) ((pci)->vendor == 0x8086 && (pci)->device == 0x5a98) -#define IS_BXT_T(pci) ((pci)->vendor == 0x8086 && (pci)->device == 0x1a98) -#define IS_GLK(pci) ((pci)->vendor == 0x8086 && (pci)->device == 0x3198) -#define IS_CFL(pci) ((pci)->vendor == 0x8086 && (pci)->device == 0xa348) -#define IS_SKL_PLUS(pci) (IS_SKL(pci) || IS_SKL_LP(pci) || IS_BXT(pci) || \ - IS_BXT_T(pci) || IS_KBL(pci) || IS_KBL_LP(pci) || \ - IS_KBL_H(pci) || IS_GLK(pci) || IS_CFL(pci)) static char *driver_short_names[] = { [AZX_DRIVER_ICH] = "HDA Intel", [AZX_DRIVER_PCH] = "HDA Intel PCH", [AZX_DRIVER_SCH] = "HDA Intel MID", + [AZX_DRIVER_SKL] = "HDA Intel PCH", /* kept old name for compatibility */ [AZX_DRIVER_HDMI] = "HDA Intel HDMI", [AZX_DRIVER_ATI] = "HDA ATI SB", [AZX_DRIVER_ATIHDMI] = "HDA ATI HDMI", @@ -644,13 +640,13 @@ static void hda_intel_init_chip(struct azx *chip, bool full_reset) if (chip->driver_caps & AZX_DCAPS_I915_POWERWELL) snd_hdac_set_codec_wakeup(bus, true); - if (IS_SKL_PLUS(pci)) { + if (chip->driver_type == AZX_DRIVER_SKL) { pci_read_config_dword(pci, INTEL_HDA_CGCTL, &val); val = val & ~INTEL_HDA_CGCTL_MISCBDCGE; pci_write_config_dword(pci, INTEL_HDA_CGCTL, val); } azx_init_chip(chip, full_reset); - if (IS_SKL_PLUS(pci)) { + if (chip->driver_type == AZX_DRIVER_SKL) { pci_read_config_dword(pci, INTEL_HDA_CGCTL, &val); val = val | INTEL_HDA_CGCTL_MISCBDCGE; pci_write_config_dword(pci, INTEL_HDA_CGCTL, val); @@ -1017,7 +1013,7 @@ static int azx_suspend(struct device *dev) if (chip->msi) pci_disable_msi(chip->pci); - if (chip->driver_caps & AZX_DCAPS_I915_POWERWELL + if ((chip->driver_caps & AZX_DCAPS_I915_POWERWELL) && hda->need_i915_power) snd_hdac_display_power(bus, false); @@ -1075,9 +1071,11 @@ static int azx_resume(struct device *dev) */ static int azx_freeze_noirq(struct device *dev) { + struct snd_card *card = dev_get_drvdata(dev); + struct azx *chip = card->private_data; struct pci_dev *pci = to_pci_dev(dev); - if (IS_SKL_PLUS(pci)) + if (chip->driver_type == AZX_DRIVER_SKL) pci_set_power_state(pci, PCI_D3hot); return 0; @@ -1085,9 +1083,11 @@ static int azx_freeze_noirq(struct device *dev) static int azx_thaw_noirq(struct device *dev) { + struct snd_card *card = dev_get_drvdata(dev); + struct azx *chip = card->private_data; struct pci_dev *pci = to_pci_dev(dev); - if (IS_SKL_PLUS(pci)) + if (chip->driver_type == AZX_DRIVER_SKL) pci_set_power_state(pci, PCI_D0); return 0; @@ -1119,7 +1119,7 @@ static int azx_runtime_suspend(struct device *dev) azx_stop_chip(chip); azx_enter_link_reset(chip); azx_clear_irq_pending(chip); - if (chip->driver_caps & AZX_DCAPS_I915_POWERWELL + if ((chip->driver_caps & AZX_DCAPS_I915_POWERWELL) && hda->need_i915_power) snd_hdac_display_power(azx_bus(chip), false); @@ -1384,8 +1384,9 @@ static int azx_free(struct azx *chip) if (chip->driver_caps & AZX_DCAPS_I915_POWERWELL) { if (hda->need_i915_power) snd_hdac_display_power(bus, false); - snd_hdac_i915_exit(bus); } + if (chip->driver_caps & AZX_DCAPS_I915_COMPONENT) + snd_hdac_i915_exit(bus); kfree(hda); return 0; @@ -1497,7 +1498,7 @@ static int check_position_fix(struct azx *chip, int fix) dev_dbg(chip->card->dev, "Using LPIB position fix\n"); return POS_FIX_LPIB; } - if (IS_SKL_PLUS(chip->pci)) { + if (chip->driver_type == AZX_DRIVER_SKL) { dev_dbg(chip->card->dev, "Using SKL position fix\n"); return POS_FIX_SKL; } @@ -1798,7 +1799,7 @@ static int azx_first_init(struct azx *chip) return -ENXIO; } - if (IS_SKL_PLUS(pci)) + if (chip->driver_type == AZX_DRIVER_SKL) snd_hdac_bus_parse_capabilities(bus); /* @@ -2201,16 +2202,8 @@ static int azx_probe_continue(struct azx *chip) hda->probe_continued = 1; - /* Request display power well for the HDA controller or codec. For - * Haswell/Broadwell, both the display HDA controller and codec need - * this power. For other platforms, like Baytrail/Braswell, only the - * display codec needs the power and it can be released after probe. - */ - if (chip->driver_caps & AZX_DCAPS_I915_POWERWELL) { - /* HSW/BDW controllers need this power */ - if (CONTROLLER_IN_GPU(pci)) - hda->need_i915_power = 1; - + /* bind with i915 if needed */ + if (chip->driver_caps & AZX_DCAPS_I915_COMPONENT) { err = snd_hdac_i915_init(bus); if (err < 0) { /* if the controller is bound only with HDMI/DP @@ -2222,9 +2215,23 @@ static int azx_probe_continue(struct azx *chip) dev_err(chip->card->dev, "HSW/BDW HD-audio HDMI/DP requires binding with gfx driver\n"); goto out_free; - } else - goto skip_i915; + } else { + /* don't bother any longer */ + chip->driver_caps &= + ~(AZX_DCAPS_I915_COMPONENT | AZX_DCAPS_I915_POWERWELL); + } } + } + + /* Request display power well for the HDA controller or codec. For + * Haswell/Broadwell, both the display HDA controller and codec need + * this power. For other platforms, like Baytrail/Braswell, only the + * display codec needs the power and it can be released after probe. + */ + if (chip->driver_caps & AZX_DCAPS_I915_POWERWELL) { + /* HSW/BDW controllers need this power */ + if (CONTROLLER_IN_GPU(pci)) + hda->need_i915_power = 1; err = snd_hdac_display_power(bus, true); if (err < 0) { @@ -2234,7 +2241,6 @@ static int azx_probe_continue(struct azx *chip) } } - skip_i915: err = azx_first_init(chip); if (err < 0) goto out_free; @@ -2277,7 +2283,7 @@ static int azx_probe_continue(struct azx *chip) pm_runtime_put_autosuspend(&pci->dev); out_free: - if (chip->driver_caps & AZX_DCAPS_I915_POWERWELL + if ((chip->driver_caps & AZX_DCAPS_I915_POWERWELL) && !hda->need_i915_power) snd_hdac_display_power(bus, false); @@ -2367,31 +2373,31 @@ static const struct pci_device_id azx_ids[] = { .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH }, /* Sunrise Point */ { PCI_DEVICE(0x8086, 0xa170), - .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_SKYLAKE }, + .driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE }, /* Sunrise Point-LP */ { PCI_DEVICE(0x8086, 0x9d70), - .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_SKYLAKE }, + .driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE }, /* Kabylake */ { PCI_DEVICE(0x8086, 0xa171), - .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_SKYLAKE }, + .driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE }, /* Kabylake-LP */ { PCI_DEVICE(0x8086, 0x9d71), - .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_SKYLAKE }, + .driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE }, /* Kabylake-H */ { PCI_DEVICE(0x8086, 0xa2f0), - .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_SKYLAKE }, + .driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE }, /* Coffelake */ { PCI_DEVICE(0x8086, 0xa348), - .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_SKYLAKE}, + .driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE}, /* Broxton-P(Apollolake) */ { PCI_DEVICE(0x8086, 0x5a98), - .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_BROXTON }, + .driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_BROXTON }, /* Broxton-T */ { PCI_DEVICE(0x8086, 0x1a98), - .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_BROXTON }, + .driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_BROXTON }, /* Gemini-Lake */ { PCI_DEVICE(0x8086, 0x3198), - .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_BROXTON }, + .driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_BROXTON }, /* Haswell */ { PCI_DEVICE(0x8086, 0x0a0c), .driver_data = AZX_DRIVER_HDMI | AZX_DCAPS_INTEL_HASWELL }, diff --git a/sound/pci/hda/hda_local.h b/sound/pci/hda/hda_local.h index d0e066e4c985..5b5c324c99b9 100644 --- a/sound/pci/hda/hda_local.h +++ b/sound/pci/hda/hda_local.h @@ -178,67 +178,6 @@ void snd_hda_sync_vmaster_hook(struct hda_vmaster_mute_hook *hook); #define HDA_AMP_UNMUTE 0x00 #define HDA_AMP_VOLMASK 0x7f -/* mono switch binding multiple inputs */ -#define HDA_BIND_MUTE_MONO(xname, nid, channel, indices, direction) \ - { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = 0, \ - .info = snd_hda_mixer_amp_switch_info, \ - .get = snd_hda_mixer_bind_switch_get, \ - .put = snd_hda_mixer_bind_switch_put, \ - .private_value = HDA_COMPOSE_AMP_VAL(nid, channel, indices, direction) } - -/* stereo switch binding multiple inputs */ -#define HDA_BIND_MUTE(xname,nid,indices,dir) \ - HDA_BIND_MUTE_MONO(xname,nid,3,indices,dir) - -int snd_hda_mixer_bind_switch_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol); -int snd_hda_mixer_bind_switch_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol); - -/* more generic bound controls */ -struct hda_ctl_ops { - snd_kcontrol_info_t *info; - snd_kcontrol_get_t *get; - snd_kcontrol_put_t *put; - snd_kcontrol_tlv_rw_t *tlv; -}; - -extern struct hda_ctl_ops snd_hda_bind_vol; /* for bind-volume with TLV */ -extern struct hda_ctl_ops snd_hda_bind_sw; /* for bind-switch */ - -struct hda_bind_ctls { - struct hda_ctl_ops *ops; - unsigned long values[]; -}; - -int snd_hda_mixer_bind_ctls_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo); -int snd_hda_mixer_bind_ctls_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol); -int snd_hda_mixer_bind_ctls_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol); -int snd_hda_mixer_bind_tlv(struct snd_kcontrol *kcontrol, int op_flag, - unsigned int size, unsigned int __user *tlv); - -#define HDA_BIND_VOL(xname, bindrec) \ - { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ - .name = xname, \ - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |\ - SNDRV_CTL_ELEM_ACCESS_TLV_READ |\ - SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK,\ - .info = snd_hda_mixer_bind_ctls_info,\ - .get = snd_hda_mixer_bind_ctls_get,\ - .put = snd_hda_mixer_bind_ctls_put,\ - .tlv = { .c = snd_hda_mixer_bind_tlv },\ - .private_value = (long) (bindrec) } -#define HDA_BIND_SW(xname, bindrec) \ - { .iface = SNDRV_CTL_ELEM_IFACE_MIXER,\ - .name = xname, \ - .info = snd_hda_mixer_bind_ctls_info,\ - .get = snd_hda_mixer_bind_ctls_get,\ - .put = snd_hda_mixer_bind_ctls_put,\ - .private_value = (long) (bindrec) } - /* * SPDIF I/O */ diff --git a/sound/pci/hda/hda_sysfs.c b/sound/pci/hda/hda_sysfs.c index 9739fce9e032..9b7efece4484 100644 --- a/sound/pci/hda/hda_sysfs.c +++ b/sound/pci/hda/hda_sysfs.c @@ -761,7 +761,7 @@ static struct attribute *hda_dev_attrs[] = { NULL }; -static struct attribute_group hda_dev_attr_group = { +static const struct attribute_group hda_dev_attr_group = { .attrs = hda_dev_attrs, }; diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c index 90e4ff87445e..76c85f08bea6 100644 --- a/sound/pci/hda/patch_hdmi.c +++ b/sound/pci/hda/patch_hdmi.c @@ -174,7 +174,6 @@ struct hdmi_spec { /* i915/powerwell (Haswell+/Valleyview+) specific */ bool use_acomp_notifier; /* use i915 eld_notify callback for hotplug */ struct i915_audio_component_audio_ops i915_audio_ops; - bool i915_bound; /* was i915 bound in this driver? */ struct hdac_chmap chmap; hda_nid_t vendor_nid; @@ -2234,8 +2233,6 @@ static void generic_spec_free(struct hda_codec *codec) struct hdmi_spec *spec = codec->spec; if (spec) { - if (spec->i915_bound) - snd_hdac_i915_exit(&codec->bus->core); hdmi_array_free(spec); kfree(spec); codec->spec = NULL; @@ -2506,19 +2503,41 @@ static void i915_pin_cvt_fixup(struct hda_codec *codec, } } -/* Intel Haswell and onwards; audio component with eld notifier */ -static int intel_hsw_common_init(struct hda_codec *codec, hda_nid_t vendor_nid) +/* precondition and allocation for Intel codecs */ +static int alloc_intel_hdmi(struct hda_codec *codec) { - struct hdmi_spec *spec; - int err; - - /* HSW+ requires i915 binding */ + /* requires i915 binding */ if (!codec->bus->core.audio_component) { codec_info(codec, "No i915 binding for Intel HDMI/DP codec\n"); return -ENODEV; } - err = alloc_generic_hdmi(codec); + return alloc_generic_hdmi(codec); +} + +/* parse and post-process for Intel codecs */ +static int parse_intel_hdmi(struct hda_codec *codec) +{ + int err; + + err = hdmi_parse_codec(codec); + if (err < 0) { + generic_spec_free(codec); + return err; + } + + generic_hdmi_init_per_pins(codec); + register_i915_notifier(codec); + return 0; +} + +/* Intel Haswell and onwards; audio component with eld notifier */ +static int intel_hsw_common_init(struct hda_codec *codec, hda_nid_t vendor_nid) +{ + struct hdmi_spec *spec; + int err; + + err = alloc_intel_hdmi(codec); if (err < 0) return err; spec = codec->spec; @@ -2542,15 +2561,7 @@ static int intel_hsw_common_init(struct hda_codec *codec, hda_nid_t vendor_nid) spec->ops.setup_stream = i915_hsw_setup_stream; spec->ops.pin_cvt_fixup = i915_pin_cvt_fixup; - err = hdmi_parse_codec(codec); - if (err < 0) { - generic_spec_free(codec); - return err; - } - - generic_hdmi_init_per_pins(codec); - register_i915_notifier(codec); - return 0; + return parse_intel_hdmi(codec); } static int patch_i915_hsw_hdmi(struct hda_codec *codec) @@ -2569,13 +2580,7 @@ static int patch_i915_byt_hdmi(struct hda_codec *codec) struct hdmi_spec *spec; int err; - /* requires i915 binding */ - if (!codec->bus->core.audio_component) { - codec_info(codec, "No i915 binding for Intel HDMI/DP codec\n"); - return -ENODEV; - } - - err = alloc_generic_hdmi(codec); + err = alloc_intel_hdmi(codec); if (err < 0) return err; spec = codec->spec; @@ -2590,49 +2595,18 @@ static int patch_i915_byt_hdmi(struct hda_codec *codec) spec->ops.pin_cvt_fixup = i915_pin_cvt_fixup; - err = hdmi_parse_codec(codec); - if (err < 0) { - generic_spec_free(codec); - return err; - } - - generic_hdmi_init_per_pins(codec); - register_i915_notifier(codec); - return 0; + return parse_intel_hdmi(codec); } /* Intel IronLake, SandyBridge and IvyBridge; with eld notifier */ static int patch_i915_cpt_hdmi(struct hda_codec *codec) { - struct hdmi_spec *spec; int err; - /* no i915 component should have been bound before this */ - if (WARN_ON(codec->bus->core.audio_component)) - return -EBUSY; - - err = alloc_generic_hdmi(codec); + err = alloc_intel_hdmi(codec); if (err < 0) return err; - spec = codec->spec; - - /* Try to bind with i915 now */ - err = snd_hdac_i915_init(&codec->bus->core); - if (err < 0) - goto error; - spec->i915_bound = true; - - err = hdmi_parse_codec(codec); - if (err < 0) - goto error; - - generic_hdmi_init_per_pins(codec); - register_i915_notifier(codec); - return 0; - - error: - generic_spec_free(codec); - return err; + return parse_intel_hdmi(codec); } /* @@ -2782,21 +2756,21 @@ static int nvhdmi_7x_init_8ch(struct hda_codec *codec) return 0; } -static unsigned int channels_2_6_8[] = { +static const unsigned int channels_2_6_8[] = { 2, 6, 8 }; -static unsigned int channels_2_8[] = { +static const unsigned int channels_2_8[] = { 2, 8 }; -static struct snd_pcm_hw_constraint_list hw_constraints_2_6_8_channels = { +static const struct snd_pcm_hw_constraint_list hw_constraints_2_6_8_channels = { .count = ARRAY_SIZE(channels_2_6_8), .list = channels_2_6_8, .mask = 0, }; -static struct snd_pcm_hw_constraint_list hw_constraints_2_8_channels = { +static const struct snd_pcm_hw_constraint_list hw_constraints_2_8_channels = { .count = ARRAY_SIZE(channels_2_8), .list = channels_2_8, .mask = 0, @@ -2807,7 +2781,7 @@ static int simple_playback_pcm_open(struct hda_pcm_stream *hinfo, struct snd_pcm_substream *substream) { struct hdmi_spec *spec = codec->spec; - struct snd_pcm_hw_constraint_list *hw_constraints_channels = NULL; + const struct snd_pcm_hw_constraint_list *hw_constraints_channels = NULL; switch (codec->preset->vendor_id) { case 0x10de0002: diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index cbeebc0a9711..cd6987b5c6d9 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -41,9 +41,6 @@ /* keep halting ALC5505 DSP, for power saving */ #define HALT_REALTEK_ALC5505 -/* for GPIO Poll */ -#define GPIO_MASK 0x03 - /* extra amp-initialization sequence types */ enum { ALC_INIT_NONE, @@ -327,6 +324,7 @@ static void alc_fill_eapd_coef(struct hda_codec *codec) case 0x10ec0292: alc_update_coef_idx(codec, 0x4, 1<<15, 0); break; + case 0x10ec0215: case 0x10ec0225: case 0x10ec0233: case 0x10ec0255: @@ -335,12 +333,13 @@ static void alc_fill_eapd_coef(struct hda_codec *codec) case 0x10ec0283: case 0x10ec0286: case 0x10ec0288: + case 0x10ec0285: case 0x10ec0295: case 0x10ec0298: + case 0x10ec0289: case 0x10ec0299: alc_update_coef_idx(codec, 0x10, 1<<9, 0); break; - case 0x10ec0285: case 0x10ec0293: alc_update_coef_idx(codec, 0xa, 1<<13, 0); break; @@ -2575,18 +2574,37 @@ static int patch_alc262(struct hda_codec *codec) * ALC268 */ /* bind Beep switches of both NID 0x0f and 0x10 */ -static const struct hda_bind_ctls alc268_bind_beep_sw = { - .ops = &snd_hda_bind_sw, - .values = { - HDA_COMPOSE_AMP_VAL(0x0f, 3, 1, HDA_INPUT), - HDA_COMPOSE_AMP_VAL(0x10, 3, 1, HDA_INPUT), - 0 - }, -}; +static int alc268_beep_switch_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct hda_codec *codec = snd_kcontrol_chip(kcontrol); + unsigned long pval; + int err; + + mutex_lock(&codec->control_mutex); + pval = kcontrol->private_value; + kcontrol->private_value = (pval & ~0xff) | 0x0f; + err = snd_hda_mixer_amp_switch_put(kcontrol, ucontrol); + if (err >= 0) { + kcontrol->private_value = (pval & ~0xff) | 0x10; + err = snd_hda_mixer_amp_switch_put(kcontrol, ucontrol); + } + kcontrol->private_value = pval; + mutex_unlock(&codec->control_mutex); + return err; +} static const struct snd_kcontrol_new alc268_beep_mixer[] = { HDA_CODEC_VOLUME("Beep Playback Volume", 0x1d, 0x0, HDA_INPUT), - HDA_BIND_SW("Beep Playback Switch", &alc268_bind_beep_sw), + { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = "Beep Playback Switch", + .subdevice = HDA_SUBDEV_AMP_FLAG, + .info = snd_hda_mixer_amp_switch_info, + .get = snd_hda_mixer_amp_switch_get, + .put = alc268_beep_switch_put, + .private_value = HDA_COMPOSE_AMP_VAL(0x0f, 3, 1, HDA_INPUT) + }, { } }; @@ -2719,11 +2737,12 @@ enum { ALC269_TYPE_ALC282, ALC269_TYPE_ALC283, ALC269_TYPE_ALC284, - ALC269_TYPE_ALC285, + ALC269_TYPE_ALC293, ALC269_TYPE_ALC286, ALC269_TYPE_ALC298, ALC269_TYPE_ALC255, ALC269_TYPE_ALC256, + ALC269_TYPE_ALC215, ALC269_TYPE_ALC225, ALC269_TYPE_ALC294, ALC269_TYPE_ALC700, @@ -2745,7 +2764,7 @@ static int alc269_parse_auto_config(struct hda_codec *codec) case ALC269_TYPE_ALC269VC: case ALC269_TYPE_ALC280: case ALC269_TYPE_ALC284: - case ALC269_TYPE_ALC285: + case ALC269_TYPE_ALC293: ssids = alc269va_ssids; break; case ALC269_TYPE_ALC269VB: @@ -2756,6 +2775,7 @@ static int alc269_parse_auto_config(struct hda_codec *codec) case ALC269_TYPE_ALC298: case ALC269_TYPE_ALC255: case ALC269_TYPE_ALC256: + case ALC269_TYPE_ALC215: case ALC269_TYPE_ALC225: case ALC269_TYPE_ALC294: case ALC269_TYPE_ALC700: @@ -3043,6 +3063,135 @@ static void alc283_shutup(struct hda_codec *codec) alc_write_coef_idx(codec, 0x43, 0x9614); } +static void alc256_init(struct hda_codec *codec) +{ + struct alc_spec *spec = codec->spec; + hda_nid_t hp_pin = spec->gen.autocfg.hp_pins[0]; + bool hp_pin_sense; + + if (!hp_pin) + return; + + msleep(30); + + hp_pin_sense = snd_hda_jack_detect(codec, hp_pin); + + if (hp_pin_sense) + msleep(2); + + alc_update_coefex_idx(codec, 0x57, 0x04, 0x0007, 0x1); /* Low power */ + + snd_hda_codec_write(codec, hp_pin, 0, + AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE); + + if (hp_pin_sense) + msleep(85); + + snd_hda_codec_write(codec, hp_pin, 0, + AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT); + + if (hp_pin_sense) + msleep(100); + + alc_update_coef_idx(codec, 0x46, 3 << 12, 0); + alc_update_coefex_idx(codec, 0x57, 0x04, 0x0007, 0x4); /* Hight power */ +} + +static void alc256_shutup(struct hda_codec *codec) +{ + struct alc_spec *spec = codec->spec; + hda_nid_t hp_pin = spec->gen.autocfg.hp_pins[0]; + bool hp_pin_sense; + + if (!hp_pin) { + alc269_shutup(codec); + return; + } + + hp_pin_sense = snd_hda_jack_detect(codec, hp_pin); + + if (hp_pin_sense) + msleep(2); + + snd_hda_codec_write(codec, hp_pin, 0, + AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE); + + if (hp_pin_sense) + msleep(85); + + snd_hda_codec_write(codec, hp_pin, 0, + AC_VERB_SET_PIN_WIDGET_CONTROL, 0x0); + + alc_update_coef_idx(codec, 0x46, 0, 3 << 12); /* 3k pull low control for Headset jack. */ + + if (hp_pin_sense) + msleep(100); + + alc_auto_setup_eapd(codec, false); + snd_hda_shutup_pins(codec); +} + +static void alc_default_init(struct hda_codec *codec) +{ + struct alc_spec *spec = codec->spec; + hda_nid_t hp_pin = spec->gen.autocfg.hp_pins[0]; + bool hp_pin_sense; + + if (!hp_pin) + return; + + msleep(30); + + hp_pin_sense = snd_hda_jack_detect(codec, hp_pin); + + if (hp_pin_sense) + msleep(2); + + snd_hda_codec_write(codec, hp_pin, 0, + AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE); + + if (hp_pin_sense) + msleep(85); + + snd_hda_codec_write(codec, hp_pin, 0, + AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT); + + if (hp_pin_sense) + msleep(100); +} + +static void alc_default_shutup(struct hda_codec *codec) +{ + struct alc_spec *spec = codec->spec; + hda_nid_t hp_pin = spec->gen.autocfg.hp_pins[0]; + bool hp_pin_sense; + + if (!hp_pin) { + alc269_shutup(codec); + return; + } + + hp_pin_sense = snd_hda_jack_detect(codec, hp_pin); + + if (hp_pin_sense) + msleep(2); + + snd_hda_codec_write(codec, hp_pin, 0, + AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE); + + if (hp_pin_sense) + msleep(85); + + snd_hda_codec_write(codec, hp_pin, 0, + AC_VERB_SET_PIN_WIDGET_CONTROL, 0x0); + + if (hp_pin_sense) + msleep(100); + + alc_auto_setup_eapd(codec, false); + snd_hda_shutup_pins(codec); +} + static void alc5505_coef_set(struct hda_codec *codec, unsigned int index_reg, unsigned int val) { @@ -3754,6 +3903,16 @@ static void alc_headset_mode_unplugged(struct hda_codec *codec) UPDATE_COEF(0x4a, 3<<10, 0), {} }; + static struct coef_fw coef0274[] = { + UPDATE_COEF(0x4a, 0x0100, 0), + UPDATE_COEFEX(0x57, 0x05, 0x4000, 0), + UPDATE_COEF(0x6b, 0xf000, 0x5000), + UPDATE_COEF(0x4a, 0x0010, 0), + UPDATE_COEF(0x4a, 0x0c00, 0x0c00), + WRITE_COEF(0x45, 0x5289), + UPDATE_COEF(0x4a, 0x0c00, 0), + {} + }; switch (codec->core.vendor_id) { case 0x10ec0255: @@ -3764,6 +3923,11 @@ static void alc_headset_mode_unplugged(struct hda_codec *codec) alc_process_coef_fw(codec, coef0256); alc_process_coef_fw(codec, coef0255); break; + case 0x10ec0234: + case 0x10ec0274: + case 0x10ec0294: + alc_process_coef_fw(codec, coef0274); + break; case 0x10ec0233: case 0x10ec0283: alc_process_coef_fw(codec, coef0233); @@ -3841,7 +4005,12 @@ static void alc_headset_mode_mic_in(struct hda_codec *codec, hda_nid_t hp_pin, UPDATE_COEF(0x63, 3<<14, 0), {} }; - + static struct coef_fw coef0274[] = { + UPDATE_COEFEX(0x57, 0x05, 0x4000, 0x4000), + UPDATE_COEF(0x4a, 0x0010, 0), + UPDATE_COEF(0x6b, 0xf000, 0), + {} + }; switch (codec->core.vendor_id) { case 0x10ec0255: @@ -3851,6 +4020,14 @@ static void alc_headset_mode_mic_in(struct hda_codec *codec, hda_nid_t hp_pin, alc_process_coef_fw(codec, coef0255); snd_hda_set_pin_ctl_cache(codec, mic_pin, PIN_VREF50); break; + case 0x10ec0234: + case 0x10ec0274: + case 0x10ec0294: + alc_write_coef_idx(codec, 0x45, 0x4689); + snd_hda_set_pin_ctl_cache(codec, hp_pin, 0); + alc_process_coef_fw(codec, coef0274); + snd_hda_set_pin_ctl_cache(codec, mic_pin, PIN_VREF50); + break; case 0x10ec0233: case 0x10ec0283: alc_write_coef_idx(codec, 0x45, 0xc429); @@ -3948,6 +4125,13 @@ static void alc_headset_mode_default(struct hda_codec *codec) WRITE_COEF(0xb7, 0x802b), {} }; + static struct coef_fw coef0274[] = { + WRITE_COEF(0x45, 0x4289), + UPDATE_COEF(0x4a, 0x0010, 0x0010), + UPDATE_COEF(0x6b, 0x0f00, 0), + UPDATE_COEF(0x49, 0x0300, 0x0300), + {} + }; switch (codec->core.vendor_id) { case 0x10ec0225: @@ -3959,6 +4143,11 @@ static void alc_headset_mode_default(struct hda_codec *codec) case 0x10ec0256: alc_process_coef_fw(codec, coef0255); break; + case 0x10ec0234: + case 0x10ec0274: + case 0x10ec0294: + alc_process_coef_fw(codec, coef0274); + break; case 0x10ec0233: case 0x10ec0283: alc_process_coef_fw(codec, coef0233); @@ -4044,6 +4233,11 @@ static void alc_headset_mode_ctia(struct hda_codec *codec) case 0x10ec0256: alc_process_coef_fw(codec, coef0256); break; + case 0x10ec0234: + case 0x10ec0274: + case 0x10ec0294: + alc_write_coef_idx(codec, 0x45, 0xd689); + break; case 0x10ec0233: case 0x10ec0283: alc_process_coef_fw(codec, coef0233); @@ -4138,6 +4332,11 @@ static void alc_headset_mode_omtp(struct hda_codec *codec) case 0x10ec0256: alc_process_coef_fw(codec, coef0256); break; + case 0x10ec0234: + case 0x10ec0274: + case 0x10ec0294: + alc_write_coef_idx(codec, 0x45, 0xe689); + break; case 0x10ec0233: case 0x10ec0283: alc_process_coef_fw(codec, coef0233); @@ -4201,6 +4400,13 @@ static void alc_determine_headset_type(struct hda_codec *codec) UPDATE_COEF(0x49, 1<<8, 1<<8), {} }; + static struct coef_fw coef0274[] = { + UPDATE_COEF(0x4a, 0x0010, 0), + UPDATE_COEF(0x4a, 0x8000, 0), + WRITE_COEF(0x45, 0xd289), + UPDATE_COEF(0x49, 0x0300, 0x0300), + {} + }; switch (codec->core.vendor_id) { case 0x10ec0255: @@ -4210,6 +4416,14 @@ static void alc_determine_headset_type(struct hda_codec *codec) val = alc_read_coef_idx(codec, 0x46); is_ctia = (val & 0x0070) == 0x0070; break; + case 0x10ec0234: + case 0x10ec0274: + case 0x10ec0294: + alc_process_coef_fw(codec, coef0274); + msleep(80); + val = alc_read_coef_idx(codec, 0x46); + is_ctia = (val & 0x00f0) == 0x00f0; + break; case 0x10ec0233: case 0x10ec0283: alc_write_coef_idx(codec, 0x45, 0xd029); @@ -4892,6 +5106,7 @@ enum { ALC269_FIXUP_DELL1_MIC_NO_PRESENCE, ALC269_FIXUP_DELL2_MIC_NO_PRESENCE, ALC269_FIXUP_DELL3_MIC_NO_PRESENCE, + ALC269_FIXUP_DELL4_MIC_NO_PRESENCE, ALC269_FIXUP_HEADSET_MODE, ALC269_FIXUP_HEADSET_MODE_NO_HP_MIC, ALC269_FIXUP_ASPIRE_HEADSET_MIC, @@ -5192,6 +5407,16 @@ static const struct hda_fixup alc269_fixups[] = { .chained = true, .chain_id = ALC269_FIXUP_HEADSET_MODE_NO_HP_MIC }, + [ALC269_FIXUP_DELL4_MIC_NO_PRESENCE] = { + .type = HDA_FIXUP_PINS, + .v.pins = (const struct hda_pintbl[]) { + { 0x19, 0x01a1913c }, /* use as headset mic, without its own jack detect */ + { 0x1b, 0x01a1913d }, /* use as headphone mic, without its own jack detect */ + { } + }, + .chained = true, + .chain_id = ALC269_FIXUP_HEADSET_MODE + }, [ALC269_FIXUP_HEADSET_MODE] = { .type = HDA_FIXUP_FUNC, .v.func = alc_fixup_headset_mode, @@ -6322,6 +6547,11 @@ static const struct snd_hda_pin_quirk alc269_pin_fixup_tbl[] = { {0x17, 0x90170110}, {0x1a, 0x03011020}, {0x21, 0x03211030}), + SND_HDA_PIN_QUIRK(0x10ec0299, 0x1028, "Dell", ALC269_FIXUP_DELL4_MIC_NO_PRESENCE, + ALC225_STANDARD_PINS, + {0x12, 0xb7a60130}, + {0x13, 0xb8a61140}, + {0x17, 0x90170110}), {} }; @@ -6384,7 +6614,8 @@ static int patch_alc269(struct hda_codec *codec) codec->patch_ops.suspend = alc269_suspend; codec->patch_ops.resume = alc269_resume; #endif - spec->shutup = alc269_shutup; + spec->shutup = alc_default_shutup; + spec->init_hook = alc_default_init; snd_hda_pick_fixup(codec, alc269_fixup_models, alc269_fixup_tbl, alc269_fixups); @@ -6424,6 +6655,7 @@ static int patch_alc269(struct hda_codec *codec) } if (err < 0) goto error; + spec->shutup = alc269_shutup; spec->init_hook = alc269_fill_coef; alc269_fill_coef(codec); break; @@ -6447,9 +6679,8 @@ static int patch_alc269(struct hda_codec *codec) case 0x10ec0292: spec->codec_variant = ALC269_TYPE_ALC284; break; - case 0x10ec0285: case 0x10ec0293: - spec->codec_variant = ALC269_TYPE_ALC285; + spec->codec_variant = ALC269_TYPE_ALC293; break; case 0x10ec0286: case 0x10ec0288: @@ -6464,9 +6695,17 @@ static int patch_alc269(struct hda_codec *codec) break; case 0x10ec0256: spec->codec_variant = ALC269_TYPE_ALC256; + spec->shutup = alc256_shutup; + spec->init_hook = alc256_init; spec->gen.mixer_nid = 0; /* ALC256 does not have any loopback mixer path */ alc_update_coef_idx(codec, 0x36, 1 << 13, 1 << 5); /* Switch pcbeep path to Line in path*/ break; + case 0x10ec0215: + case 0x10ec0285: + case 0x10ec0289: + spec->codec_variant = ALC269_TYPE_ALC215; + spec->gen.mixer_nid = 0; + break; case 0x10ec0225: case 0x10ec0295: spec->codec_variant = ALC269_TYPE_ALC225; @@ -6479,6 +6718,8 @@ static int patch_alc269(struct hda_codec *codec) case 0x10ec0274: case 0x10ec0294: spec->codec_variant = ALC269_TYPE_ALC294; + spec->gen.mixer_nid = 0; /* ALC2x4 does not have any loopback mixer path */ + alc_update_coef_idx(codec, 0x6b, 0x0018, (1<<4) | (1<<3)); /* UAJ MIC Vref control by verb */ break; case 0x10ec0700: case 0x10ec0701: @@ -7495,6 +7736,7 @@ static int patch_alc680(struct hda_codec *codec) * patch entries */ static const struct hda_device_id snd_hda_id_realtek[] = { + HDA_CODEC_ENTRY(0x10ec0215, "ALC215", patch_alc269), HDA_CODEC_ENTRY(0x10ec0221, "ALC221", patch_alc269), HDA_CODEC_ENTRY(0x10ec0225, "ALC225", patch_alc269), HDA_CODEC_ENTRY(0x10ec0231, "ALC231", patch_alc269), @@ -7520,6 +7762,7 @@ static const struct hda_device_id snd_hda_id_realtek[] = { HDA_CODEC_ENTRY(0x10ec0285, "ALC285", patch_alc269), HDA_CODEC_ENTRY(0x10ec0286, "ALC286", patch_alc269), HDA_CODEC_ENTRY(0x10ec0288, "ALC288", patch_alc269), + HDA_CODEC_ENTRY(0x10ec0289, "ALC289", patch_alc269), HDA_CODEC_ENTRY(0x10ec0290, "ALC290", patch_alc269), HDA_CODEC_ENTRY(0x10ec0292, "ALC292", patch_alc269), HDA_CODEC_ENTRY(0x10ec0293, "ALC293", patch_alc269), diff --git a/sound/pci/hda/patch_si3054.c b/sound/pci/hda/patch_si3054.c index ffda38c45509..f63acb1b965c 100644 --- a/sound/pci/hda/patch_si3054.c +++ b/sound/pci/hda/patch_si3054.c @@ -169,8 +169,8 @@ static int si3054_pcm_open(struct hda_pcm_stream *hinfo, struct hda_codec *codec, struct snd_pcm_substream *substream) { - static unsigned int rates[] = { 8000, 9600, 16000 }; - static struct snd_pcm_hw_constraint_list hw_constraints_rates = { + static const unsigned int rates[] = { 8000, 9600, 16000 }; + static const struct snd_pcm_hw_constraint_list hw_constraints_rates = { .count = ARRAY_SIZE(rates), .list = rates, .mask = 0, |