Commit 2aa0a369 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull sound fixes from Takashi Iwai:
 "A bunch of small fixes. One minor fix is found in the core side for
  data race in PCM OSS layer, while remaining changes are various
  device-specific fixes and quirks.

   - Core: PCM OSS data race fix

   - HD-audio: Fixes for TAS2781, CS35L56, and Realtek/Conexant quirks;
     avoidance of a WARN_ON for HDMI channel mapping

   - USB-audio: Improvements in UAC3 parsing robustness (leaks, size
     checks) and fixes for potential endless loops

   - ASoC: Driver-specific fixes for CS35L56, Intel bytcr_wm5102,
     Spacemit, AW88395, and others, plus a new quirk for Steam Deck
     OLED

   - Misc: A UAF fix in aloop driver, division by zero fix in ua101
     driver and leak fixes in caiaq driver"

* tag 'sound-7.1-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound: (32 commits)
  ALSA: hda/tas2781: Fix incorrect bit update for non-book-zero or book 0 pages >1
  ALSA: hda: cs35l56: Fix uninitialized value in cs35l56_hda_read_acpi()
  ALSA: hda/conexant: Fix missing error check for jack detection
  ALSA: hda: Avoid WARN_ON() for HDMI chmap slot checks
  ALSA: usb-audio: Fix quirk entry placement for PreSonus AudioBox USB
  ASoC: spacemit: adjust FIFO trigger threshold to half FIFO size
  ASoC: spacemit: move hw constraints from hw_params to startup
  ASoC: codecs: ab8500: Fix casting of private data
  ASoC: cs35l56: Fix illegal writes to OTP_MEM registers
  ASoC: Intel: bytcr_wm5102: Fix MCLK leak on platform_clock_control error
  ALSA: usb-audio: Avoid potential endless loop in convert_chmap_v3()
  ALSA: usb-audio: Fix potential leak of pd at parsing UAC3 streams
  ALSA: caiaq: Don't abort when no input device is available
  ALSA: caiaq: Fix potentially leftover ep1_in_urb at error path
  ASoC: aw88395: Fix kernel panic caused by invalid GPIO error pointer
  ALSA: caiaq: fix usb_dev refcount leak on probe failure
  sound: ua101: fix division by zero at probe
  ALSA: usb-audio: apply quirk for Playstation PDP Riffmaster
  ALSA: hda: Remove duplicate cmedia entries in codecs Makefile
  ALSA: hda/realtek: Add micmute LED quirk for Acer Aspire A315-44P
  ...
parents e75a43c7 e052a1f7
Loading
Loading
Loading
Loading
+23 −6
Original line number Diff line number Diff line
@@ -2155,10 +2155,16 @@ static int snd_pcm_oss_get_trigger(struct snd_pcm_oss_file *pcm_oss_file)

	psubstream = pcm_oss_file->streams[SNDRV_PCM_STREAM_PLAYBACK];
	csubstream = pcm_oss_file->streams[SNDRV_PCM_STREAM_CAPTURE];
	if (psubstream && psubstream->runtime && psubstream->runtime->oss.trigger)
	if (psubstream && psubstream->runtime) {
		guard(mutex)(&psubstream->runtime->oss.params_lock);
		if (psubstream->runtime->oss.trigger)
			result |= PCM_ENABLE_OUTPUT;
	if (csubstream && csubstream->runtime && csubstream->runtime->oss.trigger)
	}
	if (csubstream && csubstream->runtime) {
		guard(mutex)(&csubstream->runtime->oss.params_lock);
		if (csubstream->runtime->oss.trigger)
			result |= PCM_ENABLE_INPUT;
	}
	return result;
}

@@ -2832,6 +2838,17 @@ static int snd_pcm_oss_capture_ready(struct snd_pcm_substream *substream)
						runtime->oss.period_frames;
}

static bool need_input_retrigger(struct snd_pcm_runtime *runtime)
{
	bool ret;

	guard(mutex)(&runtime->oss.params_lock);
	ret = runtime->oss.trigger;
	if (ret)
		runtime->oss.trigger = 0;
	return ret;
}

static __poll_t snd_pcm_oss_poll(struct file *file, poll_table * wait)
{
	struct snd_pcm_oss_file *pcm_oss_file;
@@ -2864,11 +2881,11 @@ static __poll_t snd_pcm_oss_poll(struct file *file, poll_table * wait)
			    snd_pcm_oss_capture_ready(csubstream))
				mask |= EPOLLIN | EPOLLRDNORM;
		}
		if (ostate != SNDRV_PCM_STATE_RUNNING && runtime->oss.trigger) {
		if (ostate != SNDRV_PCM_STATE_RUNNING &&
		    need_input_retrigger(runtime)) {
			struct snd_pcm_oss_file ofile;
			memset(&ofile, 0, sizeof(ofile));
			ofile.streams[SNDRV_PCM_STREAM_CAPTURE] = pcm_oss_file->streams[SNDRV_PCM_STREAM_CAPTURE];
			runtime->oss.trigger = 0;
			snd_pcm_oss_set_trigger(&ofile, PCM_ENABLE_INPUT);
		}
	}
+30 −13
Original line number Diff line number Diff line
@@ -99,6 +99,9 @@ struct loopback_ops {
struct loopback_cable {
	spinlock_t lock;
	struct loopback_pcm *streams[2];
	/* in-flight peer stops running outside cable->lock */
	atomic_t stop_count;
	wait_queue_head_t stop_wait;
	struct snd_pcm_hardware hw;
	/* flags */
	unsigned int valid;
@@ -366,9 +369,12 @@ static int loopback_check_format(struct loopback_cable *cable, int stream)
				return 0;
			if (stream == SNDRV_PCM_STREAM_CAPTURE)
				return -EIO;
			else if (cruntime->state == SNDRV_PCM_STATE_RUNNING)
			else if (cruntime->state == SNDRV_PCM_STATE_RUNNING) {
				/* close must not free the peer runtime below */
				atomic_inc(&cable->stop_count);
				stop_capture = true;
			}
		}

		setup = get_setup(dpcm_play);
		card = dpcm_play->loopback->card;
@@ -396,8 +402,11 @@ static int loopback_check_format(struct loopback_cable *cable, int stream)
		}
	}

	if (stop_capture)
	if (stop_capture) {
		snd_pcm_stop(dpcm_capt->substream, SNDRV_PCM_STATE_DRAINING);
		if (atomic_dec_and_test(&cable->stop_count))
			wake_up(&cable->stop_wait);
	}

	return 0;
}
@@ -1049,24 +1058,30 @@ static void free_cable(struct snd_pcm_substream *substream)
	struct loopback *loopback = substream->private_data;
	int dev = get_cable_index(substream);
	struct loopback_cable *cable;
	struct loopback_pcm *dpcm;
	bool other_alive;

	cable = loopback->cables[substream->number][dev];
	if (!cable)
		return;
	if (cable->streams[!substream->stream]) {
		/* other stream is still alive */
		guard(spinlock_irq)(&cable->lock);

	scoped_guard(spinlock_irq, &cable->lock) {
		cable->streams[substream->stream] = NULL;
	} else {
		struct loopback_pcm *dpcm = substream->runtime->private_data;
		other_alive = cable->streams[!substream->stream];
	}

	/* Pair with the stop_count increment in loopback_check_format(). */
	wait_event(cable->stop_wait, !atomic_read(&cable->stop_count));
	if (other_alive)
		return;

	dpcm = substream->runtime->private_data;
	if (cable->ops && cable->ops->close_cable && dpcm)
		cable->ops->close_cable(dpcm);
	/* free the cable */
	loopback->cables[substream->number][dev] = NULL;
	kfree(cable);
}
}

static int loopback_jiffies_timer_open(struct loopback_pcm *dpcm)
{
@@ -1260,6 +1275,8 @@ static int loopback_open(struct snd_pcm_substream *substream)
			goto unlock;
		}
		spin_lock_init(&cable->lock);
		atomic_set(&cable->stop_count, 0);
		init_waitqueue_head(&cable->stop_wait);
		cable->hw = loopback_pcm_hardware;
		if (loopback->timer_source)
			cable->ops = &loopback_snd_timer_ops;
+0 −2
Original line number Diff line number Diff line
@@ -7,7 +7,6 @@ snd-hda-codec-cm9825-y := cm9825.o
snd-hda-codec-analog-y :=	analog.o
snd-hda-codec-ca0110-y :=	ca0110.o
snd-hda-codec-ca0132-y :=	ca0132.o
snd-hda-codec-cmedia-y :=	cmedia.o
snd-hda-codec-conexant-y :=	conexant.o
snd-hda-codec-idt-y :=		sigmatel.o
snd-hda-codec-senarytech-y :=	senarytech.o
@@ -26,7 +25,6 @@ obj-$(CONFIG_SND_HDA_CODEC_CM9825) += snd-hda-codec-cm9825.o
obj-$(CONFIG_SND_HDA_CODEC_ANALOG) += snd-hda-codec-analog.o
obj-$(CONFIG_SND_HDA_CODEC_CA0110) += snd-hda-codec-ca0110.o
obj-$(CONFIG_SND_HDA_CODEC_CA0132) += snd-hda-codec-ca0132.o
obj-$(CONFIG_SND_HDA_CODEC_CMEDIA) += snd-hda-codec-cmedia.o
obj-$(CONFIG_SND_HDA_CODEC_CONEXANT) += snd-hda-codec-conexant.o
obj-$(CONFIG_SND_HDA_CODEC_SIGMATEL) += snd-hda-codec-idt.o
obj-$(CONFIG_SND_HDA_CODEC_SENARYTECH) += snd-hda-codec-senarytech.o
+7 −1
Original line number Diff line number Diff line
@@ -1175,6 +1175,7 @@ static void add_cx5051_fake_mutes(struct hda_codec *codec)
static int cx_probe(struct hda_codec *codec, const struct hda_device_id *id)
{
	struct conexant_spec *spec;
	struct hda_jack_callback *callback;
	int err;

	codec_info(codec, "%s: BIOS auto-probing.\n", codec->core.chip_name);
@@ -1190,7 +1191,12 @@ static int cx_probe(struct hda_codec *codec, const struct hda_device_id *id)
	case 0x14f11f86:
	case 0x14f11f87:
		spec->is_cx11880_sn6140 = true;
		snd_hda_jack_detect_enable_callback(codec, 0x19, cx_update_headset_mic_vref);
		callback = snd_hda_jack_detect_enable_callback(codec, 0x19,
				cx_update_headset_mic_vref);
		if (IS_ERR(callback)) {
			err = PTR_ERR(callback);
			goto error;
		}
		break;
	}

+13 −1
Original line number Diff line number Diff line
@@ -3694,6 +3694,17 @@ static void alc287_fixup_lenovo_thinkpad_with_alc1318(struct hda_codec *codec,
	spec->power_hook = alc287_s4_power_gpio3_default;
	spec->gen.pcm_playback_hook = alc287_alc1318_playback_pcm_hook;
}

static void alc287_fixup_tb_vmaster_led(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->gen.vmaster_mute_led = 1;

	alc287_fixup_bind_dacs(codec, fix, action);
}
/* GPIO2: mute led GPIO3: micmute led */
static void alc245_tas2781_spi_hp_fixup_muteled(struct hda_codec *codec,
					  const struct hda_fixup *fix, int action)
@@ -6448,7 +6459,7 @@ static const struct hda_fixup alc269_fixups[] = {
	},
	[ALC287_FIXUP_MG_RTKC_CSAMP_CS35L41_I2C_THINKPAD] = {
		.type = HDA_FIXUP_FUNC,
		.v.func = alc287_fixup_bind_dacs,
		.v.func = alc287_fixup_tb_vmaster_led,
		.chained = true,
		.chain_id = ALC287_FIXUP_CS35L41_I2C_2_THINKPAD_ACPI,
	},
@@ -6717,6 +6728,7 @@ static const struct hda_quirk alc269_fixup_tbl[] = {
	SND_PCI_QUIRK(0x1025, 0x159c, "Acer Nitro 5 AN515-58", ALC2XX_FIXUP_HEADSET_MIC),
	SND_PCI_QUIRK(0x1025, 0x1597, "Acer Nitro 5 AN517-55", ALC2XX_FIXUP_HEADSET_MIC),
	SND_PCI_QUIRK(0x1025, 0x160e, "Acer PT316-51S", ALC2XX_FIXUP_HEADSET_MIC),
	SND_PCI_QUIRK(0x1025, 0x1640, "Acer Aspire A315-44P", ALC256_FIXUP_ACER_SFG16_MICMUTE_LED),
	SND_PCI_QUIRK(0x1025, 0x1679, "Acer Nitro 16 AN16-41", ALC2XX_FIXUP_HEADSET_MIC),
	SND_PCI_QUIRK(0x1025, 0x169a, "Acer Swift SFG16", ALC256_FIXUP_ACER_SFG16_MICMUTE_LED),
	SND_PCI_QUIRK(0x1025, 0x171e, "Acer Nitro ANV15-51", ALC245_FIXUP_ACER_MICMUTE_LED),
Loading