Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 7b612255 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull sound fixes from Takashi Iwai:
 "As usual in rc6, this update contains only a few HD-audio and
  USB-audio device-specific quirks: yet another Thinkpad noise fixes,
  Dell headphone mic fixes, and AudioQuest DragonFly fixes"

* tag 'sound-4.4-rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound:
  ALSA: hda - Add a fixup for Thinkpad X1 Carbon 2nd
  ALSA: hda - Set codec to D3 at reboot/shutdown on Thinkpads
  ALSA: hda - Apply click noise workaround for Thinkpads generically
  ALSA: hda - Fix headphone mic input on a few Dell ALC293 machines
  ALSA: usb-audio: Add sample rate inquiry quirk for AudioQuest DragonFly
  ALSA: usb-audio: Add a more accurate volume quirk for AudioQuest DragonFly
parents 19c52240 b6903c0e
Loading
Loading
Loading
Loading
+37 −19
Original line number Diff line number Diff line
@@ -111,6 +111,7 @@ struct alc_spec {
	void (*power_hook)(struct hda_codec *codec);
#endif
	void (*shutup)(struct hda_codec *codec);
	void (*reboot_notify)(struct hda_codec *codec);

	int init_amp;
	int codec_variant;	/* flag for other variants */
@@ -773,6 +774,25 @@ static inline void alc_shutup(struct hda_codec *codec)
		snd_hda_shutup_pins(codec);
}

static void alc_reboot_notify(struct hda_codec *codec)
{
	struct alc_spec *spec = codec->spec;

	if (spec && spec->reboot_notify)
		spec->reboot_notify(codec);
	else
		alc_shutup(codec);
}

/* power down codec to D3 at reboot/shutdown; set as reboot_notify ops */
static void alc_d3_at_reboot(struct hda_codec *codec)
{
	snd_hda_codec_set_power_to_all(codec, codec->core.afg, AC_PWRST_D3);
	snd_hda_codec_write(codec, codec->core.afg, 0,
			    AC_VERB_SET_POWER_STATE, AC_PWRST_D3);
	msleep(10);
}

#define alc_free	snd_hda_gen_free

#ifdef CONFIG_PM
@@ -818,7 +838,7 @@ static const struct hda_codec_ops alc_patch_ops = {
	.suspend = alc_suspend,
	.check_power_status = snd_hda_gen_check_power_status,
#endif
	.reboot_notify = alc_shutup,
	.reboot_notify = alc_reboot_notify,
};


@@ -4198,24 +4218,14 @@ static void alc_fixup_tpt440_dock(struct hda_codec *codec,
	struct alc_spec *spec = codec->spec;

	if (action == HDA_FIXUP_ACT_PRE_PROBE) {
		spec->shutup = alc_no_shutup; /* reduce click noise */
		spec->reboot_notify = alc_d3_at_reboot; /* reduce noise */
		spec->parse_flags = HDA_PINCFG_NO_HP_FIXUP;
		codec->power_save_node = 0; /* avoid click noises */
		snd_hda_apply_pincfgs(codec, pincfgs);
	}
}

/* additional fixup for Thinkpad T440s noise problem */
static void alc_fixup_tpt440(struct hda_codec *codec,
				  const struct hda_fixup *fix, int action)
{
	struct alc_spec *spec = codec->spec;

	if (action == HDA_FIXUP_ACT_PRE_PROBE) {
		spec->shutup = alc_no_shutup; /* reduce click noise */
		spec->gen.mixer_nid = 0; /* reduce background noise */
	}
}

static void alc_shutup_dell_xps13(struct hda_codec *codec)
{
	struct alc_spec *spec = codec->spec;
@@ -4606,6 +4616,7 @@ enum {
	ALC288_FIXUP_DISABLE_AAMIX,
	ALC292_FIXUP_DELL_E7X,
	ALC292_FIXUP_DISABLE_AAMIX,
	ALC293_FIXUP_DISABLE_AAMIX_MULTIJACK,
	ALC298_FIXUP_DELL1_MIC_NO_PRESENCE,
	ALC275_FIXUP_DELL_XPS,
	ALC256_FIXUP_DELL_XPS_13_HEADPHONE_NOISE,
@@ -5066,7 +5077,7 @@ static const struct hda_fixup alc269_fixups[] = {
	},
	[ALC292_FIXUP_TPT440] = {
		.type = HDA_FIXUP_FUNC,
		.v.func = alc_fixup_tpt440,
		.v.func = alc_fixup_disable_aamix,
		.chained = true,
		.chain_id = ALC292_FIXUP_TPT440_DOCK,
	},
@@ -5169,6 +5180,12 @@ static const struct hda_fixup alc269_fixups[] = {
		.chained = true,
		.chain_id = ALC269_FIXUP_DELL2_MIC_NO_PRESENCE
	},
	[ALC293_FIXUP_DISABLE_AAMIX_MULTIJACK] = {
		.type = HDA_FIXUP_FUNC,
		.v.func = alc_fixup_disable_aamix,
		.chained = true,
		.chain_id = ALC293_FIXUP_DELL1_MIC_NO_PRESENCE
	},
	[ALC292_FIXUP_DELL_E7X] = {
		.type = HDA_FIXUP_FUNC,
		.v.func = alc_fixup_dell_xps13,
@@ -5247,11 +5264,11 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
	SND_PCI_QUIRK(0x1028, 0x06c7, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE),
	SND_PCI_QUIRK(0x1028, 0x06d9, "Dell", ALC293_FIXUP_DELL1_MIC_NO_PRESENCE),
	SND_PCI_QUIRK(0x1028, 0x06da, "Dell", ALC293_FIXUP_DELL1_MIC_NO_PRESENCE),
	SND_PCI_QUIRK(0x1028, 0x06db, "Dell", ALC292_FIXUP_DISABLE_AAMIX),
	SND_PCI_QUIRK(0x1028, 0x06dd, "Dell", ALC292_FIXUP_DISABLE_AAMIX),
	SND_PCI_QUIRK(0x1028, 0x06de, "Dell", ALC292_FIXUP_DISABLE_AAMIX),
	SND_PCI_QUIRK(0x1028, 0x06df, "Dell", ALC292_FIXUP_DISABLE_AAMIX),
	SND_PCI_QUIRK(0x1028, 0x06e0, "Dell", ALC292_FIXUP_DISABLE_AAMIX),
	SND_PCI_QUIRK(0x1028, 0x06db, "Dell", ALC293_FIXUP_DISABLE_AAMIX_MULTIJACK),
	SND_PCI_QUIRK(0x1028, 0x06dd, "Dell", ALC293_FIXUP_DISABLE_AAMIX_MULTIJACK),
	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", ALC256_FIXUP_DELL_XPS_13_HEADPHONE_NOISE),
	SND_PCI_QUIRK(0x1028, 0x164a, "Dell", ALC293_FIXUP_DELL1_MIC_NO_PRESENCE),
	SND_PCI_QUIRK(0x1028, 0x164b, "Dell", ALC293_FIXUP_DELL1_MIC_NO_PRESENCE),
@@ -5358,6 +5375,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
	SND_PCI_QUIRK(0x17aa, 0x2212, "Thinkpad T440", ALC292_FIXUP_TPT440_DOCK),
	SND_PCI_QUIRK(0x17aa, 0x2214, "Thinkpad X240", ALC292_FIXUP_TPT440_DOCK),
	SND_PCI_QUIRK(0x17aa, 0x2215, "Thinkpad", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
	SND_PCI_QUIRK(0x17aa, 0x2218, "Thinkpad X1 Carbon 2nd", ALC292_FIXUP_TPT440_DOCK),
	SND_PCI_QUIRK(0x17aa, 0x2223, "ThinkPad T550", ALC292_FIXUP_TPT440_DOCK),
	SND_PCI_QUIRK(0x17aa, 0x2226, "ThinkPad X250", ALC292_FIXUP_TPT440_DOCK),
	SND_PCI_QUIRK(0x17aa, 0x2233, "Thinkpad", ALC293_FIXUP_LENOVO_SPK_NOISE),
+2 −0
Original line number Diff line number Diff line
@@ -1354,6 +1354,8 @@ static void build_feature_ctl(struct mixer_build *state, void *raw_desc,
		}
	}

	snd_usb_mixer_fu_apply_quirk(state->mixer, cval, unitid, kctl);

	range = (cval->max - cval->min) / cval->res;
	/*
	 * Are there devices with volume range more than 255? I use a bit more
+0 −12
Original line number Diff line number Diff line
@@ -348,13 +348,6 @@ static struct usbmix_name_map bose_companion5_map[] = {
	{ 0 }	/* terminator */
};

/* Dragonfly DAC 1.2, the dB conversion factor is 1 instead of 256 */
static struct usbmix_dB_map dragonfly_1_2_dB = {0, 5000};
static struct usbmix_name_map dragonfly_1_2_map[] = {
	{ 7, NULL, .dB = &dragonfly_1_2_dB },
	{ 0 }	/* terminator */
};

/*
 * Control map entries
 */
@@ -470,11 +463,6 @@ static struct usbmix_ctl_map usbmix_ctl_maps[] = {
		.id = USB_ID(0x05a7, 0x1020),
		.map = bose_companion5_map,
	},
	{
		/* Dragonfly DAC 1.2 */
		.id = USB_ID(0x21b4, 0x0081),
		.map = dragonfly_1_2_map,
	},
	{ 0 } /* terminator */
};
+37 −0
Original line number Diff line number Diff line
@@ -37,6 +37,7 @@
#include <sound/control.h>
#include <sound/hwdep.h>
#include <sound/info.h>
#include <sound/tlv.h>

#include "usbaudio.h"
#include "mixer.h"
@@ -1825,3 +1826,39 @@ void snd_usb_mixer_rc_memory_change(struct usb_mixer_interface *mixer,
	}
}

static void snd_dragonfly_quirk_db_scale(struct usb_mixer_interface *mixer,
					 struct snd_kcontrol *kctl)
{
	/* Approximation using 10 ranges based on output measurement on hw v1.2.
	 * This seems close to the cubic mapping e.g. alsamixer uses. */
	static const DECLARE_TLV_DB_RANGE(scale,
		 0,  1, TLV_DB_MINMAX_ITEM(-5300, -4970),
		 2,  5, TLV_DB_MINMAX_ITEM(-4710, -4160),
		 6,  7, TLV_DB_MINMAX_ITEM(-3884, -3710),
		 8, 14, TLV_DB_MINMAX_ITEM(-3443, -2560),
		15, 16, TLV_DB_MINMAX_ITEM(-2475, -2324),
		17, 19, TLV_DB_MINMAX_ITEM(-2228, -2031),
		20, 26, TLV_DB_MINMAX_ITEM(-1910, -1393),
		27, 31, TLV_DB_MINMAX_ITEM(-1322, -1032),
		32, 40, TLV_DB_MINMAX_ITEM(-968, -490),
		41, 50, TLV_DB_MINMAX_ITEM(-441, 0),
	);

	usb_audio_info(mixer->chip, "applying DragonFly dB scale quirk\n");
	kctl->tlv.p = scale;
	kctl->vd[0].access |= SNDRV_CTL_ELEM_ACCESS_TLV_READ;
	kctl->vd[0].access &= ~SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK;
}

void snd_usb_mixer_fu_apply_quirk(struct usb_mixer_interface *mixer,
				  struct usb_mixer_elem_info *cval, int unitid,
				  struct snd_kcontrol *kctl)
{
	switch (mixer->chip->usb_id) {
	case USB_ID(0x21b4, 0x0081): /* AudioQuest DragonFly */
		if (unitid == 7 && cval->min == 0 && cval->max == 50)
			snd_dragonfly_quirk_db_scale(mixer, kctl);
		break;
	}
}
+4 −0
Original line number Diff line number Diff line
@@ -9,5 +9,9 @@ void snd_emuusb_set_samplerate(struct snd_usb_audio *chip,
void snd_usb_mixer_rc_memory_change(struct usb_mixer_interface *mixer,
				    int unitid);

void snd_usb_mixer_fu_apply_quirk(struct usb_mixer_interface *mixer,
				  struct usb_mixer_elem_info *cval, int unitid,
				  struct snd_kcontrol *kctl);

#endif /* SND_USB_MIXER_QUIRKS_H */
Loading