summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Documentation/sound/kernel-api/writing-an-alsa-driver.rst21
-rw-r--r--include/sound/hda_codec.h2
-rw-r--r--include/sound/hda_register.h20
-rw-r--r--include/sound/hdaudio.h10
-rw-r--r--include/sound/hdaudio_ext.h14
-rw-r--r--include/sound/memalloc.h3
-rw-r--r--sound/core/memalloc.c113
-rw-r--r--sound/core/memalloc_local.h4
-rw-r--r--sound/drivers/dummy.c42
-rw-r--r--sound/drivers/vx/vx_pcm.c3
-rw-r--r--sound/hda/ext/hdac_ext_bus.c53
-rw-r--r--sound/hda/ext/hdac_ext_controller.c16
-rw-r--r--sound/hda/ext/hdac_ext_stream.c34
-rw-r--r--sound/hda/hdac_stream.c100
-rw-r--r--sound/isa/es18xx.c5
-rw-r--r--sound/oss/dmasound/dmasound.h3
-rw-r--r--sound/pci/asihpi/hpifunc.c1
-rw-r--r--sound/pci/hda/cs35l41_hda.c57
-rw-r--r--sound/pci/hda/hda_beep.c15
-rw-r--r--sound/pci/hda/hda_beep.h1
-rw-r--r--sound/pci/hda/hda_codec.c49
-rw-r--r--sound/pci/hda/hda_controller.c4
-rw-r--r--sound/pci/hda/hda_intel.c21
-rw-r--r--sound/pci/hda/hda_sysfs.c2
-rw-r--r--sound/pci/hda/patch_hdmi.c32
-rw-r--r--sound/pci/hda/patch_sigmatel.c25
-rw-r--r--sound/pcmcia/pdaudiocf/pdaudiocf_pcm.c3
-rw-r--r--sound/ppc/tumbler.c6
-rw-r--r--sound/soc/codecs/hdac_hda.c26
-rw-r--r--sound/soc/codecs/hdac_hda.h2
-rw-r--r--sound/soc/intel/atom/sst-mfld-platform-pcm.c7
-rw-r--r--sound/soc/intel/avs/core.c4
-rw-r--r--sound/soc/intel/boards/hda_dsp_common.c2
-rw-r--r--sound/soc/intel/boards/skl_hda_dsp_generic.c2
-rw-r--r--sound/soc/intel/skylake/skl.c57
-rw-r--r--sound/soc/sof/intel/hda-codec.c55
-rw-r--r--sound/usb/card.c32
-rw-r--r--sound/usb/line6/driver.h2
-rw-r--r--sound/usb/quirks-table.h76
-rw-r--r--sound/usb/quirks.c344
-rw-r--r--sound/usb/quirks.h2
-rw-r--r--sound/usb/stream.c6
-rw-r--r--sound/usb/usbaudio.h1
43 files changed, 785 insertions, 492 deletions
diff --git a/Documentation/sound/kernel-api/writing-an-alsa-driver.rst b/Documentation/sound/kernel-api/writing-an-alsa-driver.rst
index 176b73583b7a..07a620c5ca74 100644
--- a/Documentation/sound/kernel-api/writing-an-alsa-driver.rst
+++ b/Documentation/sound/kernel-api/writing-an-alsa-driver.rst
@@ -3565,13 +3565,17 @@ given size.
The second argument (type) and the third argument (device pointer) are
dependent on the bus. For normal devices, pass the device pointer
(typically identical as ``card->dev``) to the third argument with
-``SNDRV_DMA_TYPE_DEV`` type. For the continuous buffer unrelated to the
+``SNDRV_DMA_TYPE_DEV`` type.
+
+For the continuous buffer unrelated to the
bus can be pre-allocated with ``SNDRV_DMA_TYPE_CONTINUOUS`` type.
You can pass NULL to the device pointer in that case, which is the
default mode implying to allocate with ``GFP_KERNEL`` flag.
-If you need a different GFP flag, you can pass it by encoding the flag
-into the device pointer via a special macro
-:c:func:`snd_dma_continuous_data()`.
+If you need a restricted (lower) address, set up the coherent DMA mask
+bits for the device, and pass the device pointer, like the normal
+device memory allocations. For this type, it's still allowed to pass
+NULL to the device pointer, too, if no address restriction is needed.
+
For the scatter-gather buffers, use ``SNDRV_DMA_TYPE_DEV_SG`` with the
device pointer (see the `Non-Contiguous Buffers`_ section).
@@ -3811,15 +3815,6 @@ arguments here. Since each vmalloc call should succeed at any time,
we don't need to pre-allocate the buffers like other continuous
pages.
-If you need the 32bit DMA allocation, pass the device pointer encoded
-by :c:func:`snd_dma_continuous_data()` with ``GFP_KERNEL|__GFP_DMA32``
-argument.
-
-::
-
- snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_VMALLOC,
- snd_dma_continuous_data(GFP_KERNEL | __GFP_DMA32), 0, 0);
-
Proc Interface
==============
diff --git a/include/sound/hda_codec.h b/include/sound/hda_codec.h
index 6d3c82c4b6ac..2a8fe7240f10 100644
--- a/include/sound/hda_codec.h
+++ b/include/sound/hda_codec.h
@@ -293,8 +293,6 @@ struct hda_codec {
#define dev_to_hda_codec(_dev) container_of(_dev, struct hda_codec, core.dev)
#define hda_codec_dev(_dev) (&(_dev)->core.dev)
-#define hdac_to_hda_priv(_hdac) \
- container_of(_hdac, struct hdac_hda_priv, codec.core)
#define hdac_to_hda_codec(_hdac) container_of(_hdac, struct hda_codec, core)
#define list_for_each_codec(c, bus) \
diff --git a/include/sound/hda_register.h b/include/sound/hda_register.h
index ad8b71b1dbb6..d37cf43546eb 100644
--- a/include/sound/hda_register.h
+++ b/include/sound/hda_register.h
@@ -260,7 +260,18 @@ enum { SDI0, SDI1, SDI2, SDI3, SDO0, SDO1, SDO2, SDO3 };
#define AZX_REG_ML_LCAP 0x00
#define AZX_REG_ML_LCTL 0x04
+
+#define AZX_ML_LCTL_CPA BIT(23)
+#define AZX_ML_LCTL_CPA_SHIFT 23
+#define AZX_ML_LCTL_SPA BIT(16)
+#define AZX_ML_LCTL_SPA_SHIFT 16
+#define AZX_ML_LCTL_SCF GENMASK(3, 0)
+
#define AZX_REG_ML_LOSIDV 0x08
+
+/* bit0 is reserved, with BIT(1) mapping to stream1 */
+#define AZX_ML_LOSIDV_STREAM_MASK 0xFFFE
+
#define AZX_REG_ML_LSDIID 0x0C
#define AZX_REG_ML_LPSOO 0x10
#define AZX_REG_ML_LPSIO 0x12
@@ -268,15 +279,6 @@ enum { SDI0, SDI1, SDI2, SDI3, SDO0, SDO1, SDO2, SDO3 };
#define AZX_REG_ML_LOUTPAY 0x20
#define AZX_REG_ML_LINPAY 0x30
-/* bit0 is reserved, with BIT(1) mapping to stream1 */
-#define ML_LOSIDV_STREAM_MASK 0xFFFE
-
-#define ML_LCTL_SCF_MASK 0xF
-#define AZX_MLCTL_SPA (0x1 << 16)
-#define AZX_MLCTL_CPA (0x1 << 23)
-#define AZX_MLCTL_SPA_SHIFT 16
-#define AZX_MLCTL_CPA_SHIFT 23
-
/* registers for DMA Resume Capability Structure */
#define AZX_DRSM_CAP_ID 0x5
#define AZX_REG_DRSM_CTL 0x4
diff --git a/include/sound/hdaudio.h b/include/sound/hdaudio.h
index 797bf67a164d..ddff03e546e9 100644
--- a/include/sound/hdaudio.h
+++ b/include/sound/hdaudio.h
@@ -10,6 +10,7 @@
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/io-64-nonatomic-lo-hi.h>
+#include <linux/iopoll.h>
#include <linux/pm_runtime.h>
#include <linux/timecounter.h>
#include <sound/core.h>
@@ -550,6 +551,7 @@ void snd_hdac_stream_init(struct hdac_bus *bus, struct hdac_stream *azx_dev,
int idx, int direction, int tag);
struct hdac_stream *snd_hdac_stream_assign(struct hdac_bus *bus,
struct snd_pcm_substream *substream);
+void snd_hdac_stream_release_locked(struct hdac_stream *azx_dev);
void snd_hdac_stream_release(struct hdac_stream *azx_dev);
struct hdac_stream *snd_hdac_get_stream(struct hdac_bus *bus,
int dir, int stream_tag);
@@ -560,8 +562,8 @@ int snd_hdac_stream_setup_periods(struct hdac_stream *azx_dev);
int snd_hdac_stream_set_params(struct hdac_stream *azx_dev,
unsigned int format_val);
void snd_hdac_stream_start(struct hdac_stream *azx_dev, bool fresh_start);
-void snd_hdac_stream_clear(struct hdac_stream *azx_dev);
void snd_hdac_stream_stop(struct hdac_stream *azx_dev);
+void snd_hdac_stop_streams(struct hdac_bus *bus);
void snd_hdac_stop_streams_and_chip(struct hdac_bus *bus);
void snd_hdac_stream_reset(struct hdac_stream *azx_dev);
void snd_hdac_stream_sync_trigger(struct hdac_stream *azx_dev, bool set,
@@ -589,6 +591,12 @@ int snd_hdac_get_stream_stripe_ctl(struct hdac_bus *bus,
snd_hdac_reg_readw((dev)->bus, (dev)->sd_addr + AZX_REG_ ## reg)
#define snd_hdac_stream_readb(dev, reg) \
snd_hdac_reg_readb((dev)->bus, (dev)->sd_addr + AZX_REG_ ## reg)
+#define snd_hdac_stream_readb_poll(dev, reg, val, cond, delay_us, timeout_us) \
+ readb_poll_timeout((dev)->sd_addr + AZX_REG_ ## reg, val, cond, \
+ delay_us, timeout_us)
+#define snd_hdac_stream_readl_poll(dev, reg, val, cond, delay_us, timeout_us) \
+ readl_poll_timeout((dev)->sd_addr + AZX_REG_ ## reg, val, cond, \
+ delay_us, timeout_us)
/* update a register, pass without AZX_REG_ prefix */
#define snd_hdac_stream_updatel(dev, reg, mask, val) \
diff --git a/include/sound/hdaudio_ext.h b/include/sound/hdaudio_ext.h
index d26234f9ee46..83aed26ab143 100644
--- a/include/sound/hdaudio_ext.h
+++ b/include/sound/hdaudio_ext.h
@@ -11,9 +11,6 @@ int snd_hdac_ext_bus_init(struct hdac_bus *bus, struct device *dev,
const struct hdac_ext_bus_ops *ext_ops);
void snd_hdac_ext_bus_exit(struct hdac_bus *bus);
-int snd_hdac_ext_bus_device_init(struct hdac_bus *bus, int addr,
- struct hdac_device *hdev, int type);
-void snd_hdac_ext_bus_device_exit(struct hdac_device *hdev);
void snd_hdac_ext_bus_device_remove(struct hdac_bus *bus);
#define HDA_CODEC_REV_EXT_ENTRY(_vid, _rev, _name, drv_data) \
@@ -80,12 +77,9 @@ struct hdac_ext_stream {
#define stream_to_hdac_ext_stream(s) \
container_of(s, struct hdac_ext_stream, hstream)
-void snd_hdac_ext_stream_init(struct hdac_bus *bus,
- struct hdac_ext_stream *hext_stream, int idx,
- int direction, int tag);
int snd_hdac_ext_stream_init_all(struct hdac_bus *bus, int start_idx,
int num_stream, int dir);
-void snd_hdac_stream_free_all(struct hdac_bus *bus);
+void snd_hdac_ext_stream_free_all(struct hdac_bus *bus);
void snd_hdac_link_free_all(struct hdac_bus *bus);
struct hdac_ext_stream *snd_hdac_ext_stream_assign(struct hdac_bus *bus,
struct snd_pcm_substream *substream,
@@ -188,12 +182,6 @@ void snd_hdac_ext_bus_link_power(struct hdac_device *codec, bool enable);
#define snd_hdac_adsp_readq_poll(chip, reg, val, cond, delay_us, timeout_us) \
readq_poll_timeout((chip)->dsp_ba + (reg), val, cond, \
delay_us, timeout_us)
-#define snd_hdac_stream_readb_poll(strm, reg, val, cond, delay_us, timeout_us) \
- readb_poll_timeout((strm)->sd_addr + AZX_REG_ ## reg, val, cond, \
- delay_us, timeout_us)
-#define snd_hdac_stream_readl_poll(strm, reg, val, cond, delay_us, timeout_us) \
- readl_poll_timeout((strm)->sd_addr + AZX_REG_ ## reg, val, cond, \
- delay_us, timeout_us)
struct hdac_ext_device;
diff --git a/include/sound/memalloc.h b/include/sound/memalloc.h
index 8d79cebf95f3..43d524580bd2 100644
--- a/include/sound/memalloc.h
+++ b/include/sound/memalloc.h
@@ -26,9 +26,6 @@ struct snd_dma_device {
struct device *dev; /* generic device */
};
-#define snd_dma_continuous_data(x) ((struct device *)(__force unsigned long)(x))
-
-
/*
* buffer types
*/
diff --git a/sound/core/memalloc.c b/sound/core/memalloc.c
index cfcd8eff4139..2c11413bea61 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_NORETRY | /* 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/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/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/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/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/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/hda/cs35l41_hda.c b/sound/pci/hda/cs35l41_hda.c
index 15e2a0009080..3952f2853703 100644
--- a/sound/pci/hda/cs35l41_hda.c
+++ b/sound/pci/hda/cs35l41_hda.c
@@ -842,8 +842,8 @@ static int cs35l41_hda_bind(struct device *dev, struct device *master, void *mas
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));
@@ -1048,36 +1048,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 +1124,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 +1152,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 +1166,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 +1265,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 +1404,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,6 +1427,7 @@ 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);
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_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_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_intel.c b/sound/pci/hda/hda_intel.c
index 6f30c374f896..2a93bc64c2d8 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);
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_hdmi.c b/sound/pci/hda/patch_hdmi.c
index c239d9dbbaef..1eb894e6cdf1 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;
@@ -231,7 +232,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);
};
/*
@@ -988,7 +989,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;
@@ -1003,6 +1005,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;
@@ -1013,7 +1018,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;
@@ -1199,12 +1204,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);
@@ -1267,18 +1272,17 @@ static int hdmi_pcm_open(struct hda_pcm_stream *hinfo,
}
}
- 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);
per_pin->cvt_nid = per_cvt->cvt_nid;
- per_pin->silent_stream = false;
hinfo->nid = per_cvt->cvt_nid;
/* flip stripe flag for the assigned stream if supported */
@@ -1308,7 +1312,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;
@@ -1760,14 +1764,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;
@@ -1827,7 +1831,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) {
@@ -2223,7 +2227,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;
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/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/hdac_hda.c b/sound/soc/codecs/hdac_hda.c
index 8debcee59224..77df4c5b274a 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;
@@ -515,8 +515,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 +584,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 +594,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 +603,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/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/skylake/skl.c b/sound/soc/intel/skylake/skl.c
index aeca58246fc7..0122926f9c58 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
*/
@@ -697,12 +726,11 @@ static int probe_codec(struct hdac_bus *bus, int addr)
unsigned int cmd = (addr << 28) | (AC_NODE_ROOT << 20) |
(AC_VERB_PARAMETERS << 8) | AC_PAR_VENDOR_ID;
unsigned int res = -1;
- struct skl_dev *skl = bus_to_skl(bus);
#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/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/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/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;