Commit 81f3011c authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull sound fixes from Takashi Iwai:
 "The only common change is the regression fix of the previous PCM fix
  patch for managed buffers while the rest are usual suspects, USB-audio
  and HD-audio device-specific quirks.

  The change for UAC2 clock validation workaround became a bit big, but
  the changes are fairly straightforward"

* tag 'sound-5.6-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound:
  ALSA: pcm: Fix double hw_free calls
  ALSA: usb-audio: Add clock validity quirk for Denon MC7000/MCX8000
  ALSA: hda/realtek - Fix silent output on MSI-GL73
  ALSA: hda/realtek - Add more codec supported Headset Button
  ALSA: usb-audio: Apply sample rate quirk for Audioengine D1
  ALSA: usb-audio: Fix UAC2/3 effect unit parsing
  ALSA: usb-audio: Apply 48kHz fixed rate playback for Jabra Evolve 65 headset
parents 3f0d3293 0fbb027b
Loading
Loading
Loading
Loading
+2 −1
Original line number Original line Diff line number Diff line
@@ -2594,6 +2594,7 @@ void snd_pcm_release_substream(struct snd_pcm_substream *substream)


	snd_pcm_drop(substream);
	snd_pcm_drop(substream);
	if (substream->hw_opened) {
	if (substream->hw_opened) {
		if (substream->runtime->status->state != SNDRV_PCM_STATE_OPEN)
			do_hw_free(substream);
			do_hw_free(substream);
		substream->ops->close(substream);
		substream->ops->close(substream);
		substream->hw_opened = 0;
		substream->hw_opened = 0;
+4 −0
Original line number Original line Diff line number Diff line
@@ -2447,6 +2447,7 @@ static const struct snd_pci_quirk alc882_fixup_tbl[] = {
	SND_PCI_QUIRK(0x1071, 0x8258, "Evesham Voyaeger", ALC882_FIXUP_EAPD),
	SND_PCI_QUIRK(0x1071, 0x8258, "Evesham Voyaeger", ALC882_FIXUP_EAPD),
	SND_PCI_QUIRK(0x1458, 0xa002, "Gigabyte EP45-DS3/Z87X-UD3H", ALC889_FIXUP_FRONT_HP_NO_PRESENCE),
	SND_PCI_QUIRK(0x1458, 0xa002, "Gigabyte EP45-DS3/Z87X-UD3H", ALC889_FIXUP_FRONT_HP_NO_PRESENCE),
	SND_PCI_QUIRK(0x1458, 0xa0b8, "Gigabyte AZ370-Gaming", ALC1220_FIXUP_GB_DUAL_CODECS),
	SND_PCI_QUIRK(0x1458, 0xa0b8, "Gigabyte AZ370-Gaming", ALC1220_FIXUP_GB_DUAL_CODECS),
	SND_PCI_QUIRK(0x1462, 0x1276, "MSI-GL73", ALC1220_FIXUP_CLEVO_P950),
	SND_PCI_QUIRK(0x1462, 0x7350, "MSI-7350", ALC889_FIXUP_CD),
	SND_PCI_QUIRK(0x1462, 0x7350, "MSI-7350", ALC889_FIXUP_CD),
	SND_PCI_QUIRK(0x1462, 0xda57, "MSI Z270-Gaming", ALC1220_FIXUP_GB_DUAL_CODECS),
	SND_PCI_QUIRK(0x1462, 0xda57, "MSI Z270-Gaming", ALC1220_FIXUP_GB_DUAL_CODECS),
	SND_PCI_QUIRK_VENDOR(0x1462, "MSI", ALC882_FIXUP_GPIO3),
	SND_PCI_QUIRK_VENDOR(0x1462, "MSI", ALC882_FIXUP_GPIO3),
@@ -5701,8 +5702,11 @@ static void alc_fixup_headset_jack(struct hda_codec *codec,
		break;
		break;
	case HDA_FIXUP_ACT_INIT:
	case HDA_FIXUP_ACT_INIT:
		switch (codec->core.vendor_id) {
		switch (codec->core.vendor_id) {
		case 0x10ec0215:
		case 0x10ec0225:
		case 0x10ec0225:
		case 0x10ec0285:
		case 0x10ec0295:
		case 0x10ec0295:
		case 0x10ec0289:
		case 0x10ec0299:
		case 0x10ec0299:
			alc_write_coef_idx(codec, 0x48, 0xd011);
			alc_write_coef_idx(codec, 0x48, 0xd011);
			alc_update_coef_idx(codec, 0x49, 0x007f, 0x0045);
			alc_update_coef_idx(codec, 0x49, 0x007f, 0x0045);
+63 −28
Original line number Original line Diff line number Diff line
@@ -151,8 +151,34 @@ static int uac_clock_selector_set_val(struct snd_usb_audio *chip, int selector_i
	return ret;
	return ret;
}
}


/*
 * Assume the clock is valid if clock source supports only one single sample
 * rate, the terminal is connected directly to it (there is no clock selector)
 * and clock type is internal. This is to deal with some Denon DJ controllers
 * that always reports that clock is invalid.
 */
static bool uac_clock_source_is_valid_quirk(struct snd_usb_audio *chip,
					    struct audioformat *fmt,
					    int source_id)
{
	if (fmt->protocol == UAC_VERSION_2) {
		struct uac_clock_source_descriptor *cs_desc =
			snd_usb_find_clock_source(chip->ctrl_intf, source_id);

		if (!cs_desc)
			return false;

		return (fmt->nr_rates == 1 &&
			(fmt->clock & 0xff) == cs_desc->bClockID &&
			(cs_desc->bmAttributes & 0x3) !=
				UAC_CLOCK_SOURCE_TYPE_EXT);
	}

	return false;
}

static bool uac_clock_source_is_valid(struct snd_usb_audio *chip,
static bool uac_clock_source_is_valid(struct snd_usb_audio *chip,
				      int protocol,
				      struct audioformat *fmt,
				      int source_id)
				      int source_id)
{
{
	int err;
	int err;
@@ -160,7 +186,7 @@ static bool uac_clock_source_is_valid(struct snd_usb_audio *chip,
	struct usb_device *dev = chip->dev;
	struct usb_device *dev = chip->dev;
	u32 bmControls;
	u32 bmControls;


	if (protocol == UAC_VERSION_3) {
	if (fmt->protocol == UAC_VERSION_3) {
		struct uac3_clock_source_descriptor *cs_desc =
		struct uac3_clock_source_descriptor *cs_desc =
			snd_usb_find_clock_source_v3(chip->ctrl_intf, source_id);
			snd_usb_find_clock_source_v3(chip->ctrl_intf, source_id);


@@ -194,10 +220,14 @@ static bool uac_clock_source_is_valid(struct snd_usb_audio *chip,
		return false;
		return false;
	}
	}


	return data ? true :  false;
	if (data)
		return true;
	else
		return uac_clock_source_is_valid_quirk(chip, fmt, source_id);
}
}


static int __uac_clock_find_source(struct snd_usb_audio *chip, int entity_id,
static int __uac_clock_find_source(struct snd_usb_audio *chip,
				   struct audioformat *fmt, int entity_id,
				   unsigned long *visited, bool validate)
				   unsigned long *visited, bool validate)
{
{
	struct uac_clock_source_descriptor *source;
	struct uac_clock_source_descriptor *source;
@@ -217,7 +247,7 @@ static int __uac_clock_find_source(struct snd_usb_audio *chip, int entity_id,
	source = snd_usb_find_clock_source(chip->ctrl_intf, entity_id);
	source = snd_usb_find_clock_source(chip->ctrl_intf, entity_id);
	if (source) {
	if (source) {
		entity_id = source->bClockID;
		entity_id = source->bClockID;
		if (validate && !uac_clock_source_is_valid(chip, UAC_VERSION_2,
		if (validate && !uac_clock_source_is_valid(chip, fmt,
								entity_id)) {
								entity_id)) {
			usb_audio_err(chip,
			usb_audio_err(chip,
				"clock source %d is not valid, cannot use\n",
				"clock source %d is not valid, cannot use\n",
@@ -248,7 +278,8 @@ static int __uac_clock_find_source(struct snd_usb_audio *chip, int entity_id,
		}
		}


		cur = ret;
		cur = ret;
		ret = __uac_clock_find_source(chip, selector->baCSourceID[ret - 1],
		ret = __uac_clock_find_source(chip, fmt,
					      selector->baCSourceID[ret - 1],
					      visited, validate);
					      visited, validate);
		if (!validate || ret > 0 || !chip->autoclock)
		if (!validate || ret > 0 || !chip->autoclock)
			return ret;
			return ret;
@@ -260,7 +291,8 @@ static int __uac_clock_find_source(struct snd_usb_audio *chip, int entity_id,
			if (i == cur)
			if (i == cur)
				continue;
				continue;


			ret = __uac_clock_find_source(chip, selector->baCSourceID[i - 1],
			ret = __uac_clock_find_source(chip, fmt,
						      selector->baCSourceID[i - 1],
						      visited, true);
						      visited, true);
			if (ret < 0)
			if (ret < 0)
				continue;
				continue;
@@ -281,13 +313,15 @@ static int __uac_clock_find_source(struct snd_usb_audio *chip, int entity_id,
	/* FIXME: multipliers only act as pass-thru element for now */
	/* FIXME: multipliers only act as pass-thru element for now */
	multiplier = snd_usb_find_clock_multiplier(chip->ctrl_intf, entity_id);
	multiplier = snd_usb_find_clock_multiplier(chip->ctrl_intf, entity_id);
	if (multiplier)
	if (multiplier)
		return __uac_clock_find_source(chip, multiplier->bCSourceID,
		return __uac_clock_find_source(chip, fmt,
					       multiplier->bCSourceID,
					       visited, validate);
					       visited, validate);


	return -EINVAL;
	return -EINVAL;
}
}


static int __uac3_clock_find_source(struct snd_usb_audio *chip, int entity_id,
static int __uac3_clock_find_source(struct snd_usb_audio *chip,
				    struct audioformat *fmt, int entity_id,
				    unsigned long *visited, bool validate)
				    unsigned long *visited, bool validate)
{
{
	struct uac3_clock_source_descriptor *source;
	struct uac3_clock_source_descriptor *source;
@@ -307,7 +341,7 @@ static int __uac3_clock_find_source(struct snd_usb_audio *chip, int entity_id,
	source = snd_usb_find_clock_source_v3(chip->ctrl_intf, entity_id);
	source = snd_usb_find_clock_source_v3(chip->ctrl_intf, entity_id);
	if (source) {
	if (source) {
		entity_id = source->bClockID;
		entity_id = source->bClockID;
		if (validate && !uac_clock_source_is_valid(chip, UAC_VERSION_3,
		if (validate && !uac_clock_source_is_valid(chip, fmt,
								entity_id)) {
								entity_id)) {
			usb_audio_err(chip,
			usb_audio_err(chip,
				"clock source %d is not valid, cannot use\n",
				"clock source %d is not valid, cannot use\n",
@@ -338,7 +372,8 @@ static int __uac3_clock_find_source(struct snd_usb_audio *chip, int entity_id,
		}
		}


		cur = ret;
		cur = ret;
		ret = __uac3_clock_find_source(chip, selector->baCSourceID[ret - 1],
		ret = __uac3_clock_find_source(chip, fmt,
					       selector->baCSourceID[ret - 1],
					       visited, validate);
					       visited, validate);
		if (!validate || ret > 0 || !chip->autoclock)
		if (!validate || ret > 0 || !chip->autoclock)
			return ret;
			return ret;
@@ -350,7 +385,8 @@ static int __uac3_clock_find_source(struct snd_usb_audio *chip, int entity_id,
			if (i == cur)
			if (i == cur)
				continue;
				continue;


			ret = __uac3_clock_find_source(chip, selector->baCSourceID[i - 1],
			ret = __uac3_clock_find_source(chip, fmt,
						       selector->baCSourceID[i - 1],
						       visited, true);
						       visited, true);
			if (ret < 0)
			if (ret < 0)
				continue;
				continue;
@@ -372,7 +408,8 @@ static int __uac3_clock_find_source(struct snd_usb_audio *chip, int entity_id,
	multiplier = snd_usb_find_clock_multiplier_v3(chip->ctrl_intf,
	multiplier = snd_usb_find_clock_multiplier_v3(chip->ctrl_intf,
						      entity_id);
						      entity_id);
	if (multiplier)
	if (multiplier)
		return __uac3_clock_find_source(chip, multiplier->bCSourceID,
		return __uac3_clock_find_source(chip, fmt,
						multiplier->bCSourceID,
						visited, validate);
						visited, validate);


	return -EINVAL;
	return -EINVAL;
@@ -389,18 +426,18 @@ static int __uac3_clock_find_source(struct snd_usb_audio *chip, int entity_id,
 *
 *
 * Returns the clock source UnitID (>=0) on success, or an error.
 * Returns the clock source UnitID (>=0) on success, or an error.
 */
 */
int snd_usb_clock_find_source(struct snd_usb_audio *chip, int protocol,
int snd_usb_clock_find_source(struct snd_usb_audio *chip,
			      int entity_id, bool validate)
			      struct audioformat *fmt, bool validate)
{
{
	DECLARE_BITMAP(visited, 256);
	DECLARE_BITMAP(visited, 256);
	memset(visited, 0, sizeof(visited));
	memset(visited, 0, sizeof(visited));


	switch (protocol) {
	switch (fmt->protocol) {
	case UAC_VERSION_2:
	case UAC_VERSION_2:
		return __uac_clock_find_source(chip, entity_id, visited,
		return __uac_clock_find_source(chip, fmt, fmt->clock, visited,
					       validate);
					       validate);
	case UAC_VERSION_3:
	case UAC_VERSION_3:
		return __uac3_clock_find_source(chip, entity_id, visited,
		return __uac3_clock_find_source(chip, fmt, fmt->clock, visited,
					       validate);
					       validate);
	default:
	default:
		return -EINVAL;
		return -EINVAL;
@@ -501,8 +538,7 @@ static int set_sample_rate_v2v3(struct snd_usb_audio *chip, int iface,
	 * automatic clock selection if the current clock is not
	 * automatic clock selection if the current clock is not
	 * valid.
	 * valid.
	 */
	 */
	clock = snd_usb_clock_find_source(chip, fmt->protocol,
	clock = snd_usb_clock_find_source(chip, fmt, true);
					  fmt->clock, true);
	if (clock < 0) {
	if (clock < 0) {
		/* We did not find a valid clock, but that might be
		/* We did not find a valid clock, but that might be
		 * because the current sample rate does not match an
		 * because the current sample rate does not match an
@@ -510,8 +546,7 @@ static int set_sample_rate_v2v3(struct snd_usb_audio *chip, int iface,
		 * and we will do another validation after setting the
		 * and we will do another validation after setting the
		 * rate.
		 * rate.
		 */
		 */
		clock = snd_usb_clock_find_source(chip, fmt->protocol,
		clock = snd_usb_clock_find_source(chip, fmt, false);
						  fmt->clock, false);
		if (clock < 0)
		if (clock < 0)
			return clock;
			return clock;
	}
	}
@@ -577,7 +612,7 @@ static int set_sample_rate_v2v3(struct snd_usb_audio *chip, int iface,


validation:
validation:
	/* validate clock after rate change */
	/* validate clock after rate change */
	if (!uac_clock_source_is_valid(chip, fmt->protocol, clock))
	if (!uac_clock_source_is_valid(chip, fmt, clock))
		return -ENXIO;
		return -ENXIO;
	return 0;
	return 0;
}
}
+2 −2
Original line number Original line Diff line number Diff line
@@ -6,7 +6,7 @@ int snd_usb_init_sample_rate(struct snd_usb_audio *chip, int iface,
			     struct usb_host_interface *alts,
			     struct usb_host_interface *alts,
			     struct audioformat *fmt, int rate);
			     struct audioformat *fmt, int rate);


int snd_usb_clock_find_source(struct snd_usb_audio *chip, int protocol,
int snd_usb_clock_find_source(struct snd_usb_audio *chip,
			     int entity_id, bool validate);
			      struct audioformat *fmt, bool validate);


#endif /* __USBAUDIO_CLOCK_H */
#endif /* __USBAUDIO_CLOCK_H */
+23 −13
Original line number Original line Diff line number Diff line
@@ -151,6 +151,19 @@ static u64 parse_audio_format_i_type(struct snd_usb_audio *chip,
	return pcm_formats;
	return pcm_formats;
}
}


static int set_fixed_rate(struct audioformat *fp, int rate, int rate_bits)
{
	kfree(fp->rate_table);
	fp->rate_table = kmalloc(sizeof(int), GFP_KERNEL);
	if (!fp->rate_table)
		return -ENOMEM;
	fp->nr_rates = 1;
	fp->rate_min = rate;
	fp->rate_max = rate;
	fp->rates = rate_bits;
	fp->rate_table[0] = rate;
	return 0;
}


/*
/*
 * parse the format descriptor and stores the possible sample rates
 * parse the format descriptor and stores the possible sample rates
@@ -223,6 +236,14 @@ static int parse_audio_format_rates_v1(struct snd_usb_audio *chip, struct audiof
		fp->rate_min = combine_triple(&fmt[offset + 1]);
		fp->rate_min = combine_triple(&fmt[offset + 1]);
		fp->rate_max = combine_triple(&fmt[offset + 4]);
		fp->rate_max = combine_triple(&fmt[offset + 4]);
	}
	}

	/* Jabra Evolve 65 headset */
	if (chip->usb_id == USB_ID(0x0b0e, 0x030b)) {
		/* only 48kHz for playback while keeping 16kHz for capture */
		if (fp->nr_rates != 1)
			return set_fixed_rate(fp, 48000, SNDRV_PCM_RATE_48000);
	}

	return 0;
	return 0;
}
}


@@ -299,17 +320,7 @@ static int line6_parse_audio_format_rates_quirk(struct snd_usb_audio *chip,
	case USB_ID(0x0e41, 0x4248): /* Line6 Helix >= fw 2.82 */
	case USB_ID(0x0e41, 0x4248): /* Line6 Helix >= fw 2.82 */
	case USB_ID(0x0e41, 0x4249): /* Line6 Helix Rack >= fw 2.82 */
	case USB_ID(0x0e41, 0x4249): /* Line6 Helix Rack >= fw 2.82 */
	case USB_ID(0x0e41, 0x424a): /* Line6 Helix LT >= fw 2.82 */
	case USB_ID(0x0e41, 0x424a): /* Line6 Helix LT >= fw 2.82 */
		/* supported rates: 48Khz */
		return set_fixed_rate(fp, 48000, SNDRV_PCM_RATE_48000);
		kfree(fp->rate_table);
		fp->rate_table = kmalloc(sizeof(int), GFP_KERNEL);
		if (!fp->rate_table)
			return -ENOMEM;
		fp->nr_rates = 1;
		fp->rate_min = 48000;
		fp->rate_max = 48000;
		fp->rates = SNDRV_PCM_RATE_48000;
		fp->rate_table[0] = 48000;
		return 0;
	}
	}


	return -ENODEV;
	return -ENODEV;
@@ -325,8 +336,7 @@ static int parse_audio_format_rates_v2v3(struct snd_usb_audio *chip,
	struct usb_device *dev = chip->dev;
	struct usb_device *dev = chip->dev;
	unsigned char tmp[2], *data;
	unsigned char tmp[2], *data;
	int nr_triplets, data_size, ret = 0, ret_l6;
	int nr_triplets, data_size, ret = 0, ret_l6;
	int clock = snd_usb_clock_find_source(chip, fp->protocol,
	int clock = snd_usb_clock_find_source(chip, fp, false);
					      fp->clock, false);


	if (clock < 0) {
	if (clock < 0) {
		dev_err(&dev->dev,
		dev_err(&dev->dev,
Loading