diff options
author | Mark Brown | 2022-10-19 16:37:01 +0100 |
---|---|---|
committer | Mark Brown | 2022-10-19 16:37:01 +0100 |
commit | 008f05a72d32dcc14038801649ec67af765fcc3c (patch) | |
tree | c958a2ab7039ea3e03621b1cbae4fcad41ee947c /sound | |
parent | 32def55d237e8507d4eb8442628fc2e59a899ea0 (diff) | |
parent | df496157a5afa1b6d1f4c46ad6549c2c346d1e59 (diff) |
ASoC: jz4752b: Capture fixes
Merge series from Siarhei Volkau <lis8215@gmail.com>:
The patchset fixes:
- Line In path stays powered off during capturing or
bypass to mixer.
- incorrectly represented dB values in alsamixer, et al.
- incorrect represented Capture input selector in alsamixer
in Playback tab.
- wrong control selected as Capture Master
Diffstat (limited to 'sound')
165 files changed, 1543 insertions, 1200 deletions
diff --git a/sound/aoa/codecs/onyx.c b/sound/aoa/codecs/onyx.c index 1abee841cc45..2d0f904aba00 100644 --- a/sound/aoa/codecs/onyx.c +++ b/sound/aoa/codecs/onyx.c @@ -1029,7 +1029,7 @@ static int onyx_i2c_probe(struct i2c_client *client, return -ENODEV; } -static int onyx_i2c_remove(struct i2c_client *client) +static void onyx_i2c_remove(struct i2c_client *client) { struct onyx *onyx = i2c_get_clientdata(client); @@ -1037,7 +1037,6 @@ static int onyx_i2c_remove(struct i2c_client *client) of_node_put(onyx->codec.node); kfree(onyx->codec_info); kfree(onyx); - return 0; } static const struct i2c_device_id onyx_i2c_id[] = { diff --git a/sound/aoa/codecs/tas.c b/sound/aoa/codecs/tas.c index ab19a37e2a68..ab89475b7715 100644 --- a/sound/aoa/codecs/tas.c +++ b/sound/aoa/codecs/tas.c @@ -912,7 +912,7 @@ static int tas_i2c_probe(struct i2c_client *client, return -EINVAL; } -static int tas_i2c_remove(struct i2c_client *client) +static void tas_i2c_remove(struct i2c_client *client) { struct tas *tas = i2c_get_clientdata(client); u8 tmp = TAS_ACR_ANALOG_PDOWN; @@ -925,7 +925,6 @@ static int tas_i2c_remove(struct i2c_client *client) mutex_destroy(&tas->mtx); kfree(tas); - return 0; } static const struct i2c_device_id tas_i2c_id[] = { diff --git a/sound/core/init.c b/sound/core/init.c index 193dae361fac..5377f94eb211 100644 --- a/sound/core/init.c +++ b/sound/core/init.c @@ -178,10 +178,8 @@ int snd_card_new(struct device *parent, int idx, const char *xid, return -ENOMEM; err = snd_card_init(card, parent, idx, xid, module, extra_size); - if (err < 0) { - kfree(card); - return err; - } + if (err < 0) + return err; /* card is freed by error handler */ *card_ret = card; return 0; @@ -233,7 +231,7 @@ int snd_devm_card_new(struct device *parent, int idx, const char *xid, card->managed = true; err = snd_card_init(card, parent, idx, xid, module, extra_size); if (err < 0) { - devres_free(card); + devres_free(card); /* in managed mode, we need to free manually */ return err; } @@ -297,6 +295,8 @@ static int snd_card_init(struct snd_card *card, struct device *parent, mutex_unlock(&snd_card_mutex); dev_err(parent, "cannot find the slot for index %d (range 0-%i), error: %d\n", idx, snd_ecards_limit - 1, err); + if (!card->managed) + kfree(card); /* manually free here, as no destructor called */ return err; } set_bit(idx, snd_cards_lock); /* lock it */ diff --git a/sound/core/memalloc.c b/sound/core/memalloc.c index cfcd8eff4139..03cffe771366 100644 --- a/sound/core/memalloc.c +++ b/sound/core/memalloc.c @@ -18,25 +18,18 @@ #include <sound/memalloc.h> #include "memalloc_local.h" +#define DEFAULT_GFP \ + (GFP_KERNEL | \ + __GFP_COMP | /* compound page lets parts be mapped */ \ + __GFP_RETRY_MAYFAIL | /* don't trigger OOM-killer */ \ + __GFP_NOWARN) /* no stack trace print - this call is non-critical */ + static const struct snd_malloc_ops *snd_dma_get_ops(struct snd_dma_buffer *dmab); #ifdef CONFIG_SND_DMA_SGBUF -static void *do_alloc_fallback_pages(struct device *dev, size_t size, - dma_addr_t *addr, bool wc); -static void do_free_fallback_pages(void *p, size_t size, bool wc); static void *snd_dma_sg_fallback_alloc(struct snd_dma_buffer *dmab, size_t size); #endif -/* a cast to gfp flag from the dev pointer; for CONTINUOUS and VMALLOC types */ -static inline gfp_t snd_mem_get_gfp_flags(const struct snd_dma_buffer *dmab, - gfp_t default_gfp) -{ - if (!dmab->dev.dev) - return default_gfp; - else - return (__force gfp_t)(unsigned long)dmab->dev.dev; -} - static void *__snd_dma_alloc_pages(struct snd_dma_buffer *dmab, size_t size) { const struct snd_malloc_ops *ops = snd_dma_get_ops(dmab); @@ -284,24 +277,54 @@ EXPORT_SYMBOL(snd_sgbuf_get_chunk_size); /* * Continuous pages allocator */ -static void *do_alloc_pages(size_t size, dma_addr_t *addr, gfp_t gfp) +static void *do_alloc_pages(struct device *dev, size_t size, dma_addr_t *addr, + bool wc) { - void *p = alloc_pages_exact(size, gfp); + void *p; + gfp_t gfp = GFP_KERNEL | __GFP_NORETRY | __GFP_NOWARN; - if (p) - *addr = page_to_phys(virt_to_page(p)); + again: + p = alloc_pages_exact(size, gfp); + if (!p) + return NULL; + *addr = page_to_phys(virt_to_page(p)); + if (!dev) + return p; + if ((*addr + size - 1) & ~dev->coherent_dma_mask) { + if (IS_ENABLED(CONFIG_ZONE_DMA32) && !(gfp & GFP_DMA32)) { + gfp |= GFP_DMA32; + goto again; + } + if (IS_ENABLED(CONFIG_ZONE_DMA) && !(gfp & GFP_DMA)) { + gfp = (gfp & ~GFP_DMA32) | GFP_DMA; + goto again; + } + } +#ifdef CONFIG_X86 + if (wc) + set_memory_wc((unsigned long)(p), size >> PAGE_SHIFT); +#endif return p; } +static void do_free_pages(void *p, size_t size, bool wc) +{ +#ifdef CONFIG_X86 + if (wc) + set_memory_wb((unsigned long)(p), size >> PAGE_SHIFT); +#endif + free_pages_exact(p, size); +} + + static void *snd_dma_continuous_alloc(struct snd_dma_buffer *dmab, size_t size) { - return do_alloc_pages(size, &dmab->addr, - snd_mem_get_gfp_flags(dmab, GFP_KERNEL)); + return do_alloc_pages(dmab->dev.dev, size, &dmab->addr, false); } static void snd_dma_continuous_free(struct snd_dma_buffer *dmab) { - free_pages_exact(dmab->area, dmab->bytes); + do_free_pages(dmab->area, dmab->bytes, false); } static int snd_dma_continuous_mmap(struct snd_dma_buffer *dmab, @@ -324,9 +347,7 @@ static const struct snd_malloc_ops snd_dma_continuous_ops = { */ static void *snd_dma_vmalloc_alloc(struct snd_dma_buffer *dmab, size_t size) { - gfp_t gfp = snd_mem_get_gfp_flags(dmab, GFP_KERNEL | __GFP_HIGHMEM); - - return __vmalloc(size, gfp); + return vmalloc(size); } static void snd_dma_vmalloc_free(struct snd_dma_buffer *dmab) @@ -440,12 +461,6 @@ static const struct snd_malloc_ops snd_dma_iram_ops = { }; #endif /* CONFIG_GENERIC_ALLOCATOR */ -#define DEFAULT_GFP \ - (GFP_KERNEL | \ - __GFP_COMP | /* compound page lets parts be mapped */ \ - __GFP_NORETRY | /* don't trigger OOM-killer */ \ - __GFP_NOWARN) /* no stack trace print - this call is non-critical */ - /* * Coherent device pages allocator */ @@ -479,12 +494,12 @@ static const struct snd_malloc_ops snd_dma_dev_ops = { #ifdef CONFIG_SND_DMA_SGBUF static void *snd_dma_wc_alloc(struct snd_dma_buffer *dmab, size_t size) { - return do_alloc_fallback_pages(dmab->dev.dev, size, &dmab->addr, true); + return do_alloc_pages(dmab->dev.dev, size, &dmab->addr, true); } static void snd_dma_wc_free(struct snd_dma_buffer *dmab) { - do_free_fallback_pages(dmab->area, dmab->bytes, true); + do_free_pages(dmab->area, dmab->bytes, true); } static int snd_dma_wc_mmap(struct snd_dma_buffer *dmab, @@ -700,37 +715,6 @@ static const struct snd_malloc_ops snd_dma_sg_wc_ops = { .get_chunk_size = snd_dma_noncontig_get_chunk_size, }; -/* manual page allocations with wc setup */ -static void *do_alloc_fallback_pages(struct device *dev, size_t size, - dma_addr_t *addr, bool wc) -{ - gfp_t gfp = GFP_KERNEL | __GFP_NORETRY | __GFP_NOWARN; - void *p; - - again: - p = do_alloc_pages(size, addr, gfp); - if (!p || (*addr + size - 1) & ~dev->coherent_dma_mask) { - if (IS_ENABLED(CONFIG_ZONE_DMA32) && !(gfp & GFP_DMA32)) { - gfp |= GFP_DMA32; - goto again; - } - if (IS_ENABLED(CONFIG_ZONE_DMA) && !(gfp & GFP_DMA)) { - gfp = (gfp & ~GFP_DMA32) | GFP_DMA; - goto again; - } - } - if (p && wc) - set_memory_wc((unsigned long)(p), size >> PAGE_SHIFT); - return p; -} - -static void do_free_fallback_pages(void *p, size_t size, bool wc) -{ - if (wc) - set_memory_wb((unsigned long)(p), size >> PAGE_SHIFT); - free_pages_exact(p, size); -} - /* Fallback SG-buffer allocations for x86 */ struct snd_dma_sg_fallback { size_t count; @@ -745,7 +729,7 @@ static void __snd_dma_sg_fallback_free(struct snd_dma_buffer *dmab, size_t i; for (i = 0; i < sgbuf->count && sgbuf->pages[i]; i++) - do_free_fallback_pages(page_address(sgbuf->pages[i]), PAGE_SIZE, wc); + do_free_pages(page_address(sgbuf->pages[i]), PAGE_SIZE, wc); kvfree(sgbuf->pages); kvfree(sgbuf->addrs); kfree(sgbuf); @@ -772,8 +756,7 @@ static void *snd_dma_sg_fallback_alloc(struct snd_dma_buffer *dmab, size_t size) goto error; for (i = 0; i < count; sgbuf->count++, i++) { - p = do_alloc_fallback_pages(dmab->dev.dev, PAGE_SIZE, - &sgbuf->addrs[i], wc); + p = do_alloc_pages(dmab->dev.dev, PAGE_SIZE, &sgbuf->addrs[i], wc); if (!p) goto error; sgbuf->pages[i] = virt_to_page(p); diff --git a/sound/core/memalloc_local.h b/sound/core/memalloc_local.h index a6f3a87194da..8b19f3a68a4b 100644 --- a/sound/core/memalloc_local.h +++ b/sound/core/memalloc_local.h @@ -13,8 +13,4 @@ struct snd_malloc_ops { void (*sync)(struct snd_dma_buffer *dmab, enum snd_dma_sync_mode mode); }; -#ifdef CONFIG_SND_DMA_SGBUF -extern const struct snd_malloc_ops snd_dma_sg_ops; -#endif - #endif /* __MEMALLOC_LOCAL_H */ diff --git a/sound/core/oss/pcm_oss.c b/sound/core/oss/pcm_oss.c index 02df915eb3c6..ac2efeb63a39 100644 --- a/sound/core/oss/pcm_oss.c +++ b/sound/core/oss/pcm_oss.c @@ -1237,12 +1237,12 @@ snd_pcm_sframes_t snd_pcm_oss_write3(struct snd_pcm_substream *substream, const struct snd_pcm_runtime *runtime = substream->runtime; int ret; while (1) { - if (runtime->status->state == SNDRV_PCM_STATE_XRUN || - runtime->status->state == SNDRV_PCM_STATE_SUSPENDED) { + if (runtime->state == SNDRV_PCM_STATE_XRUN || + runtime->state == SNDRV_PCM_STATE_SUSPENDED) { #ifdef OSS_DEBUG pcm_dbg(substream->pcm, "pcm_oss: write: recovering from %s\n", - runtime->status->state == SNDRV_PCM_STATE_XRUN ? + runtime->state == SNDRV_PCM_STATE_XRUN ? "XRUN" : "SUSPEND"); #endif ret = snd_pcm_oss_prepare(substream); @@ -1257,7 +1257,7 @@ snd_pcm_sframes_t snd_pcm_oss_write3(struct snd_pcm_substream *substream, const break; /* test, if we can't store new data, because the stream */ /* has not been started */ - if (runtime->status->state == SNDRV_PCM_STATE_PREPARED) + if (runtime->state == SNDRV_PCM_STATE_PREPARED) return -EAGAIN; } return ret; @@ -1269,18 +1269,18 @@ snd_pcm_sframes_t snd_pcm_oss_read3(struct snd_pcm_substream *substream, char *p snd_pcm_sframes_t delay; int ret; while (1) { - if (runtime->status->state == SNDRV_PCM_STATE_XRUN || - runtime->status->state == SNDRV_PCM_STATE_SUSPENDED) { + if (runtime->state == SNDRV_PCM_STATE_XRUN || + runtime->state == SNDRV_PCM_STATE_SUSPENDED) { #ifdef OSS_DEBUG pcm_dbg(substream->pcm, "pcm_oss: read: recovering from %s\n", - runtime->status->state == SNDRV_PCM_STATE_XRUN ? + runtime->state == SNDRV_PCM_STATE_XRUN ? "XRUN" : "SUSPEND"); #endif ret = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DRAIN, NULL); if (ret < 0) break; - } else if (runtime->status->state == SNDRV_PCM_STATE_SETUP) { + } else if (runtime->state == SNDRV_PCM_STATE_SETUP) { ret = snd_pcm_oss_prepare(substream); if (ret < 0) break; @@ -1293,7 +1293,7 @@ snd_pcm_sframes_t snd_pcm_oss_read3(struct snd_pcm_substream *substream, char *p frames, in_kernel); mutex_lock(&runtime->oss.params_lock); if (ret == -EPIPE) { - if (runtime->status->state == SNDRV_PCM_STATE_DRAINING) { + if (runtime->state == SNDRV_PCM_STATE_DRAINING) { ret = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DROP, NULL); if (ret < 0) break; @@ -1312,12 +1312,12 @@ snd_pcm_sframes_t snd_pcm_oss_writev3(struct snd_pcm_substream *substream, void struct snd_pcm_runtime *runtime = substream->runtime; int ret; while (1) { - if (runtime->status->state == SNDRV_PCM_STATE_XRUN || - runtime->status->state == SNDRV_PCM_STATE_SUSPENDED) { + if (runtime->state == SNDRV_PCM_STATE_XRUN || + runtime->state == SNDRV_PCM_STATE_SUSPENDED) { #ifdef OSS_DEBUG pcm_dbg(substream->pcm, "pcm_oss: writev: recovering from %s\n", - runtime->status->state == SNDRV_PCM_STATE_XRUN ? + runtime->state == SNDRV_PCM_STATE_XRUN ? "XRUN" : "SUSPEND"); #endif ret = snd_pcm_oss_prepare(substream); @@ -1330,7 +1330,7 @@ snd_pcm_sframes_t snd_pcm_oss_writev3(struct snd_pcm_substream *substream, void /* test, if we can't store new data, because the stream */ /* has not been started */ - if (runtime->status->state == SNDRV_PCM_STATE_PREPARED) + if (runtime->state == SNDRV_PCM_STATE_PREPARED) return -EAGAIN; } return ret; @@ -1341,18 +1341,18 @@ snd_pcm_sframes_t snd_pcm_oss_readv3(struct snd_pcm_substream *substream, void * struct snd_pcm_runtime *runtime = substream->runtime; int ret; while (1) { - if (runtime->status->state == SNDRV_PCM_STATE_XRUN || - runtime->status->state == SNDRV_PCM_STATE_SUSPENDED) { + if (runtime->state == SNDRV_PCM_STATE_XRUN || + runtime->state == SNDRV_PCM_STATE_SUSPENDED) { #ifdef OSS_DEBUG pcm_dbg(substream->pcm, "pcm_oss: readv: recovering from %s\n", - runtime->status->state == SNDRV_PCM_STATE_XRUN ? + runtime->state == SNDRV_PCM_STATE_XRUN ? "XRUN" : "SUSPEND"); #endif ret = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DRAIN, NULL); if (ret < 0) break; - } else if (runtime->status->state == SNDRV_PCM_STATE_SETUP) { + } else if (runtime->state == SNDRV_PCM_STATE_SETUP) { ret = snd_pcm_oss_prepare(substream); if (ret < 0) break; @@ -1635,7 +1635,7 @@ static int snd_pcm_oss_sync1(struct snd_pcm_substream *substream, size_t size) result = 0; set_current_state(TASK_INTERRUPTIBLE); snd_pcm_stream_lock_irq(substream); - state = runtime->status->state; + state = runtime->state; snd_pcm_stream_unlock_irq(substream); if (state != SNDRV_PCM_STATE_RUNNING) { set_current_state(TASK_RUNNING); @@ -2854,8 +2854,8 @@ static __poll_t snd_pcm_oss_poll(struct file *file, poll_table * wait) struct snd_pcm_runtime *runtime = psubstream->runtime; poll_wait(file, &runtime->sleep, wait); snd_pcm_stream_lock_irq(psubstream); - if (runtime->status->state != SNDRV_PCM_STATE_DRAINING && - (runtime->status->state != SNDRV_PCM_STATE_RUNNING || + if (runtime->state != SNDRV_PCM_STATE_DRAINING && + (runtime->state != SNDRV_PCM_STATE_RUNNING || snd_pcm_oss_playback_ready(psubstream))) mask |= EPOLLOUT | EPOLLWRNORM; snd_pcm_stream_unlock_irq(psubstream); @@ -2865,7 +2865,7 @@ static __poll_t snd_pcm_oss_poll(struct file *file, poll_table * wait) snd_pcm_state_t ostate; poll_wait(file, &runtime->sleep, wait); snd_pcm_stream_lock_irq(csubstream); - ostate = runtime->status->state; + ostate = runtime->state; if (ostate != SNDRV_PCM_STATE_RUNNING || snd_pcm_oss_capture_ready(csubstream)) mask |= EPOLLIN | EPOLLRDNORM; diff --git a/sound/core/pcm.c b/sound/core/pcm.c index 82925709fa12..9d95e3731123 100644 --- a/sound/core/pcm.c +++ b/sound/core/pcm.c @@ -387,7 +387,7 @@ static void snd_pcm_substream_proc_hw_params_read(struct snd_info_entry *entry, snd_iprintf(buffer, "closed\n"); goto unlock; } - if (runtime->status->state == SNDRV_PCM_STATE_OPEN) { + if (runtime->state == SNDRV_PCM_STATE_OPEN) { snd_iprintf(buffer, "no setup\n"); goto unlock; } @@ -424,7 +424,7 @@ static void snd_pcm_substream_proc_sw_params_read(struct snd_info_entry *entry, snd_iprintf(buffer, "closed\n"); goto unlock; } - if (runtime->status->state == SNDRV_PCM_STATE_OPEN) { + if (runtime->state == SNDRV_PCM_STATE_OPEN) { snd_iprintf(buffer, "no setup\n"); goto unlock; } @@ -970,7 +970,7 @@ int snd_pcm_attach_substream(struct snd_pcm *pcm, int stream, init_waitqueue_head(&runtime->sleep); init_waitqueue_head(&runtime->tsleep); - runtime->status->state = SNDRV_PCM_STATE_OPEN; + __snd_pcm_set_state(runtime, SNDRV_PCM_STATE_OPEN); mutex_init(&runtime->buffer_mutex); atomic_set(&runtime->buffer_accessing, 0); @@ -1112,7 +1112,8 @@ static int snd_pcm_dev_disconnect(struct snd_device *device) if (snd_pcm_running(substream)) snd_pcm_stop(substream, SNDRV_PCM_STATE_DISCONNECTED); /* to be sure, set the state unconditionally */ - substream->runtime->status->state = SNDRV_PCM_STATE_DISCONNECTED; + __snd_pcm_set_state(substream->runtime, + SNDRV_PCM_STATE_DISCONNECTED); wake_up(&substream->runtime->sleep); wake_up(&substream->runtime->tsleep); } diff --git a/sound/core/pcm_compat.c b/sound/core/pcm_compat.c index 917c5b4f19d7..42c2ada8e888 100644 --- a/sound/core/pcm_compat.c +++ b/sound/core/pcm_compat.c @@ -295,7 +295,7 @@ static int snd_pcm_ioctl_xferi_compat(struct snd_pcm_substream *substream, return -ENOTTY; if (substream->stream != dir) return -EINVAL; - if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN) + if (substream->runtime->state == SNDRV_PCM_STATE_OPEN) return -EBADFD; if (get_user(buf, &data32->buf) || @@ -341,7 +341,7 @@ static int snd_pcm_ioctl_xfern_compat(struct snd_pcm_substream *substream, return -ENOTTY; if (substream->stream != dir) return -EINVAL; - if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN) + if (substream->runtime->state == SNDRV_PCM_STATE_OPEN) return -EBADFD; ch = substream->runtime->channels; diff --git a/sound/core/pcm_dmaengine.c b/sound/core/pcm_dmaengine.c index 5b2ca028f5aa..494ec0c207fa 100644 --- a/sound/core/pcm_dmaengine.c +++ b/sound/core/pcm_dmaengine.c @@ -133,12 +133,14 @@ EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_set_config_from_dai_data); static void dmaengine_pcm_dma_complete(void *arg) { + unsigned int new_pos; struct snd_pcm_substream *substream = arg; struct dmaengine_pcm_runtime_data *prtd = substream_to_prtd(substream); - prtd->pos += snd_pcm_lib_period_bytes(substream); - if (prtd->pos >= snd_pcm_lib_buffer_bytes(substream)) - prtd->pos = 0; + new_pos = prtd->pos + snd_pcm_lib_period_bytes(substream); + if (new_pos >= snd_pcm_lib_buffer_bytes(substream)) + new_pos = 0; + prtd->pos = new_pos; snd_pcm_period_elapsed(substream); } diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c index 40751e5aff09..8b6aeb8a78f7 100644 --- a/sound/core/pcm_lib.c +++ b/sound/core/pcm_lib.c @@ -186,7 +186,7 @@ int snd_pcm_update_state(struct snd_pcm_substream *substream, avail = snd_pcm_avail(substream); if (avail > runtime->avail_max) runtime->avail_max = avail; - if (runtime->status->state == SNDRV_PCM_STATE_DRAINING) { + if (runtime->state == SNDRV_PCM_STATE_DRAINING) { if (avail >= runtime->buffer_size) { snd_pcm_drain_done(substream); return -EPIPE; @@ -1911,7 +1911,7 @@ static int wait_for_avail(struct snd_pcm_substream *substream, snd_pcm_stream_lock_irq(substream); set_current_state(TASK_INTERRUPTIBLE); - switch (runtime->status->state) { + switch (runtime->state) { case SNDRV_PCM_STATE_SUSPENDED: err = -ESTRPIPE; goto _endloop; @@ -2099,14 +2099,14 @@ static int pcm_sanity_check(struct snd_pcm_substream *substream) runtime = substream->runtime; if (snd_BUG_ON(!substream->ops->copy_user && !runtime->dma_area)) return -EINVAL; - if (runtime->status->state == SNDRV_PCM_STATE_OPEN) + if (runtime->state == SNDRV_PCM_STATE_OPEN) return -EBADFD; return 0; } static int pcm_accessible_state(struct snd_pcm_runtime *runtime) { - switch (runtime->status->state) { + switch (runtime->state) { case SNDRV_PCM_STATE_PREPARED: case SNDRV_PCM_STATE_RUNNING: case SNDRV_PCM_STATE_PAUSED: @@ -2225,7 +2225,7 @@ snd_pcm_sframes_t __snd_pcm_lib_xfer(struct snd_pcm_substream *substream, goto _end_unlock; runtime->twake = runtime->control->avail_min ? : 1; - if (runtime->status->state == SNDRV_PCM_STATE_RUNNING) + if (runtime->state == SNDRV_PCM_STATE_RUNNING) snd_pcm_update_hw_ptr(substream); /* @@ -2233,7 +2233,7 @@ snd_pcm_sframes_t __snd_pcm_lib_xfer(struct snd_pcm_substream *substream, * thread may start capture */ if (!is_playback && - runtime->status->state == SNDRV_PCM_STATE_PREPARED && + runtime->state == SNDRV_PCM_STATE_PREPARED && size >= runtime->start_threshold) { err = snd_pcm_start(substream); if (err < 0) @@ -2247,7 +2247,7 @@ snd_pcm_sframes_t __snd_pcm_lib_xfer(struct snd_pcm_substream *substream, snd_pcm_uframes_t cont; if (!avail) { if (!is_playback && - runtime->status->state == SNDRV_PCM_STATE_DRAINING) { + runtime->state == SNDRV_PCM_STATE_DRAINING) { snd_pcm_stop(substream, SNDRV_PCM_STATE_SETUP); goto _end_unlock; } @@ -2303,7 +2303,7 @@ snd_pcm_sframes_t __snd_pcm_lib_xfer(struct snd_pcm_substream *substream, xfer += frames; avail -= frames; if (is_playback && - runtime->status->state == SNDRV_PCM_STATE_PREPARED && + runtime->state == SNDRV_PCM_STATE_PREPARED && snd_pcm_playback_hw_avail(runtime) >= (snd_pcm_sframes_t)runtime->start_threshold) { err = snd_pcm_start(substream); if (err < 0) diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c index ad0541e9e888..33769ca78cc8 100644 --- a/sound/core/pcm_native.c +++ b/sound/core/pcm_native.c @@ -595,8 +595,8 @@ static void snd_pcm_set_state(struct snd_pcm_substream *substream, snd_pcm_state_t state) { snd_pcm_stream_lock_irq(substream); - if (substream->runtime->status->state != SNDRV_PCM_STATE_DISCONNECTED) - substream->runtime->status->state = state; + if (substream->runtime->state != SNDRV_PCM_STATE_DISCONNECTED) + __snd_pcm_set_state(substream->runtime, state); snd_pcm_stream_unlock_irq(substream); } @@ -724,7 +724,7 @@ static int snd_pcm_hw_params(struct snd_pcm_substream *substream, if (err < 0) return err; snd_pcm_stream_lock_irq(substream); - switch (runtime->status->state) { + switch (runtime->state) { case SNDRV_PCM_STATE_OPEN: case SNDRV_PCM_STATE_SETUP: case SNDRV_PCM_STATE_PREPARED: @@ -889,7 +889,7 @@ static int snd_pcm_hw_free(struct snd_pcm_substream *substream) if (result < 0) return result; snd_pcm_stream_lock_irq(substream); - switch (runtime->status->state) { + switch (runtime->state) { case SNDRV_PCM_STATE_SETUP: case SNDRV_PCM_STATE_PREPARED: if (atomic_read(&substream->mmap_count)) @@ -920,7 +920,7 @@ static int snd_pcm_sw_params(struct snd_pcm_substream *substream, return -ENXIO; runtime = substream->runtime; snd_pcm_stream_lock_irq(substream); - if (runtime->status->state == SNDRV_PCM_STATE_OPEN) { + if (runtime->state == SNDRV_PCM_STATE_OPEN) { snd_pcm_stream_unlock_irq(substream); return -EBADFD; } @@ -1013,8 +1013,8 @@ int snd_pcm_status64(struct snd_pcm_substream *substream, } else runtime->audio_tstamp_report.valid = 1; - status->state = runtime->status->state; - status->suspended_state = runtime->status->suspended_state; + status->state = runtime->state; + status->suspended_state = runtime->suspended_state; if (status->state == SNDRV_PCM_STATE_OPEN) goto _end; status->trigger_tstamp_sec = runtime->trigger_tstamp.tv_sec; @@ -1148,7 +1148,7 @@ static int snd_pcm_channel_info(struct snd_pcm_substream *substream, channel = info->channel; runtime = substream->runtime; snd_pcm_stream_lock_irq(substream); - if (runtime->status->state == SNDRV_PCM_STATE_OPEN) { + if (runtime->state == SNDRV_PCM_STATE_OPEN) { snd_pcm_stream_unlock_irq(substream); return -EBADFD; } @@ -1411,7 +1411,7 @@ static int snd_pcm_pre_start(struct snd_pcm_substream *substream, snd_pcm_state_t state) { struct snd_pcm_runtime *runtime = substream->runtime; - if (runtime->status->state != SNDRV_PCM_STATE_PREPARED) + if (runtime->state != SNDRV_PCM_STATE_PREPARED) return -EBADFD; if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK && !snd_pcm_playback_data(substream)) @@ -1444,7 +1444,7 @@ static void snd_pcm_post_start(struct snd_pcm_substream *substream, runtime->hw_ptr_jiffies = jiffies; runtime->hw_ptr_buffer_jiffies = (runtime->buffer_size * HZ) / runtime->rate; - runtime->status->state = state; + __snd_pcm_set_state(runtime, state); if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK && runtime->silence_size > 0) snd_pcm_playback_silence(substream, ULONG_MAX); @@ -1485,7 +1485,7 @@ static int snd_pcm_pre_stop(struct snd_pcm_substream *substream, snd_pcm_state_t state) { struct snd_pcm_runtime *runtime = substream->runtime; - if (runtime->status->state == SNDRV_PCM_STATE_OPEN) + if (runtime->state == SNDRV_PCM_STATE_OPEN) return -EBADFD; runtime->trigger_master = substream; return 0; @@ -1506,9 +1506,9 @@ static void snd_pcm_post_stop(struct snd_pcm_substream *substream, snd_pcm_state_t state) { struct snd_pcm_runtime *runtime = substream->runtime; - if (runtime->status->state != state) { + if (runtime->state != state) { snd_pcm_trigger_tstamp(substream); - runtime->status->state = state; + __snd_pcm_set_state(runtime, state); snd_pcm_timer_notify(substream, SNDRV_TIMER_EVENT_MSTOP); } wake_up(&runtime->sleep); @@ -1584,9 +1584,9 @@ static int snd_pcm_pre_pause(struct snd_pcm_substream *substream, if (!(runtime->info & SNDRV_PCM_INFO_PAUSE)) return -ENOSYS; if (pause_pushed(state)) { - if (runtime->status->state != SNDRV_PCM_STATE_RUNNING) + if (runtime->state != SNDRV_PCM_STATE_RUNNING) return -EBADFD; - } else if (runtime->status->state != SNDRV_PCM_STATE_PAUSED) + } else if (runtime->state != SNDRV_PCM_STATE_PAUSED) return -EBADFD; runtime->trigger_master = substream; return 0; @@ -1628,12 +1628,12 @@ static void snd_pcm_post_pause(struct snd_pcm_substream *substream, struct snd_pcm_runtime *runtime = substream->runtime; snd_pcm_trigger_tstamp(substream); if (pause_pushed(state)) { - runtime->status->state = SNDRV_PCM_STATE_PAUSED; + __snd_pcm_set_state(runtime, SNDRV_PCM_STATE_PAUSED); snd_pcm_timer_notify(substream, SNDRV_TIMER_EVENT_MPAUSE); wake_up(&runtime->sleep); wake_up(&runtime->tsleep); } else { - runtime->status->state = SNDRV_PCM_STATE_RUNNING; + __snd_pcm_set_state(runtime, SNDRV_PCM_STATE_RUNNING); snd_pcm_timer_notify(substream, SNDRV_TIMER_EVENT_MCONTINUE); } } @@ -1668,7 +1668,7 @@ static int snd_pcm_pre_suspend(struct snd_pcm_substream *substream, snd_pcm_state_t state) { struct snd_pcm_runtime *runtime = substream->runtime; - switch (runtime->status->state) { + switch (runtime->state) { case SNDRV_PCM_STATE_SUSPENDED: return -EBUSY; /* unresumable PCM state; return -EBUSY for skipping suspend */ @@ -1699,8 +1699,9 @@ static void snd_pcm_post_suspend(struct snd_pcm_substream *substream, { struct snd_pcm_runtime *runtime = substream->runtime; snd_pcm_trigger_tstamp(substream); - runtime->status->suspended_state = runtime->status->state; - runtime->status->state = SNDRV_PCM_STATE_SUSPENDED; + runtime->suspended_state = runtime->state; + runtime->status->suspended_state = runtime->suspended_state; + __snd_pcm_set_state(runtime, SNDRV_PCM_STATE_SUSPENDED); snd_pcm_timer_notify(substream, SNDRV_TIMER_EVENT_MSUSPEND); wake_up(&runtime->sleep); wake_up(&runtime->tsleep); @@ -1791,8 +1792,8 @@ static int snd_pcm_do_resume(struct snd_pcm_substream *substream, if (runtime->trigger_master != substream) return 0; /* DMA not running previously? */ - if (runtime->status->suspended_state != SNDRV_PCM_STATE_RUNNING && - (runtime->status->suspended_state != SNDRV_PCM_STATE_DRAINING || + if (runtime->suspended_state != SNDRV_PCM_STATE_RUNNING && + (runtime->suspended_state != SNDRV_PCM_STATE_DRAINING || substream->stream != SNDRV_PCM_STREAM_PLAYBACK)) return 0; return substream->ops->trigger(substream, SNDRV_PCM_TRIGGER_RESUME); @@ -1811,7 +1812,7 @@ static void snd_pcm_post_resume(struct snd_pcm_substream *substream, { struct snd_pcm_runtime *runtime = substream->runtime; snd_pcm_trigger_tstamp(substream); - runtime->status->state = runtime->status->suspended_state; + __snd_pcm_set_state(runtime, runtime->suspended_state); snd_pcm_timer_notify(substream, SNDRV_TIMER_EVENT_MRESUME); } @@ -1848,7 +1849,7 @@ static int snd_pcm_xrun(struct snd_pcm_substream *substream) int result; snd_pcm_stream_lock_irq(substream); - switch (runtime->status->state) { + switch (runtime->state) { case SNDRV_PCM_STATE_XRUN: result = 0; /* already there */ break; @@ -1871,7 +1872,7 @@ static int snd_pcm_pre_reset(struct snd_pcm_substream *substream, snd_pcm_state_t state) { struct snd_pcm_runtime *runtime = substream->runtime; - switch (runtime->status->state) { + switch (runtime->state) { case SNDRV_PCM_STATE_RUNNING: case SNDRV_PCM_STATE_PREPARED: case SNDRV_PCM_STATE_PAUSED: @@ -1933,8 +1934,8 @@ static int snd_pcm_pre_prepare(struct snd_pcm_substream *substream, struct snd_pcm_runtime *runtime = substream->runtime; int f_flags = (__force int)state; - if (runtime->status->state == SNDRV_PCM_STATE_OPEN || - runtime->status->state == SNDRV_PCM_STATE_DISCONNECTED) + if (runtime->state == SNDRV_PCM_STATE_OPEN || + runtime->state == SNDRV_PCM_STATE_DISCONNECTED) return -EBADFD; if (snd_pcm_running(substream)) return -EBUSY; @@ -1985,7 +1986,7 @@ static int snd_pcm_prepare(struct snd_pcm_substream *substream, f_flags = substream->f_flags; snd_pcm_stream_lock_irq(substream); - switch (substream->runtime->status->state) { + switch (substream->runtime->state) { case SNDRV_PCM_STATE_PAUSED: snd_pcm_pause(substream, false); fallthrough; @@ -2009,7 +2010,7 @@ static int snd_pcm_pre_drain_init(struct snd_pcm_substream *substream, snd_pcm_state_t state) { struct snd_pcm_runtime *runtime = substream->runtime; - switch (runtime->status->state) { + switch (runtime->state) { case SNDRV_PCM_STATE_OPEN: case SNDRV_PCM_STATE_DISCONNECTED: case SNDRV_PCM_STATE_SUSPENDED: @@ -2024,28 +2025,28 @@ static int snd_pcm_do_drain_init(struct snd_pcm_substream *substream, { struct snd_pcm_runtime *runtime = substream->runtime; if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { - switch (runtime->status->state) { + switch (runtime->state) { case SNDRV_PCM_STATE_PREPARED: /* start playback stream if possible */ if (! snd_pcm_playback_empty(substream)) { snd_pcm_do_start(substream, SNDRV_PCM_STATE_DRAINING); snd_pcm_post_start(substream, SNDRV_PCM_STATE_DRAINING); } else { - runtime->status->state = SNDRV_PCM_STATE_SETUP; + __snd_pcm_set_state(runtime, SNDRV_PCM_STATE_SETUP); } break; case SNDRV_PCM_STATE_RUNNING: - runtime->status->state = SNDRV_PCM_STATE_DRAINING; + __snd_pcm_set_state(runtime, SNDRV_PCM_STATE_DRAINING); break; case SNDRV_PCM_STATE_XRUN: - runtime->status->state = SNDRV_PCM_STATE_SETUP; + __snd_pcm_set_state(runtime, SNDRV_PCM_STATE_SETUP); break; default: break; } } else { /* stop running stream */ - if (runtime->status->state == SNDRV_PCM_STATE_RUNNING) { + if (runtime->state == SNDRV_PCM_STATE_RUNNING) { snd_pcm_state_t new_state; new_state = snd_pcm_capture_avail(runtime) > 0 ? @@ -2055,7 +2056,7 @@ static int snd_pcm_do_drain_init(struct snd_pcm_substream *substream, } } - if (runtime->status->state == SNDRV_PCM_STATE_DRAINING && + if (runtime->state == SNDRV_PCM_STATE_DRAINING && runtime->trigger_master == substream && (runtime->hw.info & SNDRV_PCM_INFO_DRAIN_TRIGGER)) return substream->ops->trigger(substream, @@ -2096,7 +2097,7 @@ static int snd_pcm_drain(struct snd_pcm_substream *substream, card = substream->pcm->card; runtime = substream->runtime; - if (runtime->status->state == SNDRV_PCM_STATE_OPEN) + if (runtime->state == SNDRV_PCM_STATE_OPEN) return -EBADFD; if (file) { @@ -2107,7 +2108,7 @@ static int snd_pcm_drain(struct snd_pcm_substream *substream, snd_pcm_stream_lock_irq(substream); /* resume pause */ - if (runtime->status->state == SNDRV_PCM_STATE_PAUSED) + if (runtime->state == SNDRV_PCM_STATE_PAUSED) snd_pcm_pause(substream, false); /* pre-start/stop - all running streams are changed to DRAINING state */ @@ -2135,7 +2136,7 @@ static int snd_pcm_drain(struct snd_pcm_substream *substream, if (s->stream != SNDRV_PCM_STREAM_PLAYBACK) continue; runtime = s->runtime; - if (runtime->status->state == SNDRV_PCM_STATE_DRAINING) { + if (runtime->state == SNDRV_PCM_STATE_DRAINING) { to_check = runtime; break; } @@ -2174,7 +2175,7 @@ static int snd_pcm_drain(struct snd_pcm_substream *substream, break; } if (tout == 0) { - if (substream->runtime->status->state == SNDRV_PCM_STATE_SUSPENDED) + if (substream->runtime->state == SNDRV_PCM_STATE_SUSPENDED) result = -ESTRPIPE; else { dev_dbg(substream->pcm->card->dev, @@ -2206,13 +2207,13 @@ static int snd_pcm_drop(struct snd_pcm_substream *substream) return -ENXIO; runtime = substream->runtime; - if (runtime->status->state == SNDRV_PCM_STATE_OPEN || - runtime->status->state == SNDRV_PCM_STATE_DISCONNECTED) + if (runtime->state == SNDRV_PCM_STATE_OPEN || + runtime->state == SNDRV_PCM_STATE_DISCONNECTED) return -EBADFD; snd_pcm_stream_lock_irq(substream); /* resume pause */ - if (runtime->status->state == SNDRV_PCM_STATE_PAUSED) + if (runtime->state == SNDRV_PCM_STATE_PAUSED) snd_pcm_pause(substream, false); snd_pcm_stop(substream, SNDRV_PCM_STATE_SETUP); @@ -2275,8 +2276,8 @@ static int snd_pcm_link(struct snd_pcm_substream *substream, int fd) snd_pcm_group_init(group); down_write(&snd_pcm_link_rwsem); - if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN || - substream->runtime->status->state != substream1->runtime->status->state || + if (substream->runtime->state == SNDRV_PCM_STATE_OPEN || + substream->runtime->state != substream1->runtime->state || substream->pcm->nonatomic != substream1->pcm->nonatomic) { res = -EBADFD; goto _end; @@ -2700,7 +2701,7 @@ void snd_pcm_release_substream(struct snd_pcm_substream *substream) snd_pcm_drop(substream); if (substream->hw_opened) { - if (substream->runtime->status->state != SNDRV_PCM_STATE_OPEN) + if (substream->runtime->state != SNDRV_PCM_STATE_OPEN) do_hw_free(substream); substream->ops->close(substream); substream->hw_opened = 0; @@ -2904,7 +2905,7 @@ static int snd_pcm_release(struct inode *inode, struct file *file) */ static int do_pcm_hwsync(struct snd_pcm_substream *substream) { - switch (substream->runtime->status->state) { + switch (substream->runtime->state) { case SNDRV_PCM_STATE_DRAINING: if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) return -EBADFD; @@ -3203,7 +3204,7 @@ static int snd_pcm_xferi_frames_ioctl(struct snd_pcm_substream *substream, struct snd_pcm_runtime *runtime = substream->runtime; snd_pcm_sframes_t result; - if (runtime->status->state == SNDRV_PCM_STATE_OPEN) + if (runtime->state == SNDRV_PCM_STATE_OPEN) return -EBADFD; if (put_user(0, &_xferi->result)) return -EFAULT; @@ -3226,7 +3227,7 @@ static int snd_pcm_xfern_frames_ioctl(struct snd_pcm_substream *substream, void *bufs; snd_pcm_sframes_t result; - if (runtime->status->state == SNDRV_PCM_STATE_OPEN) + if (runtime->state == SNDRV_PCM_STATE_OPEN) return -EBADFD; if (runtime->channels > 128) return -EINVAL; @@ -3290,7 +3291,7 @@ static int snd_pcm_common_ioctl(struct file *file, if (PCM_RUNTIME_CHECK(substream)) return -ENXIO; - if (substream->runtime->status->state == SNDRV_PCM_STATE_DISCONNECTED) + if (substream->runtime->state == SNDRV_PCM_STATE_DISCONNECTED) return -EBADFD; res = snd_power_wait(substream->pcm->card); @@ -3421,7 +3422,7 @@ int snd_pcm_kernel_ioctl(struct snd_pcm_substream *substream, snd_pcm_uframes_t *frames = arg; snd_pcm_sframes_t result; - if (substream->runtime->status->state == SNDRV_PCM_STATE_DISCONNECTED) + if (substream->runtime->state == SNDRV_PCM_STATE_DISCONNECTED) return -EBADFD; switch (cmd) { @@ -3466,8 +3467,8 @@ static ssize_t snd_pcm_read(struct file *file, char __user *buf, size_t count, if (PCM_RUNTIME_CHECK(substream)) return -ENXIO; runtime = substream->runtime; - if (runtime->status->state == SNDRV_PCM_STATE_OPEN || - runtime->status->state == SNDRV_PCM_STATE_DISCONNECTED) + if (runtime->state == SNDRV_PCM_STATE_OPEN || + runtime->state == SNDRV_PCM_STATE_DISCONNECTED) return -EBADFD; if (!frame_aligned(runtime, count)) return -EINVAL; @@ -3491,8 +3492,8 @@ static ssize_t snd_pcm_write(struct file *file, const char __user *buf, if (PCM_RUNTIME_CHECK(substream)) return -ENXIO; runtime = substream->runtime; - if (runtime->status->state == SNDRV_PCM_STATE_OPEN || - runtime->status->state == SNDRV_PCM_STATE_DISCONNECTED) + if (runtime->state == SNDRV_PCM_STATE_OPEN || + runtime->state == SNDRV_PCM_STATE_DISCONNECTED) return -EBADFD; if (!frame_aligned(runtime, count)) return -EINVAL; @@ -3518,8 +3519,8 @@ static ssize_t snd_pcm_readv(struct kiocb *iocb, struct iov_iter *to) if (PCM_RUNTIME_CHECK(substream)) return -ENXIO; runtime = substream->runtime; - if (runtime->status->state == SNDRV_PCM_STATE_OPEN || - runtime->status->state == SNDRV_PCM_STATE_DISCONNECTED) + if (runtime->state == SNDRV_PCM_STATE_OPEN || + runtime->state == SNDRV_PCM_STATE_DISCONNECTED) return -EBADFD; if (!iter_is_iovec(to)) return -EINVAL; @@ -3555,8 +3556,8 @@ static ssize_t snd_pcm_writev(struct kiocb *iocb, struct iov_iter *from) if (PCM_RUNTIME_CHECK(substream)) return -ENXIO; runtime = substream->runtime; - if (runtime->status->state == SNDRV_PCM_STATE_OPEN || - runtime->status->state == SNDRV_PCM_STATE_DISCONNECTED) + if (runtime->state == SNDRV_PCM_STATE_OPEN || + runtime->state == SNDRV_PCM_STATE_DISCONNECTED) return -EBADFD; if (!iter_is_iovec(from)) return -EINVAL; @@ -3595,7 +3596,7 @@ static __poll_t snd_pcm_poll(struct file *file, poll_table *wait) return ok | EPOLLERR; runtime = substream->runtime; - if (runtime->status->state == SNDRV_PCM_STATE_DISCONNECTED) + if (runtime->state == SNDRV_PCM_STATE_DISCONNECTED) return ok | EPOLLERR; poll_wait(file, &runtime->sleep, wait); @@ -3603,7 +3604,7 @@ static __poll_t snd_pcm_poll(struct file *file, poll_table *wait) mask = 0; snd_pcm_stream_lock_irq(substream); avail = snd_pcm_avail(substream); - switch (runtime->status->state) { + switch (runtime->state) { case SNDRV_PCM_STATE_RUNNING: case SNDRV_PCM_STATE_PREPARED: case SNDRV_PCM_STATE_PAUSED: @@ -3667,6 +3668,7 @@ static int snd_pcm_mmap_status(struct snd_pcm_substream *substream, struct file area->vm_ops = &snd_pcm_vm_ops_status; area->vm_private_data = substream; area->vm_flags |= VM_DONTEXPAND | VM_DONTDUMP; + area->vm_flags &= ~(VM_WRITE | VM_MAYWRITE); return 0; } @@ -3874,7 +3876,7 @@ int snd_pcm_mmap_data(struct snd_pcm_substream *substream, struct file *file, return -EINVAL; } runtime = substream->runtime; - if (runtime->status->state == SNDRV_PCM_STATE_OPEN) + if (runtime->state == SNDRV_PCM_STATE_OPEN) return -EBADFD; if (!(runtime->info & SNDRV_PCM_INFO_MMAP)) return -ENXIO; @@ -3911,7 +3913,7 @@ static int snd_pcm_mmap(struct file *file, struct vm_area_struct *area) substream = pcm_file->substream; if (PCM_RUNTIME_CHECK(substream)) return -ENXIO; - if (substream->runtime->status->state == SNDRV_PCM_STATE_DISCONNECTED) + if (substream->runtime->state == SNDRV_PCM_STATE_DISCONNECTED) return -EBADFD; offset = area->vm_pgoff << PAGE_SHIFT; @@ -3949,7 +3951,7 @@ static int snd_pcm_fasync(int fd, struct file * file, int on) if (PCM_RUNTIME_CHECK(substream)) return -ENXIO; runtime = substream->runtime; - if (runtime->status->state == SNDRV_PCM_STATE_DISCONNECTED) + if (runtime->state == SNDRV_PCM_STATE_DISCONNECTED) return -EBADFD; return snd_fasync_helper(fd, file, on, &runtime->fasync); } diff --git a/sound/core/rawmidi.c b/sound/core/rawmidi.c index 6963d5a487b3..d8edb6055072 100644 --- a/sound/core/rawmidi.c +++ b/sound/core/rawmidi.c @@ -1899,10 +1899,8 @@ static int snd_rawmidi_free(struct snd_rawmidi *rmidi) snd_info_free_entry(rmidi->proc_entry); rmidi->proc_entry = NULL; - mutex_lock(®ister_mutex); if (rmidi->ops && rmidi->ops->dev_unregister) rmidi->ops->dev_unregister(rmidi); - mutex_unlock(®ister_mutex); snd_rawmidi_free_substreams(&rmidi->streams[SNDRV_RAWMIDI_STREAM_INPUT]); snd_rawmidi_free_substreams(&rmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT]); diff --git a/sound/core/sound_oss.c b/sound/core/sound_oss.c index 7ed0a2a91035..2751bf2ff61b 100644 --- a/sound/core/sound_oss.c +++ b/sound/core/sound_oss.c @@ -162,7 +162,6 @@ int snd_unregister_oss_device(int type, struct snd_card *card, int dev) mutex_unlock(&sound_oss_mutex); return -ENOENT; } - unregister_sound_special(minor); switch (SNDRV_MINOR_OSS_DEVICE(minor)) { case SNDRV_MINOR_OSS_PCM: track2 = SNDRV_MINOR_OSS(cidx, SNDRV_MINOR_OSS_AUDIO); @@ -174,12 +173,18 @@ int snd_unregister_oss_device(int type, struct snd_card *card, int dev) track2 = SNDRV_MINOR_OSS(cidx, SNDRV_MINOR_OSS_DMMIDI1); break; } - if (track2 >= 0) { - unregister_sound_special(track2); + if (track2 >= 0) snd_oss_minors[track2] = NULL; - } snd_oss_minors[minor] = NULL; mutex_unlock(&sound_oss_mutex); + + /* call unregister_sound_special() outside sound_oss_mutex; + * otherwise may deadlock, as it can trigger the release of a card + */ + unregister_sound_special(minor); + if (track2 >= 0) + unregister_sound_special(track2); + kfree(mptr); return 0; } diff --git a/sound/drivers/aloop.c b/sound/drivers/aloop.c index 12f12a294df5..a38e602b4fc6 100644 --- a/sound/drivers/aloop.c +++ b/sound/drivers/aloop.c @@ -535,7 +535,7 @@ static void copy_play_buf(struct loopback_pcm *play, /* check if playback is draining, trim the capture copy size * when our pointer is at the end of playback ring buffer */ - if (runtime->status->state == SNDRV_PCM_STATE_DRAINING && + if (runtime->state == SNDRV_PCM_STATE_DRAINING && snd_pcm_playback_hw_avail(runtime) < runtime->buffer_size) { snd_pcm_uframes_t appl_ptr, appl_ptr1, diff; appl_ptr = appl_ptr1 = runtime->control->appl_ptr; @@ -730,7 +730,7 @@ static void loopback_snd_timer_period_elapsed(struct loopback_cable *cable, if (event == SNDRV_TIMER_EVENT_MSTOP) { if (!dpcm_play || - dpcm_play->substream->runtime->status->state != + dpcm_play->substream->runtime->state != SNDRV_PCM_STATE_DRAINING) { spin_unlock_irqrestore(&cable->lock, flags); return; diff --git a/sound/drivers/dummy.c b/sound/drivers/dummy.c index 2a7fc49c1a7c..9c17b49a2ae1 100644 --- a/sound/drivers/dummy.c +++ b/sound/drivers/dummy.c @@ -42,6 +42,8 @@ MODULE_LICENSE("GPL"); #define USE_CHANNELS_MAX 2 #define USE_PERIODS_MIN 1 #define USE_PERIODS_MAX 1024 +#define USE_MIXER_VOLUME_LEVEL_MIN -50 +#define USE_MIXER_VOLUME_LEVEL_MAX 100 static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ @@ -50,6 +52,8 @@ static char *model[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = NULL}; static int pcm_devs[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 1}; static int pcm_substreams[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 8}; //static int midi_devs[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 2}; +static int mixer_volume_level_min = USE_MIXER_VOLUME_LEVEL_MIN; +static int mixer_volume_level_max = USE_MIXER_VOLUME_LEVEL_MAX; #ifdef CONFIG_HIGH_RES_TIMERS static bool hrtimer = 1; #endif @@ -69,6 +73,10 @@ module_param_array(pcm_substreams, int, NULL, 0444); MODULE_PARM_DESC(pcm_substreams, "PCM substreams # (1-128) for dummy driver."); //module_param_array(midi_devs, int, NULL, 0444); //MODULE_PARM_DESC(midi_devs, "MIDI devices # (0-2) for dummy driver."); +module_param(mixer_volume_level_min, int, 0444); +MODULE_PARM_DESC(mixer_volume_level_min, "Minimum mixer volume level for dummy driver. Default: -50"); +module_param(mixer_volume_level_max, int, 0444); +MODULE_PARM_DESC(mixer_volume_level_max, "Maximum mixer volume level for dummy driver. Default: 100"); module_param(fake_buffer, bool, 0444); MODULE_PARM_DESC(fake_buffer, "Fake buffer allocations."); #ifdef CONFIG_HIGH_RES_TIMERS @@ -296,7 +304,7 @@ static void dummy_systimer_callback(struct timer_list *t) struct dummy_systimer_pcm *dpcm = from_timer(dpcm, t, timer); unsigned long flags; int elapsed = 0; - + spin_lock_irqsave(&dpcm->lock, flags); dummy_systimer_update(dpcm); dummy_systimer_rearm(dpcm); @@ -713,11 +721,11 @@ static int snd_dummy_volume_info(struct snd_kcontrol *kcontrol, { uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; uinfo->count = 2; - uinfo->value.integer.min = -50; - uinfo->value.integer.max = 100; + uinfo->value.integer.min = mixer_volume_level_min; + uinfo->value.integer.max = mixer_volume_level_max; return 0; } - + static int snd_dummy_volume_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { @@ -739,15 +747,15 @@ static int snd_dummy_volume_put(struct snd_kcontrol *kcontrol, int left, right; left = ucontrol->value.integer.value[0]; - if (left < -50) - left = -50; - if (left > 100) - left = 100; + if (left < mixer_volume_level_min) + left = mixer_volume_level_min; + if (left > mixer_volume_level_max) + left = mixer_volume_level_max; right = ucontrol->value.integer.value[1]; - if (right < -50) - right = -50; - if (right > 100) - right = 100; + if (right < mixer_volume_level_min) + right = mixer_volume_level_min; + if (right > mixer_volume_level_max) + right = mixer_volume_level_max; spin_lock_irq(&dummy->mixer_lock); change = dummy->mixer_volume[addr][0] != left || dummy->mixer_volume[addr][1] != right; @@ -766,7 +774,7 @@ static const DECLARE_TLV_DB_SCALE(db_scale_dummy, -4500, 30, 0); .private_value = addr } #define snd_dummy_capsrc_info snd_ctl_boolean_stereo_info - + static int snd_dummy_capsrc_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { @@ -1076,6 +1084,12 @@ static int snd_dummy_probe(struct platform_device *devptr) dummy->pcm_hw.channels_max = m->channels_max; } + if (mixer_volume_level_min > mixer_volume_level_max) { + pr_warn("snd-dummy: Invalid mixer volume level: min=%d, max=%d. Fall back to default value.\n", + mixer_volume_level_min, mixer_volume_level_max); + mixer_volume_level_min = USE_MIXER_VOLUME_LEVEL_MIN; + mixer_volume_level_max = USE_MIXER_VOLUME_LEVEL_MAX; + } err = snd_card_dummy_new_mixer(dummy); if (err < 0) return err; @@ -1100,7 +1114,7 @@ static int snd_dummy_suspend(struct device *pdev) snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); return 0; } - + static int snd_dummy_resume(struct device *pdev) { struct snd_card *card = dev_get_drvdata(pdev); diff --git a/sound/drivers/vx/vx_pcm.c b/sound/drivers/vx/vx_pcm.c index 3924f5283745..ceaeb257003b 100644 --- a/sound/drivers/vx/vx_pcm.c +++ b/sound/drivers/vx/vx_pcm.c @@ -1215,8 +1215,7 @@ int snd_vx_pcm_new(struct vx_core *chip) if (ins) snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &vx_pcm_capture_ops); snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_VMALLOC, - snd_dma_continuous_data(GFP_KERNEL | GFP_DMA32), - 0, 0); + NULL, 0, 0); pcm->private_data = chip; pcm->private_free = snd_vx_pcm_free; diff --git a/sound/firewire/bebob/bebob_pcm.c b/sound/firewire/bebob/bebob_pcm.c index f8d9a2041264..ce49eef0fcba 100644 --- a/sound/firewire/bebob/bebob_pcm.c +++ b/sound/firewire/bebob/bebob_pcm.c @@ -214,7 +214,7 @@ static int pcm_hw_params(struct snd_pcm_substream *substream, struct snd_bebob *bebob = substream->private_data; int err = 0; - if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN) { + if (substream->runtime->state == SNDRV_PCM_STATE_OPEN) { unsigned int rate = params_rate(hw_params); unsigned int frames_per_period = params_period_size(hw_params); unsigned int frames_per_buffer = params_buffer_size(hw_params); @@ -236,7 +236,7 @@ static int pcm_hw_free(struct snd_pcm_substream *substream) mutex_lock(&bebob->mutex); - if (substream->runtime->status->state != SNDRV_PCM_STATE_OPEN) + if (substream->runtime->state != SNDRV_PCM_STATE_OPEN) bebob->substreams_counter--; snd_bebob_stream_stop_duplex(bebob); diff --git a/sound/firewire/dice/dice-harman.c b/sound/firewire/dice/dice-harman.c index a8ca00c397e8..212ae77dfca2 100644 --- a/sound/firewire/dice/dice-harman.c +++ b/sound/firewire/dice/dice-harman.c @@ -2,8 +2,6 @@ // dice-harman.c - a part of driver for DICE based devices // // Copyright (c) 2021 Takashi Sakamoto -// -// Licensed under the terms of the GNU General Public License, version 2. #include "dice.h" diff --git a/sound/firewire/dice/dice-pcm.c b/sound/firewire/dice/dice-pcm.c index a69ca1111b03..d64366217d57 100644 --- a/sound/firewire/dice/dice-pcm.c +++ b/sound/firewire/dice/dice-pcm.c @@ -266,7 +266,7 @@ static int pcm_hw_params(struct snd_pcm_substream *substream, struct snd_dice *dice = substream->private_data; int err = 0; - if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN) { + if (substream->runtime->state == SNDRV_PCM_STATE_OPEN) { unsigned int rate = params_rate(hw_params); unsigned int events_per_period = params_period_size(hw_params); unsigned int events_per_buffer = params_buffer_size(hw_params); @@ -293,7 +293,7 @@ static int pcm_hw_free(struct snd_pcm_substream *substream) mutex_lock(&dice->mutex); - if (substream->runtime->status->state != SNDRV_PCM_STATE_OPEN) + if (substream->runtime->state != SNDRV_PCM_STATE_OPEN) --dice->substreams_counter; snd_dice_stream_stop_duplex(dice); diff --git a/sound/firewire/dice/dice-presonus.c b/sound/firewire/dice/dice-presonus.c index 503f462a83f4..967cc3119a64 100644 --- a/sound/firewire/dice/dice-presonus.c +++ b/sound/firewire/dice/dice-presonus.c @@ -2,8 +2,6 @@ // dice-presonus.c - a part of driver for DICE based devices // // Copyright (c) 2019 Takashi Sakamoto -// -// Licensed under the terms of the GNU General Public License, version 2. #include "dice.h" diff --git a/sound/firewire/digi00x/digi00x-pcm.c b/sound/firewire/digi00x/digi00x-pcm.c index b7f6eda09f9f..3bd1575c9d9c 100644 --- a/sound/firewire/digi00x/digi00x-pcm.c +++ b/sound/firewire/digi00x/digi00x-pcm.c @@ -190,7 +190,7 @@ static int pcm_hw_params(struct snd_pcm_substream *substream, struct snd_dg00x *dg00x = substream->private_data; int err = 0; - if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN) { + if (substream->runtime->state == SNDRV_PCM_STATE_OPEN) { unsigned int rate = params_rate(hw_params); unsigned int frames_per_period = params_period_size(hw_params); unsigned int frames_per_buffer = params_buffer_size(hw_params); @@ -212,7 +212,7 @@ static int pcm_hw_free(struct snd_pcm_substream *substream) mutex_lock(&dg00x->mutex); - if (substream->runtime->status->state != SNDRV_PCM_STATE_OPEN) + if (substream->runtime->state != SNDRV_PCM_STATE_OPEN) --dg00x->substreams_counter; snd_dg00x_stream_stop_duplex(dg00x); diff --git a/sound/firewire/fireface/ff-pcm.c b/sound/firewire/fireface/ff-pcm.c index f978cc2fed7d..ec915671a79b 100644 --- a/sound/firewire/fireface/ff-pcm.c +++ b/sound/firewire/fireface/ff-pcm.c @@ -230,7 +230,7 @@ static int pcm_hw_params(struct snd_pcm_substream *substream, struct snd_ff *ff = substream->private_data; int err = 0; - if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN) { + if (substream->runtime->state == SNDRV_PCM_STATE_OPEN) { unsigned int rate = params_rate(hw_params); unsigned int frames_per_period = params_period_size(hw_params); unsigned int frames_per_buffer = params_buffer_size(hw_params); @@ -252,7 +252,7 @@ static int pcm_hw_free(struct snd_pcm_substream *substream) mutex_lock(&ff->mutex); - if (substream->runtime->status->state != SNDRV_PCM_STATE_OPEN) + if (substream->runtime->state != SNDRV_PCM_STATE_OPEN) --ff->substreams_counter; snd_ff_stream_stop_duplex(ff); diff --git a/sound/firewire/fireface/ff-protocol-former.c b/sound/firewire/fireface/ff-protocol-former.c index bf44cad7985e..8900ffe517ed 100644 --- a/sound/firewire/fireface/ff-protocol-former.c +++ b/sound/firewire/fireface/ff-protocol-former.c @@ -2,8 +2,6 @@ // ff-protocol-former.c - a part of driver for RME Fireface series // // Copyright (c) 2019 Takashi Sakamoto -// -// Licensed under the terms of the GNU General Public License, version 2. #include <linux/delay.h> diff --git a/sound/firewire/fireface/ff-protocol-latter.c b/sound/firewire/fireface/ff-protocol-latter.c index 7ddb7b97f02d..76c3eab36d4e 100644 --- a/sound/firewire/fireface/ff-protocol-latter.c +++ b/sound/firewire/fireface/ff-protocol-latter.c @@ -1,9 +1,7 @@ // SPDX-License-Identifier: GPL-2.0 -// ff-protocol-latter - a part of driver for RME Fireface series +// ff-protocol-latter.c - a part of driver for RME Fireface series // // Copyright (c) 2019 Takashi Sakamoto -// -// Licensed under the terms of the GNU General Public License, version 2. #include <linux/delay.h> diff --git a/sound/firewire/fireworks/fireworks_pcm.c b/sound/firewire/fireworks/fireworks_pcm.c index a0d5db1d8eb2..c3c21860b245 100644 --- a/sound/firewire/fireworks/fireworks_pcm.c +++ b/sound/firewire/fireworks/fireworks_pcm.c @@ -250,7 +250,7 @@ static int pcm_hw_params(struct snd_pcm_substream *substream, struct snd_efw *efw = substream->private_data; int err = 0; - if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN) { + if (substream->runtime->state == SNDRV_PCM_STATE_OPEN) { unsigned int rate = params_rate(hw_params); unsigned int frames_per_period = params_period_size(hw_params); unsigned int frames_per_buffer = params_buffer_size(hw_params); @@ -272,7 +272,7 @@ static int pcm_hw_free(struct snd_pcm_substream *substream) mutex_lock(&efw->mutex); - if (substream->runtime->status->state != SNDRV_PCM_STATE_OPEN) + if (substream->runtime->state != SNDRV_PCM_STATE_OPEN) --efw->substreams_counter; snd_efw_stream_stop_duplex(efw); diff --git a/sound/firewire/motu/motu-pcm.c b/sound/firewire/motu/motu-pcm.c index 8e1437371263..d410c2efbde5 100644 --- a/sound/firewire/motu/motu-pcm.c +++ b/sound/firewire/motu/motu-pcm.c @@ -210,7 +210,7 @@ static int pcm_hw_params(struct snd_pcm_substream *substream, struct snd_motu *motu = substream->private_data; int err = 0; - if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN) { + if (substream->runtime->state == SNDRV_PCM_STATE_OPEN) { unsigned int rate = params_rate(hw_params); unsigned int frames_per_period = params_period_size(hw_params); unsigned int frames_per_buffer = params_buffer_size(hw_params); @@ -232,7 +232,7 @@ static int pcm_hw_free(struct snd_pcm_substream *substream) mutex_lock(&motu->mutex); - if (substream->runtime->status->state != SNDRV_PCM_STATE_OPEN) + if (substream->runtime->state != SNDRV_PCM_STATE_OPEN) --motu->substreams_counter; snd_motu_stream_stop_duplex(motu); diff --git a/sound/firewire/motu/motu-protocol-v1.c b/sound/firewire/motu/motu-protocol-v1.c index f1d6a326dc07..e811629f167b 100644 --- a/sound/firewire/motu/motu-protocol-v1.c +++ b/sound/firewire/motu/motu-protocol-v1.c @@ -1,10 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-only - // motu-protocol-v1.c - a part of driver for MOTU FireWire series // // Copyright (c) 2021 Takashi Sakamoto <o-takashi@sakamocchi.jp> -// -// Licensed under the terms of the GNU General Public License, version 2. #include "motu.h" diff --git a/sound/firewire/oxfw/oxfw-pcm.c b/sound/firewire/oxfw/oxfw-pcm.c index 2dfa7e179cb6..5f43a0b826d2 100644 --- a/sound/firewire/oxfw/oxfw-pcm.c +++ b/sound/firewire/oxfw/oxfw-pcm.c @@ -239,7 +239,7 @@ static int pcm_capture_hw_params(struct snd_pcm_substream *substream, struct snd_oxfw *oxfw = substream->private_data; int err = 0; - if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN) { + if (substream->runtime->state == SNDRV_PCM_STATE_OPEN) { unsigned int rate = params_rate(hw_params); unsigned int channels = params_channels(hw_params); unsigned int frames_per_period = params_period_size(hw_params); @@ -262,7 +262,7 @@ static int pcm_playback_hw_params(struct snd_pcm_substream *substream, struct snd_oxfw *oxfw = substream->private_data; int err = 0; - if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN) { + if (substream->runtime->state == SNDRV_PCM_STATE_OPEN) { unsigned int rate = params_rate(hw_params); unsigned int channels = params_channels(hw_params); unsigned int frames_per_period = params_period_size(hw_params); @@ -286,7 +286,7 @@ static int pcm_capture_hw_free(struct snd_pcm_substream *substream) mutex_lock(&oxfw->mutex); - if (substream->runtime->status->state != SNDRV_PCM_STATE_OPEN) + if (substream->runtime->state != SNDRV_PCM_STATE_OPEN) --oxfw->substreams_count; snd_oxfw_stream_stop_duplex(oxfw); @@ -301,7 +301,7 @@ static int pcm_playback_hw_free(struct snd_pcm_substream *substream) mutex_lock(&oxfw->mutex); - if (substream->runtime->status->state != SNDRV_PCM_STATE_OPEN) + if (substream->runtime->state != SNDRV_PCM_STATE_OPEN) --oxfw->substreams_count; snd_oxfw_stream_stop_duplex(oxfw); diff --git a/sound/firewire/tascam/tascam-pcm.c b/sound/firewire/tascam/tascam-pcm.c index 36c1353f2494..f6da571707ac 100644 --- a/sound/firewire/tascam/tascam-pcm.c +++ b/sound/firewire/tascam/tascam-pcm.c @@ -119,7 +119,7 @@ static int pcm_hw_params(struct snd_pcm_substream *substream, struct snd_tscm *tscm = substream->private_data; int err = 0; - if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN) { + if (substream->runtime->state == SNDRV_PCM_STATE_OPEN) { unsigned int rate = params_rate(hw_params); unsigned int frames_per_period = params_period_size(hw_params); unsigned int frames_per_buffer = params_buffer_size(hw_params); @@ -141,7 +141,7 @@ static int pcm_hw_free(struct snd_pcm_substream *substream) mutex_lock(&tscm->mutex); - if (substream->runtime->status->state != SNDRV_PCM_STATE_OPEN) + if (substream->runtime->state != SNDRV_PCM_STATE_OPEN) --tscm->substreams_counter; snd_tscm_stream_stop_duplex(tscm); diff --git a/sound/hda/ext/hdac_ext_bus.c b/sound/hda/ext/hdac_ext_bus.c index 765c40a6ccba..6004ea1c373e 100644 --- a/sound/hda/ext/hdac_ext_bus.c +++ b/sound/hda/ext/hdac_ext_bus.c @@ -60,59 +60,6 @@ void snd_hdac_ext_bus_exit(struct hdac_bus *bus) } EXPORT_SYMBOL_GPL(snd_hdac_ext_bus_exit); -static void default_release(struct device *dev) -{ - snd_hdac_ext_bus_device_exit(dev_to_hdac_dev(dev)); -} - -/** - * snd_hdac_ext_bus_device_init - initialize the HDA extended codec base device - * @bus: hdac bus to attach to - * @addr: codec address - * @hdev: hdac device to init - * @type: codec type (HDAC_DEV_*) to use for this device - * - * Returns zero for success or a negative error code. - */ -int snd_hdac_ext_bus_device_init(struct hdac_bus *bus, int addr, - struct hdac_device *hdev, int type) -{ - char name[15]; - int ret; - - hdev->bus = bus; - - snprintf(name, sizeof(name), "ehdaudio%dD%d", bus->idx, addr); - - ret = snd_hdac_device_init(hdev, bus, name, addr); - if (ret < 0) { - dev_err(bus->dev, "device init failed for hdac device\n"); - return ret; - } - hdev->type = type; - hdev->dev.release = default_release; - - ret = snd_hdac_device_register(hdev); - if (ret) { - dev_err(bus->dev, "failed to register hdac device\n"); - snd_hdac_ext_bus_device_exit(hdev); - return ret; - } - - return 0; -} -EXPORT_SYMBOL_GPL(snd_hdac_ext_bus_device_init); - -/** - * snd_hdac_ext_bus_device_exit - clean up a HD-audio extended codec base device - * @hdev: hdac device to clean up - */ -void snd_hdac_ext_bus_device_exit(struct hdac_device *hdev) -{ - snd_hdac_device_exit(hdev); -} -EXPORT_SYMBOL_GPL(snd_hdac_ext_bus_device_exit); - /** * snd_hdac_ext_bus_device_remove - remove HD-audio extended codec base devices * diff --git a/sound/hda/ext/hdac_ext_controller.c b/sound/hda/ext/hdac_ext_controller.c index a42f66f561f5..80876b9a87f4 100644 --- a/sound/hda/ext/hdac_ext_controller.c +++ b/sound/hda/ext/hdac_ext_controller.c @@ -170,7 +170,7 @@ static int check_hdac_link_power_active(struct hdac_ext_link *link, bool enable) { int timeout; u32 val; - int mask = (1 << AZX_MLCTL_CPA_SHIFT); + int mask = (1 << AZX_ML_LCTL_CPA_SHIFT); udelay(3); timeout = 150; @@ -178,10 +178,10 @@ static int check_hdac_link_power_active(struct hdac_ext_link *link, bool enable) do { val = readl(link->ml_addr + AZX_REG_ML_LCTL); if (enable) { - if (((val & mask) >> AZX_MLCTL_CPA_SHIFT)) + if (((val & mask) >> AZX_ML_LCTL_CPA_SHIFT)) return 0; } else { - if (!((val & mask) >> AZX_MLCTL_CPA_SHIFT)) + if (!((val & mask) >> AZX_ML_LCTL_CPA_SHIFT)) return 0; } udelay(3); @@ -197,7 +197,7 @@ static int check_hdac_link_power_active(struct hdac_ext_link *link, bool enable) int snd_hdac_ext_bus_link_power_up(struct hdac_ext_link *link) { snd_hdac_updatel(link->ml_addr, AZX_REG_ML_LCTL, - AZX_MLCTL_SPA, AZX_MLCTL_SPA); + AZX_ML_LCTL_SPA, AZX_ML_LCTL_SPA); return check_hdac_link_power_active(link, true); } @@ -209,7 +209,7 @@ EXPORT_SYMBOL_GPL(snd_hdac_ext_bus_link_power_up); */ int snd_hdac_ext_bus_link_power_down(struct hdac_ext_link *link) { - snd_hdac_updatel(link->ml_addr, AZX_REG_ML_LCTL, AZX_MLCTL_SPA, 0); + snd_hdac_updatel(link->ml_addr, AZX_REG_ML_LCTL, AZX_ML_LCTL_SPA, 0); return check_hdac_link_power_active(link, false); } @@ -226,7 +226,7 @@ int snd_hdac_ext_bus_link_power_up_all(struct hdac_bus *bus) list_for_each_entry(hlink, &bus->hlink_list, list) { snd_hdac_updatel(hlink->ml_addr, AZX_REG_ML_LCTL, - AZX_MLCTL_SPA, AZX_MLCTL_SPA); + AZX_ML_LCTL_SPA, AZX_ML_LCTL_SPA); ret = check_hdac_link_power_active(hlink, true); if (ret < 0) return ret; @@ -247,7 +247,7 @@ int snd_hdac_ext_bus_link_power_down_all(struct hdac_bus *bus) list_for_each_entry(hlink, &bus->hlink_list, list) { snd_hdac_updatel(hlink->ml_addr, AZX_REG_ML_LCTL, - AZX_MLCTL_SPA, 0); + AZX_ML_LCTL_SPA, 0); ret = check_hdac_link_power_active(hlink, false); if (ret < 0) return ret; @@ -281,7 +281,7 @@ int snd_hdac_ext_bus_link_get(struct hdac_bus *bus, * clear the register to invalidate all the output streams */ snd_hdac_updatew(link->ml_addr, AZX_REG_ML_LOSIDV, - ML_LOSIDV_STREAM_MASK, 0); + AZX_ML_LOSIDV_STREAM_MASK, 0); /* * wait for 521usec for codec to report status * HDA spec section 4.3 - Codec Discovery diff --git a/sound/hda/ext/hdac_ext_stream.c b/sound/hda/ext/hdac_ext_stream.c index d2b5724b463f..70f3ad71aaf0 100644 --- a/sound/hda/ext/hdac_ext_stream.c +++ b/sound/hda/ext/hdac_ext_stream.c @@ -26,9 +26,9 @@ * initialize the stream, if ppcap is enabled then init those and then * invoke hdac stream initialization routine */ -void snd_hdac_ext_stream_init(struct hdac_bus *bus, - struct hdac_ext_stream *hext_stream, - int idx, int direction, int tag) +static void snd_hdac_ext_stream_init(struct hdac_bus *bus, + struct hdac_ext_stream *hext_stream, + int idx, int direction, int tag) { if (bus->ppcap) { hext_stream->pphc_addr = bus->ppcap + AZX_PPHC_BASE + @@ -56,7 +56,6 @@ void snd_hdac_ext_stream_init(struct hdac_bus *bus, hext_stream->decoupled = false; snd_hdac_stream_init(bus, &hext_stream->hstream, idx, direction, tag); } -EXPORT_SYMBOL_GPL(snd_hdac_ext_stream_init); /** * snd_hdac_ext_stream_init_all - create and initialize the stream objects @@ -88,11 +87,11 @@ int snd_hdac_ext_stream_init_all(struct hdac_bus *bus, int start_idx, EXPORT_SYMBOL_GPL(snd_hdac_ext_stream_init_all); /** - * snd_hdac_stream_free_all - free hdac extended stream objects + * snd_hdac_ext_stream_free_all - free hdac extended stream objects * * @bus: HD-audio core bus */ -void snd_hdac_stream_free_all(struct hdac_bus *bus) +void snd_hdac_ext_stream_free_all(struct hdac_bus *bus) { struct hdac_stream *s, *_s; struct hdac_ext_stream *hext_stream; @@ -104,7 +103,7 @@ void snd_hdac_stream_free_all(struct hdac_bus *bus) kfree(hext_stream); } } -EXPORT_SYMBOL_GPL(snd_hdac_stream_free_all); +EXPORT_SYMBOL_GPL(snd_hdac_ext_stream_free_all); void snd_hdac_ext_stream_decouple_locked(struct hdac_bus *bus, struct hdac_ext_stream *hext_stream, @@ -268,19 +267,15 @@ hdac_ext_link_stream_assign(struct hdac_bus *bus, if (hstream->direction != substream->stream) continue; - /* check if decoupled stream and not in use is available */ - if (hext_stream->decoupled && !hext_stream->link_locked) { - res = hext_stream; - break; - } - + /* check if link stream is available */ if (!hext_stream->link_locked) { - snd_hdac_ext_stream_decouple_locked(bus, hext_stream, true); res = hext_stream; break; } + } if (res) { + snd_hdac_ext_stream_decouple_locked(bus, res, true); res->link_locked = 1; res->link_substream = substream; } @@ -309,13 +304,12 @@ hdac_ext_host_stream_assign(struct hdac_bus *bus, continue; if (!hstream->opened) { - if (!hext_stream->decoupled) - snd_hdac_ext_stream_decouple_locked(bus, hext_stream, true); res = hext_stream; break; } } if (res) { + snd_hdac_ext_stream_decouple_locked(bus, res, true); res->hstream.opened = 1; res->hstream.running = 0; res->hstream.substream = substream; @@ -388,15 +382,17 @@ void snd_hdac_ext_stream_release(struct hdac_ext_stream *hext_stream, int type) case HDAC_EXT_STREAM_TYPE_HOST: spin_lock_irq(&bus->reg_lock); - if (hext_stream->decoupled && !hext_stream->link_locked) + /* couple link only if not in use */ + if (!hext_stream->link_locked) snd_hdac_ext_stream_decouple_locked(bus, hext_stream, false); + snd_hdac_stream_release_locked(&hext_stream->hstream); spin_unlock_irq(&bus->reg_lock); - snd_hdac_stream_release(&hext_stream->hstream); break; case HDAC_EXT_STREAM_TYPE_LINK: spin_lock_irq(&bus->reg_lock); - if (hext_stream->decoupled && !hext_stream->hstream.opened) + /* couple host only if not in use */ + if (!hext_stream->hstream.opened) snd_hdac_ext_stream_decouple_locked(bus, hext_stream, false); hext_stream->link_locked = 0; hext_stream->link_substream = NULL; diff --git a/sound/hda/hdac_stream.c b/sound/hda/hdac_stream.c index f3582012d22f..1b8be39c38a9 100644 --- a/sound/hda/hdac_stream.c +++ b/sound/hda/hdac_stream.c @@ -13,6 +13,39 @@ #include <sound/hda_register.h> #include "trace.h" +/* + * the hdac_stream library is intended to be used with the following + * transitions. The states are not formally defined in the code but loosely + * inspired by boolean variables. Note that the 'prepared' field is not used + * in this library but by the callers during the hw_params/prepare transitions + * + * | + * stream_init() | + * v + * +--+-------+ + * | unused | + * +--+----+--+ + * | ^ + * stream_assign() | | stream_release() + * v | + * +--+----+--+ + * | opened | + * +--+----+--+ + * | ^ + * stream_reset() | | + * stream_setup() | | stream_cleanup() + * v | + * +--+----+--+ + * | prepared | + * +--+----+--+ + * | ^ + * stream_start() | | stream_stop() + * v | + * +--+----+--+ + * | running | + * +----------+ + */ + /** * snd_hdac_get_stream_stripe_ctl - get stripe control value * @bus: HD-audio core bus @@ -112,10 +145,10 @@ void snd_hdac_stream_start(struct hdac_stream *azx_dev, bool fresh_start) EXPORT_SYMBOL_GPL(snd_hdac_stream_start); /** - * snd_hdac_stream_clear - stop a stream DMA + * snd_hdac_stream_clear - helper to clear stream registers and stop DMA transfers * @azx_dev: HD-audio core stream to stop */ -void snd_hdac_stream_clear(struct hdac_stream *azx_dev) +static void snd_hdac_stream_clear(struct hdac_stream *azx_dev) { snd_hdac_stream_updateb(azx_dev, SD_CTL, SD_CTL_DMA_START | SD_INT_MASK, 0); @@ -124,7 +157,6 @@ void snd_hdac_stream_clear(struct hdac_stream *azx_dev) snd_hdac_stream_updateb(azx_dev, SD_CTL_3B, SD_CTL_STRIPE_MASK, 0); azx_dev->running = false; } -EXPORT_SYMBOL_GPL(snd_hdac_stream_clear); /** * snd_hdac_stream_stop - stop a stream @@ -143,16 +175,27 @@ void snd_hdac_stream_stop(struct hdac_stream *azx_dev) EXPORT_SYMBOL_GPL(snd_hdac_stream_stop); /** + * snd_hdac_stop_streams - stop all streams + * @bus: HD-audio core bus + */ +void snd_hdac_stop_streams(struct hdac_bus *bus) +{ + struct hdac_stream *stream; + + list_for_each_entry(stream, &bus->stream_list, list) + snd_hdac_stream_stop(stream); +} +EXPORT_SYMBOL_GPL(snd_hdac_stop_streams); + +/** * snd_hdac_stop_streams_and_chip - stop all streams and chip if running * @bus: HD-audio core bus */ void snd_hdac_stop_streams_and_chip(struct hdac_bus *bus) { - struct hdac_stream *stream; if (bus->chip_init) { - list_for_each_entry(stream, &bus->stream_list, list) - snd_hdac_stream_stop(stream); + snd_hdac_stop_streams(bus); snd_hdac_bus_stop_chip(bus); } } @@ -165,7 +208,6 @@ EXPORT_SYMBOL_GPL(snd_hdac_stop_streams_and_chip); void snd_hdac_stream_reset(struct hdac_stream *azx_dev) { unsigned char val; - int timeout; int dma_run_state; snd_hdac_stream_clear(azx_dev); @@ -173,30 +215,17 @@ void snd_hdac_stream_reset(struct hdac_stream *azx_dev) dma_run_state = snd_hdac_stream_readb(azx_dev, SD_CTL) & SD_CTL_DMA_START; snd_hdac_stream_updateb(azx_dev, SD_CTL, 0, SD_CTL_STREAM_RESET); - udelay(3); - timeout = 300; - do { - val = snd_hdac_stream_readb(azx_dev, SD_CTL) & - SD_CTL_STREAM_RESET; - if (val) - break; - } while (--timeout); + + /* wait for hardware to report that the stream entered reset */ + snd_hdac_stream_readb_poll(azx_dev, SD_CTL, val, (val & SD_CTL_STREAM_RESET), 3, 300); if (azx_dev->bus->dma_stop_delay && dma_run_state) udelay(azx_dev->bus->dma_stop_delay); - val &= ~SD_CTL_STREAM_RESET; - snd_hdac_stream_writeb(azx_dev, SD_CTL, val); - udelay(3); + snd_hdac_stream_updateb(azx_dev, SD_CTL, SD_CTL_STREAM_RESET, 0); - timeout = 300; - /* waiting for hardware to report that the stream is out of reset */ - do { - val = snd_hdac_stream_readb(azx_dev, SD_CTL) & - SD_CTL_STREAM_RESET; - if (!val) - break; - } while (--timeout); + /* wait for hardware to report that the stream is out of reset */ + snd_hdac_stream_readb_poll(azx_dev, SD_CTL, val, !(val & SD_CTL_STREAM_RESET), 3, 300); /* reset first position - may not be synced with hw at this time */ if (azx_dev->posbuf) @@ -337,6 +366,21 @@ struct hdac_stream *snd_hdac_stream_assign(struct hdac_bus *bus, EXPORT_SYMBOL_GPL(snd_hdac_stream_assign); /** + * snd_hdac_stream_release_locked - release the assigned stream + * @azx_dev: HD-audio core stream to release + * + * Release the stream that has been assigned by snd_hdac_stream_assign(). + * The bus->reg_lock needs to be taken at a higher level + */ +void snd_hdac_stream_release_locked(struct hdac_stream *azx_dev) +{ + azx_dev->opened = 0; + azx_dev->running = 0; + azx_dev->substream = NULL; +} +EXPORT_SYMBOL_GPL(snd_hdac_stream_release_locked); + +/** * snd_hdac_stream_release - release the assigned stream * @azx_dev: HD-audio core stream to release * @@ -347,9 +391,7 @@ void snd_hdac_stream_release(struct hdac_stream *azx_dev) struct hdac_bus *bus = azx_dev->bus; spin_lock_irq(&bus->reg_lock); - azx_dev->opened = 0; - azx_dev->running = 0; - azx_dev->substream = NULL; + snd_hdac_stream_release_locked(azx_dev); spin_unlock_irq(&bus->reg_lock); } EXPORT_SYMBOL_GPL(snd_hdac_stream_release); diff --git a/sound/hda/hdmi_chmap.c b/sound/hda/hdmi_chmap.c index aad5c4bf4d34..5d8e1d944b0a 100644 --- a/sound/hda/hdmi_chmap.c +++ b/sound/hda/hdmi_chmap.c @@ -774,7 +774,7 @@ static int hdmi_chmap_ctl_put(struct snd_kcontrol *kcontrol, substream = snd_pcm_chmap_substream(info, ctl_idx); if (!substream || !substream->runtime) return 0; /* just for avoiding error from alsactl restore */ - switch (substream->runtime->status->state) { + switch (substream->runtime->state) { case SNDRV_PCM_STATE_OPEN: case SNDRV_PCM_STATE_SETUP: break; diff --git a/sound/hda/intel-dsp-config.c b/sound/hda/intel-dsp-config.c index 1997ffc16663..b9eb3208f288 100644 --- a/sound/hda/intel-dsp-config.c +++ b/sound/hda/intel-dsp-config.c @@ -455,6 +455,16 @@ static const struct config_entry config_table[] = { .flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE, .device = 0x51cb, }, + /* RaptorLake-M */ + { + .flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE, + .device = 0x51ce, + }, + /* RaptorLake-PX */ + { + .flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE, + .device = 0x51cf, + }, #endif }; diff --git a/sound/isa/es18xx.c b/sound/isa/es18xx.c index 3fcd168480b6..0a32845b1017 100644 --- a/sound/isa/es18xx.c +++ b/sound/isa/es18xx.c @@ -1344,11 +1344,8 @@ ES18XX_SINGLE("GPO1 Switch", 0, ES18XX_PM, 1, 1, ES18XX_FL_PMPORT), static int snd_es18xx_config_read(struct snd_es18xx *chip, unsigned char reg) { - int data; - outb(reg, chip->ctrl_port); - data = inb(chip->ctrl_port + 1); - return data; + return inb(chip->ctrl_port + 1); } static void snd_es18xx_config_write(struct snd_es18xx *chip, diff --git a/sound/isa/sb/emu8000_pcm.c b/sound/isa/sb/emu8000_pcm.c index f8d90a1e989b..c8afc4347c54 100644 --- a/sound/isa/sb/emu8000_pcm.c +++ b/sound/isa/sb/emu8000_pcm.c @@ -236,7 +236,7 @@ static int emu8k_pcm_open(struct snd_pcm_substream *subs) /* use timer to update periods.. (specified in msec) */ snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_PERIOD_TIME, - (1000000 + HZ - 1) / HZ, UINT_MAX); + DIV_ROUND_UP(1000000, HZ), UINT_MAX); return 0; } diff --git a/sound/oss/dmasound/dmasound.h b/sound/oss/dmasound/dmasound.h index ad8ce6a1c25c..f065840c0efb 100644 --- a/sound/oss/dmasound/dmasound.h +++ b/sound/oss/dmasound/dmasound.h @@ -250,7 +250,4 @@ extern int dmasound_catchRadius; #define SW_INPUT_VOLUME_SCALE 4 #define SW_INPUT_VOLUME_DEFAULT (128 / SW_INPUT_VOLUME_SCALE) -extern int expand_read_bal; /* Balance factor for reading */ -extern uint software_input_volume; /* software implemented recording volume! */ - #endif /* _dmasound_h_ */ diff --git a/sound/pci/asihpi/asihpi.c b/sound/pci/asihpi/asihpi.c index 5e1f9f10051b..8de43aaa10aa 100644 --- a/sound/pci/asihpi/asihpi.c +++ b/sound/pci/asihpi/asihpi.c @@ -632,7 +632,7 @@ static int snd_card_asihpi_trigger(struct snd_pcm_substream *substream, /*? workaround linked streams don't transition to SETUP 20070706*/ - s->runtime->status->state = SNDRV_PCM_STATE_SETUP; + __snd_pcm_set_state(s->runtime, SNDRV_PCM_STATE_SETUP); if (card->support_grouping) { snd_printdd("%d group\n", s->number); diff --git a/sound/pci/asihpi/hpifunc.c b/sound/pci/asihpi/hpifunc.c index 1de05383126a..24047fafef51 100644 --- a/sound/pci/asihpi/hpifunc.c +++ b/sound/pci/asihpi/hpifunc.c @@ -2020,7 +2020,6 @@ u16 hpi_meter_get_peak(u32 h_control, short an_peakdB[HPI_MAX_CHANNELS] HPI_CONTROL_GET_STATE); if (hpi_handle_indexes(h_control, &hm.adapter_index, &hm.obj_index)) return HPI_ERROR_INVALID_HANDLE; - hm.obj_index = hm.obj_index; hm.u.c.attribute = HPI_METER_PEAK; hpi_send_recv(&hm, &hr); diff --git a/sound/pci/asihpi/hpimsgx.c b/sound/pci/asihpi/hpimsgx.c index f7427f8eb630..d0caef299481 100644 --- a/sound/pci/asihpi/hpimsgx.c +++ b/sound/pci/asihpi/hpimsgx.c @@ -93,11 +93,6 @@ static void HPIMSGX__cleanup(u16 adapter_index, void *h_owner); #pragma pack(push, 1) #endif -struct hpi_subsys_response { - struct hpi_response_header h; - struct hpi_subsys_res s; -}; - struct hpi_adapter_response { struct hpi_response_header h; struct hpi_adapter_res a; diff --git a/sound/pci/hda/cs35l41_hda.c b/sound/pci/hda/cs35l41_hda.c index 15e2a0009080..e5f0549bf06d 100644 --- a/sound/pci/hda/cs35l41_hda.c +++ b/sound/pci/hda/cs35l41_hda.c @@ -91,20 +91,18 @@ static const struct reg_sequence cs35l41_hda_mute[] = { { CS35L41_AMP_DIG_VOL_CTRL, 0x0000A678 }, // AMP_VOL_PCM Mute }; -static int cs35l41_control_add(struct cs_dsp_coeff_ctl *cs_ctl) +static void cs35l41_add_controls(struct cs35l41_hda *cs35l41) { - struct cs35l41_hda *cs35l41 = container_of(cs_ctl->dsp, struct cs35l41_hda, cs_dsp); struct hda_cs_dsp_ctl_info info; info.device_name = cs35l41->amp_name; info.fw_type = cs35l41->firmware_type; info.card = cs35l41->codec->card; - return hda_cs_dsp_control_add(cs_ctl, &info); + hda_cs_dsp_add_controls(&cs35l41->cs_dsp, &info); } static const struct cs_dsp_client_ops client_ops = { - .control_add = cs35l41_control_add, .control_remove = hda_cs_dsp_control_remove, }; @@ -435,6 +433,8 @@ static int cs35l41_init_dsp(struct cs35l41_hda *cs35l41) if (ret) goto err_release; + cs35l41_add_controls(cs35l41); + ret = cs35l41_save_calibration(cs35l41); err_release: @@ -461,9 +461,12 @@ static void cs35l41_remove_dsp(struct cs35l41_hda *cs35l41) struct cs_dsp *dsp = &cs35l41->cs_dsp; cancel_work_sync(&cs35l41->fw_load_work); + + mutex_lock(&cs35l41->fw_mutex); cs35l41_shutdown_dsp(cs35l41); cs_dsp_remove(dsp); cs35l41->halo_initialized = false; + mutex_unlock(&cs35l41->fw_mutex); } /* Protection release cycle to get the speaker out of Safe-Mode */ @@ -487,10 +490,10 @@ static void cs35l41_hda_playback_hook(struct device *dev, int action) struct regmap *reg = cs35l41->regmap; int ret = 0; - mutex_lock(&cs35l41->fw_mutex); - switch (action) { case HDA_GEN_PCM_ACT_OPEN: + pm_runtime_get_sync(dev); + mutex_lock(&cs35l41->fw_mutex); cs35l41->playback_started = true; if (cs35l41->firmware_running) { regmap_multi_reg_write(reg, cs35l41_hda_config_dsp, @@ -508,15 +511,21 @@ static void cs35l41_hda_playback_hook(struct device *dev, int action) CS35L41_AMP_EN_MASK, 1 << CS35L41_AMP_EN_SHIFT); if (cs35l41->hw_cfg.bst_type == CS35L41_EXT_BOOST) regmap_write(reg, CS35L41_GPIO1_CTRL1, 0x00008001); + mutex_unlock(&cs35l41->fw_mutex); break; case HDA_GEN_PCM_ACT_PREPARE: + mutex_lock(&cs35l41->fw_mutex); ret = cs35l41_global_enable(reg, cs35l41->hw_cfg.bst_type, 1); + mutex_unlock(&cs35l41->fw_mutex); break; case HDA_GEN_PCM_ACT_CLEANUP: + mutex_lock(&cs35l41->fw_mutex); regmap_multi_reg_write(reg, cs35l41_hda_mute, ARRAY_SIZE(cs35l41_hda_mute)); ret = cs35l41_global_enable(reg, cs35l41->hw_cfg.bst_type, 0); + mutex_unlock(&cs35l41->fw_mutex); break; case HDA_GEN_PCM_ACT_CLOSE: + mutex_lock(&cs35l41->fw_mutex); ret = regmap_update_bits(reg, CS35L41_PWR_CTRL2, CS35L41_AMP_EN_MASK, 0 << CS35L41_AMP_EN_SHIFT); if (cs35l41->hw_cfg.bst_type == CS35L41_EXT_BOOST) @@ -530,14 +539,16 @@ static void cs35l41_hda_playback_hook(struct device *dev, int action) } cs35l41_irq_release(cs35l41); cs35l41->playback_started = false; + mutex_unlock(&cs35l41->fw_mutex); + + pm_runtime_mark_last_busy(dev); + pm_runtime_put_autosuspend(dev); break; default: dev_warn(cs35l41->dev, "Playback action not supported: %d\n", action); break; } - mutex_unlock(&cs35l41->fw_mutex); - if (ret) dev_err(cs35l41->dev, "Regmap access fail: %d\n", ret); } @@ -562,45 +573,148 @@ static int cs35l41_hda_channel_map(struct device *dev, unsigned int tx_num, unsi rx_slot); } +static void cs35l41_ready_for_reset(struct cs35l41_hda *cs35l41) +{ + mutex_lock(&cs35l41->fw_mutex); + if (cs35l41->firmware_running) { + + regcache_cache_only(cs35l41->regmap, false); + + cs35l41_exit_hibernate(cs35l41->dev, cs35l41->regmap); + cs35l41_shutdown_dsp(cs35l41); + cs35l41_safe_reset(cs35l41->regmap, cs35l41->hw_cfg.bst_type); + + regcache_cache_only(cs35l41->regmap, true); + regcache_mark_dirty(cs35l41->regmap); + } + mutex_unlock(&cs35l41->fw_mutex); +} + +static int cs35l41_system_suspend(struct device *dev) +{ + struct cs35l41_hda *cs35l41 = dev_get_drvdata(dev); + int ret; + + dev_dbg(cs35l41->dev, "System Suspend\n"); + + if (cs35l41->hw_cfg.bst_type == CS35L41_EXT_BOOST_NO_VSPK_SWITCH) { + dev_err(cs35l41->dev, "System Suspend not supported\n"); + return -EINVAL; + } + + ret = pm_runtime_force_suspend(dev); + if (ret) + return ret; + + /* Shutdown DSP before system suspend */ + cs35l41_ready_for_reset(cs35l41); + + /* + * Reset GPIO may be shared, so cannot reset here. + * However beyond this point, amps may be powered down. + */ + return 0; +} + +static int cs35l41_system_resume(struct device *dev) +{ + struct cs35l41_hda *cs35l41 = dev_get_drvdata(dev); + int ret; + + dev_dbg(cs35l41->dev, "System Resume\n"); + + if (cs35l41->hw_cfg.bst_type == CS35L41_EXT_BOOST_NO_VSPK_SWITCH) { + dev_err(cs35l41->dev, "System Resume not supported\n"); + return -EINVAL; + } + + if (cs35l41->reset_gpio) { + usleep_range(2000, 2100); + gpiod_set_value_cansleep(cs35l41->reset_gpio, 1); + } + + usleep_range(2000, 2100); + + ret = pm_runtime_force_resume(dev); + + mutex_lock(&cs35l41->fw_mutex); + if (!ret && cs35l41->request_fw_load && !cs35l41->fw_request_ongoing) { + cs35l41->fw_request_ongoing = true; + schedule_work(&cs35l41->fw_load_work); + } + mutex_unlock(&cs35l41->fw_mutex); + + return ret; +} + static int cs35l41_runtime_suspend(struct device *dev) { struct cs35l41_hda *cs35l41 = dev_get_drvdata(dev); + int ret = 0; - dev_dbg(cs35l41->dev, "Suspend\n"); + dev_dbg(cs35l41->dev, "Runtime Suspend\n"); - if (!cs35l41->firmware_running) + if (cs35l41->hw_cfg.bst_type == CS35L41_EXT_BOOST_NO_VSPK_SWITCH) { + dev_dbg(cs35l41->dev, "Runtime Suspend not supported\n"); return 0; + } - if (cs35l41_enter_hibernate(cs35l41->dev, cs35l41->regmap, cs35l41->hw_cfg.bst_type) < 0) - return 0; + mutex_lock(&cs35l41->fw_mutex); + + if (cs35l41->playback_started) { + regmap_multi_reg_write(cs35l41->regmap, cs35l41_hda_mute, + ARRAY_SIZE(cs35l41_hda_mute)); + cs35l41_global_enable(cs35l41->regmap, cs35l41->hw_cfg.bst_type, 0); + regmap_update_bits(cs35l41->regmap, CS35L41_PWR_CTRL2, + CS35L41_AMP_EN_MASK, 0 << CS35L41_AMP_EN_SHIFT); + if (cs35l41->hw_cfg.bst_type == CS35L41_EXT_BOOST) + regmap_write(cs35l41->regmap, CS35L41_GPIO1_CTRL1, 0x00000001); + regmap_update_bits(cs35l41->regmap, CS35L41_PWR_CTRL2, + CS35L41_VMON_EN_MASK | CS35L41_IMON_EN_MASK, + 0 << CS35L41_VMON_EN_SHIFT | 0 << CS35L41_IMON_EN_SHIFT); + cs35l41->playback_started = false; + } + + if (cs35l41->firmware_running) { + ret = cs35l41_enter_hibernate(cs35l41->dev, cs35l41->regmap, + cs35l41->hw_cfg.bst_type); + if (ret) + goto err; + } else { + cs35l41_safe_reset(cs35l41->regmap, cs35l41->hw_cfg.bst_type); + } regcache_cache_only(cs35l41->regmap, true); regcache_mark_dirty(cs35l41->regmap); - return 0; +err: + mutex_unlock(&cs35l41->fw_mutex); + + return ret; } static int cs35l41_runtime_resume(struct device *dev) { struct cs35l41_hda *cs35l41 = dev_get_drvdata(dev); - int ret; + int ret = 0; - dev_dbg(cs35l41->dev, "Resume.\n"); + dev_dbg(cs35l41->dev, "Runtime Resume\n"); if (cs35l41->hw_cfg.bst_type == CS35L41_EXT_BOOST_NO_VSPK_SWITCH) { - dev_dbg(cs35l41->dev, "System does not support Resume\n"); + dev_dbg(cs35l41->dev, "Runtime Resume not supported\n"); return 0; } - if (!cs35l41->firmware_running) - return 0; + mutex_lock(&cs35l41->fw_mutex); regcache_cache_only(cs35l41->regmap, false); - ret = cs35l41_exit_hibernate(cs35l41->dev, cs35l41->regmap); - if (ret) { - regcache_cache_only(cs35l41->regmap, true); - return ret; + if (cs35l41->firmware_running) { + ret = cs35l41_exit_hibernate(cs35l41->dev, cs35l41->regmap); + if (ret) { + dev_warn(cs35l41->dev, "Unable to exit Hibernate."); + goto err; + } } /* Test key needs to be unlocked to allow the OTP settings to re-apply */ @@ -609,26 +723,16 @@ static int cs35l41_runtime_resume(struct device *dev) cs35l41_test_key_lock(cs35l41->dev, cs35l41->regmap); if (ret) { dev_err(cs35l41->dev, "Failed to restore register cache: %d\n", ret); - return ret; + goto err; } if (cs35l41->hw_cfg.bst_type == CS35L41_EXT_BOOST) cs35l41_init_boost(cs35l41->dev, cs35l41->regmap, &cs35l41->hw_cfg); - return 0; -} - -static int cs35l41_hda_suspend_hook(struct device *dev) -{ - dev_dbg(dev, "Request Suspend\n"); - pm_runtime_mark_last_busy(dev); - return pm_runtime_put_autosuspend(dev); -} +err: + mutex_unlock(&cs35l41->fw_mutex); -static int cs35l41_hda_resume_hook(struct device *dev) -{ - dev_dbg(dev, "Request Resume\n"); - return pm_runtime_get_sync(dev); + return ret; } static int cs35l41_smart_amp(struct cs35l41_hda *cs35l41) @@ -678,8 +782,6 @@ clean_dsp: static void cs35l41_load_firmware(struct cs35l41_hda *cs35l41, bool load) { - pm_runtime_get_sync(cs35l41->dev); - if (cs35l41->firmware_running && !load) { dev_dbg(cs35l41->dev, "Unloading Firmware\n"); cs35l41_shutdown_dsp(cs35l41); @@ -689,9 +791,6 @@ static void cs35l41_load_firmware(struct cs35l41_hda *cs35l41, bool load) } else { dev_dbg(cs35l41->dev, "Unable to Load firmware.\n"); } - - pm_runtime_mark_last_busy(cs35l41->dev); - pm_runtime_put_autosuspend(cs35l41->dev); } static int cs35l41_fw_load_ctl_get(struct snd_kcontrol *kcontrol, @@ -707,16 +806,21 @@ static void cs35l41_fw_load_work(struct work_struct *work) { struct cs35l41_hda *cs35l41 = container_of(work, struct cs35l41_hda, fw_load_work); + pm_runtime_get_sync(cs35l41->dev); + mutex_lock(&cs35l41->fw_mutex); /* Recheck if playback is ongoing, mutex will block playback during firmware loading */ if (cs35l41->playback_started) - dev_err(cs35l41->dev, "Cannot Load/Unload firmware during Playback\n"); + dev_err(cs35l41->dev, "Cannot Load/Unload firmware during Playback. Retrying...\n"); else cs35l41_load_firmware(cs35l41, cs35l41->request_fw_load); cs35l41->fw_request_ongoing = false; mutex_unlock(&cs35l41->fw_mutex); + + pm_runtime_mark_last_busy(cs35l41->dev); + pm_runtime_put_autosuspend(cs35l41->dev); } static int cs35l41_fw_load_ctl_put(struct snd_kcontrol *kcontrol, @@ -840,10 +944,12 @@ static int cs35l41_hda_bind(struct device *dev, struct device *master, void *mas pm_runtime_get_sync(dev); + mutex_lock(&cs35l41->fw_mutex); + comps->dev = dev; if (!cs35l41->acpi_subsystem_id) - cs35l41->acpi_subsystem_id = devm_kasprintf(dev, GFP_KERNEL, "%.8x", - comps->codec->core.subsystem_id); + cs35l41->acpi_subsystem_id = kasprintf(GFP_KERNEL, "%.8x", + comps->codec->core.subsystem_id); cs35l41->codec = comps->codec; strscpy(comps->name, dev_name(dev), sizeof(comps->name)); @@ -852,10 +958,8 @@ static int cs35l41_hda_bind(struct device *dev, struct device *master, void *mas if (firmware_autostart) { dev_dbg(cs35l41->dev, "Firmware Autostart.\n"); cs35l41->request_fw_load = true; - mutex_lock(&cs35l41->fw_mutex); if (cs35l41_smart_amp(cs35l41) < 0) dev_warn(cs35l41->dev, "Cannot Run Firmware, reverting to dsp bypass...\n"); - mutex_unlock(&cs35l41->fw_mutex); } else { dev_dbg(cs35l41->dev, "Firmware Autostart is disabled.\n"); } @@ -863,8 +967,8 @@ static int cs35l41_hda_bind(struct device *dev, struct device *master, void *mas ret = cs35l41_create_controls(cs35l41); comps->playback_hook = cs35l41_hda_playback_hook; - comps->suspend_hook = cs35l41_hda_suspend_hook; - comps->resume_hook = cs35l41_hda_resume_hook; + + mutex_unlock(&cs35l41->fw_mutex); pm_runtime_mark_last_busy(dev); pm_runtime_put_autosuspend(dev); @@ -1048,36 +1152,6 @@ static int cs35l41_hda_apply_properties(struct cs35l41_hda *cs35l41) return cs35l41_hda_channel_map(cs35l41->dev, 0, NULL, 1, &hw_cfg->spk_pos); } -static int cs35l41_get_acpi_sub_string(struct device *dev, struct acpi_device *adev, - const char **subsysid) -{ - struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; - union acpi_object *obj; - acpi_status status; - int ret = 0; - - status = acpi_evaluate_object(adev->handle, "_SUB", NULL, &buffer); - if (ACPI_SUCCESS(status)) { - obj = buffer.pointer; - if (obj->type == ACPI_TYPE_STRING) { - *subsysid = devm_kstrdup(dev, obj->string.pointer, GFP_KERNEL); - if (*subsysid == NULL) { - dev_err(dev, "Cannot allocate Subsystem ID"); - ret = -ENOMEM; - } - } else { - dev_warn(dev, "Warning ACPI _SUB did not return a string\n"); - ret = -ENODEV; - } - acpi_os_free(buffer.pointer); - } else { - dev_dbg(dev, "Warning ACPI _SUB failed: %#x\n", status); - ret = -ENODEV; - } - - return ret; -} - static int cs35l41_get_speaker_id(struct device *dev, int amp_index, int num_amps, int fixed_gpio_id) { @@ -1154,7 +1228,6 @@ static int cs35l41_no_acpi_dsd(struct cs35l41_hda *cs35l41, struct device *physd hw_cfg->gpio2.func = CS35L41_INTERRUPT; hw_cfg->gpio2.valid = true; hw_cfg->valid = true; - put_device(physdev); if (strncmp(hid, "CLSA0100", 8) == 0) { hw_cfg->bst_type = CS35L41_EXT_BOOST_NO_VSPK_SWITCH; @@ -1183,6 +1256,7 @@ static int cs35l41_hda_read_acpi(struct cs35l41_hda *cs35l41, const char *hid, i u32 values[HDA_MAX_COMPONENTS]; struct acpi_device *adev; struct device *physdev; + const char *sub; char *property; size_t nval; int i, ret; @@ -1196,17 +1270,17 @@ static int cs35l41_hda_read_acpi(struct cs35l41_hda *cs35l41, const char *hid, i physdev = get_device(acpi_get_first_physical_node(adev)); acpi_dev_put(adev); - ret = cs35l41_get_acpi_sub_string(cs35l41->dev, adev, &cs35l41->acpi_subsystem_id); - if (ret) - dev_info(cs35l41->dev, "No Subsystem ID found in ACPI: %d", ret); - else - dev_dbg(cs35l41->dev, "Subsystem ID %s found", cs35l41->acpi_subsystem_id); + sub = acpi_get_subsystem_id(ACPI_HANDLE(physdev)); + if (IS_ERR(sub)) + sub = NULL; + cs35l41->acpi_subsystem_id = sub; property = "cirrus,dev-index"; ret = device_property_count_u32(physdev, property); - if (ret <= 0) - return cs35l41_no_acpi_dsd(cs35l41, physdev, id, hid); - + if (ret <= 0) { + ret = cs35l41_no_acpi_dsd(cs35l41, physdev, id, hid); + goto err_put_physdev; + } if (ret > ARRAY_SIZE(values)) { ret = -EINVAL; goto err; @@ -1295,8 +1369,9 @@ static int cs35l41_hda_read_acpi(struct cs35l41_hda *cs35l41, const char *hid, i return 0; err: - put_device(physdev); dev_err(cs35l41->dev, "Failed property %s: %d\n", property, ret); +err_put_physdev: + put_device(physdev); return ret; } @@ -1433,6 +1508,7 @@ err: if (cs35l41_safe_reset(cs35l41->regmap, cs35l41->hw_cfg.bst_type)) gpiod_set_value_cansleep(cs35l41->reset_gpio, 0); gpiod_put(cs35l41->reset_gpio); + kfree(cs35l41->acpi_subsystem_id); return ret; } @@ -1455,11 +1531,13 @@ void cs35l41_hda_remove(struct device *dev) if (cs35l41_safe_reset(cs35l41->regmap, cs35l41->hw_cfg.bst_type)) gpiod_set_value_cansleep(cs35l41->reset_gpio, 0); gpiod_put(cs35l41->reset_gpio); + kfree(cs35l41->acpi_subsystem_id); } EXPORT_SYMBOL_NS_GPL(cs35l41_hda_remove, SND_HDA_SCODEC_CS35L41); const struct dev_pm_ops cs35l41_hda_pm_ops = { RUNTIME_PM_OPS(cs35l41_runtime_suspend, cs35l41_runtime_resume, NULL) + SYSTEM_SLEEP_PM_OPS(cs35l41_system_suspend, cs35l41_system_resume) }; EXPORT_SYMBOL_NS_GPL(cs35l41_hda_pm_ops, SND_HDA_SCODEC_CS35L41); diff --git a/sound/pci/hda/cs35l41_hda_i2c.c b/sound/pci/hda/cs35l41_hda_i2c.c index 5baacfde4f16..5a6252d9b9e1 100644 --- a/sound/pci/hda/cs35l41_hda_i2c.c +++ b/sound/pci/hda/cs35l41_hda_i2c.c @@ -33,11 +33,9 @@ static int cs35l41_hda_i2c_probe(struct i2c_client *clt, const struct i2c_device devm_regmap_init_i2c(clt, &cs35l41_regmap_i2c)); } -static int cs35l41_hda_i2c_remove(struct i2c_client *clt) +static void cs35l41_hda_i2c_remove(struct i2c_client *clt) { cs35l41_hda_remove(&clt->dev); - - return 0; } static const struct i2c_device_id cs35l41_hda_i2c_id[] = { diff --git a/sound/pci/hda/hda_beep.c b/sound/pci/hda/hda_beep.c index 53a2b89f8983..e63621bcb214 100644 --- a/sound/pci/hda/hda_beep.c +++ b/sound/pci/hda/hda_beep.c @@ -118,6 +118,12 @@ static int snd_hda_beep_event(struct input_dev *dev, unsigned int type, return 0; } +static void turn_on_beep(struct hda_beep *beep) +{ + if (beep->keep_power_at_enable) + snd_hda_power_up_pm(beep->codec); +} + static void turn_off_beep(struct hda_beep *beep) { cancel_work_sync(&beep->beep_work); @@ -125,6 +131,8 @@ static void turn_off_beep(struct hda_beep *beep) /* turn off beep */ generate_tone(beep, 0); } + if (beep->keep_power_at_enable) + snd_hda_power_down_pm(beep->codec); } /** @@ -140,7 +148,9 @@ int snd_hda_enable_beep_device(struct hda_codec *codec, int enable) enable = !!enable; if (beep->enabled != enable) { beep->enabled = enable; - if (!enable) + if (enable) + turn_on_beep(beep); + else turn_off_beep(beep); return 1; } @@ -167,7 +177,8 @@ static int beep_dev_disconnect(struct snd_device *device) input_unregister_device(beep->dev); else input_free_device(beep->dev); - turn_off_beep(beep); + if (beep->enabled) + turn_off_beep(beep); return 0; } diff --git a/sound/pci/hda/hda_beep.h b/sound/pci/hda/hda_beep.h index a25358a4807a..db76e3ddba65 100644 --- a/sound/pci/hda/hda_beep.h +++ b/sound/pci/hda/hda_beep.h @@ -25,6 +25,7 @@ struct hda_beep { unsigned int enabled:1; unsigned int linear_tone:1; /* linear tone for IDT/STAC codec */ unsigned int playing:1; + unsigned int keep_power_at_enable:1; /* set by driver */ struct work_struct beep_work; /* scheduled task for beep event */ struct mutex mutex; void (*power_hook)(struct hda_beep *beep, bool on); diff --git a/sound/pci/hda/hda_bind.c b/sound/pci/hda/hda_bind.c index cae9a975cbcc..1a868dd9dc4b 100644 --- a/sound/pci/hda/hda_bind.c +++ b/sound/pci/hda/hda_bind.c @@ -157,10 +157,10 @@ static int hda_codec_driver_remove(struct device *dev) return codec->bus->core.ext_ops->hdev_detach(&codec->core); } - refcount_dec(&codec->pcm_ref); snd_hda_codec_disconnect_pcms(codec); snd_hda_jack_tbl_disconnect(codec); - wait_event(codec->remove_sleep, !refcount_read(&codec->pcm_ref)); + if (!refcount_dec_and_test(&codec->pcm_ref)) + wait_event(codec->remove_sleep, !refcount_read(&codec->pcm_ref)); snd_power_sync_ref(codec->bus->card); if (codec->patch_ops.free) diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index 384426d7e9dd..b4d1e658c556 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c @@ -883,13 +883,7 @@ static void snd_hda_codec_dev_release(struct device *dev) snd_hda_sysfs_clear(codec); kfree(codec->modelname); kfree(codec->wcaps); - - /* - * In the case of ASoC HD-audio, hda_codec is device managed. - * It will be freed when the ASoC device is removed. - */ - if (codec->core.type == HDA_DEV_LEGACY) - kfree(codec); + kfree(codec); } #define DEV_NAME_LEN 31 @@ -931,8 +925,28 @@ snd_hda_codec_device_init(struct hda_bus *bus, unsigned int codec_addr, } codec->bus = bus; + codec->depop_delay = -1; + codec->fixup_id = HDA_FIXUP_ID_NOT_SET; + codec->core.dev.release = snd_hda_codec_dev_release; + codec->core.exec_verb = codec_exec_verb; codec->core.type = HDA_DEV_LEGACY; + mutex_init(&codec->spdif_mutex); + mutex_init(&codec->control_mutex); + snd_array_init(&codec->mixers, sizeof(struct hda_nid_item), 32); + snd_array_init(&codec->nids, sizeof(struct hda_nid_item), 32); + snd_array_init(&codec->init_pins, sizeof(struct hda_pincfg), 16); + snd_array_init(&codec->driver_pins, sizeof(struct hda_pincfg), 16); + snd_array_init(&codec->cvt_setups, sizeof(struct hda_cvt_setup), 8); + snd_array_init(&codec->spdif_out, sizeof(struct hda_spdif_out), 16); + snd_array_init(&codec->jacktbl, sizeof(struct hda_jack_tbl), 16); + snd_array_init(&codec->verbs, sizeof(struct hda_verb *), 8); + INIT_LIST_HEAD(&codec->conn_list); + INIT_LIST_HEAD(&codec->pcm_list_head); + INIT_DELAYED_WORK(&codec->jackpoll_work, hda_jackpoll_work); + refcount_set(&codec->pcm_ref, 1); + init_waitqueue_head(&codec->remove_sleep); + return codec; } EXPORT_SYMBOL_GPL(snd_hda_codec_device_init); @@ -985,29 +999,8 @@ int snd_hda_codec_device_new(struct hda_bus *bus, struct snd_card *card, if (snd_BUG_ON(codec_addr > HDA_MAX_CODEC_ADDRESS)) return -EINVAL; - codec->core.dev.release = snd_hda_codec_dev_release; - codec->core.exec_verb = codec_exec_verb; - codec->card = card; codec->addr = codec_addr; - mutex_init(&codec->spdif_mutex); - mutex_init(&codec->control_mutex); - snd_array_init(&codec->mixers, sizeof(struct hda_nid_item), 32); - snd_array_init(&codec->nids, sizeof(struct hda_nid_item), 32); - snd_array_init(&codec->init_pins, sizeof(struct hda_pincfg), 16); - snd_array_init(&codec->driver_pins, sizeof(struct hda_pincfg), 16); - snd_array_init(&codec->cvt_setups, sizeof(struct hda_cvt_setup), 8); - snd_array_init(&codec->spdif_out, sizeof(struct hda_spdif_out), 16); - snd_array_init(&codec->jacktbl, sizeof(struct hda_jack_tbl), 16); - snd_array_init(&codec->verbs, sizeof(struct hda_verb *), 8); - INIT_LIST_HEAD(&codec->conn_list); - INIT_LIST_HEAD(&codec->pcm_list_head); - refcount_set(&codec->pcm_ref, 1); - init_waitqueue_head(&codec->remove_sleep); - - INIT_DELAYED_WORK(&codec->jackpoll_work, hda_jackpoll_work); - codec->depop_delay = -1; - codec->fixup_id = HDA_FIXUP_ID_NOT_SET; #ifdef CONFIG_PM codec->power_jiffies = jiffies; diff --git a/sound/pci/hda/hda_component.h b/sound/pci/hda/hda_component.h index 1223621bd62c..534e845b9cd1 100644 --- a/sound/pci/hda/hda_component.h +++ b/sound/pci/hda/hda_component.h @@ -16,6 +16,4 @@ struct hda_component { char name[HDA_MAX_NAME_SIZE]; struct hda_codec *codec; void (*playback_hook)(struct device *dev, int action); - int (*suspend_hook)(struct device *dev); - int (*resume_hook)(struct device *dev); }; diff --git a/sound/pci/hda/hda_controller.c b/sound/pci/hda/hda_controller.c index 75dcb14ff20a..0ff286b7b66b 100644 --- a/sound/pci/hda/hda_controller.c +++ b/sound/pci/hda/hda_controller.c @@ -1033,10 +1033,8 @@ EXPORT_SYMBOL_GPL(azx_init_chip); void azx_stop_all_streams(struct azx *chip) { struct hdac_bus *bus = azx_bus(chip); - struct hdac_stream *s; - list_for_each_entry(s, &bus->stream_list, list) - snd_hdac_stream_stop(s); + snd_hdac_stop_streams(bus); } EXPORT_SYMBOL_GPL(azx_stop_all_streams); diff --git a/sound/pci/hda/hda_cs_dsp_ctl.c b/sound/pci/hda/hda_cs_dsp_ctl.c index 89ee549cb7d5..1622a22f96f6 100644 --- a/sound/pci/hda/hda_cs_dsp_ctl.c +++ b/sound/pci/hda/hda_cs_dsp_ctl.c @@ -97,7 +97,7 @@ static unsigned int wmfw_convert_flags(unsigned int in) return out; } -static int hda_cs_dsp_add_kcontrol(struct hda_cs_dsp_coeff_ctl *ctl, const char *name) +static void hda_cs_dsp_add_kcontrol(struct hda_cs_dsp_coeff_ctl *ctl, const char *name) { struct cs_dsp_coeff_ctl *cs_ctl = ctl->cs_ctl; struct snd_kcontrol_new kcontrol = {0}; @@ -107,7 +107,7 @@ static int hda_cs_dsp_add_kcontrol(struct hda_cs_dsp_coeff_ctl *ctl, const char if (cs_ctl->len > ADSP_MAX_STD_CTRL_SIZE) { dev_err(cs_ctl->dsp->dev, "KControl %s: length %zu exceeds maximum %d\n", name, cs_ctl->len, ADSP_MAX_STD_CTRL_SIZE); - return -EINVAL; + return; } kcontrol.name = name; @@ -120,24 +120,21 @@ static int hda_cs_dsp_add_kcontrol(struct hda_cs_dsp_coeff_ctl *ctl, const char /* Save ctl inside private_data, ctl is owned by cs_dsp, * and will be freed when cs_dsp removes the control */ kctl = snd_ctl_new1(&kcontrol, (void *)ctl); - if (!kctl) { - ret = -ENOMEM; - return ret; - } + if (!kctl) + return; ret = snd_ctl_add(ctl->card, kctl); if (ret) { dev_err(cs_ctl->dsp->dev, "Failed to add KControl %s = %d\n", kcontrol.name, ret); - return ret; + return; } dev_dbg(cs_ctl->dsp->dev, "Added KControl: %s\n", kcontrol.name); ctl->kctl = kctl; - - return 0; } -int hda_cs_dsp_control_add(struct cs_dsp_coeff_ctl *cs_ctl, struct hda_cs_dsp_ctl_info *info) +static void hda_cs_dsp_control_add(struct cs_dsp_coeff_ctl *cs_ctl, + const struct hda_cs_dsp_ctl_info *info) { struct cs_dsp *cs_dsp = cs_ctl->dsp; char name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN]; @@ -145,13 +142,10 @@ int hda_cs_dsp_control_add(struct cs_dsp_coeff_ctl *cs_ctl, struct hda_cs_dsp_ct const char *region_name; int ret; - if (cs_ctl->flags & WMFW_CTL_FLAG_SYS) - return 0; - region_name = cs_dsp_mem_region_name(cs_ctl->alg_region.type); if (!region_name) { - dev_err(cs_dsp->dev, "Unknown region type: %d\n", cs_ctl->alg_region.type); - return -EINVAL; + dev_warn(cs_dsp->dev, "Unknown region type: %d\n", cs_ctl->alg_region.type); + return; } ret = scnprintf(name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN, "%s %s %.12s %x", info->device_name, @@ -171,22 +165,39 @@ int hda_cs_dsp_control_add(struct cs_dsp_coeff_ctl *cs_ctl, struct hda_cs_dsp_ct ctl = kzalloc(sizeof(*ctl), GFP_KERNEL); if (!ctl) - return -ENOMEM; + return; ctl->cs_ctl = cs_ctl; ctl->card = info->card; cs_ctl->priv = ctl; - ret = hda_cs_dsp_add_kcontrol(ctl, name); - if (ret) { - dev_err(cs_dsp->dev, "Error (%d) adding control %s\n", ret, name); - kfree(ctl); - return ret; - } + hda_cs_dsp_add_kcontrol(ctl, name); +} - return 0; +void hda_cs_dsp_add_controls(struct cs_dsp *dsp, const struct hda_cs_dsp_ctl_info *info) +{ + struct cs_dsp_coeff_ctl *cs_ctl; + + /* + * pwr_lock would cause mutex inversion with ALSA control lock compared + * to the get/put functions. + * It is safe to walk the list without holding a mutex because entries + * are persistent and only cs_dsp_power_up() or cs_dsp_remove() can + * change the list. + */ + lockdep_assert_not_held(&dsp->pwr_lock); + + list_for_each_entry(cs_ctl, &dsp->ctl_list, list) { + if (cs_ctl->flags & WMFW_CTL_FLAG_SYS) + continue; + + if (cs_ctl->priv) + continue; + + hda_cs_dsp_control_add(cs_ctl, info); + } } -EXPORT_SYMBOL_NS_GPL(hda_cs_dsp_control_add, SND_HDA_CS_DSP_CONTROLS); +EXPORT_SYMBOL_NS_GPL(hda_cs_dsp_add_controls, SND_HDA_CS_DSP_CONTROLS); void hda_cs_dsp_control_remove(struct cs_dsp_coeff_ctl *cs_ctl) { @@ -203,19 +214,18 @@ int hda_cs_dsp_write_ctl(struct cs_dsp *dsp, const char *name, int type, struct hda_cs_dsp_coeff_ctl *ctl; int ret; + mutex_lock(&dsp->pwr_lock); cs_ctl = cs_dsp_get_ctl(dsp, name, type, alg); - if (!cs_ctl) - return -EINVAL; - - ctl = cs_ctl->priv; - ret = cs_dsp_coeff_write_ctrl(cs_ctl, 0, buf, len); + mutex_unlock(&dsp->pwr_lock); if (ret) return ret; if (cs_ctl->flags & WMFW_CTL_FLAG_SYS) return 0; + ctl = cs_ctl->priv; + snd_ctl_notify(ctl->card, SNDRV_CTL_EVENT_MASK_VALUE, &ctl->kctl->id); return 0; @@ -225,13 +235,14 @@ EXPORT_SYMBOL_NS_GPL(hda_cs_dsp_write_ctl, SND_HDA_CS_DSP_CONTROLS); int hda_cs_dsp_read_ctl(struct cs_dsp *dsp, const char *name, int type, unsigned int alg, void *buf, size_t len) { - struct cs_dsp_coeff_ctl *cs_ctl; + int ret; - cs_ctl = cs_dsp_get_ctl(dsp, name, type, alg); - if (!cs_ctl) - return -EINVAL; + mutex_lock(&dsp->pwr_lock); + ret = cs_dsp_coeff_read_ctrl(cs_dsp_get_ctl(dsp, name, type, alg), 0, buf, len); + mutex_unlock(&dsp->pwr_lock); + + return ret; - return cs_dsp_coeff_read_ctrl(cs_ctl, 0, buf, len); } EXPORT_SYMBOL_NS_GPL(hda_cs_dsp_read_ctl, SND_HDA_CS_DSP_CONTROLS); diff --git a/sound/pci/hda/hda_cs_dsp_ctl.h b/sound/pci/hda/hda_cs_dsp_ctl.h index 4babc69cf2f0..2cf93359c4f2 100644 --- a/sound/pci/hda/hda_cs_dsp_ctl.h +++ b/sound/pci/hda/hda_cs_dsp_ctl.h @@ -29,7 +29,7 @@ struct hda_cs_dsp_ctl_info { extern const char * const hda_cs_dsp_fw_ids[HDA_CS_DSP_NUM_FW]; -int hda_cs_dsp_control_add(struct cs_dsp_coeff_ctl *cs_ctl, struct hda_cs_dsp_ctl_info *info); +void hda_cs_dsp_add_controls(struct cs_dsp *dsp, const struct hda_cs_dsp_ctl_info *info); void hda_cs_dsp_control_remove(struct cs_dsp_coeff_ctl *cs_ctl); int hda_cs_dsp_write_ctl(struct cs_dsp *dsp, const char *name, int type, unsigned int alg, const void *buf, size_t len); diff --git a/sound/pci/hda/hda_eld.c b/sound/pci/hda/hda_eld.c index 9e97443795f8..1d108ed5c6f2 100644 --- a/sound/pci/hda/hda_eld.c +++ b/sound/pci/hda/hda_eld.c @@ -440,7 +440,8 @@ static void hdmi_print_sad_info(int i, struct cea_sad *a, } void snd_hdmi_print_eld_info(struct hdmi_eld *eld, - struct snd_info_buffer *buffer) + struct snd_info_buffer *buffer, + hda_nid_t pin_nid, int dev_id, hda_nid_t cvt_nid) { struct parsed_hdmi_eld *e = &eld->info; char buf[SND_PRINT_CHANNEL_ALLOCATION_ADVISED_BUFSIZE]; @@ -462,6 +463,9 @@ void snd_hdmi_print_eld_info(struct hdmi_eld *eld, snd_iprintf(buffer, "monitor_present\t\t%d\n", eld->monitor_present); snd_iprintf(buffer, "eld_valid\t\t%d\n", eld->eld_valid); + snd_iprintf(buffer, "codec_pin_nid\t\t0x%x\n", pin_nid); + snd_iprintf(buffer, "codec_dev_id\t\t0x%x\n", dev_id); + snd_iprintf(buffer, "codec_cvt_nid\t\t0x%x\n", cvt_nid); if (!eld->eld_valid) return; snd_iprintf(buffer, "monitor_name\t\t%s\n", e->monitor_name); diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index b20694fd69de..6ff19dd0d10c 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c @@ -86,9 +86,6 @@ enum { #define INTEL_SCH_HDA_DEVC 0x78 #define INTEL_SCH_HDA_DEVC_NOSNOOP (0x1<<11) -/* Define VIA HD Audio Device ID*/ -#define VIA_HDAC_DEVICE_ID 0x3288 - /* max number of SDs */ /* ICH, ATI and VIA have 4 playback and 4 capture */ #define ICH6_NUM_CAPTURE 4 @@ -102,10 +99,6 @@ enum { #define ATIHDMI_NUM_CAPTURE 0 #define ATIHDMI_NUM_PLAYBACK 8 -/* TERA has 4 playback and 3 capture */ -#define TERA_NUM_CAPTURE 3 -#define TERA_NUM_PLAYBACK 4 - static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; @@ -496,14 +489,14 @@ static int intel_ml_lctl_set_power(struct azx *chip, int state) * If other links are enabled for stream, they need similar fix */ val = readl(bus->mlcap + AZX_ML_BASE + AZX_REG_ML_LCTL); - val &= ~AZX_MLCTL_SPA; - val |= state << AZX_MLCTL_SPA_SHIFT; + val &= ~AZX_ML_LCTL_SPA; + val |= state << AZX_ML_LCTL_SPA_SHIFT; writel(val, bus->mlcap + AZX_ML_BASE + AZX_REG_ML_LCTL); /* wait for CPA */ timeout = 50; while (timeout) { if (((readl(bus->mlcap + AZX_ML_BASE + AZX_REG_ML_LCTL)) & - AZX_MLCTL_CPA) == (state << AZX_MLCTL_CPA_SHIFT)) + AZX_ML_LCTL_CPA) == (state << AZX_ML_LCTL_CPA_SHIFT)) return 0; timeout--; udelay(10); @@ -521,15 +514,15 @@ static void intel_init_lctl(struct azx *chip) /* 0. check lctl register value is correct or not */ val = readl(bus->mlcap + AZX_ML_BASE + AZX_REG_ML_LCTL); /* if SCF is already set, let's use it */ - if ((val & ML_LCTL_SCF_MASK) != 0) + if ((val & AZX_ML_LCTL_SCF) != 0) return; /* * Before operating on SPA, CPA must match SPA. * Any deviation may result in undefined behavior. */ - if (((val & AZX_MLCTL_SPA) >> AZX_MLCTL_SPA_SHIFT) != - ((val & AZX_MLCTL_CPA) >> AZX_MLCTL_CPA_SHIFT)) + if (((val & AZX_ML_LCTL_SPA) >> AZX_ML_LCTL_SPA_SHIFT) != + ((val & AZX_ML_LCTL_CPA) >> AZX_ML_LCTL_CPA_SHIFT)) return; /* 1. turn link down: set SPA to 0 and wait CPA to 0 */ @@ -539,7 +532,7 @@ static void intel_init_lctl(struct azx *chip) goto set_spa; /* 2. update SCF to select a properly audio clock*/ - val &= ~ML_LCTL_SCF_MASK; + val &= ~AZX_ML_LCTL_SCF; val |= intel_get_lctl_scf(chip); writel(val, bus->mlcap + AZX_ML_BASE + AZX_REG_ML_LCTL); @@ -2550,9 +2543,12 @@ static const struct pci_device_id azx_ids[] = { /* 5 Series/3400 */ { PCI_DEVICE(0x8086, 0x3b56), .driver_data = AZX_DRIVER_SCH | AZX_DCAPS_INTEL_PCH_NOPM }, + { PCI_DEVICE(0x8086, 0x3b57), + .driver_data = AZX_DRIVER_SCH | AZX_DCAPS_INTEL_PCH_NOPM }, /* Poulsbo */ { PCI_DEVICE(0x8086, 0x811b), - .driver_data = AZX_DRIVER_SCH | AZX_DCAPS_INTEL_PCH_BASE }, + .driver_data = AZX_DRIVER_SCH | AZX_DCAPS_INTEL_PCH_BASE | + AZX_DCAPS_POSFIX_LPIB }, /* Oaktrail */ { PCI_DEVICE(0x8086, 0x080a), .driver_data = AZX_DRIVER_SCH | AZX_DCAPS_INTEL_PCH_BASE }, diff --git a/sound/pci/hda/hda_local.h b/sound/pci/hda/hda_local.h index 682dca2057db..53a5a62b78fa 100644 --- a/sound/pci/hda/hda_local.h +++ b/sound/pci/hda/hda_local.h @@ -712,7 +712,8 @@ int snd_hdmi_get_eld_ati(struct hda_codec *codec, hda_nid_t nid, #ifdef CONFIG_SND_PROC_FS void snd_hdmi_print_eld_info(struct hdmi_eld *eld, - struct snd_info_buffer *buffer); + struct snd_info_buffer *buffer, + hda_nid_t pin_nid, int dev_id, hda_nid_t cvt_nid); void snd_hdmi_write_eld_info(struct hdmi_eld *eld, struct snd_info_buffer *buffer); #endif diff --git a/sound/pci/hda/hda_sysfs.c b/sound/pci/hda/hda_sysfs.c index bf951c10ae61..69ebc37a4d6f 100644 --- a/sound/pci/hda/hda_sysfs.c +++ b/sound/pci/hda/hda_sysfs.c @@ -375,8 +375,6 @@ static ssize_t user_pin_configs_show(struct device *dev, return pin_configs_show(codec, &codec->user_pins, buf); } -#define MAX_PIN_CONFIGS 32 - static int parse_user_pin_configs(struct hda_codec *codec, const char *buf) { int nid, cfg, err; diff --git a/sound/pci/hda/patch_ca0132.c b/sound/pci/hda/patch_ca0132.c index 208933792787..9580fe00cbd9 100644 --- a/sound/pci/hda/patch_ca0132.c +++ b/sound/pci/hda/patch_ca0132.c @@ -2962,7 +2962,6 @@ static int dsp_allocate_ports_format(struct hda_codec *codec, const unsigned short fmt, unsigned int *port_map) { - int status; unsigned int num_chans; unsigned int sample_rate_div = ((get_hdafmt_rate(fmt) >> 0) & 3) + 1; @@ -2976,9 +2975,7 @@ static int dsp_allocate_ports_format(struct hda_codec *codec, num_chans = get_hdafmt_chs(fmt) + 1; - status = dsp_allocate_ports(codec, num_chans, rate_multi, port_map); - - return status; + return dsp_allocate_ports(codec, num_chans, rate_multi, port_map); } /* diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c index 6c209cd26c0c..21edf7a619f0 100644 --- a/sound/pci/hda/patch_hdmi.c +++ b/sound/pci/hda/patch_hdmi.c @@ -53,7 +53,8 @@ MODULE_PARM_DESC(enable_all_pins, "Forcibly enable all pins"); struct hdmi_spec_per_cvt { hda_nid_t cvt_nid; - int assigned; + bool assigned; /* the stream has been assigned */ + bool silent_stream; /* silent stream activated */ unsigned int channels_min; unsigned int channels_max; u32 rates; @@ -150,7 +151,7 @@ struct hdmi_spec { */ int dev_num; struct snd_array pins; /* struct hdmi_spec_per_pin */ - struct hdmi_pcm pcm_rec[16]; + struct hdmi_pcm pcm_rec[8]; struct mutex pcm_lock; struct mutex bind_lock; /* for audio component binding */ /* pcm_bitmap means which pcms have been assigned to pins*/ @@ -166,10 +167,10 @@ struct hdmi_spec { struct hdmi_ops ops; bool dyn_pin_out; - bool dyn_pcm_assign; - bool dyn_pcm_no_legacy; /* hdmi interrupt trigger control flag for Nvidia codec */ bool hdmi_intr_trig_ctrl; + bool nv_dp_workaround; /* workaround DP audio infoframe for Nvidia */ + bool intel_hsw_fixup; /* apply Intel platform-specific fixups */ /* * Non-generic VIA/NVIDIA specific @@ -229,7 +230,7 @@ struct dp_audio_infoframe { union audio_infoframe { struct hdmi_audio_infoframe hdmi; struct dp_audio_infoframe dp; - u8 bytes[0]; + DECLARE_FLEX_ARRAY(u8, bytes); }; /* @@ -493,7 +494,8 @@ static void print_eld_info(struct snd_info_entry *entry, struct hdmi_spec_per_pin *per_pin = entry->private_data; mutex_lock(&per_pin->lock); - snd_hdmi_print_eld_info(&per_pin->sink_eld, buffer); + snd_hdmi_print_eld_info(&per_pin->sink_eld, buffer, per_pin->pin_nid, + per_pin->dev_id, per_pin->cvt_nid); mutex_unlock(&per_pin->lock); } @@ -679,15 +681,24 @@ static void hdmi_pin_setup_infoframe(struct hda_codec *codec, int ca, int active_channels, int conn_type) { + struct hdmi_spec *spec = codec->spec; union audio_infoframe ai; memset(&ai, 0, sizeof(ai)); - if (conn_type == 0) { /* HDMI */ + if ((conn_type == 0) || /* HDMI */ + /* Nvidia DisplayPort: Nvidia HW expects same layout as HDMI */ + (conn_type == 1 && spec->nv_dp_workaround)) { struct hdmi_audio_infoframe *hdmi_ai = &ai.hdmi; - hdmi_ai->type = 0x84; - hdmi_ai->ver = 0x01; - hdmi_ai->len = 0x0a; + if (conn_type == 0) { /* HDMI */ + hdmi_ai->type = 0x84; + hdmi_ai->ver = 0x01; + hdmi_ai->len = 0x0a; + } else {/* Nvidia DP */ + hdmi_ai->type = 0x84; + hdmi_ai->ver = 0x1b; + hdmi_ai->len = 0x11 << 2; + } hdmi_ai->CC02_CT47 = active_channels - 1; hdmi_ai->CA = ca; hdmi_checksum_audio_infoframe(hdmi_ai); @@ -977,7 +988,8 @@ static int hdmi_setup_stream(struct hda_codec *codec, hda_nid_t cvt_nid, * of the pin. */ static int hdmi_choose_cvt(struct hda_codec *codec, - int pin_idx, int *cvt_id) + int pin_idx, int *cvt_id, + bool silent) { struct hdmi_spec *spec = codec->spec; struct hdmi_spec_per_pin *per_pin; @@ -992,6 +1004,9 @@ static int hdmi_choose_cvt(struct hda_codec *codec, if (per_pin && per_pin->silent_stream) { cvt_idx = cvt_nid_to_cvt_index(codec, per_pin->cvt_nid); + per_cvt = get_cvt(spec, cvt_idx); + if (per_cvt->assigned && !silent) + return -EBUSY; if (cvt_id) *cvt_id = cvt_idx; return 0; @@ -1002,7 +1017,7 @@ static int hdmi_choose_cvt(struct hda_codec *codec, per_cvt = get_cvt(spec, cvt_idx); /* Must not already be assigned */ - if (per_cvt->assigned) + if (per_cvt->assigned || per_cvt->silent_stream) continue; if (per_pin == NULL) break; @@ -1171,9 +1186,7 @@ static void pin_cvt_fixup(struct hda_codec *codec, spec->ops.pin_cvt_fixup(codec, per_pin, cvt_nid); } -/* called in hdmi_pcm_open when no pin is assigned to the PCM - * in dyn_pcm_assign mode. - */ +/* called in hdmi_pcm_open when no pin is assigned to the PCM */ static int hdmi_pcm_open_no_pin(struct hda_pcm_stream *hinfo, struct hda_codec *codec, struct snd_pcm_substream *substream) @@ -1188,12 +1201,12 @@ static int hdmi_pcm_open_no_pin(struct hda_pcm_stream *hinfo, if (pcm_idx < 0) return -EINVAL; - err = hdmi_choose_cvt(codec, -1, &cvt_idx); + err = hdmi_choose_cvt(codec, -1, &cvt_idx, false); if (err) return err; per_cvt = get_cvt(spec, cvt_idx); - per_cvt->assigned = 1; + per_cvt->assigned = true; hinfo->nid = per_cvt->cvt_nid; pin_cvt_fixup(codec, NULL, per_cvt->cvt_nid); @@ -1241,28 +1254,21 @@ static int hdmi_pcm_open(struct hda_pcm_stream *hinfo, mutex_lock(&spec->pcm_lock); pin_idx = hinfo_to_pin_index(codec, hinfo); - if (!spec->dyn_pcm_assign) { - if (snd_BUG_ON(pin_idx < 0)) { - err = -EINVAL; - goto unlock; - } - } else { - /* no pin is assigned to the PCM - * PA need pcm open successfully when probe - */ - if (pin_idx < 0) { - err = hdmi_pcm_open_no_pin(hinfo, codec, substream); - goto unlock; - } + /* no pin is assigned to the PCM + * PA need pcm open successfully when probe + */ + if (pin_idx < 0) { + err = hdmi_pcm_open_no_pin(hinfo, codec, substream); + goto unlock; } - err = hdmi_choose_cvt(codec, pin_idx, &cvt_idx); + err = hdmi_choose_cvt(codec, pin_idx, &cvt_idx, false); if (err < 0) goto unlock; per_cvt = get_cvt(spec, cvt_idx); /* Claim converter */ - per_cvt->assigned = 1; + per_cvt->assigned = true; set_bit(pcm_idx, &spec->pcm_in_use); per_pin = get_pin(spec, pin_idx); @@ -1296,7 +1302,7 @@ static int hdmi_pcm_open(struct hda_pcm_stream *hinfo, snd_hdmi_eld_update_pcm_info(&eld->info, hinfo); if (hinfo->channels_min > hinfo->channels_max || !hinfo->rates || !hinfo->formats) { - per_cvt->assigned = 0; + per_cvt->assigned = false; hinfo->nid = 0; snd_hda_spdif_ctls_unassign(codec, pcm_idx); err = -ENODEV; @@ -1358,43 +1364,6 @@ static int hdmi_find_pcm_slot(struct hdmi_spec *spec, { int i; - /* on the new machines, try to assign the pcm slot dynamically, - * not use the preferred fixed map (legacy way) anymore. - */ - if (spec->dyn_pcm_no_legacy) - goto last_try; - - /* - * generic_hdmi_build_pcms() may allocate extra PCMs on some - * platforms (with maximum of 'num_nids + dev_num - 1') - * - * The per_pin of pin_nid_idx=n and dev_id=m prefers to get pcm-n - * if m==0. This guarantees that dynamic pcm assignments are compatible - * with the legacy static per_pin-pcm assignment that existed in the - * days before DP-MST. - * - * Intel DP-MST prefers this legacy behavior for compatibility, too. - * - * per_pin of m!=0 prefers to get pcm=(num_nids + (m - 1)). - */ - - if (per_pin->dev_id == 0 || spec->intel_hsw_fixup) { - if (!test_bit(per_pin->pin_nid_idx, &spec->pcm_bitmap)) - return per_pin->pin_nid_idx; - } else { - i = spec->num_nids + (per_pin->dev_id - 1); - if (i < spec->pcm_used && !(test_bit(i, &spec->pcm_bitmap))) - return i; - } - - /* have a second try; check the area over num_nids */ - for (i = spec->num_nids; i < spec->pcm_used; i++) { - if (!test_bit(i, &spec->pcm_bitmap)) - return i; - } - - last_try: - /* the last try; check the empty slots in pins */ for (i = 0; i < spec->pcm_used; i++) { if (!test_bit(i, &spec->pcm_bitmap)) return i; @@ -1456,10 +1425,9 @@ static void hdmi_pcm_setup_pin(struct hdmi_spec *spec, int mux_idx; bool non_pcm; - if (per_pin->pcm_idx >= 0 && per_pin->pcm_idx < spec->pcm_used) - pcm = get_pcm_rec(spec, per_pin->pcm_idx); - else + if (per_pin->pcm_idx < 0 || per_pin->pcm_idx >= spec->pcm_used) return; + pcm = get_pcm_rec(spec, per_pin->pcm_idx); if (!pcm->pcm) return; if (!test_bit(per_pin->pcm_idx, &spec->pcm_in_use)) @@ -1557,14 +1525,12 @@ static void update_eld(struct hda_codec *codec, */ pcm_jack = pin_idx_to_pcm_jack(codec, per_pin); - if (spec->dyn_pcm_assign) { - if (eld->eld_valid) { - hdmi_attach_hda_pcm(spec, per_pin); - hdmi_pcm_setup_pin(spec, per_pin); - } else { - hdmi_pcm_reset_pin(spec, per_pin); - hdmi_detach_hda_pcm(spec, per_pin); - } + if (eld->eld_valid) { + hdmi_attach_hda_pcm(spec, per_pin); + hdmi_pcm_setup_pin(spec, per_pin); + } else { + hdmi_pcm_reset_pin(spec, per_pin); + hdmi_detach_hda_pcm(spec, per_pin); } /* if pcm_idx == -1, it means this is in monitor connection event * we can get the correct pcm_idx now. @@ -1748,14 +1714,14 @@ static void silent_stream_enable(struct hda_codec *codec, } pin_idx = pin_id_to_pin_index(codec, per_pin->pin_nid, per_pin->dev_id); - err = hdmi_choose_cvt(codec, pin_idx, &cvt_idx); + err = hdmi_choose_cvt(codec, pin_idx, &cvt_idx, true); if (err) { codec_err(codec, "hdmi: no free converter to enable silent mode\n"); goto unlock_out; } per_cvt = get_cvt(spec, cvt_idx); - per_cvt->assigned = 1; + per_cvt->silent_stream = true; per_pin->cvt_nid = per_cvt->cvt_nid; per_pin->silent_stream = true; @@ -1815,7 +1781,7 @@ static void silent_stream_disable(struct hda_codec *codec, cvt_idx = cvt_nid_to_cvt_index(codec, per_pin->cvt_nid); if (cvt_idx >= 0 && cvt_idx < spec->num_cvts) { per_cvt = get_cvt(spec, cvt_idx); - per_cvt->assigned = 0; + per_cvt->silent_stream = false; } if (spec->silent_stream_type == SILENT_STREAM_I915) { @@ -1926,7 +1892,7 @@ static int hdmi_add_pin(struct hda_codec *codec, hda_nid_t pin_nid) * structures based on worst case. */ dev_num = spec->dev_num; - } else if (spec->dyn_pcm_assign && codec->dp_mst) { + } else if (codec->dp_mst) { dev_num = snd_hda_get_num_devices(codec, pin_nid) + 1; /* * spec->dev_num is the maxinum number of device entries @@ -1951,13 +1917,8 @@ static int hdmi_add_pin(struct hda_codec *codec, hda_nid_t pin_nid) if (!per_pin) return -ENOMEM; - if (spec->dyn_pcm_assign) { - per_pin->pcm = NULL; - per_pin->pcm_idx = -1; - } else { - per_pin->pcm = get_hdmi_pcm(spec, pin_idx); - per_pin->pcm_idx = pin_idx; - } + per_pin->pcm = NULL; + per_pin->pcm_idx = -1; per_pin->pin_nid = pin_nid; per_pin->pin_nid_idx = spec->num_nids; per_pin->dev_id = i; @@ -1966,6 +1927,8 @@ static int hdmi_add_pin(struct hda_codec *codec, hda_nid_t pin_nid) err = hdmi_read_pin_conn(codec, pin_idx); if (err < 0) return err; + if (!is_jack_detectable(codec, pin_nid)) + codec_warn(codec, "HDMI: pin NID 0x%x - jack not detectable\n", pin_nid); spec->num_pins++; } spec->num_nids++; @@ -2113,10 +2076,9 @@ static int generic_hdmi_playback_pcm_prepare(struct hda_pcm_stream *hinfo, mutex_lock(&spec->pcm_lock); pin_idx = hinfo_to_pin_index(codec, hinfo); - if (spec->dyn_pcm_assign && pin_idx < 0) { - /* when dyn_pcm_assign and pcm is not bound to a pin - * skip pin setup and return 0 to make audio playback - * be ongoing + if (pin_idx < 0) { + /* when pcm is not bound to a pin skip pin setup and return 0 + * to make audio playback be ongoing */ pin_cvt_fixup(codec, NULL, cvt_nid); snd_hda_codec_setup_stream(codec, cvt_nid, @@ -2211,7 +2173,7 @@ static int hdmi_pcm_close(struct hda_pcm_stream *hinfo, goto unlock; } per_cvt = get_cvt(spec, cvt_idx); - per_cvt->assigned = 0; + per_cvt->assigned = false; hinfo->nid = 0; azx_stream(get_azx_dev(substream))->stripe = 0; @@ -2219,7 +2181,7 @@ static int hdmi_pcm_close(struct hda_pcm_stream *hinfo, snd_hda_spdif_ctls_unassign(codec, pcm_idx); clear_bit(pcm_idx, &spec->pcm_in_use); pin_idx = hinfo_to_pin_index(codec, hinfo); - if (spec->dyn_pcm_assign && pin_idx < 0) + if (pin_idx < 0) goto unlock; if (snd_BUG_ON(pin_idx < 0)) { @@ -2317,21 +2279,8 @@ static int generic_hdmi_build_pcms(struct hda_codec *codec) struct hdmi_spec *spec = codec->spec; int idx, pcm_num; - /* - * for non-mst mode, pcm number is the same as before - * for DP MST mode without extra PCM, pcm number is same - * for DP MST mode with extra PCMs, pcm number is - * (nid number + dev_num - 1) - * dev_num is the device entry number in a pin - */ - - if (spec->dyn_pcm_no_legacy && codec->mst_no_extra_pcms) - pcm_num = spec->num_cvts; - else if (codec->mst_no_extra_pcms) - pcm_num = spec->num_nids; - else - pcm_num = spec->num_nids + spec->dev_num - 1; - + /* limit the PCM devices to the codec converters */ + pcm_num = spec->num_cvts; codec_dbg(codec, "hdmi: pcm_num set to %d\n", pcm_num); for (idx = 0; idx < pcm_num; idx++) { @@ -2350,8 +2299,8 @@ static int generic_hdmi_build_pcms(struct hda_codec *codec) pstr = &info->stream[SNDRV_PCM_STREAM_PLAYBACK]; pstr->substreams = 1; pstr->ops = generic_ops; - /* pcm number is less than 16 */ - if (spec->pcm_used >= 16) + /* pcm number is less than pcm_rec array size */ + if (spec->pcm_used >= ARRAY_SIZE(spec->pcm_rec)) break; /* other pstr fields are set in open */ } @@ -2370,17 +2319,12 @@ static int generic_hdmi_build_jack(struct hda_codec *codec, int pcm_idx) { char hdmi_str[32] = "HDMI/DP"; struct hdmi_spec *spec = codec->spec; - struct hdmi_spec_per_pin *per_pin = get_pin(spec, pcm_idx); struct snd_jack *jack; int pcmdev = get_pcm_rec(spec, pcm_idx)->device; int err; if (pcmdev > 0) sprintf(hdmi_str + strlen(hdmi_str), ",pcm=%d", pcmdev); - if (!spec->dyn_pcm_assign && - !is_jack_detectable(codec, per_pin->pin_nid)) - strncat(hdmi_str, " Phantom", - sizeof(hdmi_str) - strlen(hdmi_str) - 1); err = snd_jack_new(codec->card, hdmi_str, SND_JACK_AVOUT, &jack, true, false); @@ -2413,18 +2357,9 @@ static int generic_hdmi_build_controls(struct hda_codec *codec) /* create the spdif for each pcm * pin will be bound when monitor is connected */ - if (spec->dyn_pcm_assign) - err = snd_hda_create_dig_out_ctls(codec, + err = snd_hda_create_dig_out_ctls(codec, 0, spec->cvt_nids[0], HDA_PCM_TYPE_HDMI); - else { - struct hdmi_spec_per_pin *per_pin = - get_pin(spec, pcm_idx); - err = snd_hda_create_dig_out_ctls(codec, - per_pin->pin_nid, - per_pin->mux_nids[0], - HDA_PCM_TYPE_HDMI); - } if (err < 0) return err; snd_hda_spdif_ctls_unassign(codec, pcm_idx); @@ -2544,11 +2479,7 @@ static void generic_hdmi_free(struct hda_codec *codec) for (pcm_idx = 0; pcm_idx < spec->pcm_used; pcm_idx++) { if (spec->pcm_rec[pcm_idx].jack == NULL) continue; - if (spec->dyn_pcm_assign) - snd_device_free(codec->card, - spec->pcm_rec[pcm_idx].jack); - else - spec->pcm_rec[pcm_idx].jack = NULL; + snd_device_free(codec->card, spec->pcm_rec[pcm_idx].jack); } generic_spec_free(codec); @@ -2735,9 +2666,6 @@ static void generic_acomp_pin_eld_notify(void *audio_ptr, int port, int dev_id) */ if (codec->core.dev.power.power_state.event == PM_EVENT_SUSPEND) return; - /* ditto during suspend/resume process itself */ - if (snd_hdac_is_in_pm(&codec->core)) - return; check_presence_and_report(codec, pin_nid, dev_id); } @@ -2921,9 +2849,6 @@ static void intel_pin_eld_notify(void *audio_ptr, int port, int pipe) */ if (codec->core.dev.power.power_state.event == PM_EVENT_SUSPEND) return; - /* ditto during suspend/resume process itself */ - if (snd_hdac_is_in_pm(&codec->core)) - return; snd_hdac_i915_set_bclk(&codec->bus->core); check_presence_and_report(codec, pin_nid, dev_id); @@ -3028,7 +2953,6 @@ static int intel_hsw_common_init(struct hda_codec *codec, hda_nid_t vendor_nid, return err; spec = codec->spec; codec->dp_mst = true; - spec->dyn_pcm_assign = true; spec->vendor_nid = vendor_nid; spec->port_map = port_map; spec->port_num = port_num; @@ -3092,17 +3016,9 @@ static int patch_i915_tgl_hdmi(struct hda_codec *codec) * the index indicate the port number. */ static const int map[] = {0x4, 0x6, 0x8, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf}; - int ret; - - ret = intel_hsw_common_init(codec, 0x02, map, ARRAY_SIZE(map), 4, - enable_silent_stream); - if (!ret) { - struct hdmi_spec *spec = codec->spec; - spec->dyn_pcm_no_legacy = true; - } - - return ret; + return intel_hsw_common_init(codec, 0x02, map, ARRAY_SIZE(map), 4, + enable_silent_stream); } static int patch_i915_adlp_hdmi(struct hda_codec *codec) @@ -3617,6 +3533,7 @@ static int patch_nvhdmi_2ch(struct hda_codec *codec) spec->pcm_playback.rates = SUPPORTED_RATES; spec->pcm_playback.maxbps = SUPPORTED_MAXBPS; spec->pcm_playback.formats = SUPPORTED_FORMATS; + spec->nv_dp_workaround = true; return 0; } @@ -3741,7 +3658,6 @@ static int patch_nvhdmi(struct hda_codec *codec) codec->dp_mst = true; spec = codec->spec; - spec->dyn_pcm_assign = true; err = hdmi_parse_codec(codec); if (err < 0) { @@ -3756,6 +3672,7 @@ static int patch_nvhdmi(struct hda_codec *codec) spec->chmap.ops.chmap_cea_alloc_validate_get_type = nvhdmi_chmap_cea_alloc_validate_get_type; spec->chmap.ops.chmap_validate = nvhdmi_chmap_validate; + spec->nv_dp_workaround = true; codec->link_down_at_suspend = 1; @@ -3779,6 +3696,7 @@ static int patch_nvhdmi_legacy(struct hda_codec *codec) spec->chmap.ops.chmap_cea_alloc_validate_get_type = nvhdmi_chmap_cea_alloc_validate_get_type; spec->chmap.ops.chmap_validate = nvhdmi_chmap_validate; + spec->nv_dp_workaround = true; codec->link_down_at_suspend = 1; @@ -3984,6 +3902,7 @@ static int tegra_hdmi_init(struct hda_codec *codec) generic_hdmi_init_per_pins(codec); + codec->depop_delay = 10; codec->patch_ops.build_pcms = tegra_hdmi_build_pcms; spec->chmap.ops.chmap_cea_alloc_validate_get_type = nvhdmi_chmap_cea_alloc_validate_get_type; @@ -3992,6 +3911,7 @@ static int tegra_hdmi_init(struct hda_codec *codec) spec->chmap.ops.chmap_cea_alloc_validate_get_type = nvhdmi_chmap_cea_alloc_validate_get_type; spec->chmap.ops.chmap_validate = nvhdmi_chmap_validate; + spec->nv_dp_workaround = true; return 0; } @@ -4017,10 +3937,8 @@ static int patch_tegra234_hdmi(struct hda_codec *codec) return err; codec->dp_mst = true; - codec->mst_no_extra_pcms = true; spec = codec->spec; spec->dyn_pin_out = true; - spec->dyn_pcm_assign = true; spec->hdmi_intr_trig_ctrl = true; return tegra_hdmi_init(codec); diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 38930cf5aace..e6c4bb5fa041 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -18,6 +18,7 @@ #include <linux/module.h> #include <linux/input.h> #include <linux/leds.h> +#include <linux/ctype.h> #include <sound/core.h> #include <sound/jack.h> #include <sound/hda_codec.h> @@ -4021,22 +4022,16 @@ static void alc5505_dsp_init(struct hda_codec *codec) static int alc269_suspend(struct hda_codec *codec) { struct alc_spec *spec = codec->spec; - int i; if (spec->has_alc5505_dsp) alc5505_dsp_suspend(codec); - for (i = 0; i < HDA_MAX_COMPONENTS; i++) - if (spec->comps[i].suspend_hook) - spec->comps[i].suspend_hook(spec->comps[i].dev); - return alc_suspend(codec); } static int alc269_resume(struct hda_codec *codec) { struct alc_spec *spec = codec->spec; - int i; if (spec->codec_variant == ALC269_TYPE_ALC269VB) alc269vb_toggle_power_output(codec, 0); @@ -4067,10 +4062,6 @@ static int alc269_resume(struct hda_codec *codec) if (spec->has_alc5505_dsp) alc5505_dsp_resume(codec); - for (i = 0; i < HDA_MAX_COMPONENTS; i++) - if (spec->comps[i].resume_hook) - spec->comps[i].resume_hook(spec->comps[i].dev); - return 0; } #endif /* CONFIG_PM */ @@ -6663,19 +6654,12 @@ static int comp_bind(struct device *dev) { struct hda_codec *cdc = dev_to_hda_codec(dev); struct alc_spec *spec = cdc->spec; - int ret, i; + int ret; ret = component_bind_all(dev, spec->comps); if (ret) return ret; - if (snd_hdac_is_power_on(&cdc->core)) { - codec_dbg(cdc, "Resuming after bind.\n"); - for (i = 0; i < HDA_MAX_COMPONENTS; i++) - if (spec->comps[i].resume_hook) - spec->comps[i].resume_hook(spec->comps[i].dev); - } - return 0; } @@ -6704,23 +6688,51 @@ static void comp_generic_playback_hook(struct hda_pcm_stream *hinfo, struct hda_ } } +struct cs35l41_dev_name { + const char *bus; + const char *hid; + int index; +}; + +/* match the device name in a slightly relaxed manner */ +static int comp_match_cs35l41_dev_name(struct device *dev, void *data) +{ + struct cs35l41_dev_name *p = data; + const char *d = dev_name(dev); + int n = strlen(p->bus); + char tmp[32]; + + /* check the bus name */ + if (strncmp(d, p->bus, n)) + return 0; + /* skip the bus number */ + if (isdigit(d[n])) + n++; + /* the rest must be exact matching */ + snprintf(tmp, sizeof(tmp), "-%s:00-cs35l41-hda.%d", p->hid, p->index); + return !strcmp(d + n, tmp); +} + static void cs35l41_generic_fixup(struct hda_codec *cdc, int action, const char *bus, const char *hid, int count) { struct device *dev = hda_codec_dev(cdc); struct alc_spec *spec = cdc->spec; - char *name; + struct cs35l41_dev_name *rec; int ret, i; switch (action) { case HDA_FIXUP_ACT_PRE_PROBE: for (i = 0; i < count; i++) { - name = devm_kasprintf(dev, GFP_KERNEL, - "%s-%s:00-cs35l41-hda.%d", bus, hid, i); - if (!name) + rec = devm_kmalloc(dev, sizeof(*rec), GFP_KERNEL); + if (!rec) return; + rec->bus = bus; + rec->hid = hid; + rec->index = i; spec->comps[i].codec = cdc; - component_match_add(dev, &spec->match, component_compare_dev_name, name); + component_match_add(dev, &spec->match, + comp_match_cs35l41_dev_name, rec); } ret = component_master_add_with_match(dev, &comp_master_ops, spec->match); if (ret) @@ -6738,12 +6750,12 @@ static void cs35l41_fixup_i2c_two(struct hda_codec *cdc, const struct hda_fixup static void cs35l41_fixup_spi_two(struct hda_codec *codec, const struct hda_fixup *fix, int action) { - cs35l41_generic_fixup(codec, action, "spi0", "CSC3551", 2); + cs35l41_generic_fixup(codec, action, "spi", "CSC3551", 2); } static void cs35l41_fixup_spi_four(struct hda_codec *codec, const struct hda_fixup *fix, int action) { - cs35l41_generic_fixup(codec, action, "spi0", "CSC3551", 4); + cs35l41_generic_fixup(codec, action, "spi", "CSC3551", 4); } static void alc287_fixup_legion_16achg6_speakers(struct hda_codec *cdc, const struct hda_fixup *fix, @@ -7067,6 +7079,8 @@ enum { ALC294_FIXUP_ASUS_GU502_HP, ALC294_FIXUP_ASUS_GU502_PINS, ALC294_FIXUP_ASUS_GU502_VERBS, + ALC294_FIXUP_ASUS_G513_PINS, + ALC285_FIXUP_ASUS_G533Z_PINS, ALC285_FIXUP_HP_GPIO_LED, ALC285_FIXUP_HP_MUTE_LED, ALC236_FIXUP_HP_GPIO_LED, @@ -8406,6 +8420,26 @@ static const struct hda_fixup alc269_fixups[] = { .type = HDA_FIXUP_FUNC, .v.func = alc294_fixup_gu502_hp, }, + [ALC294_FIXUP_ASUS_G513_PINS] = { + .type = HDA_FIXUP_PINS, + .v.pins = (const struct hda_pintbl[]) { + { 0x19, 0x03a11050 }, /* front HP mic */ + { 0x1a, 0x03a11c30 }, /* rear external mic */ + { 0x21, 0x03211420 }, /* front HP out */ + { } + }, + }, + [ALC285_FIXUP_ASUS_G533Z_PINS] = { + .type = HDA_FIXUP_PINS, + .v.pins = (const struct hda_pintbl[]) { + { 0x14, 0x90170152 }, /* Speaker Surround Playback Switch */ + { 0x19, 0x03a19020 }, /* Mic Boost Volume */ + { 0x1a, 0x03a11c30 }, /* Mic Boost Volume */ + { 0x1e, 0x90170151 }, /* Rear jack, IN OUT EAPD Detect */ + { 0x21, 0x03211420 }, + { } + }, + }, [ALC294_FIXUP_ASUS_COEF_1B] = { .type = HDA_FIXUP_VERBS, .v.verbs = (const struct hda_verb[]) { @@ -9165,6 +9199,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { SND_PCI_QUIRK(0x1028, 0x0a9d, "Dell Latitude 5430", ALC269_FIXUP_DELL4_MIC_NO_PRESENCE), SND_PCI_QUIRK(0x1028, 0x0a9e, "Dell Latitude 5430", ALC269_FIXUP_DELL4_MIC_NO_PRESENCE), SND_PCI_QUIRK(0x1028, 0x0b19, "Dell XPS 15 9520", ALC289_FIXUP_DUAL_SPK), + SND_PCI_QUIRK(0x1028, 0x0b1a, "Dell Precision 5570", ALC289_FIXUP_DUAL_SPK), SND_PCI_QUIRK(0x1028, 0x164a, "Dell", ALC293_FIXUP_DELL1_MIC_NO_PRESENCE), SND_PCI_QUIRK(0x1028, 0x164b, "Dell", ALC293_FIXUP_DELL1_MIC_NO_PRESENCE), SND_PCI_QUIRK(0x103c, 0x1586, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC2), @@ -9292,6 +9327,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { SND_PCI_QUIRK(0x103c, 0x8896, "HP EliteBook 855 G8 Notebook PC", ALC285_FIXUP_HP_MUTE_LED), SND_PCI_QUIRK(0x103c, 0x8898, "HP EliteBook 845 G8 Notebook PC", ALC285_FIXUP_HP_LIMIT_INT_MIC_BOOST), SND_PCI_QUIRK(0x103c, 0x88d0, "HP Pavilion 15-eh1xxx (mainboard 88D0)", ALC287_FIXUP_HP_GPIO_LED), + SND_PCI_QUIRK(0x103c, 0x8902, "HP OMEN 16", ALC285_FIXUP_HP_MUTE_LED), SND_PCI_QUIRK(0x103c, 0x896e, "HP EliteBook x360 830 G9", ALC245_FIXUP_CS35L41_SPI_2_HP_GPIO_LED), SND_PCI_QUIRK(0x103c, 0x8971, "HP EliteBook 830 G9", ALC245_FIXUP_CS35L41_SPI_2_HP_GPIO_LED), SND_PCI_QUIRK(0x103c, 0x8972, "HP EliteBook 840 G9", ALC245_FIXUP_CS35L41_SPI_2_HP_GPIO_LED), @@ -9318,6 +9354,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { SND_PCI_QUIRK(0x103c, 0x8aa3, "HP ProBook 450 G9 (MB 8AA1)", ALC236_FIXUP_HP_GPIO_LED), SND_PCI_QUIRK(0x103c, 0x8aa8, "HP EliteBook 640 G9 (MB 8AA6)", ALC236_FIXUP_HP_GPIO_LED), SND_PCI_QUIRK(0x103c, 0x8aab, "HP EliteBook 650 G9 (MB 8AA9)", ALC236_FIXUP_HP_GPIO_LED), + SND_PCI_QUIRK(0x103c, 0x8abb, "HP ZBook Firefly 14 G9", ALC245_FIXUP_CS35L41_SPI_2_HP_GPIO_LED), SND_PCI_QUIRK(0x103c, 0x8ad1, "HP EliteBook 840 14 inch G9 Notebook PC", ALC245_FIXUP_CS35L41_SPI_2_HP_GPIO_LED), SND_PCI_QUIRK(0x103c, 0x8ad2, "HP EliteBook 860 16 inch G9 Notebook PC", ALC245_FIXUP_CS35L41_SPI_2_HP_GPIO_LED), SND_PCI_QUIRK(0x1043, 0x103e, "ASUS X540SA", ALC256_FIXUP_ASUS_MIC), @@ -9339,10 +9376,11 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { SND_PCI_QUIRK(0x1043, 0x13b0, "ASUS Z550SA", ALC256_FIXUP_ASUS_MIC), SND_PCI_QUIRK(0x1043, 0x1427, "Asus Zenbook UX31E", ALC269VB_FIXUP_ASUS_ZENBOOK), SND_PCI_QUIRK(0x1043, 0x1517, "Asus Zenbook UX31A", ALC269VB_FIXUP_ASUS_ZENBOOK_UX31A), + SND_PCI_QUIRK(0x1043, 0x1662, "ASUS GV301QH", ALC294_FIXUP_ASUS_DUAL_SPK), + SND_PCI_QUIRK(0x1043, 0x16b2, "ASUS GU603", ALC289_FIXUP_ASUS_GA401), SND_PCI_QUIRK(0x1043, 0x16e3, "ASUS UX50", ALC269_FIXUP_STEREO_DMIC), SND_PCI_QUIRK(0x1043, 0x1740, "ASUS UX430UA", ALC295_FIXUP_ASUS_DACS), SND_PCI_QUIRK(0x1043, 0x17d1, "ASUS UX431FL", ALC294_FIXUP_ASUS_DUAL_SPK), - SND_PCI_QUIRK(0x1043, 0x1662, "ASUS GV301QH", ALC294_FIXUP_ASUS_DUAL_SPK), SND_PCI_QUIRK(0x1043, 0x1881, "ASUS Zephyrus S/M", ALC294_FIXUP_ASUS_GX502_PINS), SND_PCI_QUIRK(0x1043, 0x18b1, "Asus MJ401TA", ALC256_FIXUP_ASUS_HEADSET_MIC), SND_PCI_QUIRK(0x1043, 0x18f1, "Asus FX505DT", ALC256_FIXUP_ASUS_HEADSET_MIC), @@ -9358,14 +9396,17 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { SND_PCI_QUIRK(0x1043, 0x1b13, "Asus U41SV", ALC269_FIXUP_INV_DMIC), SND_PCI_QUIRK(0x1043, 0x1bbd, "ASUS Z550MA", ALC255_FIXUP_ASUS_MIC_NO_PRESENCE), SND_PCI_QUIRK(0x1043, 0x1c23, "Asus X55U", ALC269_FIXUP_LIMIT_INT_MIC_BOOST), + SND_PCI_QUIRK(0x1043, 0x1c92, "ASUS ROG Strix G15", ALC285_FIXUP_ASUS_G533Z_PINS), SND_PCI_QUIRK(0x1043, 0x1ccd, "ASUS X555UB", ALC256_FIXUP_ASUS_MIC), + SND_PCI_QUIRK(0x1043, 0x1d42, "ASUS Zephyrus G14 2022", ALC289_FIXUP_ASUS_GA401), SND_PCI_QUIRK(0x1043, 0x1d4e, "ASUS TM420", ALC256_FIXUP_ASUS_HPE), SND_PCI_QUIRK(0x1043, 0x1e11, "ASUS Zephyrus G15", ALC289_FIXUP_ASUS_GA502), SND_PCI_QUIRK(0x1043, 0x1e51, "ASUS Zephyrus M15", ALC294_FIXUP_ASUS_GU502_PINS), + SND_PCI_QUIRK(0x1043, 0x1e5e, "ASUS ROG Strix G513", ALC294_FIXUP_ASUS_G513_PINS), SND_PCI_QUIRK(0x1043, 0x1e8e, "ASUS Zephyrus G15", ALC289_FIXUP_ASUS_GA401), + SND_PCI_QUIRK(0x1043, 0x1c52, "ASUS Zephyrus G15 2022", ALC289_FIXUP_ASUS_GA401), SND_PCI_QUIRK(0x1043, 0x1f11, "ASUS Zephyrus G14", ALC289_FIXUP_ASUS_GA401), - SND_PCI_QUIRK(0x1043, 0x1d42, "ASUS Zephyrus G14 2022", ALC289_FIXUP_ASUS_GA401), - SND_PCI_QUIRK(0x1043, 0x16b2, "ASUS GU603", ALC289_FIXUP_ASUS_GA401), + SND_PCI_QUIRK(0x1043, 0x1f92, "ASUS ROG Flow X16", ALC289_FIXUP_ASUS_GA401), SND_PCI_QUIRK(0x1043, 0x3030, "ASUS ZN270IE", ALC256_FIXUP_ASUS_AIO_GPIO2), SND_PCI_QUIRK(0x1043, 0x831a, "ASUS P901", ALC269_FIXUP_STEREO_DMIC), SND_PCI_QUIRK(0x1043, 0x834a, "ASUS S101", ALC269_FIXUP_STEREO_DMIC), @@ -9387,6 +9428,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { SND_PCI_QUIRK(0x10ec, 0x10f2, "Intel Reference board", ALC700_FIXUP_INTEL_REFERENCE), SND_PCI_QUIRK(0x10ec, 0x118c, "Medion EE4254 MD62100", ALC256_FIXUP_MEDION_HEADSET_NO_PRESENCE), SND_PCI_QUIRK(0x10ec, 0x1230, "Intel Reference board", ALC295_FIXUP_CHROME_BOOK), + SND_PCI_QUIRK(0x10ec, 0x124c, "Intel Reference board", ALC295_FIXUP_CHROME_BOOK), SND_PCI_QUIRK(0x10ec, 0x1252, "Intel Reference board", ALC295_FIXUP_CHROME_BOOK), SND_PCI_QUIRK(0x10ec, 0x1254, "Intel Reference board", ALC295_FIXUP_CHROME_BOOK), SND_PCI_QUIRK(0x10f7, 0x8338, "Panasonic CF-SZ6", ALC269_FIXUP_HEADSET_MODE), @@ -9569,6 +9611,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { SND_PCI_QUIRK(0x17aa, 0x9e54, "LENOVO NB", ALC269_FIXUP_LENOVO_EAPD), SND_PCI_QUIRK(0x1849, 0x1233, "ASRock NUC Box 1100", ALC233_FIXUP_NO_AUDIO_JACK), SND_PCI_QUIRK(0x19e5, 0x3204, "Huawei MACH-WX9", ALC256_FIXUP_HUAWEI_MACH_WX9_PINS), + SND_PCI_QUIRK(0x19e5, 0x320f, "Huawei WRT-WX9 ", ALC256_FIXUP_ASUS_MIC_NO_PRESENCE), SND_PCI_QUIRK(0x1b35, 0x1235, "CZC B20", ALC269_FIXUP_CZC_B20), SND_PCI_QUIRK(0x1b35, 0x1236, "CZC TMI", ALC269_FIXUP_CZC_TMI), SND_PCI_QUIRK(0x1b35, 0x1237, "CZC L101", ALC269_FIXUP_CZC_L101), diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index 7f340f18599c..a794a01a68ca 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c @@ -4311,6 +4311,8 @@ static int stac_parse_auto_config(struct hda_codec *codec) if (codec->beep) { /* IDT/STAC codecs have linear beep tone parameter */ codec->beep->linear_tone = spec->linear_tone_beep; + /* keep power up while beep is enabled */ + codec->beep->keep_power_at_enable = 1; /* if no beep switch is available, make its own one */ caps = query_amp_caps(codec, nid, HDA_OUTPUT); if (!(caps & AC_AMPCAP_MUTE)) { @@ -4444,28 +4446,6 @@ static int stac_suspend(struct hda_codec *codec) return 0; } - -static int stac_check_power_status(struct hda_codec *codec, hda_nid_t nid) -{ -#ifdef CONFIG_SND_HDA_INPUT_BEEP - struct sigmatel_spec *spec = codec->spec; -#endif - int ret = snd_hda_gen_check_power_status(codec, nid); - -#ifdef CONFIG_SND_HDA_INPUT_BEEP - if (nid == spec->gen.beep_nid && codec->beep) { - if (codec->beep->enabled != spec->beep_power_on) { - spec->beep_power_on = codec->beep->enabled; - if (spec->beep_power_on) - snd_hda_power_up_pm(codec); - else - snd_hda_power_down_pm(codec); - } - ret |= spec->beep_power_on; - } -#endif - return ret; -} #else #define stac_suspend NULL #endif /* CONFIG_PM */ @@ -4478,7 +4458,6 @@ static const struct hda_codec_ops stac_patch_ops = { .unsol_event = snd_hda_jack_unsol_event, #ifdef CONFIG_PM .suspend = stac_suspend, - .check_power_status = stac_check_power_status, #endif }; diff --git a/sound/pcmcia/pdaudiocf/pdaudiocf_pcm.c b/sound/pcmcia/pdaudiocf/pdaudiocf_pcm.c index dfc4295b69c4..aaa82ec36540 100644 --- a/sound/pcmcia/pdaudiocf/pdaudiocf_pcm.c +++ b/sound/pcmcia/pdaudiocf/pdaudiocf_pcm.c @@ -257,8 +257,7 @@ int snd_pdacf_pcm_new(struct snd_pdacf *chip) return err; snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &pdacf_pcm_capture_ops); - snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_VMALLOC, - snd_dma_continuous_data(GFP_KERNEL | GFP_DMA32), + snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_VMALLOC, NULL, 0, 0); pcm->private_data = chip; diff --git a/sound/ppc/keywest.c b/sound/ppc/keywest.c index 6e5daae18f9d..80e5108157ef 100644 --- a/sound/ppc/keywest.c +++ b/sound/ppc/keywest.c @@ -71,14 +71,12 @@ static int keywest_attach_adapter(struct i2c_adapter *adapter) return 0; } -static int keywest_remove(struct i2c_client *client) +static void keywest_remove(struct i2c_client *client) { if (! keywest_ctx) - return 0; + return; if (client == keywest_ctx->client) keywest_ctx->client = NULL; - - return 0; } diff --git a/sound/ppc/tumbler.c b/sound/ppc/tumbler.c index c65e74d7cd0a..f3f8ad7c3df8 100644 --- a/sound/ppc/tumbler.c +++ b/sound/ppc/tumbler.c @@ -1060,8 +1060,7 @@ static struct device_node *find_audio_device(const char *name) if (! gpiop) return NULL; - for (np = of_get_next_child(gpiop, NULL); np; - np = of_get_next_child(gpiop, np)) { + for_each_child_of_node(gpiop, np) { const char *property = of_get_property(np, "audio-gpio", NULL); if (property && strcmp(property, name) == 0) break; @@ -1080,8 +1079,7 @@ static struct device_node *find_compatible_audio_device(const char *name) if (!gpiop) return NULL; - for (np = of_get_next_child(gpiop, NULL); np; - np = of_get_next_child(gpiop, np)) { + for_each_child_of_node(gpiop, np) { if (of_device_is_compatible(np, name)) break; } diff --git a/sound/soc/codecs/adau1761-i2c.c b/sound/soc/codecs/adau1761-i2c.c index 0683caf86aea..0cefff49569c 100644 --- a/sound/soc/codecs/adau1761-i2c.c +++ b/sound/soc/codecs/adau1761-i2c.c @@ -30,10 +30,9 @@ static int adau1761_i2c_probe(struct i2c_client *client) id->driver_data, NULL); } -static int adau1761_i2c_remove(struct i2c_client *client) +static void adau1761_i2c_remove(struct i2c_client *client) { adau17x1_remove(&client->dev); - return 0; } static const struct i2c_device_id adau1761_i2c_ids[] = { diff --git a/sound/soc/codecs/adau1781-i2c.c b/sound/soc/codecs/adau1781-i2c.c index e046de0ebcc7..39021b8cfb62 100644 --- a/sound/soc/codecs/adau1781-i2c.c +++ b/sound/soc/codecs/adau1781-i2c.c @@ -30,10 +30,9 @@ static int adau1781_i2c_probe(struct i2c_client *client) id->driver_data, NULL); } -static int adau1781_i2c_remove(struct i2c_client *client) +static void adau1781_i2c_remove(struct i2c_client *client) { adau17x1_remove(&client->dev); - return 0; } static const struct i2c_device_id adau1781_i2c_ids[] = { diff --git a/sound/soc/codecs/ak4375.c b/sound/soc/codecs/ak4375.c index 1ed004ba7cd2..573389e402f8 100644 --- a/sound/soc/codecs/ak4375.c +++ b/sound/soc/codecs/ak4375.c @@ -580,11 +580,9 @@ static int ak4375_i2c_probe(struct i2c_client *i2c) return 0; } -static int ak4375_i2c_remove(struct i2c_client *i2c) +static void ak4375_i2c_remove(struct i2c_client *i2c) { pm_runtime_disable(&i2c->dev); - - return 0; } static const struct of_device_id ak4375_of_match[] = { diff --git a/sound/soc/codecs/ak4458.c b/sound/soc/codecs/ak4458.c index 626310859814..1db73552c746 100644 --- a/sound/soc/codecs/ak4458.c +++ b/sound/soc/codecs/ak4458.c @@ -786,14 +786,12 @@ static int ak4458_i2c_probe(struct i2c_client *i2c) return 0; } -static int ak4458_i2c_remove(struct i2c_client *i2c) +static void ak4458_i2c_remove(struct i2c_client *i2c) { struct ak4458_priv *ak4458 = i2c_get_clientdata(i2c); ak4458_reset(ak4458, true); pm_runtime_disable(&i2c->dev); - - return 0; } static const struct of_device_id ak4458_of_match[] = { diff --git a/sound/soc/codecs/ak4641.c b/sound/soc/codecs/ak4641.c index 88851e94b045..0d3ee195b3cc 100644 --- a/sound/soc/codecs/ak4641.c +++ b/sound/soc/codecs/ak4641.c @@ -604,7 +604,7 @@ err_out: return ret; } -static int ak4641_i2c_remove(struct i2c_client *i2c) +static void ak4641_i2c_remove(struct i2c_client *i2c) { struct ak4641_platform_data *pdata = i2c->dev.platform_data; @@ -616,8 +616,6 @@ static int ak4641_i2c_remove(struct i2c_client *i2c) if (gpio_is_valid(pdata->gpio_npdn)) gpio_free(pdata->gpio_npdn); } - - return 0; } static const struct i2c_device_id ak4641_i2c_id[] = { diff --git a/sound/soc/codecs/ak5558.c b/sound/soc/codecs/ak5558.c index 887d2c04d647..60abcffe6a0c 100644 --- a/sound/soc/codecs/ak5558.c +++ b/sound/soc/codecs/ak5558.c @@ -479,11 +479,9 @@ static int ak5558_i2c_probe(struct i2c_client *i2c) return 0; } -static int ak5558_i2c_remove(struct i2c_client *i2c) +static void ak5558_i2c_remove(struct i2c_client *i2c) { pm_runtime_disable(&i2c->dev); - - return 0; } static const struct of_device_id ak5558_i2c_dt_ids[] __maybe_unused = { diff --git a/sound/soc/codecs/cs35l32.c b/sound/soc/codecs/cs35l32.c index 8ff6f66be86f..dc7a58d68076 100644 --- a/sound/soc/codecs/cs35l32.c +++ b/sound/soc/codecs/cs35l32.c @@ -497,14 +497,12 @@ err_supplies: return ret; } -static int cs35l32_i2c_remove(struct i2c_client *i2c_client) +static void cs35l32_i2c_remove(struct i2c_client *i2c_client) { struct cs35l32_private *cs35l32 = i2c_get_clientdata(i2c_client); /* Hold down reset */ gpiod_set_value_cansleep(cs35l32->reset_gpio, 0); - - return 0; } #ifdef CONFIG_PM diff --git a/sound/soc/codecs/cs35l33.c b/sound/soc/codecs/cs35l33.c index 082025fa0370..15e79168d256 100644 --- a/sound/soc/codecs/cs35l33.c +++ b/sound/soc/codecs/cs35l33.c @@ -1250,7 +1250,7 @@ err_enable: return ret; } -static int cs35l33_i2c_remove(struct i2c_client *client) +static void cs35l33_i2c_remove(struct i2c_client *client) { struct cs35l33_private *cs35l33 = i2c_get_clientdata(client); @@ -1259,8 +1259,6 @@ static int cs35l33_i2c_remove(struct i2c_client *client) pm_runtime_disable(&client->dev); regulator_bulk_disable(cs35l33->num_core_supplies, cs35l33->core_supplies); - - return 0; } static const struct of_device_id cs35l33_of_match[] = { diff --git a/sound/soc/codecs/cs35l34.c b/sound/soc/codecs/cs35l34.c index 472ac982779b..b3f98023e6a7 100644 --- a/sound/soc/codecs/cs35l34.c +++ b/sound/soc/codecs/cs35l34.c @@ -1128,7 +1128,7 @@ err_regulator: return ret; } -static int cs35l34_i2c_remove(struct i2c_client *client) +static void cs35l34_i2c_remove(struct i2c_client *client) { struct cs35l34_private *cs35l34 = i2c_get_clientdata(client); @@ -1137,8 +1137,6 @@ static int cs35l34_i2c_remove(struct i2c_client *client) pm_runtime_disable(&client->dev); regulator_bulk_disable(cs35l34->num_core_supplies, cs35l34->core_supplies); - - return 0; } static int __maybe_unused cs35l34_runtime_resume(struct device *dev) diff --git a/sound/soc/codecs/cs35l35.c b/sound/soc/codecs/cs35l35.c index 714a759dca21..947a440a3a47 100644 --- a/sound/soc/codecs/cs35l35.c +++ b/sound/soc/codecs/cs35l35.c @@ -1627,14 +1627,12 @@ err: return ret; } -static int cs35l35_i2c_remove(struct i2c_client *i2c_client) +static void cs35l35_i2c_remove(struct i2c_client *i2c_client) { struct cs35l35_private *cs35l35 = i2c_get_clientdata(i2c_client); regulator_bulk_disable(cs35l35->num_supplies, cs35l35->supplies); gpiod_set_value_cansleep(cs35l35->reset_gpio, 0); - - return 0; } static const struct of_device_id cs35l35_of_match[] = { diff --git a/sound/soc/codecs/cs35l36.c b/sound/soc/codecs/cs35l36.c index 4dc13e6f4874..31ae752e242f 100644 --- a/sound/soc/codecs/cs35l36.c +++ b/sound/soc/codecs/cs35l36.c @@ -1910,7 +1910,7 @@ err_disable_regs: return ret; } -static int cs35l36_i2c_remove(struct i2c_client *client) +static void cs35l36_i2c_remove(struct i2c_client *client) { struct cs35l36_private *cs35l36 = i2c_get_clientdata(client); @@ -1924,8 +1924,6 @@ static int cs35l36_i2c_remove(struct i2c_client *client) gpiod_set_value_cansleep(cs35l36->reset_gpio, 0); regulator_bulk_disable(cs35l36->num_supplies, cs35l36->supplies); - - return 0; } static const struct of_device_id cs35l36_of_match[] = { {.compatible = "cirrus,cs35l36"}, diff --git a/sound/soc/codecs/cs35l41-i2c.c b/sound/soc/codecs/cs35l41-i2c.c index 37c703c08fd5..3676b596f60b 100644 --- a/sound/soc/codecs/cs35l41-i2c.c +++ b/sound/soc/codecs/cs35l41-i2c.c @@ -56,13 +56,11 @@ static int cs35l41_i2c_probe(struct i2c_client *client) return cs35l41_probe(cs35l41, hw_cfg); } -static int cs35l41_i2c_remove(struct i2c_client *client) +static void cs35l41_i2c_remove(struct i2c_client *client) { struct cs35l41_private *cs35l41 = i2c_get_clientdata(client); cs35l41_remove(cs35l41); - - return 0; } #ifdef CONFIG_OF diff --git a/sound/soc/codecs/cs35l45-i2c.c b/sound/soc/codecs/cs35l45-i2c.c index 06c2ddffb9c5..39d28641429e 100644 --- a/sound/soc/codecs/cs35l45-i2c.c +++ b/sound/soc/codecs/cs35l45-i2c.c @@ -36,13 +36,11 @@ static int cs35l45_i2c_probe(struct i2c_client *client) return cs35l45_probe(cs35l45); } -static int cs35l45_i2c_remove(struct i2c_client *client) +static void cs35l45_i2c_remove(struct i2c_client *client) { struct cs35l45_private *cs35l45 = i2c_get_clientdata(client); cs35l45_remove(cs35l45); - - return 0; } static const struct of_device_id cs35l45_of_match[] = { diff --git a/sound/soc/codecs/cs4234.c b/sound/soc/codecs/cs4234.c index b49a3cf21ebe..dee1a6662c2e 100644 --- a/sound/soc/codecs/cs4234.c +++ b/sound/soc/codecs/cs4234.c @@ -850,7 +850,7 @@ fail_shutdown: return ret; } -static int cs4234_i2c_remove(struct i2c_client *i2c_client) +static void cs4234_i2c_remove(struct i2c_client *i2c_client) { struct cs4234 *cs4234 = i2c_get_clientdata(i2c_client); struct device *dev = &i2c_client->dev; @@ -858,8 +858,6 @@ static int cs4234_i2c_remove(struct i2c_client *i2c_client) snd_soc_unregister_component(dev); pm_runtime_disable(dev); cs4234_shutdown(cs4234); - - return 0; } static int __maybe_unused cs4234_runtime_resume(struct device *dev) diff --git a/sound/soc/codecs/cs4265.c b/sound/soc/codecs/cs4265.c index 76c19802d5fe..3573363b7e31 100644 --- a/sound/soc/codecs/cs4265.c +++ b/sound/soc/codecs/cs4265.c @@ -623,14 +623,12 @@ static int cs4265_i2c_probe(struct i2c_client *i2c_client) ARRAY_SIZE(cs4265_dai)); } -static int cs4265_i2c_remove(struct i2c_client *i2c) +static void cs4265_i2c_remove(struct i2c_client *i2c) { struct cs4265_private *cs4265 = i2c_get_clientdata(i2c); if (cs4265->reset_gpio) gpiod_set_value_cansleep(cs4265->reset_gpio, 0); - - return 0; } static const struct of_device_id cs4265_of_match[] = { diff --git a/sound/soc/codecs/cs4270.c b/sound/soc/codecs/cs4270.c index ba67e43edf35..1b640d8232ba 100644 --- a/sound/soc/codecs/cs4270.c +++ b/sound/soc/codecs/cs4270.c @@ -650,13 +650,11 @@ static const struct regmap_config cs4270_regmap = { * This function puts the chip into low power mode when the i2c device * is removed. */ -static int cs4270_i2c_remove(struct i2c_client *i2c_client) +static void cs4270_i2c_remove(struct i2c_client *i2c_client) { struct cs4270_private *cs4270 = i2c_get_clientdata(i2c_client); gpiod_set_value_cansleep(cs4270->reset_gpio, 0); - - return 0; } /** diff --git a/sound/soc/codecs/cs42l42-i2c.c b/sound/soc/codecs/cs42l42-i2c.c index 1900ec75576e..67b253287daf 100644 --- a/sound/soc/codecs/cs42l42-i2c.c +++ b/sound/soc/codecs/cs42l42-i2c.c @@ -41,13 +41,11 @@ static int cs42l42_i2c_probe(struct i2c_client *i2c_client) return cs42l42_init(cs42l42); } -static int cs42l42_i2c_remove(struct i2c_client *i2c_client) +static void cs42l42_i2c_remove(struct i2c_client *i2c_client) { struct cs42l42_private *cs42l42 = dev_get_drvdata(&i2c_client->dev); cs42l42_common_remove(cs42l42); - - return 0; } static int __maybe_unused cs42l42_i2c_resume(struct device *dev) diff --git a/sound/soc/codecs/cs42l51-i2c.c b/sound/soc/codecs/cs42l51-i2c.c index 3613fb12d623..85238339fbca 100644 --- a/sound/soc/codecs/cs42l51-i2c.c +++ b/sound/soc/codecs/cs42l51-i2c.c @@ -28,11 +28,9 @@ static int cs42l51_i2c_probe(struct i2c_client *i2c) return cs42l51_probe(&i2c->dev, devm_regmap_init_i2c(i2c, &config)); } -static int cs42l51_i2c_remove(struct i2c_client *i2c) +static void cs42l51_i2c_remove(struct i2c_client *i2c) { cs42l51_remove(&i2c->dev); - - return 0; } static const struct dev_pm_ops cs42l51_pm_ops = { diff --git a/sound/soc/codecs/cs42l56.c b/sound/soc/codecs/cs42l56.c index 03e2540a0ba1..26066682c983 100644 --- a/sound/soc/codecs/cs42l56.c +++ b/sound/soc/codecs/cs42l56.c @@ -1320,13 +1320,12 @@ err_enable: return ret; } -static int cs42l56_i2c_remove(struct i2c_client *client) +static void cs42l56_i2c_remove(struct i2c_client *client) { struct cs42l56_private *cs42l56 = i2c_get_clientdata(client); regulator_bulk_disable(ARRAY_SIZE(cs42l56->supplies), cs42l56->supplies); - return 0; } static const struct of_device_id cs42l56_of_match[] = { diff --git a/sound/soc/codecs/cs42l83-i2c.c b/sound/soc/codecs/cs42l83-i2c.c index ba8772aa51e1..f90d43996a51 100644 --- a/sound/soc/codecs/cs42l83-i2c.c +++ b/sound/soc/codecs/cs42l83-i2c.c @@ -192,13 +192,11 @@ static int cs42l83_i2c_probe(struct i2c_client *i2c_client) return cs42l42_init(cs42l83); } -static int cs42l83_i2c_remove(struct i2c_client *i2c_client) +static void cs42l83_i2c_remove(struct i2c_client *i2c_client) { struct cs42l42_private *cs42l83 = dev_get_drvdata(&i2c_client->dev); cs42l42_common_remove(cs42l83); - - return 0; } static int __maybe_unused cs42l83_i2c_resume(struct device *dev) diff --git a/sound/soc/codecs/cs42xx8-i2c.c b/sound/soc/codecs/cs42xx8-i2c.c index cb06a06d48b0..bd80e9fc907f 100644 --- a/sound/soc/codecs/cs42xx8-i2c.c +++ b/sound/soc/codecs/cs42xx8-i2c.c @@ -30,11 +30,9 @@ static int cs42xx8_i2c_probe(struct i2c_client *i2c) return 0; } -static int cs42xx8_i2c_remove(struct i2c_client *i2c) +static void cs42xx8_i2c_remove(struct i2c_client *i2c) { pm_runtime_disable(&i2c->dev); - - return 0; } static struct i2c_device_id cs42xx8_i2c_id[] = { diff --git a/sound/soc/codecs/cs43130.c b/sound/soc/codecs/cs43130.c index 06c6ad3ca2b7..db39abb2a31b 100644 --- a/sound/soc/codecs/cs43130.c +++ b/sound/soc/codecs/cs43130.c @@ -2582,7 +2582,7 @@ err_supplies: return ret; } -static int cs43130_i2c_remove(struct i2c_client *client) +static void cs43130_i2c_remove(struct i2c_client *client) { struct cs43130_private *cs43130 = i2c_get_clientdata(client); @@ -2609,8 +2609,6 @@ static int cs43130_i2c_remove(struct i2c_client *client) pm_runtime_disable(&client->dev); regulator_bulk_disable(CS43130_NUM_SUPPLIES, cs43130->supplies); - - return 0; } static int __maybe_unused cs43130_runtime_suspend(struct device *dev) diff --git a/sound/soc/codecs/cs4349.c b/sound/soc/codecs/cs4349.c index f7c5c2fd4304..ba94ffd0a7e4 100644 --- a/sound/soc/codecs/cs4349.c +++ b/sound/soc/codecs/cs4349.c @@ -305,14 +305,12 @@ static int cs4349_i2c_probe(struct i2c_client *client) &cs4349_dai, 1); } -static int cs4349_i2c_remove(struct i2c_client *client) +static void cs4349_i2c_remove(struct i2c_client *client) { struct cs4349_private *cs4349 = i2c_get_clientdata(client); /* Hold down reset */ gpiod_set_value_cansleep(cs4349->reset_gpio, 0); - - return 0; } #ifdef CONFIG_PM diff --git a/sound/soc/codecs/cs53l30.c b/sound/soc/codecs/cs53l30.c index 8796d8e84b7a..69db0013d243 100644 --- a/sound/soc/codecs/cs53l30.c +++ b/sound/soc/codecs/cs53l30.c @@ -1043,7 +1043,7 @@ error_supplies: return ret; } -static int cs53l30_i2c_remove(struct i2c_client *client) +static void cs53l30_i2c_remove(struct i2c_client *client) { struct cs53l30_private *cs53l30 = i2c_get_clientdata(client); @@ -1052,8 +1052,6 @@ static int cs53l30_i2c_remove(struct i2c_client *client) regulator_bulk_disable(ARRAY_SIZE(cs53l30->supplies), cs53l30->supplies); - - return 0; } #ifdef CONFIG_PM diff --git a/sound/soc/codecs/cx2072x.c b/sound/soc/codecs/cx2072x.c index b6667e8a6099..5deceaa89282 100644 --- a/sound/soc/codecs/cx2072x.c +++ b/sound/soc/codecs/cx2072x.c @@ -1673,10 +1673,9 @@ static int cx2072x_i2c_probe(struct i2c_client *i2c) return 0; } -static int cx2072x_i2c_remove(struct i2c_client *i2c) +static void cx2072x_i2c_remove(struct i2c_client *i2c) { pm_runtime_disable(&i2c->dev); - return 0; } static const struct i2c_device_id cx2072x_i2c_id[] = { diff --git a/sound/soc/codecs/es8316.c b/sound/soc/codecs/es8316.c index 8643014472ae..056c3082fe02 100644 --- a/sound/soc/codecs/es8316.c +++ b/sound/soc/codecs/es8316.c @@ -815,6 +815,8 @@ static const struct regmap_access_table es8316_volatile_table = { static const struct regmap_config es8316_regmap = { .reg_bits = 8, .val_bits = 8, + .use_single_read = true, + .use_single_write = true, .max_register = 0x53, .volatile_table = &es8316_volatile_table, .cache_type = REGCACHE_RBTREE, diff --git a/sound/soc/codecs/hda.c b/sound/soc/codecs/hda.c index ad20a3dff9b7..61e8e9be6b8d 100644 --- a/sound/soc/codecs/hda.c +++ b/sound/soc/codecs/hda.c @@ -224,9 +224,6 @@ static int hda_codec_probe(struct snd_soc_component *component) goto err; } - /* configure codec for 1:1 PCM:DAI mapping */ - codec->mst_no_extra_pcms = 1; - ret = snd_hda_codec_parse_pcms(codec); if (ret < 0) { dev_err(&hdev->dev, "unable to map pcms to dai %d\n", ret); diff --git a/sound/soc/codecs/hdac_hda.c b/sound/soc/codecs/hdac_hda.c index 8debcee59224..8af434e14bfb 100644 --- a/sound/soc/codecs/hdac_hda.c +++ b/sound/soc/codecs/hdac_hda.c @@ -246,7 +246,7 @@ static int hdac_hda_dai_hw_free(struct snd_pcm_substream *substream, return -EINVAL; hda_stream = &pcm->stream[substream->stream]; - snd_hda_codec_cleanup(&hda_pvt->codec, hda_stream, substream); + snd_hda_codec_cleanup(hda_pvt->codec, hda_stream, substream); return 0; } @@ -264,7 +264,7 @@ static int hdac_hda_dai_prepare(struct snd_pcm_substream *substream, int ret = 0; hda_pvt = snd_soc_component_get_drvdata(component); - hdev = &hda_pvt->codec.core; + hdev = &hda_pvt->codec->core; pcm = snd_soc_find_pcm_from_dai(hda_pvt, dai); if (!pcm) return -EINVAL; @@ -274,7 +274,7 @@ static int hdac_hda_dai_prepare(struct snd_pcm_substream *substream, stream = hda_pvt->pcm[dai->id].stream_tag[substream->stream]; format_val = hda_pvt->pcm[dai->id].format_val[substream->stream]; - ret = snd_hda_codec_prepare(&hda_pvt->codec, hda_stream, + ret = snd_hda_codec_prepare(hda_pvt->codec, hda_stream, stream, format_val, substream); if (ret < 0) dev_err(&hdev->dev, "codec prepare failed %d\n", ret); @@ -299,7 +299,7 @@ static int hdac_hda_dai_open(struct snd_pcm_substream *substream, hda_stream = &pcm->stream[substream->stream]; - return hda_stream->ops.open(hda_stream, &hda_pvt->codec, substream); + return hda_stream->ops.open(hda_stream, hda_pvt->codec, substream); } static void hdac_hda_dai_close(struct snd_pcm_substream *substream, @@ -317,7 +317,7 @@ static void hdac_hda_dai_close(struct snd_pcm_substream *substream, hda_stream = &pcm->stream[substream->stream]; - hda_stream->ops.close(hda_stream, &hda_pvt->codec, substream); + hda_stream->ops.close(hda_stream, hda_pvt->codec, substream); snd_hda_codec_pcm_put(pcm); } @@ -325,7 +325,7 @@ static void hdac_hda_dai_close(struct snd_pcm_substream *substream, static struct hda_pcm *snd_soc_find_pcm_from_dai(struct hdac_hda_priv *hda_pvt, struct snd_soc_dai *dai) { - struct hda_codec *hcodec = &hda_pvt->codec; + struct hda_codec *hcodec = hda_pvt->codec; struct hda_pcm *cpcm; const char *pcm_name; @@ -394,8 +394,8 @@ static int hdac_hda_codec_probe(struct snd_soc_component *component) snd_soc_component_get_drvdata(component); struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component); - struct hdac_device *hdev = &hda_pvt->codec.core; - struct hda_codec *hcodec = &hda_pvt->codec; + struct hdac_device *hdev = &hda_pvt->codec->core; + struct hda_codec *hcodec = hda_pvt->codec; struct hdac_ext_link *hlink; hda_codec_patch_t patch; int ret; @@ -461,9 +461,6 @@ static int hdac_hda_codec_probe(struct snd_soc_component *component) dev_dbg(&hdev->dev, "no patch file found\n"); } - /* configure codec for 1:1 PCM:DAI mapping */ - hcodec->mst_no_extra_pcms = 1; - ret = snd_hda_codec_parse_pcms(hcodec); if (ret < 0) { dev_err(&hdev->dev, "unable to map pcms to dai %d\n", ret); @@ -515,8 +512,8 @@ static void hdac_hda_codec_remove(struct snd_soc_component *component) { struct hdac_hda_priv *hda_pvt = snd_soc_component_get_drvdata(component); - struct hdac_device *hdev = &hda_pvt->codec.core; - struct hda_codec *codec = &hda_pvt->codec; + struct hdac_device *hdev = &hda_pvt->codec->core; + struct hda_codec *codec = hda_pvt->codec; struct hdac_ext_link *hlink = NULL; hlink = snd_hdac_ext_bus_get_link(hdev->bus, dev_name(&hdev->dev)); @@ -584,7 +581,6 @@ static const struct snd_soc_component_driver hdac_hda_codec = { static int hdac_hda_dev_probe(struct hdac_device *hdev) { struct hdac_ext_link *hlink; - struct hdac_hda_priv *hda_pvt; int ret; /* hold the ref while we probe */ @@ -595,10 +591,6 @@ static int hdac_hda_dev_probe(struct hdac_device *hdev) } snd_hdac_ext_bus_link_get(hdev->bus, hlink); - hda_pvt = hdac_to_hda_priv(hdev); - if (!hda_pvt) - return -ENOMEM; - /* ASoC specific initialization */ ret = devm_snd_soc_register_component(&hdev->dev, &hdac_hda_codec, hdac_hda_dais, @@ -608,7 +600,6 @@ static int hdac_hda_dev_probe(struct hdac_device *hdev) return ret; } - dev_set_drvdata(&hdev->dev, hda_pvt); snd_hdac_ext_bus_link_put(hdev->bus, hlink); return ret; diff --git a/sound/soc/codecs/hdac_hda.h b/sound/soc/codecs/hdac_hda.h index d0efc5e254ae..fc19c34ca00e 100644 --- a/sound/soc/codecs/hdac_hda.h +++ b/sound/soc/codecs/hdac_hda.h @@ -23,7 +23,7 @@ struct hdac_hda_pcm { }; struct hdac_hda_priv { - struct hda_codec codec; + struct hda_codec *codec; struct hdac_hda_pcm pcm[HDAC_LAST_DAI_ID]; bool need_display_power; }; diff --git a/sound/soc/codecs/jz4725b.c b/sound/soc/codecs/jz4725b.c index 5201a8f6d7b6..71ea576f7e67 100644 --- a/sound/soc/codecs/jz4725b.c +++ b/sound/soc/codecs/jz4725b.c @@ -136,14 +136,17 @@ enum { #define REG_CGR3_GO1L_OFFSET 0 #define REG_CGR3_GO1L_MASK (0x1f << REG_CGR3_GO1L_OFFSET) +#define REG_CGR10_GIL_OFFSET 0 +#define REG_CGR10_GIR_OFFSET 4 + struct jz_icdc { struct regmap *regmap; void __iomem *base; struct clk *clk; }; -static const SNDRV_CTL_TLVD_DECLARE_DB_LINEAR(jz4725b_dac_tlv, -2250, 0); -static const SNDRV_CTL_TLVD_DECLARE_DB_LINEAR(jz4725b_line_tlv, -1500, 600); +static const SNDRV_CTL_TLVD_DECLARE_DB_SCALE(jz4725b_adc_tlv, 0, 150, 0); +static const SNDRV_CTL_TLVD_DECLARE_DB_SCALE(jz4725b_dac_tlv, -2250, 150, 0); static const struct snd_kcontrol_new jz4725b_codec_controls[] = { SOC_DOUBLE_TLV("Master Playback Volume", @@ -151,11 +154,11 @@ static const struct snd_kcontrol_new jz4725b_codec_controls[] = { REG_CGR1_GODL_OFFSET, REG_CGR1_GODR_OFFSET, 0xf, 1, jz4725b_dac_tlv), - SOC_DOUBLE_R_TLV("Master Capture Volume", - JZ4725B_CODEC_REG_CGR3, - JZ4725B_CODEC_REG_CGR2, - REG_CGR2_GO1R_OFFSET, - 0x1f, 1, jz4725b_line_tlv), + SOC_DOUBLE_TLV("Master Capture Volume", + JZ4725B_CODEC_REG_CGR10, + REG_CGR10_GIL_OFFSET, + REG_CGR10_GIR_OFFSET, + 0xf, 0, jz4725b_adc_tlv), SOC_SINGLE("Master Playback Switch", JZ4725B_CODEC_REG_CR1, REG_CR1_DAC_MUTE_OFFSET, 1, 1), @@ -180,7 +183,7 @@ static SOC_VALUE_ENUM_SINGLE_DECL(jz4725b_codec_adc_src_enum, jz4725b_codec_adc_src_texts, jz4725b_codec_adc_src_values); static const struct snd_kcontrol_new jz4725b_codec_adc_src_ctrl = - SOC_DAPM_ENUM("Route", jz4725b_codec_adc_src_enum); + SOC_DAPM_ENUM("ADC Source Capture Route", jz4725b_codec_adc_src_enum); static const struct snd_kcontrol_new jz4725b_codec_mixer_controls[] = { SOC_DAPM_SINGLE("Line In Bypass", JZ4725B_CODEC_REG_CR1, @@ -225,7 +228,7 @@ static const struct snd_soc_dapm_widget jz4725b_codec_dapm_widgets[] = { SND_SOC_DAPM_ADC("ADC", "Capture", JZ4725B_CODEC_REG_PMR1, REG_PMR1_SB_ADC_OFFSET, 1), - SND_SOC_DAPM_MUX("ADC Source", SND_SOC_NOPM, 0, 0, + SND_SOC_DAPM_MUX("ADC Source Capture Route", SND_SOC_NOPM, 0, 0, &jz4725b_codec_adc_src_ctrl), /* Mixer */ @@ -236,7 +239,8 @@ static const struct snd_soc_dapm_widget jz4725b_codec_dapm_widgets[] = { SND_SOC_DAPM_MIXER("DAC to Mixer", JZ4725B_CODEC_REG_CR1, REG_CR1_DACSEL_OFFSET, 0, NULL, 0), - SND_SOC_DAPM_MIXER("Line In", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_MIXER("Line In", JZ4725B_CODEC_REG_PMR1, + REG_PMR1_SB_LIN_OFFSET, 1, NULL, 0), SND_SOC_DAPM_MIXER("HP Out", JZ4725B_CODEC_REG_CR1, REG_CR1_HP_DIS_OFFSET, 1, NULL, 0), @@ -283,11 +287,11 @@ static const struct snd_soc_dapm_route jz4725b_codec_dapm_routes[] = { {"Mixer", NULL, "DAC to Mixer"}, {"Mixer to ADC", NULL, "Mixer"}, - {"ADC Source", "Mixer", "Mixer to ADC"}, - {"ADC Source", "Line In", "Line In"}, - {"ADC Source", "Mic 1", "Mic 1"}, - {"ADC Source", "Mic 2", "Mic 2"}, - {"ADC", NULL, "ADC Source"}, + {"ADC Source Capture Route", "Mixer", "Mixer to ADC"}, + {"ADC Source Capture Route", "Line In", "Line In"}, + {"ADC Source Capture Route", "Mic 1", "Mic 1"}, + {"ADC Source Capture Route", "Mic 2", "Mic 2"}, + {"ADC", NULL, "ADC Source Capture Route"}, {"Out Stage", NULL, "Mixer"}, {"HP Out", NULL, "Out Stage"}, diff --git a/sound/soc/codecs/max98090.c b/sound/soc/codecs/max98090.c index 142083b13ac3..06ed2a938108 100644 --- a/sound/soc/codecs/max98090.c +++ b/sound/soc/codecs/max98090.c @@ -2615,11 +2615,9 @@ static void max98090_i2c_shutdown(struct i2c_client *i2c) msleep(40); } -static int max98090_i2c_remove(struct i2c_client *client) +static void max98090_i2c_remove(struct i2c_client *client) { max98090_i2c_shutdown(client); - - return 0; } #ifdef CONFIG_PM diff --git a/sound/soc/codecs/max9860.c b/sound/soc/codecs/max9860.c index 771b3dcd6cc3..9611ab1e79e5 100644 --- a/sound/soc/codecs/max9860.c +++ b/sound/soc/codecs/max9860.c @@ -701,14 +701,13 @@ err_regulator: return ret; } -static int max9860_remove(struct i2c_client *i2c) +static void max9860_remove(struct i2c_client *i2c) { struct device *dev = &i2c->dev; struct max9860_priv *max9860 = dev_get_drvdata(dev); pm_runtime_disable(dev); regulator_disable(max9860->dvddio); - return 0; } static const struct i2c_device_id max9860_i2c_id[] = { diff --git a/sound/soc/codecs/max98927.c b/sound/soc/codecs/max98927.c index 9cce7c0f0142..331d3e1d735c 100644 --- a/sound/soc/codecs/max98927.c +++ b/sound/soc/codecs/max98927.c @@ -934,15 +934,13 @@ static int max98927_i2c_probe(struct i2c_client *i2c) return ret; } -static int max98927_i2c_remove(struct i2c_client *i2c) +static void max98927_i2c_remove(struct i2c_client *i2c) { struct max98927_priv *max98927 = i2c_get_clientdata(i2c); if (max98927->reset_gpio) { gpiod_set_value_cansleep(max98927->reset_gpio, 1); } - - return 0; } static const struct i2c_device_id max98927_i2c_id[] = { diff --git a/sound/soc/codecs/mt6660.c b/sound/soc/codecs/mt6660.c index b8369eeccc30..cc2df5f7ea19 100644 --- a/sound/soc/codecs/mt6660.c +++ b/sound/soc/codecs/mt6660.c @@ -520,14 +520,13 @@ probe_fail: return ret; } -static int mt6660_i2c_remove(struct i2c_client *client) +static void mt6660_i2c_remove(struct i2c_client *client) { struct mt6660_chip *chip = i2c_get_clientdata(client); pm_runtime_disable(chip->dev); pm_runtime_set_suspended(chip->dev); mutex_destroy(&chip->io_lock); - return 0; } static int __maybe_unused mt6660_i2c_runtime_suspend(struct device *dev) diff --git a/sound/soc/codecs/nau8824.c b/sound/soc/codecs/nau8824.c index 15596452ca37..4f19fd9b65d1 100644 --- a/sound/soc/codecs/nau8824.c +++ b/sound/soc/codecs/nau8824.c @@ -901,7 +901,10 @@ static void nau8824_jdet_work(struct work_struct *work) NAU8824_IRQ_KEY_RELEASE_DIS | NAU8824_IRQ_KEY_SHORT_PRESS_DIS, 0); - nau8824_sema_release(nau8824); + if (nau8824->resume_lock) { + nau8824_sema_release(nau8824); + nau8824->resume_lock = false; + } } static void nau8824_setup_auto_irq(struct nau8824 *nau8824) @@ -966,7 +969,10 @@ static irqreturn_t nau8824_interrupt(int irq, void *data) /* release semaphore held after resume, * and cancel jack detection */ - nau8824_sema_release(nau8824); + if (nau8824->resume_lock) { + nau8824_sema_release(nau8824); + nau8824->resume_lock = false; + } cancel_work_sync(&nau8824->jdet_work); } else if (active_irq & NAU8824_KEY_SHORT_PRESS_IRQ) { int key_status, button_pressed; @@ -1524,6 +1530,7 @@ static int __maybe_unused nau8824_suspend(struct snd_soc_component *component) static int __maybe_unused nau8824_resume(struct snd_soc_component *component) { struct nau8824 *nau8824 = snd_soc_component_get_drvdata(component); + int ret; regcache_cache_only(nau8824->regmap, false); regcache_sync(nau8824->regmap); @@ -1531,7 +1538,10 @@ static int __maybe_unused nau8824_resume(struct snd_soc_component *component) /* Hold semaphore to postpone playback happening * until jack detection done. */ - nau8824_sema_acquire(nau8824, 0); + nau8824->resume_lock = true; + ret = nau8824_sema_acquire(nau8824, 0); + if (ret) + nau8824->resume_lock = false; enable_irq(nau8824->irq); } @@ -1940,6 +1950,7 @@ static int nau8824_i2c_probe(struct i2c_client *i2c) nau8824->regmap = devm_regmap_init_i2c(i2c, &nau8824_regmap_config); if (IS_ERR(nau8824->regmap)) return PTR_ERR(nau8824->regmap); + nau8824->resume_lock = false; nau8824->dev = dev; nau8824->irq = i2c->irq; sema_init(&nau8824->jd_sem, 1); diff --git a/sound/soc/codecs/nau8824.h b/sound/soc/codecs/nau8824.h index de4bae8281d0..5fcfc43dfc85 100644 --- a/sound/soc/codecs/nau8824.h +++ b/sound/soc/codecs/nau8824.h @@ -436,6 +436,7 @@ struct nau8824 { struct semaphore jd_sem; int fs; int irq; + int resume_lock; int micbias_voltage; int vref_impedance; int jkdet_polarity; diff --git a/sound/soc/codecs/nau8825.c b/sound/soc/codecs/nau8825.c index 6a2c2e373efd..3eac7c92df88 100644 --- a/sound/soc/codecs/nau8825.c +++ b/sound/soc/codecs/nau8825.c @@ -2778,10 +2778,8 @@ static int nau8825_i2c_probe(struct i2c_client *i2c) &nau8825_dai, 1); } -static int nau8825_i2c_remove(struct i2c_client *client) -{ - return 0; -} +static void nau8825_i2c_remove(struct i2c_client *client) +{} static const struct i2c_device_id nau8825_i2c_ids[] = { { "nau8825", 0 }, diff --git a/sound/soc/codecs/pcm1789-i2c.c b/sound/soc/codecs/pcm1789-i2c.c index 1d2f7480a6e4..fafe0dcbe4ea 100644 --- a/sound/soc/codecs/pcm1789-i2c.c +++ b/sound/soc/codecs/pcm1789-i2c.c @@ -27,11 +27,9 @@ static int pcm1789_i2c_probe(struct i2c_client *client) return pcm1789_common_init(&client->dev, regmap); } -static int pcm1789_i2c_remove(struct i2c_client *client) +static void pcm1789_i2c_remove(struct i2c_client *client) { pcm1789_common_exit(&client->dev); - - return 0; } #ifdef CONFIG_OF diff --git a/sound/soc/codecs/pcm3168a-i2c.c b/sound/soc/codecs/pcm3168a-i2c.c index c0fa0dc80e8f..a0eec82e9872 100644 --- a/sound/soc/codecs/pcm3168a-i2c.c +++ b/sound/soc/codecs/pcm3168a-i2c.c @@ -26,11 +26,9 @@ static int pcm3168a_i2c_probe(struct i2c_client *i2c) return pcm3168a_probe(&i2c->dev, regmap); } -static int pcm3168a_i2c_remove(struct i2c_client *i2c) +static void pcm3168a_i2c_remove(struct i2c_client *i2c) { pcm3168a_remove(&i2c->dev); - - return 0; } static const struct i2c_device_id pcm3168a_i2c_id[] = { diff --git a/sound/soc/codecs/pcm512x-i2c.c b/sound/soc/codecs/pcm512x-i2c.c index 81754e141a55..9dfbbe8f4a0b 100644 --- a/sound/soc/codecs/pcm512x-i2c.c +++ b/sound/soc/codecs/pcm512x-i2c.c @@ -29,10 +29,9 @@ static int pcm512x_i2c_probe(struct i2c_client *i2c) return pcm512x_probe(&i2c->dev, regmap); } -static int pcm512x_i2c_remove(struct i2c_client *i2c) +static void pcm512x_i2c_remove(struct i2c_client *i2c) { pcm512x_remove(&i2c->dev); - return 0; } static const struct i2c_device_id pcm512x_i2c_id[] = { diff --git a/sound/soc/codecs/rt274.c b/sound/soc/codecs/rt274.c index f2c50b11e4d0..4667bf7561b1 100644 --- a/sound/soc/codecs/rt274.c +++ b/sound/soc/codecs/rt274.c @@ -1204,14 +1204,12 @@ static int rt274_i2c_probe(struct i2c_client *i2c) return ret; } -static int rt274_i2c_remove(struct i2c_client *i2c) +static void rt274_i2c_remove(struct i2c_client *i2c) { struct rt274_priv *rt274 = i2c_get_clientdata(i2c); if (i2c->irq) free_irq(i2c->irq, rt274); - - return 0; } diff --git a/sound/soc/codecs/rt286.c b/sound/soc/codecs/rt286.c index c4f7c4c2d793..ceb56647e369 100644 --- a/sound/soc/codecs/rt286.c +++ b/sound/soc/codecs/rt286.c @@ -1249,14 +1249,12 @@ static int rt286_i2c_probe(struct i2c_client *i2c) return ret; } -static int rt286_i2c_remove(struct i2c_client *i2c) +static void rt286_i2c_remove(struct i2c_client *i2c) { struct rt286_priv *rt286 = i2c_get_clientdata(i2c); if (i2c->irq) free_irq(i2c->irq, rt286); - - return 0; } diff --git a/sound/soc/codecs/rt298.c b/sound/soc/codecs/rt298.c index b0b53d4f07df..a2ce52dafea8 100644 --- a/sound/soc/codecs/rt298.c +++ b/sound/soc/codecs/rt298.c @@ -1290,14 +1290,12 @@ static int rt298_i2c_probe(struct i2c_client *i2c) return ret; } -static int rt298_i2c_remove(struct i2c_client *i2c) +static void rt298_i2c_remove(struct i2c_client *i2c) { struct rt298_priv *rt298 = i2c_get_clientdata(i2c); if (i2c->irq) free_irq(i2c->irq, rt298); - - return 0; } diff --git a/sound/soc/codecs/rt5616.c b/sound/soc/codecs/rt5616.c index 970d6c4a358e..948abde10463 100644 --- a/sound/soc/codecs/rt5616.c +++ b/sound/soc/codecs/rt5616.c @@ -1388,10 +1388,8 @@ static int rt5616_i2c_probe(struct i2c_client *i2c) rt5616_dai, ARRAY_SIZE(rt5616_dai)); } -static int rt5616_i2c_remove(struct i2c_client *i2c) -{ - return 0; -} +static void rt5616_i2c_remove(struct i2c_client *i2c) +{} static void rt5616_i2c_shutdown(struct i2c_client *client) { diff --git a/sound/soc/codecs/rt5631.c b/sound/soc/codecs/rt5631.c index 957f6b19beec..55c232413e2b 100644 --- a/sound/soc/codecs/rt5631.c +++ b/sound/soc/codecs/rt5631.c @@ -1720,10 +1720,8 @@ static int rt5631_i2c_probe(struct i2c_client *i2c) return ret; } -static int rt5631_i2c_remove(struct i2c_client *client) -{ - return 0; -} +static void rt5631_i2c_remove(struct i2c_client *client) +{} static struct i2c_driver rt5631_i2c_driver = { .driver = { diff --git a/sound/soc/codecs/rt5640.c b/sound/soc/codecs/rt5640.c index 5a844329800f..0f8e6dd214b0 100644 --- a/sound/soc/codecs/rt5640.c +++ b/sound/soc/codecs/rt5640.c @@ -2494,7 +2494,7 @@ static void rt5640_enable_jack_detect(struct snd_soc_component *component, /* Select JD-source */ snd_soc_component_update_bits(component, RT5640_JD_CTRL, - RT5640_JD_MASK, rt5640->jd_src); + RT5640_JD_MASK, rt5640->jd_src << RT5640_JD_SFT); /* Selecting GPIO01 as an interrupt */ snd_soc_component_update_bits(component, RT5640_GPIO_CTRL1, @@ -2504,12 +2504,8 @@ static void rt5640_enable_jack_detect(struct snd_soc_component *component, snd_soc_component_update_bits(component, RT5640_GPIO_CTRL3, RT5640_GP1_PF_MASK, RT5640_GP1_PF_OUT); - /* Enabling jd2 in general control 1 */ snd_soc_component_write(component, RT5640_DUMMY1, 0x3f41); - /* Enabling jd2 in general control 2 */ - snd_soc_component_write(component, RT5640_DUMMY2, 0x4001); - rt5640_set_ovcd_params(component); /* @@ -2518,12 +2514,25 @@ static void rt5640_enable_jack_detect(struct snd_soc_component *component, * pin 0/1 instead of it being stuck to 1. So we invert the JD polarity * on systems where the hardware does not already do this. */ - if (rt5640->jd_inverted) - snd_soc_component_write(component, RT5640_IRQ_CTRL1, - RT5640_IRQ_JD_NOR); - else - snd_soc_component_write(component, RT5640_IRQ_CTRL1, - RT5640_IRQ_JD_NOR | RT5640_JD_P_INV); + if (rt5640->jd_inverted) { + if (rt5640->jd_src == RT5640_JD_SRC_JD1_IN4P) + snd_soc_component_write(component, RT5640_IRQ_CTRL1, + RT5640_IRQ_JD_NOR); + else if (rt5640->jd_src == RT5640_JD_SRC_JD2_IN4N) + snd_soc_component_update_bits(component, RT5640_DUMMY2, + RT5640_IRQ_JD2_MASK | RT5640_JD2_MASK, + RT5640_IRQ_JD2_NOR | RT5640_JD2_EN); + } else { + if (rt5640->jd_src == RT5640_JD_SRC_JD1_IN4P) + snd_soc_component_write(component, RT5640_IRQ_CTRL1, + RT5640_IRQ_JD_NOR | RT5640_JD_P_INV); + else if (rt5640->jd_src == RT5640_JD_SRC_JD2_IN4N) + snd_soc_component_update_bits(component, RT5640_DUMMY2, + RT5640_IRQ_JD2_MASK | RT5640_JD2_P_MASK | + RT5640_JD2_MASK, + RT5640_IRQ_JD2_NOR | RT5640_JD2_P_INV | + RT5640_JD2_EN); + } rt5640->jack = jack; if (rt5640->jack->status & SND_JACK_MICROPHONE) { @@ -2725,10 +2734,8 @@ static int rt5640_probe(struct snd_soc_component *component) if (device_property_read_u32(component->dev, "realtek,jack-detect-source", &val) == 0) { - if (val <= RT5640_JD_SRC_GPIO4) - rt5640->jd_src = val << RT5640_JD_SFT; - else if (val == RT5640_JD_SRC_HDA_HEADER) - rt5640->jd_src = RT5640_JD_SRC_HDA_HEADER; + if (val <= RT5640_JD_SRC_HDA_HEADER) + rt5640->jd_src = val; else dev_warn(component->dev, "Warning: Invalid jack-detect-source value: %d, leaving jack-detect disabled\n", val); @@ -2809,12 +2816,31 @@ static int rt5640_resume(struct snd_soc_component *component) regcache_sync(rt5640->regmap); if (rt5640->jack) { - if (rt5640->jd_src == RT5640_JD_SRC_HDA_HEADER) + if (rt5640->jd_src == RT5640_JD_SRC_HDA_HEADER) { snd_soc_component_update_bits(component, RT5640_DUMMY2, 0x1100, 0x1100); - else - snd_soc_component_write(component, RT5640_DUMMY2, - 0x4001); + } else { + if (rt5640->jd_inverted) { + if (rt5640->jd_src == RT5640_JD_SRC_JD2_IN4N) + snd_soc_component_update_bits( + component, RT5640_DUMMY2, + RT5640_IRQ_JD2_MASK | + RT5640_JD2_MASK, + RT5640_IRQ_JD2_NOR | + RT5640_JD2_EN); + + } else { + if (rt5640->jd_src == RT5640_JD_SRC_JD2_IN4N) + snd_soc_component_update_bits( + component, RT5640_DUMMY2, + RT5640_IRQ_JD2_MASK | + RT5640_JD2_P_MASK | + RT5640_JD2_MASK, + RT5640_IRQ_JD2_NOR | + RT5640_JD2_P_INV | + RT5640_JD2_EN); + } + } queue_delayed_work(system_long_wq, &rt5640->jack_work, 0); } diff --git a/sound/soc/codecs/rt5640.h b/sound/soc/codecs/rt5640.h index 505c93514051..f58b88e3325b 100644 --- a/sound/soc/codecs/rt5640.h +++ b/sound/soc/codecs/rt5640.h @@ -1984,6 +1984,20 @@ #define RT5640_M_MONO_ADC_R_SFT 12 #define RT5640_MCLK_DET (0x1 << 11) +/* General Control 1 (0xfb) */ +#define RT5640_IRQ_JD2_MASK (0x1 << 12) +#define RT5640_IRQ_JD2_SFT 12 +#define RT5640_IRQ_JD2_BP (0x0 << 12) +#define RT5640_IRQ_JD2_NOR (0x1 << 12) +#define RT5640_JD2_P_MASK (0x1 << 10) +#define RT5640_JD2_P_SFT 10 +#define RT5640_JD2_P_NOR (0x0 << 10) +#define RT5640_JD2_P_INV (0x1 << 10) +#define RT5640_JD2_MASK (0x1 << 8) +#define RT5640_JD2_SFT 8 +#define RT5640_JD2_DIS (0x0 << 8) +#define RT5640_JD2_EN (0x1 << 8) + /* Codec Private Register definition */ /* MIC Over current threshold scale factor (0x15) */ diff --git a/sound/soc/codecs/rt5645.c b/sound/soc/codecs/rt5645.c index 8635bc6567dc..620ecbfa4a7a 100644 --- a/sound/soc/codecs/rt5645.c +++ b/sound/soc/codecs/rt5645.c @@ -4145,7 +4145,7 @@ err_enable: return ret; } -static int rt5645_i2c_remove(struct i2c_client *i2c) +static void rt5645_i2c_remove(struct i2c_client *i2c) { struct rt5645_priv *rt5645 = i2c_get_clientdata(i2c); @@ -4162,8 +4162,6 @@ static int rt5645_i2c_remove(struct i2c_client *i2c) cancel_delayed_work_sync(&rt5645->rcclock_work); regulator_bulk_disable(ARRAY_SIZE(rt5645->supplies), rt5645->supplies); - - return 0; } static void rt5645_i2c_shutdown(struct i2c_client *i2c) diff --git a/sound/soc/codecs/rt5663.c b/sound/soc/codecs/rt5663.c index ca981b374b0c..f73751dbde30 100644 --- a/sound/soc/codecs/rt5663.c +++ b/sound/soc/codecs/rt5663.c @@ -3710,7 +3710,7 @@ err_enable: return ret; } -static int rt5663_i2c_remove(struct i2c_client *i2c) +static void rt5663_i2c_remove(struct i2c_client *i2c) { struct rt5663_priv *rt5663 = i2c_get_clientdata(i2c); @@ -3718,8 +3718,6 @@ static int rt5663_i2c_remove(struct i2c_client *i2c) free_irq(i2c->irq, rt5663); regulator_bulk_disable(ARRAY_SIZE(rt5663->supplies), rt5663->supplies); - - return 0; } static void rt5663_i2c_shutdown(struct i2c_client *client) diff --git a/sound/soc/codecs/rt5670.c b/sound/soc/codecs/rt5670.c index 60dbfa2a54f1..ebac6caeb40a 100644 --- a/sound/soc/codecs/rt5670.c +++ b/sound/soc/codecs/rt5670.c @@ -3320,11 +3320,9 @@ err: return ret; } -static int rt5670_i2c_remove(struct i2c_client *i2c) +static void rt5670_i2c_remove(struct i2c_client *i2c) { pm_runtime_disable(&i2c->dev); - - return 0; } static struct i2c_driver rt5670_i2c_driver = { diff --git a/sound/soc/codecs/rt5677.c b/sound/soc/codecs/rt5677.c index 31a2dd0aafb6..c26395f42d8e 100644 --- a/sound/soc/codecs/rt5677.c +++ b/sound/soc/codecs/rt5677.c @@ -5693,11 +5693,9 @@ static int rt5677_i2c_probe(struct i2c_client *i2c) rt5677_dai, ARRAY_SIZE(rt5677_dai)); } -static int rt5677_i2c_remove(struct i2c_client *i2c) +static void rt5677_i2c_remove(struct i2c_client *i2c) { rt5677_free_gpio(i2c); - - return 0; } static struct i2c_driver rt5677_i2c_driver = { diff --git a/sound/soc/codecs/rt5682-i2c.c b/sound/soc/codecs/rt5682-i2c.c index 3f72f6093436..2935c1bb81f3 100644 --- a/sound/soc/codecs/rt5682-i2c.c +++ b/sound/soc/codecs/rt5682-i2c.c @@ -302,11 +302,9 @@ static void rt5682_i2c_shutdown(struct i2c_client *client) rt5682_reset(rt5682); } -static int rt5682_i2c_remove(struct i2c_client *client) +static void rt5682_i2c_remove(struct i2c_client *client) { rt5682_i2c_shutdown(client); - - return 0; } static const struct of_device_id rt5682_of_match[] = { diff --git a/sound/soc/codecs/rt5682s.c b/sound/soc/codecs/rt5682s.c index 5199d3bbaf0b..80c673aa14db 100644 --- a/sound/soc/codecs/rt5682s.c +++ b/sound/soc/codecs/rt5682s.c @@ -3256,11 +3256,9 @@ static void rt5682s_i2c_shutdown(struct i2c_client *client) rt5682s_reset(rt5682s); } -static int rt5682s_i2c_remove(struct i2c_client *client) +static void rt5682s_i2c_remove(struct i2c_client *client) { rt5682s_i2c_shutdown(client); - - return 0; } static const struct of_device_id rt5682s_of_match[] = { diff --git a/sound/soc/codecs/rt9120.c b/sound/soc/codecs/rt9120.c index da495bdc8415..644300e88b4c 100644 --- a/sound/soc/codecs/rt9120.c +++ b/sound/soc/codecs/rt9120.c @@ -572,11 +572,10 @@ static int rt9120_probe(struct i2c_client *i2c) &rt9120_dai, 1); } -static int rt9120_remove(struct i2c_client *i2c) +static void rt9120_remove(struct i2c_client *i2c) { pm_runtime_disable(&i2c->dev); pm_runtime_set_suspended(&i2c->dev); - return 0; } static int __maybe_unused rt9120_runtime_suspend(struct device *dev) diff --git a/sound/soc/codecs/sgtl5000.c b/sound/soc/codecs/sgtl5000.c index 3fafd9fc5cfd..4b2135eba74d 100644 --- a/sound/soc/codecs/sgtl5000.c +++ b/sound/soc/codecs/sgtl5000.c @@ -1790,7 +1790,7 @@ disable_regs: return ret; } -static int sgtl5000_i2c_remove(struct i2c_client *client) +static void sgtl5000_i2c_remove(struct i2c_client *client) { struct sgtl5000_priv *sgtl5000 = i2c_get_clientdata(client); @@ -1800,8 +1800,6 @@ static int sgtl5000_i2c_remove(struct i2c_client *client) clk_disable_unprepare(sgtl5000->mclk); regulator_bulk_disable(sgtl5000->num_supplies, sgtl5000->supplies); regulator_bulk_free(sgtl5000->num_supplies, sgtl5000->supplies); - - return 0; } static void sgtl5000_i2c_shutdown(struct i2c_client *client) diff --git a/sound/soc/codecs/sta350.c b/sound/soc/codecs/sta350.c index 7b2c5b57d5d4..9ed13aeb3cbd 100644 --- a/sound/soc/codecs/sta350.c +++ b/sound/soc/codecs/sta350.c @@ -1242,10 +1242,8 @@ static int sta350_i2c_probe(struct i2c_client *i2c) return ret; } -static int sta350_i2c_remove(struct i2c_client *client) -{ - return 0; -} +static void sta350_i2c_remove(struct i2c_client *client) +{} static const struct i2c_device_id sta350_i2c_id[] = { { "sta350", 0 }, diff --git a/sound/soc/codecs/tas2552.c b/sound/soc/codecs/tas2552.c index 8bd667da8767..59a4ea5f6e30 100644 --- a/sound/soc/codecs/tas2552.c +++ b/sound/soc/codecs/tas2552.c @@ -736,10 +736,9 @@ static int tas2552_probe(struct i2c_client *client) return ret; } -static int tas2552_i2c_remove(struct i2c_client *client) +static void tas2552_i2c_remove(struct i2c_client *client) { pm_runtime_disable(&client->dev); - return 0; } static const struct i2c_device_id tas2552_id[] = { diff --git a/sound/soc/codecs/tas2770.c b/sound/soc/codecs/tas2770.c index bb653b664146..b6765235a4b3 100644 --- a/sound/soc/codecs/tas2770.c +++ b/sound/soc/codecs/tas2770.c @@ -495,6 +495,8 @@ static struct snd_soc_dai_driver tas2770_dai_driver[] = { }, }; +static const struct regmap_config tas2770_i2c_regmap; + static int tas2770_codec_probe(struct snd_soc_component *component) { struct tas2770_priv *tas2770 = @@ -508,6 +510,7 @@ static int tas2770_codec_probe(struct snd_soc_component *component) } tas2770_reset(tas2770); + regmap_reinit_cache(tas2770->regmap, &tas2770_i2c_regmap); return 0; } diff --git a/sound/soc/codecs/tas5086.c b/sound/soc/codecs/tas5086.c index a864984225bc..22143cc5afa7 100644 --- a/sound/soc/codecs/tas5086.c +++ b/sound/soc/codecs/tas5086.c @@ -981,10 +981,8 @@ static int tas5086_i2c_probe(struct i2c_client *i2c) return ret; } -static int tas5086_i2c_remove(struct i2c_client *i2c) -{ - return 0; -} +static void tas5086_i2c_remove(struct i2c_client *i2c) +{} static struct i2c_driver tas5086_i2c_driver = { .driver = { diff --git a/sound/soc/codecs/tas571x.c b/sound/soc/codecs/tas571x.c index 4e7f20db57c4..84ec1b527646 100644 --- a/sound/soc/codecs/tas571x.c +++ b/sound/soc/codecs/tas571x.c @@ -884,13 +884,11 @@ disable_regs: return ret; } -static int tas571x_i2c_remove(struct i2c_client *client) +static void tas571x_i2c_remove(struct i2c_client *client) { struct tas571x_private *priv = i2c_get_clientdata(client); regulator_bulk_disable(priv->chip->num_supply_names, priv->supplies); - - return 0; } static const struct of_device_id tas571x_of_match[] __maybe_unused = { diff --git a/sound/soc/codecs/tas5805m.c b/sound/soc/codecs/tas5805m.c index b1bb614534f7..beb4ec629a03 100644 --- a/sound/soc/codecs/tas5805m.c +++ b/sound/soc/codecs/tas5805m.c @@ -522,7 +522,7 @@ static int tas5805m_i2c_probe(struct i2c_client *i2c) return 0; } -static int tas5805m_i2c_remove(struct i2c_client *i2c) +static void tas5805m_i2c_remove(struct i2c_client *i2c) { struct device *dev = &i2c->dev; struct tas5805m_priv *tas5805m = dev_get_drvdata(dev); @@ -531,7 +531,6 @@ static int tas5805m_i2c_remove(struct i2c_client *i2c) gpiod_set_value(tas5805m->gpio_pdn_n, 0); usleep_range(10000, 15000); regulator_disable(tas5805m->pvdd); - return 0; } static const struct i2c_device_id tas5805m_i2c_id[] = { diff --git a/sound/soc/codecs/tas6424.c b/sound/soc/codecs/tas6424.c index 63d2983c3fcf..f8ff69fa2549 100644 --- a/sound/soc/codecs/tas6424.c +++ b/sound/soc/codecs/tas6424.c @@ -774,7 +774,7 @@ disable_regs: return ret; } -static int tas6424_i2c_remove(struct i2c_client *client) +static void tas6424_i2c_remove(struct i2c_client *client) { struct device *dev = &client->dev; struct tas6424_data *tas6424 = dev_get_drvdata(dev); @@ -790,8 +790,6 @@ static int tas6424_i2c_remove(struct i2c_client *client) tas6424->supplies); if (ret < 0) dev_err(dev, "unable to disable supplies: %d\n", ret); - - return 0; } static const struct i2c_device_id tas6424_i2c_ids[] = { diff --git a/sound/soc/codecs/tlv320adc3xxx.c b/sound/soc/codecs/tlv320adc3xxx.c index 8a0965cd3e66..a969547708d4 100644 --- a/sound/soc/codecs/tlv320adc3xxx.c +++ b/sound/soc/codecs/tlv320adc3xxx.c @@ -1426,7 +1426,7 @@ err_unprepare_mclk: return ret; } -static int __exit adc3xxx_i2c_remove(struct i2c_client *client) +static void __exit adc3xxx_i2c_remove(struct i2c_client *client) { struct adc3xxx *adc3xxx = i2c_get_clientdata(client); @@ -1434,7 +1434,6 @@ static int __exit adc3xxx_i2c_remove(struct i2c_client *client) clk_disable_unprepare(adc3xxx->mclk); adc3xxx_free_gpio(adc3xxx); snd_soc_unregister_component(&client->dev); - return 0; } static const struct of_device_id tlv320adc3xxx_of_match[] = { diff --git a/sound/soc/codecs/tlv320aic32x4-i2c.c b/sound/soc/codecs/tlv320aic32x4-i2c.c index 0645239901b1..d1e543ca3521 100644 --- a/sound/soc/codecs/tlv320aic32x4-i2c.c +++ b/sound/soc/codecs/tlv320aic32x4-i2c.c @@ -45,11 +45,9 @@ static int aic32x4_i2c_probe(struct i2c_client *i2c) return aic32x4_probe(&i2c->dev, regmap); } -static int aic32x4_i2c_remove(struct i2c_client *i2c) +static void aic32x4_i2c_remove(struct i2c_client *i2c) { aic32x4_remove(&i2c->dev); - - return 0; } static const struct i2c_device_id aic32x4_i2c_id[] = { diff --git a/sound/soc/codecs/tlv320aic3x-i2c.c b/sound/soc/codecs/tlv320aic3x-i2c.c index 7bd9ce08bb7b..d7e94d564dbf 100644 --- a/sound/soc/codecs/tlv320aic3x-i2c.c +++ b/sound/soc/codecs/tlv320aic3x-i2c.c @@ -41,11 +41,9 @@ static int aic3x_i2c_probe(struct i2c_client *i2c) return aic3x_probe(&i2c->dev, regmap, id->driver_data); } -static int aic3x_i2c_remove(struct i2c_client *i2c) +static void aic3x_i2c_remove(struct i2c_client *i2c) { aic3x_remove(&i2c->dev); - - return 0; } static const struct of_device_id aic3x_of_id[] = { diff --git a/sound/soc/codecs/tlv320dac33.c b/sound/soc/codecs/tlv320dac33.c index 17ae3b1d96fb..16ce3ef1134b 100644 --- a/sound/soc/codecs/tlv320dac33.c +++ b/sound/soc/codecs/tlv320dac33.c @@ -1536,7 +1536,7 @@ err_gpio: return ret; } -static int dac33_i2c_remove(struct i2c_client *client) +static void dac33_i2c_remove(struct i2c_client *client) { struct tlv320dac33_priv *dac33 = i2c_get_clientdata(client); @@ -1545,8 +1545,6 @@ static int dac33_i2c_remove(struct i2c_client *client) if (dac33->power_gpio >= 0) gpio_free(dac33->power_gpio); - - return 0; } static const struct i2c_device_id tlv320dac33_i2c_id[] = { diff --git a/sound/soc/codecs/wcd-mbhc-v2.c b/sound/soc/codecs/wcd-mbhc-v2.c index b16a18dbfe7a..1911750f7445 100644 --- a/sound/soc/codecs/wcd-mbhc-v2.c +++ b/sound/soc/codecs/wcd-mbhc-v2.c @@ -714,11 +714,12 @@ static int wcd_mbhc_initialise(struct wcd_mbhc *mbhc) struct snd_soc_component *component = mbhc->component; int ret; - ret = pm_runtime_resume_and_get(component->dev); + ret = pm_runtime_get_sync(component->dev); if (ret < 0 && ret != -EACCES) { dev_err_ratelimited(component->dev, - "pm_runtime_resume_and_get failed in %s, ret %d\n", + "pm_runtime_get_sync failed in %s, ret %d\n", __func__, ret); + pm_runtime_put_noidle(component->dev); return ret; } @@ -1096,11 +1097,12 @@ static void wcd_correct_swch_plug(struct work_struct *work) mbhc = container_of(work, struct wcd_mbhc, correct_plug_swch); component = mbhc->component; - ret = pm_runtime_resume_and_get(component->dev); + ret = pm_runtime_get_sync(component->dev); if (ret < 0 && ret != -EACCES) { dev_err_ratelimited(component->dev, - "pm_runtime_resume_and_get failed in %s, ret %d\n", + "pm_runtime_get_sync failed in %s, ret %d\n", __func__, ret); + pm_runtime_put_noidle(component->dev); return; } micbias_mv = wcd_mbhc_get_micbias(mbhc); diff --git a/sound/soc/codecs/wcd9335.c b/sound/soc/codecs/wcd9335.c index 06c6adbe5920..d2548fdf9ae5 100644 --- a/sound/soc/codecs/wcd9335.c +++ b/sound/soc/codecs/wcd9335.c @@ -1972,8 +1972,8 @@ static int wcd9335_trigger(struct snd_pcm_substream *substream, int cmd, case SNDRV_PCM_TRIGGER_STOP: case SNDRV_PCM_TRIGGER_SUSPEND: case SNDRV_PCM_TRIGGER_PAUSE_PUSH: - slim_stream_unprepare(dai_data->sruntime); slim_stream_disable(dai_data->sruntime); + slim_stream_unprepare(dai_data->sruntime); break; default: break; diff --git a/sound/soc/codecs/wcd934x.c b/sound/soc/codecs/wcd934x.c index f56907d0942d..28175c746b9a 100644 --- a/sound/soc/codecs/wcd934x.c +++ b/sound/soc/codecs/wcd934x.c @@ -1913,8 +1913,8 @@ static int wcd934x_trigger(struct snd_pcm_substream *substream, int cmd, case SNDRV_PCM_TRIGGER_STOP: case SNDRV_PCM_TRIGGER_SUSPEND: case SNDRV_PCM_TRIGGER_PAUSE_PUSH: - slim_stream_unprepare(dai_data->sruntime); slim_stream_disable(dai_data->sruntime); + slim_stream_unprepare(dai_data->sruntime); break; default: break; diff --git a/sound/soc/codecs/wm1250-ev1.c b/sound/soc/codecs/wm1250-ev1.c index 98343626078b..0064a607ec68 100644 --- a/sound/soc/codecs/wm1250-ev1.c +++ b/sound/soc/codecs/wm1250-ev1.c @@ -228,11 +228,9 @@ static int wm1250_ev1_probe(struct i2c_client *i2c) return 0; } -static int wm1250_ev1_remove(struct i2c_client *i2c) +static void wm1250_ev1_remove(struct i2c_client *i2c) { wm1250_ev1_free(i2c); - - return 0; } static const struct i2c_device_id wm1250_ev1_i2c_id[] = { diff --git a/sound/soc/codecs/wm2200.c b/sound/soc/codecs/wm2200.c index 7b4e162a298c..0a65afa44a59 100644 --- a/sound/soc/codecs/wm2200.c +++ b/sound/soc/codecs/wm2200.c @@ -2414,7 +2414,7 @@ err_enable: return ret; } -static int wm2200_i2c_remove(struct i2c_client *i2c) +static void wm2200_i2c_remove(struct i2c_client *i2c) { struct wm2200_priv *wm2200 = i2c_get_clientdata(i2c); @@ -2427,8 +2427,6 @@ static int wm2200_i2c_remove(struct i2c_client *i2c) gpio_set_value_cansleep(wm2200->pdata.ldo_ena, 0); regulator_bulk_disable(ARRAY_SIZE(wm2200->core_supplies), wm2200->core_supplies); - - return 0; } #ifdef CONFIG_PM diff --git a/sound/soc/codecs/wm5100.c b/sound/soc/codecs/wm5100.c index 35a85ce6b464..3b09d4a1684f 100644 --- a/sound/soc/codecs/wm5100.c +++ b/sound/soc/codecs/wm5100.c @@ -2635,7 +2635,7 @@ err: return ret; } -static int wm5100_i2c_remove(struct i2c_client *i2c) +static void wm5100_i2c_remove(struct i2c_client *i2c) { struct wm5100_priv *wm5100 = i2c_get_clientdata(i2c); @@ -2651,8 +2651,6 @@ static int wm5100_i2c_remove(struct i2c_client *i2c) gpio_set_value_cansleep(wm5100->pdata.ldo_ena, 0); gpio_free(wm5100->pdata.ldo_ena); } - - return 0; } #ifdef CONFIG_PM diff --git a/sound/soc/codecs/wm8804-i2c.c b/sound/soc/codecs/wm8804-i2c.c index 04dc9fb5afb4..3ce1a39d76eb 100644 --- a/sound/soc/codecs/wm8804-i2c.c +++ b/sound/soc/codecs/wm8804-i2c.c @@ -25,10 +25,9 @@ static int wm8804_i2c_probe(struct i2c_client *i2c) return wm8804_probe(&i2c->dev, regmap); } -static int wm8804_i2c_remove(struct i2c_client *i2c) +static void wm8804_i2c_remove(struct i2c_client *i2c) { wm8804_remove(&i2c->dev); - return 0; } static const struct i2c_device_id wm8804_i2c_id[] = { diff --git a/sound/soc/codecs/wm8900.c b/sound/soc/codecs/wm8900.c index d6420df3505d..03bbd85ebdf4 100644 --- a/sound/soc/codecs/wm8900.c +++ b/sound/soc/codecs/wm8900.c @@ -1282,10 +1282,8 @@ static int wm8900_i2c_probe(struct i2c_client *i2c) return ret; } -static int wm8900_i2c_remove(struct i2c_client *client) -{ - return 0; -} +static void wm8900_i2c_remove(struct i2c_client *client) +{} static const struct i2c_device_id wm8900_i2c_id[] = { { "wm8900", 0 }, diff --git a/sound/soc/codecs/wm8903.c b/sound/soc/codecs/wm8903.c index 54e0a7628cd5..41346e5ec5ad 100644 --- a/sound/soc/codecs/wm8903.c +++ b/sound/soc/codecs/wm8903.c @@ -2182,7 +2182,7 @@ err: return ret; } -static int wm8903_i2c_remove(struct i2c_client *client) +static void wm8903_i2c_remove(struct i2c_client *client) { struct wm8903_priv *wm8903 = i2c_get_clientdata(client); @@ -2191,8 +2191,6 @@ static int wm8903_i2c_remove(struct i2c_client *client) if (client->irq) free_irq(client->irq, wm8903); wm8903_free_gpio(wm8903); - - return 0; } static const struct of_device_id wm8903_of_match[] = { diff --git a/sound/soc/codecs/wm8960.c b/sound/soc/codecs/wm8960.c index 37956516d997..0d167238a369 100644 --- a/sound/soc/codecs/wm8960.c +++ b/sound/soc/codecs/wm8960.c @@ -1486,10 +1486,8 @@ static int wm8960_i2c_probe(struct i2c_client *i2c) return ret; } -static int wm8960_i2c_remove(struct i2c_client *client) -{ - return 0; -} +static void wm8960_i2c_remove(struct i2c_client *client) +{} static const struct i2c_device_id wm8960_i2c_id[] = { { "wm8960", 0 }, diff --git a/sound/soc/codecs/wm8962.c b/sound/soc/codecs/wm8962.c index 6df06fba4377..b4b4355c6728 100644 --- a/sound/soc/codecs/wm8962.c +++ b/sound/soc/codecs/wm8962.c @@ -3828,10 +3828,9 @@ err: return ret; } -static int wm8962_i2c_remove(struct i2c_client *client) +static void wm8962_i2c_remove(struct i2c_client *client) { pm_runtime_disable(&client->dev); - return 0; } #ifdef CONFIG_PM diff --git a/sound/soc/codecs/wm8993.c b/sound/soc/codecs/wm8993.c index 8db98b5a06bf..22a47acbc6d1 100644 --- a/sound/soc/codecs/wm8993.c +++ b/sound/soc/codecs/wm8993.c @@ -1722,15 +1722,13 @@ err_enable: return ret; } -static int wm8993_i2c_remove(struct i2c_client *i2c) +static void wm8993_i2c_remove(struct i2c_client *i2c) { struct wm8993_priv *wm8993 = i2c_get_clientdata(i2c); if (i2c->irq) free_irq(i2c->irq, wm8993); regulator_bulk_disable(ARRAY_SIZE(wm8993->supplies), wm8993->supplies); - - return 0; } static const struct i2c_device_id wm8993_i2c_id[] = { diff --git a/sound/soc/codecs/wm8996.c b/sound/soc/codecs/wm8996.c index 17f307a31046..b52ed89d631a 100644 --- a/sound/soc/codecs/wm8996.c +++ b/sound/soc/codecs/wm8996.c @@ -3065,7 +3065,7 @@ err: return ret; } -static int wm8996_i2c_remove(struct i2c_client *client) +static void wm8996_i2c_remove(struct i2c_client *client) { struct wm8996_priv *wm8996 = i2c_get_clientdata(client); @@ -3074,8 +3074,6 @@ static int wm8996_i2c_remove(struct i2c_client *client) gpio_set_value_cansleep(wm8996->pdata.ldo_ena, 0); gpio_free(wm8996->pdata.ldo_ena); } - - return 0; } static const struct i2c_device_id wm8996_i2c_id[] = { diff --git a/sound/soc/codecs/wm9081.c b/sound/soc/codecs/wm9081.c index d5151877d0fa..513ec0ba81bb 100644 --- a/sound/soc/codecs/wm9081.c +++ b/sound/soc/codecs/wm9081.c @@ -1356,10 +1356,8 @@ static int wm9081_i2c_probe(struct i2c_client *i2c) return 0; } -static int wm9081_i2c_remove(struct i2c_client *client) -{ - return 0; -} +static void wm9081_i2c_remove(struct i2c_client *client) +{} static const struct i2c_device_id wm9081_i2c_id[] = { { "wm9081", 0 }, diff --git a/sound/soc/fsl/fsl_audmix.c b/sound/soc/fsl/fsl_audmix.c index 43857b7a81c9..672148dd4b23 100644 --- a/sound/soc/fsl/fsl_audmix.c +++ b/sound/soc/fsl/fsl_audmix.c @@ -199,18 +199,10 @@ static int fsl_audmix_put_out_src(struct snd_kcontrol *kcontrol, static const struct snd_kcontrol_new fsl_audmix_snd_controls[] = { /* FSL_AUDMIX_CTR controls */ - { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Mixing Clock Source", - .info = snd_soc_info_enum_double, - .access = SNDRV_CTL_ELEM_ACCESS_WRITE, - .put = fsl_audmix_put_mix_clk_src, - .private_value = (unsigned long)&fsl_audmix_enum[0] }, - { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Output Source", - .info = snd_soc_info_enum_double, - .access = SNDRV_CTL_ELEM_ACCESS_WRITE, - .put = fsl_audmix_put_out_src, - .private_value = (unsigned long)&fsl_audmix_enum[1] }, + SOC_ENUM_EXT("Mixing Clock Source", fsl_audmix_enum[0], + snd_soc_get_enum_double, fsl_audmix_put_mix_clk_src), + SOC_ENUM_EXT("Output Source", fsl_audmix_enum[1], + snd_soc_get_enum_double, fsl_audmix_put_out_src), SOC_ENUM("Output Width", fsl_audmix_enum[2]), SOC_ENUM("Frame Rate Diff Error", fsl_audmix_enum[3]), SOC_ENUM("Clock Freq Diff Error", fsl_audmix_enum[4]), diff --git a/sound/soc/fsl/imx-card.c b/sound/soc/fsl/imx-card.c index 14be29530fb5..3f128ced4180 100644 --- a/sound/soc/fsl/imx-card.c +++ b/sound/soc/fsl/imx-card.c @@ -698,6 +698,10 @@ static int imx_card_parse_of(struct imx_card_data *data) of_node_put(cpu); of_node_put(codec); of_node_put(platform); + + cpu = NULL; + codec = NULL; + platform = NULL; } return 0; diff --git a/sound/soc/intel/atom/sst-mfld-platform-pcm.c b/sound/soc/intel/atom/sst-mfld-platform-pcm.c index a56dd48c045f..c75616a5fd0a 100644 --- a/sound/soc/intel/atom/sst-mfld-platform-pcm.c +++ b/sound/soc/intel/atom/sst-mfld-platform-pcm.c @@ -676,10 +676,9 @@ static int sst_soc_pcm_new(struct snd_soc_component *component, if (dai->driver->playback.channels_min || dai->driver->capture.channels_min) { - snd_pcm_set_managed_buffer_all(pcm, - SNDRV_DMA_TYPE_CONTINUOUS, - snd_dma_continuous_data(GFP_DMA), - SST_MIN_BUFFER, SST_MAX_BUFFER); + snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV, + pcm->card->dev, + SST_MIN_BUFFER, SST_MAX_BUFFER); } return 0; } diff --git a/sound/soc/intel/avs/core.c b/sound/soc/intel/avs/core.c index c50c20fd681a..bb0719c58ca4 100644 --- a/sound/soc/intel/avs/core.c +++ b/sound/soc/intel/avs/core.c @@ -466,7 +466,7 @@ static int avs_pci_probe(struct pci_dev *pci, const struct pci_device_id *id) err_acquire_irq: snd_hdac_bus_free_stream_pages(bus); - snd_hdac_stream_free_all(bus); + snd_hdac_ext_stream_free_all(bus); err_init_streams: iounmap(adev->dsp_ba); err_remap_bar4: @@ -502,7 +502,7 @@ static void avs_pci_remove(struct pci_dev *pci) snd_hda_codec_unregister(hdac_to_hda_codec(hdev)); snd_hdac_bus_free_stream_pages(bus); - snd_hdac_stream_free_all(bus); + snd_hdac_ext_stream_free_all(bus); /* reverse ml_capabilities */ snd_hdac_link_free_all(bus); snd_hdac_ext_bus_exit(bus); diff --git a/sound/soc/intel/boards/hda_dsp_common.c b/sound/soc/intel/boards/hda_dsp_common.c index 83c7dfbccd9d..04b7d4f7f9e2 100644 --- a/sound/soc/intel/boards/hda_dsp_common.c +++ b/sound/soc/intel/boards/hda_dsp_common.c @@ -54,7 +54,7 @@ int hda_dsp_hdmi_build_controls(struct snd_soc_card *card, return -EINVAL; hda_pvt = snd_soc_component_get_drvdata(comp); - hcodec = &hda_pvt->codec; + hcodec = hda_pvt->codec; list_for_each_entry(hpcm, &hcodec->pcm_list_head, list) { spcm = hda_dsp_hdmi_pcm_handle(card, i); diff --git a/sound/soc/intel/boards/skl_hda_dsp_generic.c b/sound/soc/intel/boards/skl_hda_dsp_generic.c index 81144efb4b44..879ebba52832 100644 --- a/sound/soc/intel/boards/skl_hda_dsp_generic.c +++ b/sound/soc/intel/boards/skl_hda_dsp_generic.c @@ -190,7 +190,7 @@ static void skl_set_hda_codec_autosuspend_delay(struct snd_soc_card *card) * all codecs are on the same bus, so it's sufficient * to look up only the first one */ - snd_hda_set_power_save(hda_pvt->codec.bus, + snd_hda_set_power_save(hda_pvt->codec->bus, HDA_CODEC_AUTOSUSPEND_DELAY_MS); break; } diff --git a/sound/soc/intel/boards/sof_sdw.c b/sound/soc/intel/boards/sof_sdw.c index 5223089c3426..ee9857dc3135 100644 --- a/sound/soc/intel/boards/sof_sdw.c +++ b/sound/soc/intel/boards/sof_sdw.c @@ -281,6 +281,16 @@ static const struct dmi_system_id sof_sdw_quirk_table[] = { .callback = sof_sdw_quirk_cb, .matches = { DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"), + DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0AFF") + }, + .driver_data = (void *)(SOF_SDW_TGL_HDMI | + RT711_JD2 | + SOF_SDW_FOUR_SPK), + }, + { + .callback = sof_sdw_quirk_cb, + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"), DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0B00") }, .driver_data = (void *)(SOF_SDW_TGL_HDMI | diff --git a/sound/soc/intel/skylake/skl-pcm.c b/sound/soc/intel/skylake/skl-pcm.c index 9d72ebd812af..1015716f9336 100644 --- a/sound/soc/intel/skylake/skl-pcm.c +++ b/sound/soc/intel/skylake/skl-pcm.c @@ -275,7 +275,7 @@ static int skl_pcm_prepare(struct snd_pcm_substream *substream, * calls prepare another time, reset the FW pipe to clean state */ if (mconfig && - (substream->runtime->status->state == SNDRV_PCM_STATE_XRUN || + (substream->runtime->state == SNDRV_PCM_STATE_XRUN || mconfig->pipe->state == SKL_PIPE_CREATED || mconfig->pipe->state == SKL_PIPE_PAUSED)) { @@ -593,7 +593,7 @@ static int skl_link_pcm_prepare(struct snd_pcm_substream *substream, /* In case of XRUN recovery, reset the FW pipe to clean state */ mconfig = skl_tplg_be_get_cpr_module(dai, substream->stream); if (mconfig && !mconfig->pipe->passthru && - (substream->runtime->status->state == SNDRV_PCM_STATE_XRUN)) + (substream->runtime->state == SNDRV_PCM_STATE_XRUN)) skl_reset_pipe(skl, mconfig->pipe); return 0; diff --git a/sound/soc/intel/skylake/skl.c b/sound/soc/intel/skylake/skl.c index 5707dfee603f..bbba2df33aaf 100644 --- a/sound/soc/intel/skylake/skl.c +++ b/sound/soc/intel/skylake/skl.c @@ -444,7 +444,7 @@ static int skl_free(struct hdac_bus *bus) if (bus->irq >= 0) free_irq(bus->irq, (void *)bus); snd_hdac_bus_free_stream_pages(bus); - snd_hdac_stream_free_all(bus); + snd_hdac_ext_stream_free_all(bus); snd_hdac_link_free_all(bus); if (bus->remap_addr) @@ -689,6 +689,35 @@ static void load_codec_module(struct hda_codec *codec) #endif /* CONFIG_SND_SOC_INTEL_SKYLAKE_HDAUDIO_CODEC */ +static void skl_codec_device_exit(struct device *dev) +{ + snd_hdac_device_exit(dev_to_hdac_dev(dev)); +} + +static struct hda_codec *skl_codec_device_init(struct hdac_bus *bus, int addr) +{ + struct hda_codec *codec; + int ret; + + codec = snd_hda_codec_device_init(to_hda_bus(bus), addr, "ehdaudio%dD%d", bus->idx, addr); + if (IS_ERR(codec)) { + dev_err(bus->dev, "device init failed for hdac device\n"); + return codec; + } + + codec->core.type = HDA_DEV_ASOC; + codec->core.dev.release = skl_codec_device_exit; + + ret = snd_hdac_device_register(&codec->core); + if (ret) { + dev_err(bus->dev, "failed to register hdac device\n"); + snd_hdac_device_exit(&codec->core); + return ERR_PTR(ret); + } + + return codec; +} + /* * Probe the given codec address */ @@ -700,9 +729,8 @@ static int probe_codec(struct hdac_bus *bus, int addr) #if IS_ENABLED(CONFIG_SND_SOC_INTEL_SKYLAKE_HDAUDIO_CODEC) struct skl_dev *skl = bus_to_skl(bus); struct hdac_hda_priv *hda_codec; - int err; #endif - struct hdac_device *hdev; + struct hda_codec *codec; mutex_lock(&bus->cmd_mutex); snd_hdac_bus_send_cmd(bus, cmd); @@ -718,25 +746,22 @@ static int probe_codec(struct hdac_bus *bus, int addr) if (!hda_codec) return -ENOMEM; - hda_codec->codec.bus = skl_to_hbus(skl); - hdev = &hda_codec->codec.core; + codec = skl_codec_device_init(bus, addr); + if (IS_ERR(codec)) + return PTR_ERR(codec); - err = snd_hdac_ext_bus_device_init(bus, addr, hdev, HDA_DEV_ASOC); - if (err < 0) - return err; + hda_codec->codec = codec; + dev_set_drvdata(&codec->core.dev, hda_codec); /* use legacy bus only for HDA codecs, idisp uses ext bus */ if ((res & 0xFFFF0000) != IDISP_INTEL_VENDOR_ID) { - hdev->type = HDA_DEV_LEGACY; - load_codec_module(&hda_codec->codec); + codec->core.type = HDA_DEV_LEGACY; + load_codec_module(hda_codec->codec); } return 0; #else - hdev = devm_kzalloc(&skl->pci->dev, sizeof(*hdev), GFP_KERNEL); - if (!hdev) - return -ENOMEM; - - return snd_hdac_ext_bus_device_init(bus, addr, hdev, HDA_DEV_ASOC); + codec = skl_codec_device_init(bus, addr); + return PTR_ERR_OR_ZERO(codec); #endif /* CONFIG_SND_SOC_INTEL_SKYLAKE_HDAUDIO_CODEC */ } diff --git a/sound/soc/sh/rz-ssi.c b/sound/soc/sh/rz-ssi.c index 7ace0c0db5b1..5d6bae33ae34 100644 --- a/sound/soc/sh/rz-ssi.c +++ b/sound/soc/sh/rz-ssi.c @@ -598,7 +598,7 @@ static int rz_ssi_dma_transfer(struct rz_ssi_priv *ssi, return -EINVAL; runtime = substream->runtime; - if (runtime->status->state == SNDRV_PCM_STATE_DRAINING) + if (runtime->state == SNDRV_PCM_STATE_DRAINING) /* * Stream is ending, so do not queue up any more DMA * transfers otherwise we play partial sound clips diff --git a/sound/soc/sof/intel/hda-codec.c b/sound/soc/sof/intel/hda-codec.c index 2f3f4a733d9e..1e9afc48394c 100644 --- a/sound/soc/sof/intel/hda-codec.c +++ b/sound/soc/sof/intel/hda-codec.c @@ -109,17 +109,45 @@ EXPORT_SYMBOL_NS(hda_codec_jack_check, SND_SOC_SOF_HDA_AUDIO_CODEC); #define is_generic_config(x) 0 #endif +static void hda_codec_device_exit(struct device *dev) +{ + snd_hdac_device_exit(dev_to_hdac_dev(dev)); +} + +static struct hda_codec *hda_codec_device_init(struct hdac_bus *bus, int addr, int type) +{ + struct hda_codec *codec; + int ret; + + codec = snd_hda_codec_device_init(to_hda_bus(bus), addr, "ehdaudio%dD%d", bus->idx, addr); + if (IS_ERR(codec)) { + dev_err(bus->dev, "device init failed for hdac device\n"); + return codec; + } + + codec->core.type = type; + codec->core.dev.release = hda_codec_device_exit; + + ret = snd_hdac_device_register(&codec->core); + if (ret) { + dev_err(bus->dev, "failed to register hdac device\n"); + snd_hdac_device_exit(&codec->core); + return ERR_PTR(ret); + } + + return codec; +} + /* probe individual codec */ static int hda_codec_probe(struct snd_sof_dev *sdev, int address, bool hda_codec_use_common_hdmi) { #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA_AUDIO_CODEC) struct hdac_hda_priv *hda_priv; - struct hda_codec *codec; int type = HDA_DEV_LEGACY; #endif struct hda_bus *hbus = sof_to_hbus(sdev); - struct hdac_device *hdev; + struct hda_codec *codec; u32 hda_cmd = (address << 28) | (AC_NODE_ROOT << 20) | (AC_VERB_PARAMETERS << 8) | AC_PAR_VENDOR_ID; u32 resp = -1; @@ -142,20 +170,20 @@ static int hda_codec_probe(struct snd_sof_dev *sdev, int address, if (!hda_priv) return -ENOMEM; - hda_priv->codec.bus = hbus; - hdev = &hda_priv->codec.core; - codec = &hda_priv->codec; - /* only probe ASoC codec drivers for HDAC-HDMI */ if (!hda_codec_use_common_hdmi && (resp & 0xFFFF0000) == IDISP_VID_INTEL) type = HDA_DEV_ASOC; - ret = snd_hdac_ext_bus_device_init(&hbus->core, address, hdev, type); + codec = hda_codec_device_init(&hbus->core, address, type); + ret = PTR_ERR_OR_ZERO(codec); if (ret < 0) return ret; + hda_priv->codec = codec; + dev_set_drvdata(&codec->core.dev, hda_priv); + if ((resp & 0xFFFF0000) == IDISP_VID_INTEL) { - if (!hdev->bus->audio_component) { + if (!hbus->core.audio_component) { dev_dbg(sdev->dev, "iDisp hw present but no driver\n"); ret = -ENOENT; @@ -181,15 +209,12 @@ static int hda_codec_probe(struct snd_sof_dev *sdev, int address, out: if (ret < 0) { - snd_hdac_device_unregister(hdev); - put_device(&hdev->dev); + snd_hdac_device_unregister(&codec->core); + put_device(&codec->core.dev); } #else - hdev = devm_kzalloc(sdev->dev, sizeof(*hdev), GFP_KERNEL); - if (!hdev) - return -ENOMEM; - - ret = snd_hdac_ext_bus_device_init(&hbus->core, address, hdev, HDA_DEV_ASOC); + codec = hda_codec_device_init(&hbus->core, address, HDA_DEV_ASOC); + ret = PTR_ERR_OR_ZERO(codec); #endif return ret; diff --git a/sound/usb/card.c b/sound/usb/card.c index 706d249a9ad6..a5ed11ea1145 100644 --- a/sound/usb/card.c +++ b/sound/usb/card.c @@ -690,7 +690,7 @@ static bool get_alias_id(struct usb_device *dev, unsigned int *id) return false; } -static bool check_delayed_register_option(struct snd_usb_audio *chip, int iface) +static int check_delayed_register_option(struct snd_usb_audio *chip) { int i; unsigned int id, inum; @@ -699,14 +699,31 @@ static bool check_delayed_register_option(struct snd_usb_audio *chip, int iface) if (delayed_register[i] && sscanf(delayed_register[i], "%x:%x", &id, &inum) == 2 && id == chip->usb_id) - return iface < inum; + return inum; } - return false; + return -1; } static const struct usb_device_id usb_audio_ids[]; /* defined below */ +/* look for the last interface that matches with our ids and remember it */ +static void find_last_interface(struct snd_usb_audio *chip) +{ + struct usb_host_config *config = chip->dev->actconfig; + struct usb_interface *intf; + int i; + + if (!config) + return; + for (i = 0; i < config->desc.bNumInterfaces; i++) { + intf = config->interface[i]; + if (usb_match_id(intf, usb_audio_ids)) + chip->last_iface = intf->altsetting[0].desc.bInterfaceNumber; + } + usb_audio_dbg(chip, "Found last interface = %d\n", chip->last_iface); +} + /* look for the corresponding quirk */ static const struct snd_usb_audio_quirk * get_alias_quirk(struct usb_device *dev, unsigned int id) @@ -813,6 +830,7 @@ static int usb_audio_probe(struct usb_interface *intf, err = -ENODEV; goto __error; } + find_last_interface(chip); } if (chip->num_interfaces >= MAX_CARD_INTERFACES) { @@ -862,11 +880,11 @@ static int usb_audio_probe(struct usb_interface *intf, chip->need_delayed_register = false; /* clear again */ } - /* we are allowed to call snd_card_register() many times, but first - * check to see if a device needs to skip it or do anything special + /* register card if we reach to the last interface or to the specified + * one given via option */ - if (!snd_usb_registration_quirk(chip, ifnum) && - !check_delayed_register_option(chip, ifnum)) { + if (check_delayed_register_option(chip) == ifnum || + usb_interface_claimed(usb_ifnum_to_if(dev, chip->last_iface))) { err = snd_card_register(chip->card); if (err < 0) goto __error; diff --git a/sound/usb/card.h b/sound/usb/card.h index ca75f2206170..40061550105a 100644 --- a/sound/usb/card.h +++ b/sound/usb/card.h @@ -129,7 +129,8 @@ struct snd_usb_endpoint { in a stream */ bool implicit_fb_sync; /* syncs with implicit feedback */ bool lowlatency_playback; /* low-latency playback mode */ - bool need_setup; /* (re-)need for configure? */ + bool need_setup; /* (re-)need for hw_params? */ + bool need_prepare; /* (re-)need for prepare? */ /* for hw constraints */ const struct audioformat *cur_audiofmt; diff --git a/sound/usb/endpoint.c b/sound/usb/endpoint.c index 8c8f9a851f89..d0b8d61d1d22 100644 --- a/sound/usb/endpoint.c +++ b/sound/usb/endpoint.c @@ -32,6 +32,7 @@ struct snd_usb_iface_ref { unsigned char iface; bool need_setup; int opened; + int altset; struct list_head list; }; @@ -39,7 +40,9 @@ struct snd_usb_iface_ref { struct snd_usb_clock_ref { unsigned char clock; atomic_t locked; + int opened; int rate; + bool need_setup; struct list_head list; }; @@ -93,12 +96,13 @@ static inline unsigned get_usb_high_speed_rate(unsigned int rate) */ static void release_urb_ctx(struct snd_urb_ctx *u) { - if (u->buffer_size) + if (u->urb && u->buffer_size) usb_free_coherent(u->ep->chip->dev, u->buffer_size, u->urb->transfer_buffer, u->urb->transfer_dma); usb_free_urb(u->urb); u->urb = NULL; + u->buffer_size = 0; } static const char *usb_error_string(int err) @@ -802,6 +806,7 @@ snd_usb_endpoint_open(struct snd_usb_audio *chip, ep = NULL; goto unlock; } + ep->clock_ref->opened++; } ep->cur_audiofmt = fp; @@ -819,6 +824,7 @@ snd_usb_endpoint_open(struct snd_usb_audio *chip, ep->implicit_fb_sync = fp->implicit_fb; ep->need_setup = true; + ep->need_prepare = true; usb_audio_dbg(chip, " channels=%d, rate=%d, format=%s, period_bytes=%d, periods=%d, implicit_fb=%d\n", ep->cur_channels, ep->cur_rate, @@ -895,6 +901,9 @@ static int endpoint_set_interface(struct snd_usb_audio *chip, int altset = set ? ep->altsetting : 0; int err; + if (ep->iface_ref->altset == altset) + return 0; + usb_audio_dbg(chip, "Setting usb interface %d:%d for EP 0x%x\n", ep->iface, altset, ep->ep_num); err = usb_set_interface(chip->dev, ep->iface, altset); @@ -906,6 +915,7 @@ static int endpoint_set_interface(struct snd_usb_audio *chip, if (chip->quirk_flags & QUIRK_FLAG_IFACE_DELAY) msleep(50); + ep->iface_ref->altset = altset; return 0; } @@ -925,8 +935,10 @@ void snd_usb_endpoint_close(struct snd_usb_audio *chip, endpoint_set_interface(chip, ep, false); if (!--ep->opened) { - if (ep->clock_ref && !atomic_read(&ep->clock_ref->locked)) - ep->clock_ref->rate = 0; + if (ep->clock_ref) { + if (!--ep->clock_ref->opened) + ep->clock_ref->rate = 0; + } ep->iface = 0; ep->altsetting = 0; ep->cur_audiofmt = NULL; @@ -941,7 +953,7 @@ void snd_usb_endpoint_close(struct snd_usb_audio *chip, /* Prepare for suspening EP, called from the main suspend handler */ void snd_usb_endpoint_suspend(struct snd_usb_endpoint *ep) { - ep->need_setup = true; + ep->need_prepare = true; if (ep->iface_ref) ep->iface_ref->need_setup = true; if (ep->clock_ref) @@ -1262,6 +1274,7 @@ static int sync_ep_set_params(struct snd_usb_endpoint *ep) if (!ep->syncbuf) return -ENOMEM; + ep->nurbs = SYNC_URBS; for (i = 0; i < SYNC_URBS; i++) { struct snd_urb_ctx *u = &ep->urb[i]; u->index = i; @@ -1281,8 +1294,6 @@ static int sync_ep_set_params(struct snd_usb_endpoint *ep) u->urb->complete = snd_complete_urb; } - ep->nurbs = SYNC_URBS; - return 0; out_of_memory: @@ -1290,6 +1301,29 @@ out_of_memory: return -ENOMEM; } +/* update the rate of the referred clock; return the actual rate */ +static int update_clock_ref_rate(struct snd_usb_audio *chip, + struct snd_usb_endpoint *ep) +{ + struct snd_usb_clock_ref *clock = ep->clock_ref; + int rate = ep->cur_rate; + + if (!clock || clock->rate == rate) + return rate; + if (clock->rate) { + if (atomic_read(&clock->locked)) + return clock->rate; + if (clock->rate != rate) { + usb_audio_err(chip, "Mismatched sample rate %d vs %d for EP 0x%x\n", + clock->rate, rate, ep->ep_num); + return clock->rate; + } + } + clock->rate = rate; + clock->need_setup = true; + return rate; +} + /* * snd_usb_endpoint_set_params: configure an snd_usb_endpoint * @@ -1302,12 +1336,16 @@ int snd_usb_endpoint_set_params(struct snd_usb_audio *chip, struct snd_usb_endpoint *ep) { const struct audioformat *fmt = ep->cur_audiofmt; - int err; + int err = 0; + + mutex_lock(&chip->mutex); + if (!ep->need_setup) + goto unlock; /* release old buffers, if any */ err = release_urbs(ep, false); if (err < 0) - return err; + goto unlock; ep->datainterval = fmt->datainterval; ep->maxpacksize = fmt->maxpacksize; @@ -1345,39 +1383,44 @@ int snd_usb_endpoint_set_params(struct snd_usb_audio *chip, usb_audio_dbg(chip, "Set up %d URBS, ret=%d\n", ep->nurbs, err); if (err < 0) - return err; + goto unlock; /* some unit conversions in runtime */ ep->maxframesize = ep->maxpacksize / ep->cur_frame_bytes; ep->curframesize = ep->curpacksize / ep->cur_frame_bytes; - return 0; + err = update_clock_ref_rate(chip, ep); + if (err >= 0) { + ep->need_setup = false; + err = 0; + } + + unlock: + mutex_unlock(&chip->mutex); + return err; } static int init_sample_rate(struct snd_usb_audio *chip, struct snd_usb_endpoint *ep) { struct snd_usb_clock_ref *clock = ep->clock_ref; - int err; + int rate, err; - if (clock) { - if (atomic_read(&clock->locked)) - return 0; - if (clock->rate == ep->cur_rate) - return 0; - if (clock->rate && clock->rate != ep->cur_rate) { - usb_audio_dbg(chip, "Mismatched sample rate %d vs %d for EP 0x%x\n", - clock->rate, ep->cur_rate, ep->ep_num); - return -EINVAL; - } - } + rate = update_clock_ref_rate(chip, ep); + if (rate < 0) + return rate; + if (clock && !clock->need_setup) + return 0; - err = snd_usb_init_sample_rate(chip, ep->cur_audiofmt, ep->cur_rate); - if (err < 0) + err = snd_usb_init_sample_rate(chip, ep->cur_audiofmt, rate); + if (err < 0) { + if (clock) + clock->rate = 0; /* reset rate */ return err; + } if (clock) - clock->rate = ep->cur_rate; + clock->need_setup = false; return 0; } @@ -1401,7 +1444,7 @@ int snd_usb_endpoint_prepare(struct snd_usb_audio *chip, mutex_lock(&chip->mutex); if (WARN_ON(!ep->iface_ref)) goto unlock; - if (!ep->need_setup) + if (!ep->need_prepare) goto unlock; /* If the interface has been already set up, just set EP parameters */ @@ -1455,7 +1498,7 @@ int snd_usb_endpoint_prepare(struct snd_usb_audio *chip, ep->iface_ref->need_setup = false; done: - ep->need_setup = false; + ep->need_prepare = false; err = 1; unlock: @@ -1628,8 +1671,7 @@ void snd_usb_endpoint_stop(struct snd_usb_endpoint *ep, bool keep_pending) WRITE_ONCE(ep->sync_source->sync_sink, NULL); stop_urbs(ep, false, keep_pending); if (ep->clock_ref) - if (!atomic_dec_return(&ep->clock_ref->locked)) - ep->clock_ref->rate = 0; + atomic_dec(&ep->clock_ref->locked); } } diff --git a/sound/usb/line6/driver.h b/sound/usb/line6/driver.h index ecf3a2b39c7e..dbb1d90d3647 100644 --- a/sound/usb/line6/driver.h +++ b/sound/usb/line6/driver.h @@ -193,8 +193,6 @@ extern int line6_send_raw_message_async(struct usb_line6 *line6, const char *buffer, int size); extern int line6_send_sysex_message(struct usb_line6 *line6, const char *buffer, int size); -extern ssize_t line6_set_raw(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count); extern int line6_version_request_async(struct usb_line6 *line6); extern int line6_write_data(struct usb_line6 *line6, unsigned address, void *data, unsigned datalen); diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c index b604f7e95e82..8ed165f036a0 100644 --- a/sound/usb/pcm.c +++ b/sound/usb/pcm.c @@ -433,35 +433,6 @@ static void close_endpoints(struct snd_usb_audio *chip, } } -static int configure_endpoints(struct snd_usb_audio *chip, - struct snd_usb_substream *subs) -{ - int err; - - if (subs->data_endpoint->need_setup) { - /* stop any running stream beforehand */ - if (stop_endpoints(subs, false)) - sync_pending_stops(subs); - if (subs->sync_endpoint) { - err = snd_usb_endpoint_prepare(chip, subs->sync_endpoint); - if (err < 0) - return err; - } - err = snd_usb_endpoint_prepare(chip, subs->data_endpoint); - if (err < 0) - return err; - snd_usb_set_format_quirk(subs, subs->cur_audiofmt); - } else { - if (subs->sync_endpoint) { - err = snd_usb_endpoint_prepare(chip, subs->sync_endpoint); - if (err < 0) - return err; - } - } - - return 0; -} - /* * hw_params callback * @@ -551,6 +522,9 @@ static int snd_usb_hw_params(struct snd_pcm_substream *substream, subs->cur_audiofmt = fmt; mutex_unlock(&chip->mutex); + if (!subs->data_endpoint->need_setup) + goto unlock; + if (subs->sync_endpoint) { ret = snd_usb_endpoint_set_params(chip, subs->sync_endpoint); if (ret < 0) @@ -640,9 +614,18 @@ static int snd_usb_pcm_prepare(struct snd_pcm_substream *substream) goto unlock; } - ret = configure_endpoints(chip, subs); + if (subs->sync_endpoint) { + ret = snd_usb_endpoint_prepare(chip, subs->sync_endpoint); + if (ret < 0) + goto unlock; + } + + ret = snd_usb_endpoint_prepare(chip, subs->data_endpoint); if (ret < 0) goto unlock; + else if (ret > 0) + snd_usb_set_format_quirk(subs, subs->cur_audiofmt); + ret = 0; /* reset the pointer */ subs->buffer_bytes = frames_to_bytes(runtime, runtime->buffer_size); @@ -1412,7 +1395,7 @@ static int prepare_playback_urb(struct snd_usb_substream *subs, transfer_done = subs->transfer_done; if (subs->lowlatency_playback && - runtime->status->state != SNDRV_PCM_STATE_DRAINING) { + runtime->state != SNDRV_PCM_STATE_DRAINING) { unsigned int hwptr = subs->hwptr_done / stride; /* calculate the byte offset-in-buffer of the appl_ptr */ @@ -1600,7 +1583,7 @@ static int snd_usb_substream_playback_trigger(struct snd_pcm_substream *substrea return 0; case SNDRV_PCM_TRIGGER_SUSPEND: case SNDRV_PCM_TRIGGER_STOP: - stop_endpoints(subs, substream->runtime->status->state == SNDRV_PCM_STATE_DRAINING); + stop_endpoints(subs, substream->runtime->state == SNDRV_PCM_STATE_DRAINING); snd_usb_endpoint_set_callback(subs->data_endpoint, NULL, NULL, NULL); subs->running = 0; diff --git a/sound/usb/quirks-table.h b/sound/usb/quirks-table.h index f93201a830b5..06dfdd45cff8 100644 --- a/sound/usb/quirks-table.h +++ b/sound/usb/quirks-table.h @@ -2985,6 +2985,82 @@ YAMAHA_DEVICE(0x7010, "UB99"), } } }, +/* DIGIDESIGN MBOX 3 */ +{ + USB_DEVICE(0x0dba, 0x5000), + .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) { + .vendor_name = "Digidesign", + .product_name = "Mbox 3", + .ifnum = QUIRK_ANY_INTERFACE, + .type = QUIRK_COMPOSITE, + .data = (const struct snd_usb_audio_quirk[]) { + { + .ifnum = 0, + .type = QUIRK_IGNORE_INTERFACE + }, + { + .ifnum = 1, + .type = QUIRK_IGNORE_INTERFACE + }, + { + .ifnum = 2, + .type = QUIRK_AUDIO_FIXED_ENDPOINT, + .data = &(const struct audioformat) { + .formats = SNDRV_PCM_FMTBIT_S24_3LE, + .channels = 4, + .iface = 2, + .altsetting = 1, + .altset_idx = 1, + .attributes = 0x00, + .endpoint = 0x01, + .ep_attr = USB_ENDPOINT_XFER_ISOC | + USB_ENDPOINT_SYNC_ASYNC, + .rates = SNDRV_PCM_RATE_48000, + .rate_min = 48000, + .rate_max = 48000, + .nr_rates = 1, + .rate_table = (unsigned int[]) { + 48000 + } + } + }, + { + .ifnum = 3, + .type = QUIRK_AUDIO_FIXED_ENDPOINT, + .data = &(const struct audioformat) { + .formats = SNDRV_PCM_FMTBIT_S24_3LE, + .channels = 4, + .iface = 3, + .altsetting = 1, + .altset_idx = 1, + .endpoint = 0x81, + .attributes = 0x00, + .ep_attr = USB_ENDPOINT_XFER_ISOC | + USB_ENDPOINT_SYNC_ASYNC, + .maxpacksize = 0x009c, + .rates = SNDRV_PCM_RATE_48000, + .rate_min = 48000, + .rate_max = 48000, + .nr_rates = 1, + .rate_table = (unsigned int[]) { + 48000 + } + } + }, + { + .ifnum = 4, + .type = QUIRK_MIDI_FIXED_ENDPOINT, + .data = &(const struct snd_usb_midi_endpoint_info) { + .out_cables = 0x0001, + .in_cables = 0x0001 + } + }, + { + .ifnum = -1 + } + } + } +}, { /* Tascam US122 MKII - playback-only support */ USB_DEVICE_VENDOR_SPEC(0x0644, 0x8021), diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c index 5b4d8f5eade2..eadac586bcc8 100644 --- a/sound/usb/quirks.c +++ b/sound/usb/quirks.c @@ -1020,6 +1020,304 @@ static int snd_usb_axefx3_boot_quirk(struct usb_device *dev) return 0; } +static void mbox3_setup_48_24_magic(struct usb_device *dev) +{ + /* The Mbox 3 is "little endian" */ + /* max volume is: 0x0000. */ + /* min volume is: 0x0080 (shown in little endian form) */ + + + /* Load 48000Hz rate into buffer */ + u8 com_buff[4] = {0x80, 0xbb, 0x00, 0x00}; + + /* Set 48000Hz sample rate */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 0x01, 0x21, 0x0100, 0x0001, &com_buff, 4); //Is this really needed? + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 0x01, 0x21, 0x0100, 0x8101, &com_buff, 4); + + /* Deactivate Tuner */ + /* on = 0x01*/ + /* off = 0x00*/ + com_buff[0] = 0x00; + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 0x01, 0x21, 0x0003, 0x2001, &com_buff, 1); + + /* Set clock source to Internal (as opposed to S/PDIF) */ + com_buff[0] = 0x01; + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0100, 0x8001, &com_buff, 1); + + /* Mute the hardware loopbacks to start the device in a known state. */ + com_buff[0] = 0x00; + com_buff[1] = 0x80; + /* Analogue input 1 left channel: */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0110, 0x4001, &com_buff, 2); + /* Analogue input 1 right channel: */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0111, 0x4001, &com_buff, 2); + /* Analogue input 2 left channel: */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0114, 0x4001, &com_buff, 2); + /* Analogue input 2 right channel: */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0115, 0x4001, &com_buff, 2); + /* Analogue input 3 left channel: */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0118, 0x4001, &com_buff, 2); + /* Analogue input 3 right channel: */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0119, 0x4001, &com_buff, 2); + /* Analogue input 4 left channel: */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x011c, 0x4001, &com_buff, 2); + /* Analogue input 4 right channel: */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x011d, 0x4001, &com_buff, 2); + + /* Set software sends to output */ + com_buff[0] = 0x00; + com_buff[1] = 0x00; + /* Analogue software return 1 left channel: */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0100, 0x4001, &com_buff, 2); + com_buff[0] = 0x00; + com_buff[1] = 0x80; + /* Analogue software return 1 right channel: */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0101, 0x4001, &com_buff, 2); + com_buff[0] = 0x00; + com_buff[1] = 0x80; + /* Analogue software return 2 left channel: */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0104, 0x4001, &com_buff, 2); + com_buff[0] = 0x00; + com_buff[1] = 0x00; + /* Analogue software return 2 right channel: */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0105, 0x4001, &com_buff, 2); + + com_buff[0] = 0x00; + com_buff[1] = 0x80; + /* Analogue software return 3 left channel: */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0108, 0x4001, &com_buff, 2); + /* Analogue software return 3 right channel: */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0109, 0x4001, &com_buff, 2); + /* Analogue software return 4 left channel: */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x010c, 0x4001, &com_buff, 2); + /* Analogue software return 4 right channel: */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x010d, 0x4001, &com_buff, 2); + + /* Return to muting sends */ + com_buff[0] = 0x00; + com_buff[1] = 0x80; + /* Analogue fx return left channel: */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0120, 0x4001, &com_buff, 2); + /* Analogue fx return right channel: */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0121, 0x4001, &com_buff, 2); + + /* Analogue software input 1 fx send: */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0100, 0x4201, &com_buff, 2); + /* Analogue software input 2 fx send: */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0101, 0x4201, &com_buff, 2); + /* Analogue software input 3 fx send: */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0102, 0x4201, &com_buff, 2); + /* Analogue software input 4 fx send: */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0103, 0x4201, &com_buff, 2); + /* Analogue input 1 fx send: */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0104, 0x4201, &com_buff, 2); + /* Analogue input 2 fx send: */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0105, 0x4201, &com_buff, 2); + /* Analogue input 3 fx send: */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0106, 0x4201, &com_buff, 2); + /* Analogue input 4 fx send: */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0107, 0x4201, &com_buff, 2); + + /* Toggle allowing host control */ + com_buff[0] = 0x02; + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 3, 0x21, 0x0000, 0x2001, &com_buff, 1); + + /* Do not dim fx returns */ + com_buff[0] = 0x00; + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 3, 0x21, 0x0002, 0x2001, &com_buff, 1); + + /* Do not set fx returns to mono */ + com_buff[0] = 0x00; + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 3, 0x21, 0x0001, 0x2001, &com_buff, 1); + + /* Mute the S/PDIF hardware loopback + * same odd volume logic here as above + */ + com_buff[0] = 0x00; + com_buff[1] = 0x80; + /* S/PDIF hardware input 1 left channel */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0112, 0x4001, &com_buff, 2); + /* S/PDIF hardware input 1 right channel */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0113, 0x4001, &com_buff, 2); + /* S/PDIF hardware input 2 left channel */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0116, 0x4001, &com_buff, 2); + /* S/PDIF hardware input 2 right channel */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0117, 0x4001, &com_buff, 2); + /* S/PDIF hardware input 3 left channel */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x011a, 0x4001, &com_buff, 2); + /* S/PDIF hardware input 3 right channel */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x011b, 0x4001, &com_buff, 2); + /* S/PDIF hardware input 4 left channel */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x011e, 0x4001, &com_buff, 2); + /* S/PDIF hardware input 4 right channel */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x011f, 0x4001, &com_buff, 2); + /* S/PDIF software return 1 left channel */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0102, 0x4001, &com_buff, 2); + /* S/PDIF software return 1 right channel */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0103, 0x4001, &com_buff, 2); + /* S/PDIF software return 2 left channel */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0106, 0x4001, &com_buff, 2); + /* S/PDIF software return 2 right channel */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0107, 0x4001, &com_buff, 2); + + com_buff[0] = 0x00; + com_buff[1] = 0x00; + /* S/PDIF software return 3 left channel */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x010a, 0x4001, &com_buff, 2); + + com_buff[0] = 0x00; + com_buff[1] = 0x80; + /* S/PDIF software return 3 right channel */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x010b, 0x4001, &com_buff, 2); + /* S/PDIF software return 4 left channel */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x010e, 0x4001, &com_buff, 2); + + com_buff[0] = 0x00; + com_buff[1] = 0x00; + /* S/PDIF software return 4 right channel */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x010f, 0x4001, &com_buff, 2); + + com_buff[0] = 0x00; + com_buff[1] = 0x80; + /* S/PDIF fx returns left channel */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0122, 0x4001, &com_buff, 2); + /* S/PDIF fx returns right channel */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0123, 0x4001, &com_buff, 2); + + /* Set the dropdown "Effect" to the first option */ + /* Room1 = 0x00 */ + /* Room2 = 0x01 */ + /* Room3 = 0x02 */ + /* Hall 1 = 0x03 */ + /* Hall 2 = 0x04 */ + /* Plate = 0x05 */ + /* Delay = 0x06 */ + /* Echo = 0x07 */ + com_buff[0] = 0x00; + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0200, 0x4301, &com_buff, 1); /* max is 0xff */ + /* min is 0x00 */ + + + /* Set the effect duration to 0 */ + /* max is 0xffff */ + /* min is 0x0000 */ + com_buff[0] = 0x00; + com_buff[1] = 0x00; + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0400, 0x4301, &com_buff, 2); + + /* Set the effect volume and feedback to 0 */ + /* max is 0xff */ + /* min is 0x00 */ + com_buff[0] = 0x00; + /* feedback: */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0500, 0x4301, &com_buff, 1); + /* volume: */ + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 1, 0x21, 0x0300, 0x4301, &com_buff, 1); + + /* Set soft button hold duration */ + /* 0x03 = 250ms */ + /* 0x05 = 500ms DEFAULT */ + /* 0x08 = 750ms */ + /* 0x0a = 1sec */ + com_buff[0] = 0x05; + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 3, 0x21, 0x0005, 0x2001, &com_buff, 1); + + /* Use dim LEDs for button of state */ + com_buff[0] = 0x00; + snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), + 3, 0x21, 0x0004, 0x2001, &com_buff, 1); +} + +#define MBOX3_DESCRIPTOR_SIZE 464 + +static int snd_usb_mbox3_boot_quirk(struct usb_device *dev) +{ + struct usb_host_config *config = dev->actconfig; + int err; + int descriptor_size; + + descriptor_size = le16_to_cpu(get_cfg_desc(config)->wTotalLength); + + if (descriptor_size != MBOX3_DESCRIPTOR_SIZE) { + dev_err(&dev->dev, "Invalid descriptor size=%d.\n", descriptor_size); + return -ENODEV; + } + + dev_dbg(&dev->dev, "device initialised!\n"); + + err = usb_get_descriptor(dev, USB_DT_DEVICE, 0, + &dev->descriptor, sizeof(dev->descriptor)); + config = dev->actconfig; + if (err < 0) + dev_dbg(&dev->dev, "error usb_get_descriptor: %d\n", err); + + err = usb_reset_configuration(dev); + if (err < 0) + dev_dbg(&dev->dev, "error usb_reset_configuration: %d\n", err); + dev_dbg(&dev->dev, "mbox3_boot: new boot length = %d\n", + le16_to_cpu(get_cfg_desc(config)->wTotalLength)); + + mbox3_setup_48_24_magic(dev); + dev_info(&dev->dev, "Digidesign Mbox 3: 24bit 48kHz"); + + return 0; /* Successful boot */ +} #define MICROBOOK_BUF_SIZE 128 @@ -1324,6 +1622,10 @@ int snd_usb_apply_boot_quirk(struct usb_device *dev, case USB_ID(0x0dba, 0x3000): /* Digidesign Mbox 2 */ return snd_usb_mbox2_boot_quirk(dev); + case USB_ID(0x0dba, 0x5000): + /* Digidesign Mbox 3 */ + return snd_usb_mbox3_boot_quirk(dev); + case USB_ID(0x1235, 0x0010): /* Focusrite Novation Saffire 6 USB */ case USB_ID(0x1235, 0x0018): /* Focusrite Novation Twitch */ @@ -1729,48 +2031,6 @@ void snd_usb_audioformat_attributes_quirk(struct snd_usb_audio *chip, } /* - * registration quirk: - * the registration is skipped if a device matches with the given ID, - * unless the interface reaches to the defined one. This is for delaying - * the registration until the last known interface, so that the card and - * devices appear at the same time. - */ - -struct registration_quirk { - unsigned int usb_id; /* composed via USB_ID() */ - unsigned int interface; /* the interface to trigger register */ -}; - -#define REG_QUIRK_ENTRY(vendor, product, iface) \ - { .usb_id = USB_ID(vendor, product), .interface = (iface) } - -static const struct registration_quirk registration_quirks[] = { - REG_QUIRK_ENTRY(0x0951, 0x16d8, 2), /* Kingston HyperX AMP */ - REG_QUIRK_ENTRY(0x0951, 0x16ed, 2), /* Kingston HyperX Cloud Alpha S */ - REG_QUIRK_ENTRY(0x0951, 0x16ea, 2), /* Kingston HyperX Cloud Flight S */ - REG_QUIRK_ENTRY(0x0ecb, 0x1f46, 2), /* JBL Quantum 600 */ - REG_QUIRK_ENTRY(0x0ecb, 0x1f47, 2), /* JBL Quantum 800 */ - REG_QUIRK_ENTRY(0x0ecb, 0x1f4c, 2), /* JBL Quantum 400 */ - REG_QUIRK_ENTRY(0x0ecb, 0x2039, 2), /* JBL Quantum 400 */ - REG_QUIRK_ENTRY(0x0ecb, 0x203c, 2), /* JBL Quantum 600 */ - REG_QUIRK_ENTRY(0x0ecb, 0x203e, 2), /* JBL Quantum 800 */ - { 0 } /* terminator */ -}; - -/* return true if skipping registration */ -bool snd_usb_registration_quirk(struct snd_usb_audio *chip, int iface) -{ - const struct registration_quirk *q; - - for (q = registration_quirks; q->usb_id; q++) - if (chip->usb_id == q->usb_id) - return iface < q->interface; - - /* Register as normal */ - return false; -} - -/* * driver behavior quirk flags */ struct usb_audio_quirk_flags_table { diff --git a/sound/usb/quirks.h b/sound/usb/quirks.h index 31abb7cb01a5..f9bfd5ac7bab 100644 --- a/sound/usb/quirks.h +++ b/sound/usb/quirks.h @@ -48,8 +48,6 @@ void snd_usb_audioformat_attributes_quirk(struct snd_usb_audio *chip, struct audioformat *fp, int stream); -bool snd_usb_registration_quirk(struct snd_usb_audio *chip, int iface); - void snd_usb_init_quirk_flags(struct snd_usb_audio *chip); #endif /* __USBAUDIO_QUIRKS_H */ diff --git a/sound/usb/stream.c b/sound/usb/stream.c index f10f4e6d3fb8..f75601ca2d52 100644 --- a/sound/usb/stream.c +++ b/sound/usb/stream.c @@ -1222,12 +1222,6 @@ static int __snd_usb_parse_audio_interface(struct snd_usb_audio *chip, if (err < 0) return err; } - - /* try to set the interface... */ - usb_set_interface(chip->dev, iface_no, 0); - snd_usb_init_pitch(chip, fp); - snd_usb_init_sample_rate(chip, fp, fp->rate_max); - usb_set_interface(chip->dev, iface_no, altno); } return 0; } diff --git a/sound/usb/usbaudio.h b/sound/usb/usbaudio.h index ffbb4b0d09a0..2c6575029b1c 100644 --- a/sound/usb/usbaudio.h +++ b/sound/usb/usbaudio.h @@ -37,6 +37,7 @@ struct snd_usb_audio { unsigned int quirk_flags; unsigned int need_delayed_register:1; /* warn for delayed registration */ int num_interfaces; + int last_iface; int num_suspended_intf; int sample_rate_read_error; diff --git a/sound/usb/usx2y/usbusx2yaudio.c b/sound/usb/usx2y/usbusx2yaudio.c index 9cd5e3aae4f7..5197599e7aa6 100644 --- a/sound/usb/usx2y/usbusx2yaudio.c +++ b/sound/usb/usx2y/usbusx2yaudio.c @@ -822,8 +822,7 @@ static int snd_usx2y_pcm_hw_free(struct snd_pcm_substream *substream) usx2y_urbs_release(subs); if (!cap_subs->pcm_substream || !cap_subs->pcm_substream->runtime || - !cap_subs->pcm_substream->runtime->status || - cap_subs->pcm_substream->runtime->status->state < SNDRV_PCM_STATE_PREPARED) { + cap_subs->pcm_substream->runtime->state < SNDRV_PCM_STATE_PREPARED) { atomic_set(&cap_subs->state, STATE_STOPPED); usx2y_urbs_release(cap_subs); } diff --git a/sound/usb/usx2y/usx2yhwdeppcm.c b/sound/usb/usx2y/usx2yhwdeppcm.c index 240349b644f3..767a227d54da 100644 --- a/sound/usb/usx2y/usx2yhwdeppcm.c +++ b/sound/usb/usx2y/usx2yhwdeppcm.c @@ -374,8 +374,7 @@ static int snd_usx2y_usbpcm_hw_free(struct snd_pcm_substream *substream) usx2y_usbpcm_urbs_release(subs); if (!cap_subs->pcm_substream || !cap_subs->pcm_substream->runtime || - !cap_subs->pcm_substream->runtime->status || - cap_subs->pcm_substream->runtime->status->state < SNDRV_PCM_STATE_PREPARED) { + cap_subs->pcm_substream->runtime->state < SNDRV_PCM_STATE_PREPARED) { atomic_set(&cap_subs->state, STATE_STOPPED); if (cap_subs2) atomic_set(&cap_subs2->state, STATE_STOPPED); |