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

Commit 3b98ec4e authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull sound fixes from Takashi Iwai:
 "Things get calming down, now we have only a few fix patches: a trivial
  fix for memory leak in usb-audio, a patch for the new HD-audio PCI id,
  a device-specific mute-LED fix, and a slightly big patch to cover the
  missing COEF inits of various Realtek codecs"

* tag 'sound-3.18-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound:
  ALSA: hda - Add mute LED control for Lenovo Ideapad Z560
  ALSA: hda/realtek - Change EAPD to verb control
  ALSA: usb-audio: Fix memory leak in FTU quirk
  ALSA: hda_intel: Add DeviceIDs for Sunrise Point-LP
parents 2c54396e 3542aed7
Loading
Loading
Loading
Loading
+4 −0
Original line number Original line Diff line number Diff line
@@ -219,6 +219,7 @@ MODULE_SUPPORTED_DEVICE("{{Intel, ICH6},"
			 "{Intel, LPT_LP},"
			 "{Intel, LPT_LP},"
			 "{Intel, WPT_LP},"
			 "{Intel, WPT_LP},"
			 "{Intel, SPT},"
			 "{Intel, SPT},"
			 "{Intel, SPT_LP},"
			 "{Intel, HPT},"
			 "{Intel, HPT},"
			 "{Intel, PBG},"
			 "{Intel, PBG},"
			 "{Intel, SCH},"
			 "{Intel, SCH},"
@@ -2004,6 +2005,9 @@ static const struct pci_device_id azx_ids[] = {
	/* Sunrise Point */
	/* Sunrise Point */
	{ PCI_DEVICE(0x8086, 0xa170),
	{ PCI_DEVICE(0x8086, 0xa170),
	  .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH },
	  .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH },
	/* Sunrise Point-LP */
	{ PCI_DEVICE(0x8086, 0x9d70),
	  .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH },
	/* Haswell */
	/* Haswell */
	{ PCI_DEVICE(0x8086, 0x0a0c),
	{ PCI_DEVICE(0x8086, 0x0a0c),
	  .driver_data = AZX_DRIVER_HDMI | AZX_DCAPS_INTEL_HASWELL },
	  .driver_data = AZX_DRIVER_HDMI | AZX_DCAPS_INTEL_HASWELL },
+31 −0
Original line number Original line Diff line number Diff line
@@ -43,6 +43,7 @@ struct conexant_spec {
	unsigned int num_eapds;
	unsigned int num_eapds;
	hda_nid_t eapds[4];
	hda_nid_t eapds[4];
	bool dynamic_eapd;
	bool dynamic_eapd;
	hda_nid_t mute_led_eapd;


	unsigned int parse_flags; /* flag for snd_hda_parse_pin_defcfg() */
	unsigned int parse_flags; /* flag for snd_hda_parse_pin_defcfg() */


@@ -163,6 +164,17 @@ static void cx_auto_vmaster_hook(void *private_data, int enabled)
	cx_auto_turn_eapd(codec, spec->num_eapds, spec->eapds, enabled);
	cx_auto_turn_eapd(codec, spec->num_eapds, spec->eapds, enabled);
}
}


/* turn on/off EAPD according to Master switch (inversely!) for mute LED */
static void cx_auto_vmaster_hook_mute_led(void *private_data, int enabled)
{
	struct hda_codec *codec = private_data;
	struct conexant_spec *spec = codec->spec;

	snd_hda_codec_write(codec, spec->mute_led_eapd, 0,
			    AC_VERB_SET_EAPD_BTLENABLE,
			    enabled ? 0x00 : 0x02);
}

static int cx_auto_build_controls(struct hda_codec *codec)
static int cx_auto_build_controls(struct hda_codec *codec)
{
{
	int err;
	int err;
@@ -223,6 +235,7 @@ enum {
	CXT_FIXUP_TOSHIBA_P105,
	CXT_FIXUP_TOSHIBA_P105,
	CXT_FIXUP_HP_530,
	CXT_FIXUP_HP_530,
	CXT_FIXUP_CAP_MIX_AMP_5047,
	CXT_FIXUP_CAP_MIX_AMP_5047,
	CXT_FIXUP_MUTE_LED_EAPD,
};
};


/* for hda_fixup_thinkpad_acpi() */
/* for hda_fixup_thinkpad_acpi() */
@@ -557,6 +570,18 @@ static void cxt_fixup_olpc_xo(struct hda_codec *codec,
	}
	}
}
}


static void cxt_fixup_mute_led_eapd(struct hda_codec *codec,
				    const struct hda_fixup *fix, int action)
{
	struct conexant_spec *spec = codec->spec;

	if (action == HDA_FIXUP_ACT_PRE_PROBE) {
		spec->mute_led_eapd = 0x1b;
		spec->dynamic_eapd = 1;
		spec->gen.vmaster_mute.hook = cx_auto_vmaster_hook_mute_led;
	}
}

/*
/*
 * Fix max input level on mixer widget to 0dB
 * Fix max input level on mixer widget to 0dB
 * (originally it has 0x2b steps with 0dB offset 0x14)
 * (originally it has 0x2b steps with 0dB offset 0x14)
@@ -705,6 +730,10 @@ static const struct hda_fixup cxt_fixups[] = {
		.type = HDA_FIXUP_FUNC,
		.type = HDA_FIXUP_FUNC,
		.v.func = cxt_fixup_cap_mix_amp_5047,
		.v.func = cxt_fixup_cap_mix_amp_5047,
	},
	},
	[CXT_FIXUP_MUTE_LED_EAPD] = {
		.type = HDA_FIXUP_FUNC,
		.v.func = cxt_fixup_mute_led_eapd,
	},
};
};


static const struct snd_pci_quirk cxt5045_fixups[] = {
static const struct snd_pci_quirk cxt5045_fixups[] = {
@@ -762,6 +791,7 @@ static const struct snd_pci_quirk cxt5066_fixups[] = {
	SND_PCI_QUIRK(0x17aa, 0x21cf, "Lenovo T520", CXT_PINCFG_LENOVO_TP410),
	SND_PCI_QUIRK(0x17aa, 0x21cf, "Lenovo T520", CXT_PINCFG_LENOVO_TP410),
	SND_PCI_QUIRK(0x17aa, 0x21da, "Lenovo X220", CXT_PINCFG_LENOVO_TP410),
	SND_PCI_QUIRK(0x17aa, 0x21da, "Lenovo X220", CXT_PINCFG_LENOVO_TP410),
	SND_PCI_QUIRK(0x17aa, 0x21db, "Lenovo X220-tablet", CXT_PINCFG_LENOVO_TP410),
	SND_PCI_QUIRK(0x17aa, 0x21db, "Lenovo X220-tablet", CXT_PINCFG_LENOVO_TP410),
	SND_PCI_QUIRK(0x17aa, 0x38af, "Lenovo IdeaPad Z560", CXT_FIXUP_MUTE_LED_EAPD),
	SND_PCI_QUIRK(0x17aa, 0x3975, "Lenovo U300s", CXT_FIXUP_STEREO_DMIC),
	SND_PCI_QUIRK(0x17aa, 0x3975, "Lenovo U300s", CXT_FIXUP_STEREO_DMIC),
	SND_PCI_QUIRK(0x17aa, 0x3977, "Lenovo IdeaPad U310", CXT_FIXUP_STEREO_DMIC),
	SND_PCI_QUIRK(0x17aa, 0x3977, "Lenovo IdeaPad U310", CXT_FIXUP_STEREO_DMIC),
	SND_PCI_QUIRK(0x17aa, 0x397b, "Lenovo S205", CXT_FIXUP_STEREO_DMIC),
	SND_PCI_QUIRK(0x17aa, 0x397b, "Lenovo S205", CXT_FIXUP_STEREO_DMIC),
@@ -780,6 +810,7 @@ static const struct hda_model_fixup cxt5066_fixup_models[] = {
	{ .id = CXT_PINCFG_LEMOTE_A1004, .name = "lemote-a1004" },
	{ .id = CXT_PINCFG_LEMOTE_A1004, .name = "lemote-a1004" },
	{ .id = CXT_PINCFG_LEMOTE_A1205, .name = "lemote-a1205" },
	{ .id = CXT_PINCFG_LEMOTE_A1205, .name = "lemote-a1205" },
	{ .id = CXT_FIXUP_OLPC_XO, .name = "olpc-xo" },
	{ .id = CXT_FIXUP_OLPC_XO, .name = "olpc-xo" },
	{ .id = CXT_FIXUP_MUTE_LED_EAPD, .name = "mute-led-eapd" },
	{}
	{}
};
};


+75 −30
Original line number Original line Diff line number Diff line
@@ -288,6 +288,80 @@ static void alc880_unsol_event(struct hda_codec *codec, unsigned int res)
	snd_hda_jack_unsol_event(codec, res >> 2);
	snd_hda_jack_unsol_event(codec, res >> 2);
}
}


/* Change EAPD to verb control */
static void alc_fill_eapd_coef(struct hda_codec *codec)
{
	int coef;

	coef = alc_get_coef0(codec);

	switch (codec->vendor_id) {
	case 0x10ec0262:
		alc_update_coef_idx(codec, 0x7, 0, 1<<5);
		break;
	case 0x10ec0267:
	case 0x10ec0268:
		alc_update_coef_idx(codec, 0x7, 0, 1<<13);
		break;
	case 0x10ec0269:
		if ((coef & 0x00f0) == 0x0010)
			alc_update_coef_idx(codec, 0xd, 0, 1<<14);
		if ((coef & 0x00f0) == 0x0020)
			alc_update_coef_idx(codec, 0x4, 1<<15, 0);
		if ((coef & 0x00f0) == 0x0030)
			alc_update_coef_idx(codec, 0x10, 1<<9, 0);
		break;
	case 0x10ec0280:
	case 0x10ec0284:
	case 0x10ec0290:
	case 0x10ec0292:
		alc_update_coef_idx(codec, 0x4, 1<<15, 0);
		break;
	case 0x10ec0233:
	case 0x10ec0255:
	case 0x10ec0282:
	case 0x10ec0283:
	case 0x10ec0286:
	case 0x10ec0288:
		alc_update_coef_idx(codec, 0x10, 1<<9, 0);
		break;
	case 0x10ec0285:
	case 0x10ec0293:
		alc_update_coef_idx(codec, 0xa, 1<<13, 0);
		break;
	case 0x10ec0662:
		if ((coef & 0x00f0) == 0x0030)
			alc_update_coef_idx(codec, 0x4, 1<<10, 0); /* EAPD Ctrl */
		break;
	case 0x10ec0272:
	case 0x10ec0273:
	case 0x10ec0663:
	case 0x10ec0665:
	case 0x10ec0670:
	case 0x10ec0671:
	case 0x10ec0672:
		alc_update_coef_idx(codec, 0xd, 0, 1<<14); /* EAPD Ctrl */
		break;
	case 0x10ec0668:
		alc_update_coef_idx(codec, 0x7, 3<<13, 0);
		break;
	case 0x10ec0867:
		alc_update_coef_idx(codec, 0x4, 1<<10, 0);
		break;
	case 0x10ec0888:
		if ((coef & 0x00f0) == 0x0020 || (coef & 0x00f0) == 0x0030)
			alc_update_coef_idx(codec, 0x7, 1<<5, 0);
		break;
	case 0x10ec0892:
		alc_update_coef_idx(codec, 0x7, 1<<5, 0);
		break;
	case 0x10ec0899:
	case 0x10ec0900:
		alc_update_coef_idx(codec, 0x7, 1<<1, 0);
		break;
	}
}

/* additional initialization for ALC888 variants */
/* additional initialization for ALC888 variants */
static void alc888_coef_init(struct hda_codec *codec)
static void alc888_coef_init(struct hda_codec *codec)
{
{
@@ -339,6 +413,7 @@ static void alc_eapd_shutup(struct hda_codec *codec)
/* generic EAPD initialization */
/* generic EAPD initialization */
static void alc_auto_init_amp(struct hda_codec *codec, int type)
static void alc_auto_init_amp(struct hda_codec *codec, int type)
{
{
	alc_fill_eapd_coef(codec);
	alc_auto_setup_eapd(codec, true);
	alc_auto_setup_eapd(codec, true);
	switch (type) {
	switch (type) {
	case ALC_INIT_GPIO1:
	case ALC_INIT_GPIO1:
@@ -5212,9 +5287,6 @@ static void alc269_fill_coef(struct hda_codec *codec)
		}
		}
	}
	}


	/* Class D */
	alc_update_coef_idx(codec, 0xd, 0, 1<<14);

	/* HP */
	/* HP */
	alc_update_coef_idx(codec, 0x4, 0, 1<<11);
	alc_update_coef_idx(codec, 0x4, 0, 1<<11);
}
}
@@ -6124,29 +6196,6 @@ static const struct snd_hda_pin_quirk alc662_pin_fixup_tbl[] = {
	{}
	{}
};
};


static void alc662_fill_coef(struct hda_codec *codec)
{
	int coef;

	coef = alc_get_coef0(codec);

	switch (codec->vendor_id) {
	case 0x10ec0662:
		if ((coef & 0x00f0) == 0x0030)
			alc_update_coef_idx(codec, 0x4, 1<<10, 0); /* EAPD Ctrl */
		break;
	case 0x10ec0272:
	case 0x10ec0273:
	case 0x10ec0663:
	case 0x10ec0665:
	case 0x10ec0670:
	case 0x10ec0671:
	case 0x10ec0672:
		alc_update_coef_idx(codec, 0xd, 0, 1<<14); /* EAPD Ctrl */
		break;
	}
}

/*
/*
 */
 */
static int patch_alc662(struct hda_codec *codec)
static int patch_alc662(struct hda_codec *codec)
@@ -6169,10 +6218,6 @@ static int patch_alc662(struct hda_codec *codec)
	case 0x10ec0668:
	case 0x10ec0668:
		spec->init_hook = alc668_restore_default_value;
		spec->init_hook = alc668_restore_default_value;
		break;
		break;
	default:
		spec->init_hook = alc662_fill_coef;
		alc662_fill_coef(codec);
		break;
	}
	}


	snd_hda_pick_fixup(codec, alc662_fixup_models,
	snd_hda_pick_fixup(codec, alc662_fixup_models,
+6 −0
Original line number Original line Diff line number Diff line
@@ -885,6 +885,11 @@ static int snd_ftu_eff_switch_put(struct snd_kcontrol *kctl,
	return changed;
	return changed;
}
}


static void kctl_private_value_free(struct snd_kcontrol *kctl)
{
	kfree((void *)kctl->private_value);
}

static int snd_ftu_create_effect_switch(struct usb_mixer_interface *mixer,
static int snd_ftu_create_effect_switch(struct usb_mixer_interface *mixer,
	int validx, int bUnitID)
	int validx, int bUnitID)
{
{
@@ -919,6 +924,7 @@ static int snd_ftu_create_effect_switch(struct usb_mixer_interface *mixer,
		return -ENOMEM;
		return -ENOMEM;
	}
	}


	kctl->private_free = kctl_private_value_free;
	err = snd_ctl_add(mixer->chip->card, kctl);
	err = snd_ctl_add(mixer->chip->card, kctl);
	if (err < 0)
	if (err < 0)
		return err;
		return err;