Commit ce18d3aa authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull sound fixes from Takashi Iwai:
 "A bit higher volume of changes than wished, but each change is
  relatively small and the fix targets are mostly device-specific, so
  those should be safe as a late stage merge.

  The most significant LoC is about the memalloc helper fix, which is
  applied only to Xen PV. The other major parts are ASoC Intel SOF and
  AVS fixes that are scattered as various small code changes. The rest
  are device-specific fixes and quirks for HD- and USB-audio, FireWire
  and ASoC AMD / HDMI"

* tag 'sound-6.2-rc7' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound: (30 commits)
  ALSA: firewire-motu: fix unreleased lock warning in hwdep device
  ALSA: memalloc: Workaround for Xen PV
  ASoC: cs42l56: fix DT probe
  ASoC: codecs: wsa883x: correct playback min/max rates
  ALSA: hda/realtek: Add Acer Predator PH315-54
  ASoC: amd: yc: Add Xiaomi Redmi Book Pro 15 2022 into DMI table
  ALSA: hda: Do not unset preset when cleaning up codec
  ASoC: SOF: sof-audio: prepare_widgets: Check swidget for NULL on sink failure
  ASoC: hdmi-codec: zero clear HDMI pdata
  ASoC: SOF: ipc4-mtrace: prevent underflow in sof_ipc4_priority_mask_dfs_write()
  ASoC: Intel: sof_ssp_amp: always set dpcm_capture for amplifiers
  ASoC: Intel: sof_nau8825: always set dpcm_capture for amplifiers
  ASoC: Intel: sof_cs42l42: always set dpcm_capture for amplifiers
  ASoC: Intel: sof_rt5682: always set dpcm_capture for amplifiers
  ALSA: hda/via: Avoid potential array out-of-bound in add_secret_dac_path()
  ALSA: usb-audio: Add FIXED_RATE quirk for JBL Quantum610 Wireless
  ALSA: hda/realtek: fix mute/micmute LEDs, speaker don't work for a HP platform
  ASoC: SOF: keep prepare/unprepare widgets in sink path
  ASoC: SOF: sof-audio: skip prepare/unprepare if swidget is NULL
  ASoC: SOF: sof-audio: unprepare when swidget->use_count > 0
  ...
parents c0b67534 c7a806d9
Loading
Loading
Loading
Loading
+3 −1
Original line number Diff line number Diff line
@@ -819,8 +819,10 @@ static int ioctl_send_response(struct client *client, union ioctl_arg *arg)

	r = container_of(resource, struct inbound_transaction_resource,
			 resource);
	if (is_fcp_request(r->request))
	if (is_fcp_request(r->request)) {
		kfree(r->data);
		goto out;
	}

	if (a->length != fw_get_response_length(r->request)) {
		ret = -EINVAL;
+1 −0
Original line number Diff line number Diff line
@@ -193,6 +193,7 @@ static int snd_dw_hdmi_probe(struct platform_device *pdev)
	struct hdmi_codec_pdata pdata;
	struct platform_device *platform;

	memset(&pdata, 0, sizeof(pdata));
	pdata.ops		= &dw_hdmi_i2s_ops;
	pdata.i2s		= 1;
	pdata.max_i2s_channels	= 8;
+69 −18
Original line number Diff line number Diff line
@@ -541,16 +541,15 @@ static void *snd_dma_noncontig_alloc(struct snd_dma_buffer *dmab, size_t size)
	struct sg_table *sgt;
	void *p;

#ifdef CONFIG_SND_DMA_SGBUF
	if (cpu_feature_enabled(X86_FEATURE_XENPV))
		return snd_dma_sg_fallback_alloc(dmab, size);
#endif
	sgt = dma_alloc_noncontiguous(dmab->dev.dev, size, dmab->dev.dir,
				      DEFAULT_GFP, 0);
#ifdef CONFIG_SND_DMA_SGBUF
	if (!sgt && !get_dma_ops(dmab->dev.dev)) {
		if (dmab->dev.type == SNDRV_DMA_TYPE_DEV_WC_SG)
			dmab->dev.type = SNDRV_DMA_TYPE_DEV_WC_SG_FALLBACK;
		else
			dmab->dev.type = SNDRV_DMA_TYPE_DEV_SG_FALLBACK;
	if (!sgt && !get_dma_ops(dmab->dev.dev))
		return snd_dma_sg_fallback_alloc(dmab, size);
	}
#endif
	if (!sgt)
		return NULL;
@@ -717,19 +716,38 @@ static const struct snd_malloc_ops snd_dma_sg_wc_ops = {

/* Fallback SG-buffer allocations for x86 */
struct snd_dma_sg_fallback {
	bool use_dma_alloc_coherent;
	size_t count;
	struct page **pages;
	/* DMA address array; the first page contains #pages in ~PAGE_MASK */
	dma_addr_t *addrs;
};

static void __snd_dma_sg_fallback_free(struct snd_dma_buffer *dmab,
				       struct snd_dma_sg_fallback *sgbuf)
{
	bool wc = dmab->dev.type == SNDRV_DMA_TYPE_DEV_WC_SG_FALLBACK;
	size_t i;
	size_t i, size;

	for (i = 0; i < sgbuf->count && sgbuf->pages[i]; i++)
		do_free_pages(page_address(sgbuf->pages[i]), PAGE_SIZE, wc);
	if (sgbuf->pages && sgbuf->addrs) {
		i = 0;
		while (i < sgbuf->count) {
			if (!sgbuf->pages[i] || !sgbuf->addrs[i])
				break;
			size = sgbuf->addrs[i] & ~PAGE_MASK;
			if (WARN_ON(!size))
				break;
			if (sgbuf->use_dma_alloc_coherent)
				dma_free_coherent(dmab->dev.dev, size << PAGE_SHIFT,
						  page_address(sgbuf->pages[i]),
						  sgbuf->addrs[i] & PAGE_MASK);
			else
				do_free_pages(page_address(sgbuf->pages[i]),
					      size << PAGE_SHIFT, false);
			i += size;
		}
	}
	kvfree(sgbuf->pages);
	kvfree(sgbuf->addrs);
	kfree(sgbuf);
}

@@ -738,24 +756,36 @@ static void *snd_dma_sg_fallback_alloc(struct snd_dma_buffer *dmab, size_t size)
	struct snd_dma_sg_fallback *sgbuf;
	struct page **pagep, *curp;
	size_t chunk, npages;
	dma_addr_t *addrp;
	dma_addr_t addr;
	void *p;
	bool wc = dmab->dev.type == SNDRV_DMA_TYPE_DEV_WC_SG_FALLBACK;

	/* correct the type */
	if (dmab->dev.type == SNDRV_DMA_TYPE_DEV_SG)
		dmab->dev.type = SNDRV_DMA_TYPE_DEV_SG_FALLBACK;
	else if (dmab->dev.type == SNDRV_DMA_TYPE_DEV_WC_SG)
		dmab->dev.type = SNDRV_DMA_TYPE_DEV_WC_SG_FALLBACK;

	sgbuf = kzalloc(sizeof(*sgbuf), GFP_KERNEL);
	if (!sgbuf)
		return NULL;
	sgbuf->use_dma_alloc_coherent = cpu_feature_enabled(X86_FEATURE_XENPV);
	size = PAGE_ALIGN(size);
	sgbuf->count = size >> PAGE_SHIFT;
	sgbuf->pages = kvcalloc(sgbuf->count, sizeof(*sgbuf->pages), GFP_KERNEL);
	if (!sgbuf->pages)
	sgbuf->addrs = kvcalloc(sgbuf->count, sizeof(*sgbuf->addrs), GFP_KERNEL);
	if (!sgbuf->pages || !sgbuf->addrs)
		goto error;

	pagep = sgbuf->pages;
	chunk = size;
	addrp = sgbuf->addrs;
	chunk = (PAGE_SIZE - 1) << PAGE_SHIFT; /* to fit in low bits in addrs */
	while (size > 0) {
		chunk = min(size, chunk);
		p = do_alloc_pages(dmab->dev.dev, chunk, &addr, wc);
		if (sgbuf->use_dma_alloc_coherent)
			p = dma_alloc_coherent(dmab->dev.dev, chunk, &addr, DEFAULT_GFP);
		else
			p = do_alloc_pages(dmab->dev.dev, chunk, &addr, false);
		if (!p) {
			if (chunk <= PAGE_SIZE)
				goto error;
@@ -767,17 +797,25 @@ static void *snd_dma_sg_fallback_alloc(struct snd_dma_buffer *dmab, size_t size)
		size -= chunk;
		/* fill pages */
		npages = chunk >> PAGE_SHIFT;
		*addrp = npages; /* store in lower bits */
		curp = virt_to_page(p);
		while (npages--)
		while (npages--) {
			*pagep++ = curp++;
			*addrp++ |= addr;
			addr += PAGE_SIZE;
		}
	}

	p = vmap(sgbuf->pages, sgbuf->count, VM_MAP, PAGE_KERNEL);
	if (!p)
		goto error;

	if (dmab->dev.type == SNDRV_DMA_TYPE_DEV_WC_SG_FALLBACK)
		set_pages_array_wc(sgbuf->pages, sgbuf->count);

	dmab->private_data = sgbuf;
	/* store the first page address for convenience */
	dmab->addr = snd_sgbuf_get_addr(dmab, 0);
	dmab->addr = sgbuf->addrs[0] & PAGE_MASK;
	return p;

 error:
@@ -787,10 +825,23 @@ static void *snd_dma_sg_fallback_alloc(struct snd_dma_buffer *dmab, size_t size)

static void snd_dma_sg_fallback_free(struct snd_dma_buffer *dmab)
{
	struct snd_dma_sg_fallback *sgbuf = dmab->private_data;

	if (dmab->dev.type == SNDRV_DMA_TYPE_DEV_WC_SG_FALLBACK)
		set_pages_array_wb(sgbuf->pages, sgbuf->count);
	vunmap(dmab->area);
	__snd_dma_sg_fallback_free(dmab, dmab->private_data);
}

static dma_addr_t snd_dma_sg_fallback_get_addr(struct snd_dma_buffer *dmab,
					       size_t offset)
{
	struct snd_dma_sg_fallback *sgbuf = dmab->private_data;
	size_t index = offset >> PAGE_SHIFT;

	return (sgbuf->addrs[index] & PAGE_MASK) | (offset & ~PAGE_MASK);
}

static int snd_dma_sg_fallback_mmap(struct snd_dma_buffer *dmab,
				    struct vm_area_struct *area)
{
@@ -805,8 +856,8 @@ static const struct snd_malloc_ops snd_dma_sg_fallback_ops = {
	.alloc = snd_dma_sg_fallback_alloc,
	.free = snd_dma_sg_fallback_free,
	.mmap = snd_dma_sg_fallback_mmap,
	.get_addr = snd_dma_sg_fallback_get_addr,
	/* reuse vmalloc helpers */
	.get_addr = snd_dma_vmalloc_get_addr,
	.get_page = snd_dma_vmalloc_get_page,
	.get_chunk_size = snd_dma_vmalloc_get_chunk_size,
};
+4 −0
Original line number Diff line number Diff line
@@ -87,6 +87,10 @@ static long hwdep_read(struct snd_hwdep *hwdep, char __user *buf, long count,
			return -EFAULT;

		count = consumed;
	} else {
		spin_unlock_irq(&motu->lock);

		count = 0;
	}

	return count;
+2 −0
Original line number Diff line number Diff line
@@ -144,6 +144,7 @@ static int hda_codec_driver_probe(struct device *dev)

 error:
	snd_hda_codec_cleanup_for_unbind(codec);
	codec->preset = NULL;
	return err;
}

@@ -166,6 +167,7 @@ static int hda_codec_driver_remove(struct device *dev)
	if (codec->patch_ops.free)
		codec->patch_ops.free(codec);
	snd_hda_codec_cleanup_for_unbind(codec);
	codec->preset = NULL;
	module_put(dev->driver->owner);
	return 0;
}
Loading