summaryrefslogtreecommitdiffstats
path: root/sound
diff options
context:
space:
mode:
Diffstat (limited to 'sound')
-rw-r--r--sound/Kconfig4
-rw-r--r--sound/aoa/codecs/tas.c14
-rw-r--r--sound/aoa/fabrics/layout.c8
-rw-r--r--sound/atmel/Kconfig13
-rw-r--r--sound/atmel/Makefile2
-rw-r--r--sound/atmel/abdac.c610
-rw-r--r--sound/atmel/ac97c.c447
-rw-r--r--sound/core/control.c70
-rw-r--r--sound/core/ctljack.c2
-rw-r--r--sound/core/info.c6
-rw-r--r--sound/core/oss/io.c4
-rw-r--r--sound/core/oss/pcm_oss.c101
-rw-r--r--sound/core/oss/pcm_plugin.c5
-rw-r--r--sound/core/oss/pcm_plugin.h10
-rw-r--r--sound/core/pcm.c35
-rw-r--r--sound/core/pcm_compat.c12
-rw-r--r--sound/core/pcm_drm_eld.c8
-rw-r--r--sound/core/pcm_lib.c574
-rw-r--r--sound/core/pcm_local.h51
-rw-r--r--sound/core/pcm_misc.c3
-rw-r--r--sound/core/pcm_native.c408
-rw-r--r--sound/core/pcm_timer.c14
-rw-r--r--sound/drivers/dummy.c20
-rw-r--r--sound/drivers/opl3/opl3_oss.c14
-rw-r--r--sound/drivers/opl4/opl4_lib.c4
-rw-r--r--sound/drivers/opl4/opl4_local.h2
-rw-r--r--sound/drivers/vx/vx_mixer.c24
-rw-r--r--sound/firewire/amdtp-am824.c71
-rw-r--r--sound/firewire/amdtp-am824.h6
-rw-r--r--sound/firewire/amdtp-stream.c19
-rw-r--r--sound/firewire/amdtp-stream.h1
-rw-r--r--sound/firewire/bebob/bebob_maudio.c8
-rw-r--r--sound/firewire/bebob/bebob_pcm.c20
-rw-r--r--sound/firewire/dice/dice-pcm.c24
-rw-r--r--sound/firewire/digi00x/amdtp-dot.c63
-rw-r--r--sound/firewire/digi00x/digi00x-pcm.c23
-rw-r--r--sound/firewire/digi00x/digi00x.h1
-rw-r--r--sound/firewire/fireface/ff-midi.c22
-rw-r--r--sound/firewire/fireface/ff-pcm.c62
-rw-r--r--sound/firewire/fireworks/fireworks_pcm.c20
-rw-r--r--sound/firewire/motu/motu-pcm.c16
-rw-r--r--sound/firewire/oxfw/oxfw-pcm.c20
-rw-r--r--sound/firewire/tascam/amdtp-tascam.c62
-rw-r--r--sound/firewire/tascam/tascam-pcm.c23
-rw-r--r--sound/firewire/tascam/tascam.h1
-rw-r--r--sound/i2c/other/ak4113.c23
-rw-r--r--sound/i2c/other/ak4114.c23
-rw-r--r--sound/i2c/other/ak4117.c23
-rw-r--r--sound/isa/cmi8328.c2
-rw-r--r--sound/isa/gus/gus_main.c2
-rw-r--r--sound/isa/gus/gus_pcm.c118
-rw-r--r--sound/isa/sb/emu8000.c2
-rw-r--r--sound/isa/sb/emu8000_pcm.c214
-rw-r--r--sound/isa/sb/sb16.c2
-rw-r--r--sound/isa/sb/sb16_csp.c4
-rw-r--r--sound/isa/sb/sb16_main.c2
-rw-r--r--sound/isa/sscape.c2
-rw-r--r--sound/mips/hal2.c18
-rw-r--r--sound/mips/sgio2audio.c14
-rw-r--r--sound/pci/cs4281.c2
-rw-r--r--sound/pci/cs46xx/cs46xx_lib.c10
-rw-r--r--sound/pci/emu10k1/emufx.c127
-rw-r--r--sound/pci/emu10k1/emupcm.c4
-rw-r--r--sound/pci/es1938.c33
-rw-r--r--sound/pci/hda/hda_codec.c251
-rw-r--r--sound/pci/hda/hda_generic.c46
-rw-r--r--sound/pci/hda/hda_local.h61
-rw-r--r--sound/pci/hda/patch_realtek.c37
-rw-r--r--sound/pci/ice1712/ice1712.c6
-rw-r--r--sound/pci/ice1712/ice1724.c2
-rw-r--r--sound/pci/korg1212/korg1212.c112
-rw-r--r--sound/pci/mixart/mixart_mixer.c6
-rw-r--r--sound/pci/nm256/nm256.c57
-rw-r--r--sound/pci/rme32.c75
-rw-r--r--sound/pci/rme96.c70
-rw-r--r--sound/pci/rme9652/hdsp.c67
-rw-r--r--sound/pci/rme9652/rme9652.c71
-rw-r--r--sound/pci/vx222/vx222.c4
-rw-r--r--sound/pci/vx222/vx222.h2
-rw-r--r--sound/pci/vx222/vx222_ops.c26
-rw-r--r--sound/pcmcia/vx/vxp_mixer.c14
-rw-r--r--sound/pcmcia/vx/vxp_ops.c28
-rw-r--r--sound/pcmcia/vx/vxpocket.c4
-rw-r--r--sound/pcmcia/vx/vxpocket.h2
-rw-r--r--sound/ppc/awacs.c4
-rw-r--r--sound/ppc/beep.c2
-rw-r--r--sound/ppc/tumbler.c8
-rw-r--r--sound/sh/aica.c4
-rw-r--r--sound/sh/sh_dac_audio.c54
-rw-r--r--sound/soc/blackfin/bf5xx-ac97-pcm.c27
-rw-r--r--sound/soc/blackfin/bf5xx-i2s-pcm.c36
-rw-r--r--sound/soc/sh/siu_dai.c4
-rw-r--r--sound/soc/soc-pcm.c5
-rw-r--r--sound/usb/Kconfig2
-rw-r--r--sound/usb/mixer_quirks.c2
-rw-r--r--sound/usb/usx2y/us122l.c36
-rw-r--r--sound/usb/usx2y/us122l.h2
97 files changed, 1767 insertions, 2912 deletions
diff --git a/sound/Kconfig b/sound/Kconfig
index 6a215a8..d2fadbe 100644
--- a/sound/Kconfig
+++ b/sound/Kconfig
@@ -56,7 +56,7 @@ config SOUND_OSS_CORE_PRECLAIM
source "sound/oss/dmasound/Kconfig"
-if !M68K && !UML
+if !UML
menuconfig SND
tristate "Advanced Linux Sound Architecture"
@@ -125,7 +125,7 @@ source "sound/oss/Kconfig"
endif # SOUND_PRIME
-endif # !M68K
+endif # !UML
endif # SOUND
diff --git a/sound/aoa/codecs/tas.c b/sound/aoa/codecs/tas.c
index 78ed1ff..733b636 100644
--- a/sound/aoa/codecs/tas.c
+++ b/sound/aoa/codecs/tas.c
@@ -271,7 +271,7 @@ static int tas_snd_vol_put(struct snd_kcontrol *kcontrol,
return 1;
}
-static struct snd_kcontrol_new volume_control = {
+static const struct snd_kcontrol_new volume_control = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Master Playback Volume",
.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
@@ -314,7 +314,7 @@ static int tas_snd_mute_put(struct snd_kcontrol *kcontrol,
return 1;
}
-static struct snd_kcontrol_new mute_control = {
+static const struct snd_kcontrol_new mute_control = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Master Playback Switch",
.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
@@ -426,7 +426,7 @@ static int tas_snd_drc_range_put(struct snd_kcontrol *kcontrol,
return 1;
}
-static struct snd_kcontrol_new drc_range_control = {
+static const struct snd_kcontrol_new drc_range_control = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "DRC Range",
.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
@@ -466,7 +466,7 @@ static int tas_snd_drc_switch_put(struct snd_kcontrol *kcontrol,
return 1;
}
-static struct snd_kcontrol_new drc_switch_control = {
+static const struct snd_kcontrol_new drc_switch_control = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "DRC Range Switch",
.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
@@ -524,7 +524,7 @@ static int tas_snd_capture_source_put(struct snd_kcontrol *kcontrol,
return 1;
}
-static struct snd_kcontrol_new capture_source_control = {
+static const struct snd_kcontrol_new capture_source_control = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
/* If we name this 'Input Source', it properly shows up in
* alsamixer as a selection, * but it's shown under the
@@ -586,7 +586,7 @@ static int tas_snd_treble_put(struct snd_kcontrol *kcontrol,
return 1;
}
-static struct snd_kcontrol_new treble_control = {
+static const struct snd_kcontrol_new treble_control = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Treble",
.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
@@ -637,7 +637,7 @@ static int tas_snd_bass_put(struct snd_kcontrol *kcontrol,
return 1;
}
-static struct snd_kcontrol_new bass_control = {
+static const struct snd_kcontrol_new bass_control = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Bass",
.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
diff --git a/sound/aoa/fabrics/layout.c b/sound/aoa/fabrics/layout.c
index a0c4a5d..1eddf8f 100644
--- a/sound/aoa/fabrics/layout.c
+++ b/sound/aoa/fabrics/layout.c
@@ -707,7 +707,7 @@ static int detect_choice_put(struct snd_kcontrol *kcontrol,
return 1;
}
-static struct snd_kcontrol_new headphone_detect_choice = {
+static const struct snd_kcontrol_new headphone_detect_choice = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Headphone Detect Autoswitch",
.info = control_info,
@@ -717,7 +717,7 @@ static struct snd_kcontrol_new headphone_detect_choice = {
.private_value = 0,
};
-static struct snd_kcontrol_new lineout_detect_choice = {
+static const struct snd_kcontrol_new lineout_detect_choice = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Line-Out Detect Autoswitch",
.info = control_info,
@@ -749,7 +749,7 @@ static int detected_get(struct snd_kcontrol *kcontrol,
return 0;
}
-static struct snd_kcontrol_new headphone_detected = {
+static const struct snd_kcontrol_new headphone_detected = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Headphone Detected",
.info = control_info,
@@ -758,7 +758,7 @@ static struct snd_kcontrol_new headphone_detected = {
.private_value = 0,
};
-static struct snd_kcontrol_new lineout_detected = {
+static const struct snd_kcontrol_new lineout_detected = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Line-Out Detected",
.info = control_info,
diff --git a/sound/atmel/Kconfig b/sound/atmel/Kconfig
index 94de43a..d789cbc 100644
--- a/sound/atmel/Kconfig
+++ b/sound/atmel/Kconfig
@@ -1,18 +1,11 @@
-menu "Atmel devices (AVR32 and AT91)"
- depends on AVR32 || ARCH_AT91
-
-config SND_ATMEL_ABDAC
- tristate "Atmel Audio Bitstream DAC (ABDAC) driver"
- select SND_PCM
- depends on DW_DMAC && AVR32
- help
- ALSA sound driver for the Atmel Audio Bitstream DAC (ABDAC).
+menu "Atmel devices (AT91)"
+ depends on ARCH_AT91
config SND_ATMEL_AC97C
tristate "Atmel AC97 Controller (AC97C) driver"
select SND_PCM
select SND_AC97_CODEC
- depends on (DW_DMAC && AVR32) || ARCH_AT91
+ depends on ARCH_AT91
help
ALSA sound driver for the Atmel AC97 controller.
diff --git a/sound/atmel/Makefile b/sound/atmel/Makefile
index 219dcfa..d4009d1 100644
--- a/sound/atmel/Makefile
+++ b/sound/atmel/Makefile
@@ -1,5 +1,3 @@
-snd-atmel-abdac-objs := abdac.o
snd-atmel-ac97c-objs := ac97c.o
-obj-$(CONFIG_SND_ATMEL_ABDAC) += snd-atmel-abdac.o
obj-$(CONFIG_SND_ATMEL_AC97C) += snd-atmel-ac97c.o
diff --git a/sound/atmel/abdac.c b/sound/atmel/abdac.c
deleted file mode 100644
index 5586188..0000000
--- a/sound/atmel/abdac.c
+++ /dev/null
@@ -1,610 +0,0 @@
-/*
- * Driver for the Atmel on-chip Audio Bitstream DAC (ABDAC)
- *
- * Copyright (C) 2006-2009 Atmel Corporation
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 as published by
- * the Free Software Foundation.
- */
-#include <linux/clk.h>
-#include <linux/bitmap.h>
-#include <linux/dmaengine.h>
-#include <linux/dma-mapping.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/types.h>
-#include <linux/io.h>
-
-#include <sound/core.h>
-#include <sound/initval.h>
-#include <sound/pcm.h>
-#include <sound/pcm_params.h>
-#include <sound/atmel-abdac.h>
-
-#include <linux/platform_data/dma-dw.h>
-#include <linux/dma/dw.h>
-
-/* DAC register offsets */
-#define DAC_DATA 0x0000
-#define DAC_CTRL 0x0008
-#define DAC_INT_MASK 0x000c
-#define DAC_INT_EN 0x0010
-#define DAC_INT_DIS 0x0014
-#define DAC_INT_CLR 0x0018
-#define DAC_INT_STATUS 0x001c
-
-/* Bitfields in CTRL */
-#define DAC_SWAP_OFFSET 30
-#define DAC_SWAP_SIZE 1
-#define DAC_EN_OFFSET 31
-#define DAC_EN_SIZE 1
-
-/* Bitfields in INT_MASK/INT_EN/INT_DIS/INT_STATUS/INT_CLR */
-#define DAC_UNDERRUN_OFFSET 28
-#define DAC_UNDERRUN_SIZE 1
-#define DAC_TX_READY_OFFSET 29
-#define DAC_TX_READY_SIZE 1
-
-/* Bit manipulation macros */
-#define DAC_BIT(name) \
- (1 << DAC_##name##_OFFSET)
-#define DAC_BF(name, value) \
- (((value) & ((1 << DAC_##name##_SIZE) - 1)) \
- << DAC_##name##_OFFSET)
-#define DAC_BFEXT(name, value) \
- (((value) >> DAC_##name##_OFFSET) \
- & ((1 << DAC_##name##_SIZE) - 1))
-#define DAC_BFINS(name, value, old) \
- (((old) & ~(((1 << DAC_##name##_SIZE) - 1) \
- << DAC_##name##_OFFSET)) \
- | DAC_BF(name, value))
-
-/* Register access macros */
-#define dac_readl(port, reg) \
- __raw_readl((port)->regs + DAC_##reg)
-#define dac_writel(port, reg, value) \
- __raw_writel((value), (port)->regs + DAC_##reg)
-
-/*
- * ABDAC supports a maximum of 6 different rates from a generic clock. The
- * generic clock has a power of two divider, which gives 6 steps from 192 kHz
- * to 5112 Hz.
- */
-#define MAX_NUM_RATES 6
-/* ALSA seems to use rates between 192000 Hz and 5112 Hz. */
-#define RATE_MAX 192000
-#define RATE_MIN 5112
-
-enum {
- DMA_READY = 0,
-};
-
-struct atmel_abdac_dma {
- struct dma_chan *chan;
- struct dw_cyclic_desc *cdesc;
-};
-
-struct atmel_abdac {
- struct clk *pclk;
- struct clk *sample_clk;
- struct platform_device *pdev;
- struct atmel_abdac_dma dma;
-
- struct snd_pcm_hw_constraint_list constraints_rates;
- struct snd_pcm_substream *substream;
- struct snd_card *card;
- struct snd_pcm *pcm;
-
- void __iomem *regs;
- unsigned long flags;
- unsigned int rates[MAX_NUM_RATES];
- unsigned int rates_num;
- int irq;
-};
-
-#define get_dac(card) ((struct atmel_abdac *)(card)->private_data)
-
-/* This function is called by the DMA driver. */
-static void atmel_abdac_dma_period_done(void *arg)
-{
- struct atmel_abdac *dac = arg;
- snd_pcm_period_elapsed(dac->substream);
-}
-
-static int atmel_abdac_prepare_dma(struct atmel_abdac *dac,
- struct snd_pcm_substream *substream,
- enum dma_data_direction direction)
-{
- struct dma_chan *chan = dac->dma.chan;
- struct dw_cyclic_desc *cdesc;
- struct snd_pcm_runtime *runtime = substream->runtime;
- unsigned long buffer_len, period_len;
-
- /*
- * We don't do DMA on "complex" transfers, i.e. with
- * non-halfword-aligned buffers or lengths.
- */
- if (runtime->dma_addr & 1 || runtime->buffer_size & 1) {
- dev_dbg(&dac->pdev->dev, "too complex transfer\n");
- return -EINVAL;
- }
-
- buffer_len = frames_to_bytes(runtime, runtime->buffer_size);
- period_len = frames_to_bytes(runtime, runtime->period_size);
-
- cdesc = dw_dma_cyclic_prep(chan, runtime->dma_addr, buffer_len,
- period_len, DMA_MEM_TO_DEV);
- if (IS_ERR(cdesc)) {
- dev_dbg(&dac->pdev->dev, "could not prepare cyclic DMA\n");
- return PTR_ERR(cdesc);
- }
-
- cdesc->period_callback = atmel_abdac_dma_period_done;
- cdesc->period_callback_param = dac;
-
- dac->dma.cdesc = cdesc;
-
- set_bit(DMA_READY, &dac->flags);
-
- return 0;
-}
-
-static struct snd_pcm_hardware atmel_abdac_hw = {
- .info = (SNDRV_PCM_INFO_MMAP
- | SNDRV_PCM_INFO_MMAP_VALID
- | SNDRV_PCM_INFO_INTERLEAVED
- | SNDRV_PCM_INFO_BLOCK_TRANSFER
- | SNDRV_PCM_INFO_RESUME
- | SNDRV_PCM_INFO_PAUSE),
- .formats = (SNDRV_PCM_FMTBIT_S16_BE),
- .rates = (SNDRV_PCM_RATE_KNOT),
- .rate_min = RATE_MIN,
- .rate_max = RATE_MAX,
- .channels_min = 2,
- .channels_max = 2,
- .buffer_bytes_max = 64 * 4096,
- .period_bytes_min = 4096,
- .period_bytes_max = 4096,
- .periods_min = 6,
- .periods_max = 64,
-};
-
-static int atmel_abdac_open(struct snd_pcm_substream *substream)
-{
- struct atmel_abdac *dac = snd_pcm_substream_chip(substream);
-
- dac->substream = substream;
- atmel_abdac_hw.rate_max = dac->rates[dac->rates_num - 1];
- atmel_abdac_hw.rate_min = dac->rates[0];
- substream->runtime->hw = atmel_abdac_hw;
-
- return snd_pcm_hw_constraint_list(substream->runtime, 0,
- SNDRV_PCM_HW_PARAM_RATE, &dac->constraints_rates);
-}
-
-static int atmel_abdac_close(struct snd_pcm_substream *substream)
-{
- struct atmel_abdac *dac = snd_pcm_substream_chip(substream);
- dac->substream = NULL;
- return 0;
-}
-
-static int atmel_abdac_hw_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *hw_params)
-{
- struct atmel_abdac *dac = snd_pcm_substream_chip(substream);
- int retval;
-
- retval = snd_pcm_lib_malloc_pages(substream,
- params_buffer_bytes(hw_params));
- if (retval < 0)
- return retval;
- /* snd_pcm_lib_malloc_pages returns 1 if buffer is changed. */
- if (retval == 1)
- if (test_and_clear_bit(DMA_READY, &dac->flags))
- dw_dma_cyclic_free(dac->dma.chan);
-
- return retval;
-}
-
-static int atmel_abdac_hw_free(struct snd_pcm_substream *substream)
-{
- struct atmel_abdac *dac = snd_pcm_substream_chip(substream);
- if (test_and_clear_bit(DMA_READY, &dac->flags))
- dw_dma_cyclic_free(dac->dma.chan);
- return snd_pcm_lib_free_pages(substream);
-}
-
-static int atmel_abdac_prepare(struct snd_pcm_substream *substream)
-{
- struct atmel_abdac *dac = snd_pcm_substream_chip(substream);
- int retval;
-
- retval = clk_set_rate(dac->sample_clk, 256 * substream->runtime->rate);
- if (retval)
- return retval;
-
- if (!test_bit(DMA_READY, &dac->flags))
- retval = atmel_abdac_prepare_dma(dac, substream, DMA_TO_DEVICE);
-
- return retval;
-}
-
-static int atmel_abdac_trigger(struct snd_pcm_substream *substream, int cmd)
-{
- struct atmel_abdac *dac = snd_pcm_substream_chip(substream);
- int retval = 0;
-
- switch (cmd) {
- case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: /* fall through */
- case SNDRV_PCM_TRIGGER_RESUME: /* fall through */
- case SNDRV_PCM_TRIGGER_START:
- clk_prepare_enable(dac->sample_clk);
- retval = dw_dma_cyclic_start(dac->dma.chan);
- if (retval)
- goto out;
- dac_writel(dac, CTRL, DAC_BIT(EN));
- break;
- case SNDRV_PCM_TRIGGER_PAUSE_PUSH: /* fall through */
- case SNDRV_PCM_TRIGGER_SUSPEND: /* fall through */
- case SNDRV_PCM_TRIGGER_STOP:
- dw_dma_cyclic_stop(dac->dma.chan);
- dac_writel(dac, DATA, 0);
- dac_writel(dac, CTRL, 0);
- clk_disable_unprepare(dac->sample_clk);
- break;
- default:
- retval = -EINVAL;
- break;
- }
-out:
- return retval;
-}
-
-static snd_pcm_uframes_t
-atmel_abdac_pointer(struct snd_pcm_substream *substream)
-{
- struct atmel_abdac *dac = snd_pcm_substream_chip(substream);
- struct snd_pcm_runtime *runtime = substream->runtime;
- snd_pcm_uframes_t frames;
- unsigned long bytes;
-
- bytes = dw_dma_get_src_addr(dac->dma.chan);
- bytes -= runtime->dma_addr;
-
- frames = bytes_to_frames(runtime, bytes);
- if (frames >= runtime->buffer_size)
- frames -= runtime->buffer_size;
-
- return frames;
-}
-
-static irqreturn_t abdac_interrupt(int irq, void *dev_id)
-{
- struct atmel_abdac *dac = dev_id;
- u32 status;
-
- status = dac_readl(dac, INT_STATUS);
- if (status & DAC_BIT(UNDERRUN)) {
- dev_err(&dac->pdev->dev, "underrun detected\n");
- dac_writel(dac, INT_CLR, DAC_BIT(UNDERRUN));
- } else {
- dev_err(&dac->pdev->dev, "spurious interrupt (status=0x%x)\n",
- status);
- dac_writel(dac, INT_CLR, status);
- }
-
- return IRQ_HANDLED;
-}
-
-static struct snd_pcm_ops atmel_abdac_ops = {
- .open = atmel_abdac_open,
- .close = atmel_abdac_close,
- .ioctl = snd_pcm_lib_ioctl,
- .hw_params = atmel_abdac_hw_params,
- .hw_free = atmel_abdac_hw_free,
- .prepare = atmel_abdac_prepare,
- .trigger = atmel_abdac_trigger,
- .pointer = atmel_abdac_pointer,
-};
-
-static int atmel_abdac_pcm_new(struct atmel_abdac *dac)
-{
- struct snd_pcm_hardware hw = atmel_abdac_hw;
- struct snd_pcm *pcm;
- int retval;
-
- retval = snd_pcm_new(dac->card, dac->card->shortname,
- dac->pdev->id, 1, 0, &pcm);
- if (retval)
- return retval;
-
- strcpy(pcm->name, dac->card->shortname);
- pcm->private_data = dac;
- pcm->info_flags = 0;
- dac->pcm = pcm;
-
- snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &atmel_abdac_ops);
-
- retval = snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
- &dac->pdev->dev, hw.periods_min * hw.period_bytes_min,
- hw.buffer_bytes_max);
-
- return retval;
-}
-
-static bool filter(struct dma_chan *chan, void *slave)
-{
- struct dw_dma_slave *dws = slave;
-
- if (dws->dma_dev == chan->device->dev) {
- chan->private = dws;
- return true;
- } else
- return false;
-}
-
-static int set_sample_rates(struct atmel_abdac *dac)
-{
- long new_rate = RATE_MAX;
- int retval = -EINVAL;
- int index = 0;
-
- /* we start at 192 kHz and work our way down to 5112 Hz */
- while (new_rate >= RATE_MIN && index < (MAX_NUM_RATES + 1)) {
- new_rate = clk_round_rate(dac->sample_clk, 256 * new_rate);
- if (new_rate <= 0)
- break;
- /* make sure we are below the ABDAC clock */
- if (index < MAX_NUM_RATES &&
- new_rate <= clk_get_rate(dac->pclk)) {
- dac->rates[index] = new_rate / 256;
- index++;
- }
- /* divide by 256 and then by two to get next rate */
- new_rate /= 256 * 2;
- }
-
- if (index) {
- int i;
-
- /* reverse array, smallest go first */
- for (i = 0; i < (index / 2); i++) {
- unsigned int tmp = dac->rates[index - 1 - i];
- dac->rates[index - 1 - i] = dac->rates[i];
- dac->rates[i] = tmp;
- }
-
- dac->constraints_rates.count = index;
- dac->constraints_rates.list = dac->rates;
- dac->constraints_rates.mask = 0;
- dac->rates_num = index;
-
- retval = 0;
- }
-
- return retval;
-}
-
-static int atmel_abdac_probe(struct platform_device *pdev)
-{
- struct snd_card *card;
- struct atmel_abdac *dac;
- struct resource *regs;
- struct atmel_abdac_pdata *pdata;
- struct clk *pclk;
- struct clk *sample_clk;
- int retval;
- int irq;
-
- regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (!regs) {
- dev_dbg(&pdev->dev, "no memory resource\n");
- return -ENXIO;
- }
-
- irq = platform_get_irq(pdev, 0);
- if (irq < 0) {
- dev_dbg(&pdev->dev, "could not get IRQ number\n");
- return irq;
- }
-
- pdata = pdev->dev.platform_data;
- if (!pdata) {
- dev_dbg(&pdev->dev, "no platform data\n");
- return -ENXIO;
- }
-
- pclk = clk_get(&pdev->dev, "pclk");
- if (IS_ERR(pclk)) {
- dev_dbg(&pdev->dev, "no peripheral clock\n");
- return PTR_ERR(pclk);
- }
- sample_clk = clk_get(&pdev->dev, "sample_clk");
- if (IS_ERR(sample_clk)) {
- dev_dbg(&pdev->dev, "no sample clock\n");
- retval = PTR_ERR(sample_clk);
- goto out_put_pclk;
- }
- clk_prepare_enable(pclk);
-
- retval = snd_card_new(&pdev->dev, SNDRV_DEFAULT_IDX1,
- SNDRV_DEFAULT_STR1, THIS_MODULE,
- sizeof(struct atmel_abdac), &card);
- if (retval) {
- dev_dbg(&pdev->dev, "could not create sound card device\n");
- goto out_put_sample_clk;
- }
-
- dac = get_dac(card);
-
- dac->irq = irq;
- dac->card = card;
- dac->pclk = pclk;
- dac->sample_clk = sample_clk;
- dac->pdev = pdev;
-
- retval = set_sample_rates(dac);
- if (retval < 0) {
- dev_dbg(&pdev->dev, "could not set supported rates\n");
- goto out_free_card;
- }
-
- dac->regs = ioremap(regs->start, resource_size(regs));
- if (!dac->regs) {
- dev_dbg(&pdev->dev, "could not remap register memory\n");
- retval = -ENOMEM;
- goto out_free_card;
- }
-
- /* make sure the DAC is silent and disabled */
- dac_writel(dac, DATA, 0);
- dac_writel(dac, CTRL, 0);
-
- retval = request_irq(irq, abdac_interrupt, 0, "abdac", dac);
- if (retval) {
- dev_dbg(&pdev->dev, "could not request irq\n");
- goto out_unmap_regs;
- }
-
- if (pdata->dws.dma_dev) {
- dma_cap_mask_t mask;
-
- dma_cap_zero(mask);
- dma_cap_set(DMA_SLAVE, mask);
-
- dac->dma.chan = dma_request_channel(mask, filter, &pdata->dws);
- if (dac->dma.chan) {
- struct dma_slave_config dma_conf = {
- .dst_addr = regs->start + DAC_DATA,
- .dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES,
- .src_maxburst = 1,
- .dst_maxburst = 1,
- .direction = DMA_MEM_TO_DEV,
- .device_fc = false,
- };
-
- dmaengine_slave_config(dac->dma.chan, &dma_conf);
- }
- }
- if (!pdata->dws.dma_dev || !dac->dma.chan) {
- dev_dbg(&pdev->dev, "DMA not available\n");
- retval = -ENODEV;
- goto out_unmap_regs;
- }
-
- strcpy(card->driver, "Atmel ABDAC");
- strcpy(card->shortname, "Atmel ABDAC");
- sprintf(card->longname, "Atmel Audio Bitstream DAC");
-
- retval = atmel_abdac_pcm_new(dac);
- if (retval) {
- dev_dbg(&pdev->dev, "could not register ABDAC pcm device\n");
- goto out_release_dma;
- }
-
- retval = snd_card_register(card);
- if (retval) {
- dev_dbg(&pdev->dev, "could not register sound card\n");
- goto out_release_dma;
- }
-
- platform_set_drvdata(pdev, card);
-
- dev_info(&pdev->dev, "Atmel ABDAC at 0x%p using %s\n",
- dac->regs, dev_name(&dac->dma.chan->dev->device));
-
- return retval;
-
-out_release_dma:
- dma_release_channel(dac->dma.chan);
- dac->dma.chan = NULL;
-out_unmap_regs:
- iounmap(dac->regs);
-out_free_card:
- snd_card_free(card);
-out_put_sample_clk:
- clk_put(sample_clk);
- clk_disable_unprepare(pclk);
-out_put_pclk:
- clk_put(pclk);
- return retval;
-}
-
-#ifdef CONFIG_PM_SLEEP
-static int atmel_abdac_suspend(struct device *pdev)
-{
- struct snd_card *card = dev_get_drvdata(pdev);
- struct atmel_abdac *dac = card->private_data;
-
- dw_dma_cyclic_stop(dac->dma.chan);
- clk_disable_unprepare(dac->sample_clk);
- clk_disable_unprepare(dac->pclk);
-
- return 0;
-}
-
-static int atmel_abdac_resume(struct device *pdev)
-{
- struct snd_card *card = dev_get_drvdata(pdev);
- struct atmel_abdac *dac = card->private_data;
-
- clk_prepare_enable(dac->pclk);
- clk_prepare_enable(dac->sample_clk);
- if (test_bit(DMA_READY, &dac->flags))
- dw_dma_cyclic_start(dac->dma.chan);
-
- return 0;
-}
-
-static SIMPLE_DEV_PM_OPS(atmel_abdac_pm, atmel_abdac_suspend, atmel_abdac_resume);
-#define ATMEL_ABDAC_PM_OPS &atmel_abdac_pm
-#else
-#define ATMEL_ABDAC_PM_OPS NULL
-#endif
-
-static int atmel_abdac_remove(struct platform_device *pdev)
-{
- struct snd_card *card = platform_get_drvdata(pdev);
- struct atmel_abdac *dac = get_dac(card);
-
- clk_put(dac->sample_clk);
- clk_disable_unprepare(dac->pclk);
- clk_put(dac->pclk);
-
- dma_release_channel(dac->dma.chan);
- dac->dma.chan = NULL;
- iounmap(dac->regs);
- free_irq(dac->irq, dac);
- snd_card_free(card);
-
- return 0;
-}
-
-static struct platform_driver atmel_abdac_driver = {
- .remove = atmel_abdac_remove,
- .driver = {
- .name = "atmel_abdac",
- .pm = ATMEL_ABDAC_PM_OPS,
- },
-};
-
-static int __init atmel_abdac_init(void)
-{
- return platform_driver_probe(&atmel_abdac_driver,
- atmel_abdac_probe);
-}
-module_init(atmel_abdac_init);
-
-static void __exit atmel_abdac_exit(void)
-{
- platform_driver_unregister(&atmel_abdac_driver);
-}
-module_exit(atmel_abdac_exit);
-
-MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("Driver for Atmel Audio Bitstream DAC (ABDAC)");
-MODULE_AUTHOR("Hans-Christian Egtvedt <egtvedt@samfundet.no>");
diff --git a/sound/atmel/ac97c.c b/sound/atmel/ac97c.c
index 6dad042..65e6948 100644
--- a/sound/atmel/ac97c.c
+++ b/sound/atmel/ac97c.c
@@ -11,8 +11,6 @@
#include <linux/delay.h>
#include <linux/bitmap.h>
#include <linux/device.h>
-#include <linux/dmaengine.h>
-#include <linux/dma-mapping.h>
#include <linux/atmel_pdc.h>
#include <linux/init.h>
#include <linux/interrupt.h>
@@ -34,36 +32,14 @@
#include <sound/atmel-ac97c.h>
#include <sound/memalloc.h>
-#include <linux/platform_data/dma-dw.h>
-#include <linux/dma/dw.h>
-
-#ifdef CONFIG_AVR32
-#include <mach/cpu.h>
-#else
-#define cpu_is_at32ap7000() 0
-#endif
-
#include "ac97c.h"
-enum {
- DMA_TX_READY = 0,
- DMA_RX_READY,
- DMA_TX_CHAN_PRESENT,
- DMA_RX_CHAN_PRESENT,
-};
-
/* Serialize access to opened variable */
static DEFINE_MUTEX(opened_mutex);
-struct atmel_ac97c_dma {
- struct dma_chan *rx_chan;
- struct dma_chan *tx_chan;
-};
-
struct atmel_ac97c {
struct clk *pclk;
struct platform_device *pdev;
- struct atmel_ac97c_dma dma;
struct snd_pcm_substream *playback_substream;
struct snd_pcm_substream *capture_substream;
@@ -74,7 +50,6 @@ struct atmel_ac97c {
u64 cur_format;
unsigned int cur_rate;
- unsigned long flags;
int playback_period, capture_period;
/* Serialize access to opened variable */
spinlock_t lock;
@@ -91,65 +66,6 @@ struct atmel_ac97c {
#define ac97c_readl(chip, reg) \
__raw_readl((chip)->regs + AC97C_##reg)
-/* This function is called by the DMA driver. */
-static void atmel_ac97c_dma_playback_period_done(void *arg)
-{
- struct atmel_ac97c *chip = arg;
- snd_pcm_period_elapsed(chip->playback_substream);
-}
-
-static void atmel_ac97c_dma_capture_period_done(void *arg)
-{
- struct atmel_ac97c *chip = arg;
- snd_pcm_period_elapsed(chip->capture_substream);
-}
-
-static int atmel_ac97c_prepare_dma(struct atmel_ac97c *chip,
- struct snd_pcm_substream *substream,
- enum dma_transfer_direction direction)
-{
- struct dma_chan *chan;
- struct dw_cyclic_desc *cdesc;
- struct snd_pcm_runtime *runtime = substream->runtime;
- unsigned long buffer_len, period_len;
-
- /*
- * We don't do DMA on "complex" transfers, i.e. with
- * non-halfword-aligned buffers or lengths.
- */
- if (runtime->dma_addr & 1 || runtime->buffer_size & 1) {
- dev_dbg(&chip->pdev->dev, "too complex transfer\n");
- return -EINVAL;
- }
-
- if (direction == DMA_MEM_TO_DEV)
- chan = chip->dma.tx_chan;
- else
- chan = chip->dma.rx_chan;
-
- buffer_len = frames_to_bytes(runtime, runtime->buffer_size);
- period_len = frames_to_bytes(runtime, runtime->period_size);
-
- cdesc = dw_dma_cyclic_prep(chan, runtime->dma_addr, buffer_len,
- period_len, direction);
- if (IS_ERR(cdesc)) {
- dev_dbg(&chip->pdev->dev, "could not prepare cyclic DMA\n");
- return PTR_ERR(cdesc);
- }
-
- if (direction == DMA_MEM_TO_DEV) {
- cdesc->period_callback = atmel_ac97c_dma_playback_period_done;
- set_bit(DMA_TX_READY, &chip->flags);
- } else {
- cdesc->period_callback = atmel_ac97c_dma_capture_period_done;
- set_bit(DMA_RX_READY, &chip->flags);
- }
-
- cdesc->period_callback_param = chip;
-
- return 0;
-}
-
static struct snd_pcm_hardware atmel_ac97c_hw = {
.info = (SNDRV_PCM_INFO_MMAP
| SNDRV_PCM_INFO_MMAP_VALID
@@ -254,13 +170,7 @@ static int atmel_ac97c_playback_hw_params(struct snd_pcm_substream *substream,
params_buffer_bytes(hw_params));
if (retval < 0)
return retval;
- /* snd_pcm_lib_malloc_pages returns 1 if buffer is changed. */
- if (cpu_is_at32ap7000()) {
- /* snd_pcm_lib_malloc_pages returns 1 if buffer is changed. */
- if (retval == 1)
- if (test_and_clear_bit(DMA_TX_READY, &chip->flags))
- dw_dma_cyclic_free(chip->dma.tx_chan);
- }
+
/* Set restrictions to params. */
mutex_lock(&opened_mutex);
chip->cur_rate = params_rate(hw_params);
@@ -280,10 +190,6 @@ static int atmel_ac97c_capture_hw_params(struct snd_pcm_substream *substream,
params_buffer_bytes(hw_params));
if (retval < 0)
return retval;
- /* snd_pcm_lib_malloc_pages returns 1 if buffer is changed. */
- if (cpu_is_at32ap7000() && retval == 1)
- if (test_and_clear_bit(DMA_RX_READY, &chip->flags))
- dw_dma_cyclic_free(chip->dma.rx_chan);
/* Set restrictions to params. */
mutex_lock(&opened_mutex);
@@ -294,26 +200,6 @@ static int atmel_ac97c_capture_hw_params(struct snd_pcm_substream *substream,
return retval;
}
-static int atmel_ac97c_playback_hw_free(struct snd_pcm_substream *substream)
-{
- struct atmel_ac97c *chip = snd_pcm_substream_chip(substream);
- if (cpu_is_at32ap7000()) {
- if (test_and_clear_bit(DMA_TX_READY, &chip->flags))
- dw_dma_cyclic_free(chip->dma.tx_chan);
- }
- return snd_pcm_lib_free_pages(substream);
-}
-
-static int atmel_ac97c_capture_hw_free(struct snd_pcm_substream *substream)
-{
- struct atmel_ac97c *chip = snd_pcm_substream_chip(substream);
- if (cpu_is_at32ap7000()) {
- if (test_and_clear_bit(DMA_RX_READY, &chip->flags))
- dw_dma_cyclic_free(chip->dma.rx_chan);
- }
- return snd_pcm_lib_free_pages(substream);
-}
-
static int atmel_ac97c_playback_prepare(struct snd_pcm_substream *substream)
{
struct atmel_ac97c *chip = snd_pcm_substream_chip(substream);
@@ -349,8 +235,6 @@ static int atmel_ac97c_playback_prepare(struct snd_pcm_substream *substream)
switch (runtime->format) {
case SNDRV_PCM_FORMAT_S16_LE:
- if (cpu_is_at32ap7000())
- word |= AC97C_CMR_CEM_LITTLE;
break;
case SNDRV_PCM_FORMAT_S16_BE: /* fall through */
word &= ~(AC97C_CMR_CEM_LITTLE);
@@ -389,18 +273,11 @@ static int atmel_ac97c_playback_prepare(struct snd_pcm_substream *substream)
dev_dbg(&chip->pdev->dev, "could not set rate %d Hz\n",
runtime->rate);
- if (cpu_is_at32ap7000()) {
- if (!test_bit(DMA_TX_READY, &chip->flags))
- retval = atmel_ac97c_prepare_dma(chip, substream,
- DMA_MEM_TO_DEV);
- } else {
- /* Initialize and start the PDC */
- writel(runtime->dma_addr, chip->regs + ATMEL_PDC_TPR);
- writel(block_size / 2, chip->regs + ATMEL_PDC_TCR);
- writel(runtime->dma_addr + block_size,
- chip->regs + ATMEL_PDC_TNPR);
- writel(block_size / 2, chip->regs + ATMEL_PDC_TNCR);
- }
+ /* Initialize and start the PDC */
+ writel(runtime->dma_addr, chip->regs + ATMEL_PDC_TPR);
+ writel(block_size / 2, chip->regs + ATMEL_PDC_TCR);
+ writel(runtime->dma_addr + block_size, chip->regs + ATMEL_PDC_TNPR);
+ writel(block_size / 2, chip->regs + ATMEL_PDC_TNCR);
return retval;
}
@@ -440,8 +317,6 @@ static int atmel_ac97c_capture_prepare(struct snd_pcm_substream *substream)
switch (runtime->format) {
case SNDRV_PCM_FORMAT_S16_LE:
- if (cpu_is_at32ap7000())
- word |= AC97C_CMR_CEM_LITTLE;
break;
case SNDRV_PCM_FORMAT_S16_BE: /* fall through */
word &= ~(AC97C_CMR_CEM_LITTLE);
@@ -480,18 +355,11 @@ static int atmel_ac97c_capture_prepare(struct snd_pcm_substream *substream)
dev_dbg(&chip->pdev->dev, "could not set rate %d Hz\n",
runtime->rate);
- if (cpu_is_at32ap7000()) {
- if (!test_bit(DMA_RX_READY, &chip->flags))
- retval = atmel_ac97c_prepare_dma(chip, substream,
- DMA_DEV_TO_MEM);
- } else {
- /* Initialize and start the PDC */
- writel(runtime->dma_addr, chip->regs + ATMEL_PDC_RPR);
- writel(block_size / 2, chip->regs + ATMEL_PDC_RCR);
- writel(runtime->dma_addr + block_size,
- chip->regs + ATMEL_PDC_RNPR);
- writel(block_size / 2, chip->regs + ATMEL_PDC_RNCR);
- }
+ /* Initialize and start the PDC */
+ writel(runtime->dma_addr, chip->regs + ATMEL_PDC_RPR);
+ writel(block_size / 2, chip->regs + ATMEL_PDC_RCR);
+ writel(runtime->dma_addr + block_size, chip->regs + ATMEL_PDC_RNPR);
+ writel(block_size / 2, chip->regs + ATMEL_PDC_RNCR);
return retval;
}
@@ -501,7 +369,6 @@ atmel_ac97c_playback_trigger(struct snd_pcm_substream *substream, int cmd)
{
struct atmel_ac97c *chip = snd_pcm_substream_chip(substream);
unsigned long camr, ptcr = 0;
- int retval = 0;
camr = ac97c_readl(chip, CAMR);
@@ -509,35 +376,23 @@ atmel_ac97c_playback_trigger(struct snd_pcm_substream *substream, int cmd)
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: /* fall through */
case SNDRV_PCM_TRIGGER_RESUME: /* fall through */
case SNDRV_PCM_TRIGGER_START:
- if (cpu_is_at32ap7000()) {
- retval = dw_dma_cyclic_start(chip->dma.tx_chan);
- if (retval)
- goto out;
- } else {
- ptcr = ATMEL_PDC_TXTEN;
- }
+ ptcr = ATMEL_PDC_TXTEN;
camr |= AC97C_CMR_CENA | AC97C_CSR_ENDTX;
break;
case SNDRV_PCM_TRIGGER_PAUSE_PUSH: /* fall through */
case SNDRV_PCM_TRIGGER_SUSPEND: /* fall through */
case SNDRV_PCM_TRIGGER_STOP:
- if (cpu_is_at32ap7000())
- dw_dma_cyclic_stop(chip->dma.tx_chan);
- else
- ptcr |= ATMEL_PDC_TXTDIS;
+ ptcr |= ATMEL_PDC_TXTDIS;
if (chip->opened <= 1)
camr &= ~AC97C_CMR_CENA;
break;
default:
- retval = -EINVAL;
- goto out;
+ return -EINVAL;
}
ac97c_writel(chip, CAMR, camr);
- if (!cpu_is_at32ap7000())
- writel(ptcr, chip->regs + ATMEL_PDC_PTCR);
-out:
- return retval;
+ writel(ptcr, chip->regs + ATMEL_PDC_PTCR);
+ return 0;
}
static int
@@ -545,7 +400,6 @@ atmel_ac97c_capture_trigger(struct snd_pcm_substream *substream, int cmd)
{
struct atmel_ac97c *chip = snd_pcm_substream_chip(substream);
unsigned long camr, ptcr = 0;
- int retval = 0;
camr = ac97c_readl(chip, CAMR);
ptcr = readl(chip->regs + ATMEL_PDC_PTSR);
@@ -554,35 +408,23 @@ atmel_ac97c_capture_trigger(struct snd_pcm_substream *substream, int cmd)
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: /* fall through */
case SNDRV_PCM_TRIGGER_RESUME: /* fall through */
case SNDRV_PCM_TRIGGER_START:
- if (cpu_is_at32ap7000()) {
- retval = dw_dma_cyclic_start(chip->dma.rx_chan);
- if (retval)
- goto out;
- } else {
- ptcr = ATMEL_PDC_RXTEN;
- }
+ ptcr = ATMEL_PDC_RXTEN;
camr |= AC97C_CMR_CENA | AC97C_CSR_ENDRX;
break;
case SNDRV_PCM_TRIGGER_PAUSE_PUSH: /* fall through */
case SNDRV_PCM_TRIGGER_SUSPEND: /* fall through */
case SNDRV_PCM_TRIGGER_STOP:
- if (cpu_is_at32ap7000())
- dw_dma_cyclic_stop(chip->dma.rx_chan);
- else
- ptcr |= (ATMEL_PDC_RXTDIS);
+ ptcr |= ATMEL_PDC_RXTDIS;
if (chip->opened <= 1)
camr &= ~AC97C_CMR_CENA;
break;
default:
- retval = -EINVAL;
- break;
+ return -EINVAL;
}
ac97c_writel(chip, CAMR, camr);
- if (!cpu_is_at32ap7000())
- writel(ptcr, chip->regs + ATMEL_PDC_PTCR);
-out:
- return retval;
+ writel(ptcr, chip->regs + ATMEL_PDC_PTCR);
+ return 0;
}
static snd_pcm_uframes_t
@@ -593,10 +435,7 @@ atmel_ac97c_playback_pointer(struct snd_pcm_substream *substream)
snd_pcm_uframes_t frames;
unsigned long bytes;
- if (cpu_is_at32ap7000())
- bytes = dw_dma_get_src_addr(chip->dma.tx_chan);
- else
- bytes = readl(chip->regs + ATMEL_PDC_TPR);
+ bytes = readl(chip->regs + ATMEL_PDC_TPR);
bytes -= runtime->dma_addr;
frames = bytes_to_frames(runtime, bytes);
@@ -613,10 +452,7 @@ atmel_ac97c_capture_pointer(struct snd_pcm_substream *substream)
snd_pcm_uframes_t frames;
unsigned long bytes;
- if (cpu_is_at32ap7000())
- bytes = dw_dma_get_dst_addr(chip->dma.rx_chan);
- else
- bytes = readl(chip->regs + ATMEL_PDC_RPR);
+ bytes = readl(chip->regs + ATMEL_PDC_RPR);
bytes -= runtime->dma_addr;
frames = bytes_to_frames(runtime, bytes);
@@ -630,7 +466,7 @@ static struct snd_pcm_ops atmel_ac97_playback_ops = {
.close = atmel_ac97c_playback_close,
.ioctl = snd_pcm_lib_ioctl,
.hw_params = atmel_ac97c_playback_hw_params,
- .hw_free = atmel_ac97c_playback_hw_free,
+ .hw_free = snd_pcm_lib_free_pages,
.prepare = atmel_ac97c_playback_prepare,
.trigger = atmel_ac97c_playback_trigger,
.pointer = atmel_ac97c_playback_pointer,
@@ -641,7 +477,7 @@ static struct snd_pcm_ops atmel_ac97_capture_ops = {
.close = atmel_ac97c_capture_close,
.ioctl = snd_pcm_lib_ioctl,
.hw_params = atmel_ac97c_capture_hw_params,
- .hw_free = atmel_ac97c_capture_hw_free,
+ .hw_free = snd_pcm_lib_free_pages,
.prepare = atmel_ac97c_capture_prepare,
.trigger = atmel_ac97c_capture_trigger,
.pointer = atmel_ac97c_capture_pointer,
@@ -666,49 +502,40 @@ static irqreturn_t atmel_ac97c_interrupt(int irq, void *dev)
casr & AC97C_CSR_TXEMPTY ? " TXEMPTY" : "",
casr & AC97C_CSR_TXRDY ? " TXRDY" : "",
!casr ? " NONE" : "");
- if (!cpu_is_at32ap7000()) {
- if ((casr & camr) & AC97C_CSR_ENDTX) {
- runtime = chip->playback_substream->runtime;
- block_size = frames_to_bytes(runtime,
- runtime->period_size);
- chip->playback_period++;
-
- if (chip->playback_period == runtime->periods)
- chip->playback_period = 0;
- next_period = chip->playback_period + 1;
- if (next_period == runtime->periods)
- next_period = 0;
-
- offset = block_size * next_period;
-
- writel(runtime->dma_addr + offset,
- chip->regs + ATMEL_PDC_TNPR);
- writel(block_size / 2,
- chip->regs + ATMEL_PDC_TNCR);
-
- snd_pcm_period_elapsed(
- chip->playback_substream);
- }
- if ((casr & camr) & AC97C_CSR_ENDRX) {
- runtime = chip->capture_substream->runtime;
- block_size = frames_to_bytes(runtime,
- runtime->period_size);
- chip->capture_period++;
-
- if (chip->capture_period == runtime->periods)
- chip->capture_period = 0;
- next_period = chip->capture_period + 1;
- if (next_period == runtime->periods)
- next_period = 0;
-
- offset = block_size * next_period;
-
- writel(runtime->dma_addr + offset,
- chip->regs + ATMEL_PDC_RNPR);
- writel(block_size / 2,
- chip->regs + ATMEL_PDC_RNCR);
- snd_pcm_period_elapsed(chip->capture_substream);
- }
+ if ((casr & camr) & AC97C_CSR_ENDTX) {
+ runtime = chip->playback_substream->runtime;
+ block_size = frames_to_bytes(runtime, runtime->period_size);
+ chip->playback_period++;
+
+ if (chip->playback_period == runtime->periods)
+ chip->playback_period = 0;
+ next_period = chip->playback_period + 1;
+ if (next_period == runtime->periods)
+ next_period = 0;
+
+ offset = block_size * next_period;
+
+ writel(runtime->dma_addr + offset, chip->regs + ATMEL_PDC_TNPR);
+ writel(block_size / 2, chip->regs + ATMEL_PDC_TNCR);
+
+ snd_pcm_period_elapsed(chip->playback_substream);
+ }
+ if ((casr & camr) & AC97C_CSR_ENDRX) {
+ runtime = chip->capture_substream->runtime;
+ block_size = frames_to_bytes(runtime, runtime->period_size);
+ chip->capture_period++;
+
+ if (chip->capture_period == runtime->periods)
+ chip->capture_period = 0;
+ next_period = chip->capture_period + 1;
+ if (next_period == runtime->periods)
+ next_period = 0;
+
+ offset = block_size * next_period;
+
+ writel(runtime->dma_addr + offset, chip->regs + ATMEL_PDC_RNPR);
+ writel(block_size / 2, chip->regs + ATMEL_PDC_RNCR);
+ snd_pcm_period_elapsed(chip->capture_substream);
}
retval = IRQ_HANDLED;
}
@@ -763,29 +590,20 @@ static int atmel_ac97c_pcm_new(struct atmel_ac97c *chip)
{
struct snd_pcm *pcm;
struct snd_pcm_hardware hw = atmel_ac97c_hw;
- int capture, playback, retval, err;
+ int retval;
- capture = test_bit(DMA_RX_CHAN_PRESENT, &chip->flags);
- playback = test_bit(DMA_TX_CHAN_PRESENT, &chip->flags);
+ retval = snd_ac97_pcm_assign(chip->ac97_bus,
+ ARRAY_SIZE(at91_ac97_pcm_defs),
+ at91_ac97_pcm_defs);
+ if (retval)
+ return retval;
- if (!cpu_is_at32ap7000()) {
- err = snd_ac97_pcm_assign(chip->ac97_bus,
- ARRAY_SIZE(at91_ac97_pcm_defs),
- at91_ac97_pcm_defs);
- if (err)
- return err;
- }
- retval = snd_pcm_new(chip->card, chip->card->shortname,
- 0, playback, capture, &pcm);
+ retval = snd_pcm_new(chip->card, chip->card->shortname, 0, 1, 1, &pcm);
if (retval)
return retval;
- if (capture)
- snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE,
- &atmel_ac97_capture_ops);
- if (playback)
- snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK,
- &atmel_ac97_playback_ops);
+ snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &atmel_ac97_capture_ops);
+ snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &atmel_ac97_playback_ops);
retval = snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
&chip->pdev->dev, hw.periods_min * hw.period_bytes_min,
@@ -875,17 +693,6 @@ timed_out:
return 0xffff;
}
-static bool filter(struct dma_chan *chan, void *slave)
-{
- struct dw_dma_slave *dws = slave;
-
- if (dws->dma_dev == chan->device->dev) {
- chan->private = dws;
- return true;
- } else
- return false;
-}
-
static void atmel_ac97c_reset(struct atmel_ac97c *chip)
{
ac97c_writel(chip, MR, 0);
@@ -971,12 +778,7 @@ static int atmel_ac97c_probe(struct platform_device *pdev)
return -ENXIO;
}
- if (cpu_is_at32ap7000()) {
- pclk = clk_get(&pdev->dev, "pclk");
- } else {
- pclk = clk_get(&pdev->dev, "ac97_clk");
- }
-
+ pclk = clk_get(&pdev->dev, "ac97_clk");
if (IS_ERR(pclk)) {
dev_dbg(&pdev->dev, "no peripheral clock\n");
return PTR_ERR(pclk);
@@ -1047,88 +849,16 @@ static int atmel_ac97c_probe(struct platform_device *pdev)
goto err_ac97_bus;
}
- if (cpu_is_at32ap7000()) {
- if (pdata->rx_dws.dma_dev) {
- dma_cap_mask_t mask;
-
- dma_cap_zero(mask);
- dma_cap_set(DMA_SLAVE, mask);
-
- chip->dma.rx_chan = dma_request_channel(mask, filter,
- &pdata->rx_dws);
- if (chip->dma.rx_chan) {
- struct dma_slave_config dma_conf = {
- .src_addr = regs->start + AC97C_CARHR +
- 2,
- .src_addr_width =
- DMA_SLAVE_BUSWIDTH_2_BYTES,
- .src_maxburst = 1,
- .dst_maxburst = 1,
- .direction = DMA_DEV_TO_MEM,
- .device_fc = false,
- };
-
- dmaengine_slave_config(chip->dma.rx_chan,
- &dma_conf);
- }
-
- dev_info(&chip->pdev->dev, "using %s for DMA RX\n",
- dev_name(&chip->dma.rx_chan->dev->device));
- set_bit(DMA_RX_CHAN_PRESENT, &chip->flags);
- }
-
- if (pdata->tx_dws.dma_dev) {
- dma_cap_mask_t mask;
-
- dma_cap_zero(mask);
- dma_cap_set(DMA_SLAVE, mask);
-
- chip->dma.tx_chan = dma_request_channel(mask, filter,
- &pdata->tx_dws);
- if (chip->dma.tx_chan) {
- struct dma_slave_config dma_conf = {
- .dst_addr = regs->start + AC97C_CATHR +
- 2,
- .dst_addr_width =
- DMA_SLAVE_BUSWIDTH_2_BYTES,
- .src_maxburst = 1,
- .dst_maxburst = 1,
- .direction = DMA_MEM_TO_DEV,
- .device_fc = false,
- };
-
- dmaengine_slave_config(chip->dma.tx_chan,
- &dma_conf);
- }
-
- dev_info(&chip->pdev->dev, "using %s for DMA TX\n",
- dev_name(&chip->dma.tx_chan->dev->device));
- set_bit(DMA_TX_CHAN_PRESENT, &chip->flags);
- }
-
- if (!test_bit(DMA_RX_CHAN_PRESENT, &chip->flags) &&
- !test_bit(DMA_TX_CHAN_PRESENT, &chip->flags)) {
- dev_dbg(&pdev->dev, "DMA not available\n");
- retval = -ENODEV;
- goto err_dma;
- }
- } else {
- /* Just pretend that we have DMA channel(for at91 i is actually
- * the PDC) */
- set_bit(DMA_RX_CHAN_PRESENT, &chip->flags);
- set_bit(DMA_TX_CHAN_PRESENT, &chip->flags);
- }
-
retval = atmel_ac97c_pcm_new(chip);
if (retval) {
dev_dbg(&pdev->dev, "could not register ac97 pcm device\n");
- goto err_dma;
+ goto err_ac97_bus;
}
retval = snd_card_register(card);
if (retval) {
dev_dbg(&pdev->dev, "could not register sound card\n");
- goto err_dma;
+ goto err_ac97_bus;
}
platform_set_drvdata(pdev, card);
@@ -1138,17 +868,6 @@ static int atmel_ac97c_probe(struct platform_device *pdev)
return 0;
-err_dma:
- if (cpu_is_at32ap7000()) {
- if (test_bit(DMA_RX_CHAN_PRESENT, &chip->flags))
- dma_release_channel(chip->dma.rx_chan);
- if (test_bit(DMA_TX_CHAN_PRESENT, &chip->flags))
- dma_release_channel(chip->dma.tx_chan);
- clear_bit(DMA_RX_CHAN_PRESENT, &chip->flags);
- clear_bit(DMA_TX_CHAN_PRESENT, &chip->flags);
- chip->dma.rx_chan = NULL;
- chip->dma.tx_chan = NULL;
- }
err_ac97_bus:
if (gpio_is_valid(chip->reset_pin))
gpio_free(chip->reset_pin);
@@ -1170,14 +889,7 @@ static int atmel_ac97c_suspend(struct device *pdev)
struct snd_card *card = dev_get_drvdata(pdev);
struct atmel_ac97c *chip = card->private_data;
- if (cpu_is_at32ap7000()) {
- if (test_bit(DMA_RX_READY, &chip->flags))
- dw_dma_cyclic_stop(chip->dma.rx_chan);
- if (test_bit(DMA_TX_READY, &chip->flags))
- dw_dma_cyclic_stop(chip->dma.tx_chan);
- }
clk_disable_unprepare(chip->pclk);
-
return 0;
}
@@ -1187,12 +899,6 @@ static int atmel_ac97c_resume(struct device *pdev)
struct atmel_ac97c *chip = card->private_data;
clk_prepare_enable(chip->pclk);
- if (cpu_is_at32ap7000()) {
- if (test_bit(DMA_RX_READY, &chip->flags))
- dw_dma_cyclic_start(chip->dma.rx_chan);
- if (test_bit(DMA_TX_READY, &chip->flags))
- dw_dma_cyclic_start(chip->dma.tx_chan);
- }
return 0;
}
@@ -1219,17 +925,6 @@ static int atmel_ac97c_remove(struct platform_device *pdev)
iounmap(chip->regs);
free_irq(chip->irq, chip);
- if (cpu_is_at32ap7000()) {
- if (test_bit(DMA_RX_CHAN_PRESENT, &chip->flags))
- dma_release_channel(chip->dma.rx_chan);
- if (test_bit(DMA_TX_CHAN_PRESENT, &chip->flags))
- dma_release_channel(chip->dma.tx_chan);
- clear_bit(DMA_RX_CHAN_PRESENT, &chip->flags);
- clear_bit(DMA_TX_CHAN_PRESENT, &chip->flags);
- chip->dma.rx_chan = NULL;
- chip->dma.tx_chan = NULL;
- }
-
snd_card_free(card);
return 0;
diff --git a/sound/core/control.c b/sound/core/control.c
index c109b82..ecd3582 100644
--- a/sound/core/control.c
+++ b/sound/core/control.c
@@ -747,65 +747,45 @@ static int snd_ctl_card_info(struct snd_card *card, struct snd_ctl_file * ctl,
static int snd_ctl_elem_list(struct snd_card *card,
struct snd_ctl_elem_list __user *_list)
{
- struct list_head *plist;
struct snd_ctl_elem_list list;
struct snd_kcontrol *kctl;
- struct snd_ctl_elem_id *dst, *id;
+ struct snd_ctl_elem_id id;
unsigned int offset, space, jidx;
+ int err = 0;
if (copy_from_user(&list, _list, sizeof(list)))
return -EFAULT;
offset = list.offset;
space = list.space;
- /* try limit maximum space */
- if (space > 16384)
- return -ENOMEM;
+
+ down_read(&card->controls_rwsem);
+ list.count = card->controls_count;
+ list.used = 0;
if (space > 0) {
- /* allocate temporary buffer for atomic operation */
- dst = vmalloc(space * sizeof(struct snd_ctl_elem_id));
- if (dst == NULL)
- return -ENOMEM;
- down_read(&card->controls_rwsem);
- list.count = card->controls_count;
- plist = card->controls.next;
- while (plist != &card->controls) {
- if (offset == 0)
- break;
- kctl = snd_kcontrol(plist);
- if (offset < kctl->count)
- break;
- offset -= kctl->count;
- plist = plist->next;
- }
- list.used = 0;
- id = dst;
- while (space > 0 && plist != &card->controls) {
- kctl = snd_kcontrol(plist);
- for (jidx = offset; space > 0 && jidx < kctl->count; jidx++) {
- snd_ctl_build_ioff(id, kctl, jidx);
- id++;
- space--;
+ list_for_each_entry(kctl, &card->controls, list) {
+ if (offset >= kctl->count) {
+ offset -= kctl->count;
+ continue;
+ }
+ for (jidx = offset; jidx < kctl->count; jidx++) {
+ snd_ctl_build_ioff(&id, kctl, jidx);
+ if (copy_to_user(list.pids + list.used, &id,
+ sizeof(id))) {
+ err = -EFAULT;
+ goto out;
+ }
list.used++;
+ if (!--space)
+ goto out;
}
- plist = plist->next;
offset = 0;
}
- up_read(&card->controls_rwsem);
- if (list.used > 0 &&
- copy_to_user(list.pids, dst,
- list.used * sizeof(struct snd_ctl_elem_id))) {
- vfree(dst);
- return -EFAULT;
- }
- vfree(dst);
- } else {
- down_read(&card->controls_rwsem);
- list.count = card->controls_count;
- up_read(&card->controls_rwsem);
}
- if (copy_to_user(_list, &list, sizeof(list)))
- return -EFAULT;
- return 0;
+ out:
+ up_read(&card->controls_rwsem);
+ if (!err && copy_to_user(_list, &list, sizeof(list)))
+ err = -EFAULT;
+ return err;
}
static bool validate_element_member_dimension(struct snd_ctl_elem_info *info)
diff --git a/sound/core/ctljack.c b/sound/core/ctljack.c
index 84a3cd6..0249d5e 100644
--- a/sound/core/ctljack.c
+++ b/sound/core/ctljack.c
@@ -23,7 +23,7 @@ static int jack_detect_kctl_get(struct snd_kcontrol *kcontrol,
return 0;
}
-static struct snd_kcontrol_new jack_detect_kctl = {
+static const struct snd_kcontrol_new jack_detect_kctl = {
/* name is filled later */
.iface = SNDRV_CTL_ELEM_IFACE_CARD,
.access = SNDRV_CTL_ELEM_ACCESS_READ,
diff --git a/sound/core/info.c b/sound/core/info.c
index 8ab72e0..fc14ebe 100644
--- a/sound/core/info.c
+++ b/sound/core/info.c
@@ -344,12 +344,12 @@ static ssize_t snd_info_text_entry_write(struct file *file,
}
}
if (next > buf->len) {
- char *nbuf = krealloc(buf->buffer, PAGE_ALIGN(next),
- GFP_KERNEL | __GFP_ZERO);
+ char *nbuf = kvzalloc(PAGE_ALIGN(next), GFP_KERNEL);
if (!nbuf) {
err = -ENOMEM;
goto error;
}
+ kvfree(buf->buffer);
buf->buffer = nbuf;
buf->len = PAGE_ALIGN(next);
}
@@ -427,7 +427,7 @@ static int snd_info_text_entry_release(struct inode *inode, struct file *file)
single_release(inode, file);
kfree(data->rbuffer);
if (data->wbuffer) {
- kfree(data->wbuffer->buffer);
+ kvfree(data->wbuffer->buffer);
kfree(data->wbuffer);
}
diff --git a/sound/core/oss/io.c b/sound/core/oss/io.c
index 6faa1d71..d870b2d 100644
--- a/sound/core/oss/io.c
+++ b/sound/core/oss/io.c
@@ -26,9 +26,9 @@
#include "pcm_plugin.h"
#define pcm_write(plug,buf,count) snd_pcm_oss_write3(plug,buf,count,1)
-#define pcm_writev(plug,vec,count) snd_pcm_oss_writev3(plug,vec,count,1)
+#define pcm_writev(plug,vec,count) snd_pcm_oss_writev3(plug,vec,count)
#define pcm_read(plug,buf,count) snd_pcm_oss_read3(plug,buf,count,1)
-#define pcm_readv(plug,vec,count) snd_pcm_oss_readv3(plug,vec,count,1)
+#define pcm_readv(plug,vec,count) snd_pcm_oss_readv3(plug,vec,count)
/*
* Basic io plugin
diff --git a/sound/core/oss/pcm_oss.c b/sound/core/oss/pcm_oss.c
index 36baf96..5e1009d 100644
--- a/sound/core/oss/pcm_oss.c
+++ b/sound/core/oss/pcm_oss.c
@@ -67,18 +67,6 @@ static int snd_pcm_oss_get_rate(struct snd_pcm_oss_file *pcm_oss_file);
static int snd_pcm_oss_get_channels(struct snd_pcm_oss_file *pcm_oss_file);
static int snd_pcm_oss_get_format(struct snd_pcm_oss_file *pcm_oss_file);
-static inline mm_segment_t snd_enter_user(void)
-{
- mm_segment_t fs = get_fs();
- set_fs(get_ds());
- return fs;
-}
-
-static inline void snd_leave_user(mm_segment_t fs)
-{
- set_fs(fs);
-}
-
/*
* helper functions to process hw_params
*/
@@ -799,7 +787,7 @@ static int snd_pcm_oss_period_size(struct snd_pcm_substream *substream,
static int choose_rate(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params, unsigned int best_rate)
{
- struct snd_interval *it;
+ const struct snd_interval *it;
struct snd_pcm_hw_params *save;
unsigned int rate, prev;
@@ -807,7 +795,7 @@ static int choose_rate(struct snd_pcm_substream *substream,
if (save == NULL)
return -ENOMEM;
*save = *params;
- it = hw_param_interval(save, SNDRV_PCM_HW_PARAM_RATE);
+ it = hw_param_interval_c(save, SNDRV_PCM_HW_PARAM_RATE);
/* try multiples of the best rate */
rate = best_rate;
@@ -848,7 +836,7 @@ static int snd_pcm_oss_change_params(struct snd_pcm_substream *substream,
int direct;
snd_pcm_format_t format, sformat;
int n;
- struct snd_mask sformat_mask;
+ const struct snd_mask *sformat_mask;
struct snd_mask mask;
if (trylock) {
@@ -891,18 +879,18 @@ static int snd_pcm_oss_change_params(struct snd_pcm_substream *substream,
format = snd_pcm_oss_format_from(runtime->oss.format);
- sformat_mask = *hw_param_mask(sparams, SNDRV_PCM_HW_PARAM_FORMAT);
+ sformat_mask = hw_param_mask_c(sparams, SNDRV_PCM_HW_PARAM_FORMAT);
if (direct)
sformat = format;
else
- sformat = snd_pcm_plug_slave_format(format, &sformat_mask);
+ sformat = snd_pcm_plug_slave_format(format, sformat_mask);
if ((__force int)sformat < 0 ||
- !snd_mask_test(&sformat_mask, (__force int)sformat)) {
+ !snd_mask_test(sformat_mask, (__force int)sformat)) {
for (sformat = (__force snd_pcm_format_t)0;
(__force int)sformat <= (__force int)SNDRV_PCM_FORMAT_LAST;
sformat = (__force snd_pcm_format_t)((__force int)sformat + 1)) {
- if (snd_mask_test(&sformat_mask, (__force int)sformat) &&
+ if (snd_mask_test(sformat_mask, (__force int)sformat) &&
snd_pcm_oss_format_to(sformat) >= 0)
break;
}
@@ -1191,14 +1179,8 @@ snd_pcm_sframes_t snd_pcm_oss_write3(struct snd_pcm_substream *substream, const
if (ret < 0)
break;
}
- if (in_kernel) {
- mm_segment_t fs;
- fs = snd_enter_user();
- ret = snd_pcm_lib_write(substream, (void __force __user *)ptr, frames);
- snd_leave_user(fs);
- } else {
- ret = snd_pcm_lib_write(substream, (void __force __user *)ptr, frames);
- }
+ ret = __snd_pcm_lib_xfer(substream, (void *)ptr, true,
+ frames, in_kernel);
if (ret != -EPIPE && ret != -ESTRPIPE)
break;
/* test, if we can't store new data, because the stream */
@@ -1234,14 +1216,8 @@ snd_pcm_sframes_t snd_pcm_oss_read3(struct snd_pcm_substream *substream, char *p
ret = snd_pcm_oss_capture_position_fixup(substream, &delay);
if (ret < 0)
break;
- if (in_kernel) {
- mm_segment_t fs;
- fs = snd_enter_user();
- ret = snd_pcm_lib_read(substream, (void __force __user *)ptr, frames);
- snd_leave_user(fs);
- } else {
- ret = snd_pcm_lib_read(substream, (void __force __user *)ptr, frames);
- }
+ ret = __snd_pcm_lib_xfer(substream, (void *)ptr, true,
+ frames, in_kernel);
if (ret == -EPIPE) {
if (runtime->status->state == SNDRV_PCM_STATE_DRAINING) {
ret = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DROP, NULL);
@@ -1256,7 +1232,8 @@ snd_pcm_sframes_t snd_pcm_oss_read3(struct snd_pcm_substream *substream, char *p
return ret;
}
-snd_pcm_sframes_t snd_pcm_oss_writev3(struct snd_pcm_substream *substream, void **bufs, snd_pcm_uframes_t frames, int in_kernel)
+#ifdef CONFIG_SND_PCM_OSS_PLUGINS
+snd_pcm_sframes_t snd_pcm_oss_writev3(struct snd_pcm_substream *substream, void **bufs, snd_pcm_uframes_t frames)
{
struct snd_pcm_runtime *runtime = substream->runtime;
int ret;
@@ -1273,14 +1250,7 @@ snd_pcm_sframes_t snd_pcm_oss_writev3(struct snd_pcm_substream *substream, void
if (ret < 0)
break;
}
- if (in_kernel) {
- mm_segment_t fs;
- fs = snd_enter_user();
- ret = snd_pcm_lib_writev(substream, (void __user **)bufs, frames);
- snd_leave_user(fs);
- } else {
- ret = snd_pcm_lib_writev(substream, (void __user **)bufs, frames);
- }
+ ret = snd_pcm_kernel_writev(substream, bufs, frames);
if (ret != -EPIPE && ret != -ESTRPIPE)
break;
@@ -1292,7 +1262,7 @@ snd_pcm_sframes_t snd_pcm_oss_writev3(struct snd_pcm_substream *substream, void
return ret;
}
-snd_pcm_sframes_t snd_pcm_oss_readv3(struct snd_pcm_substream *substream, void **bufs, snd_pcm_uframes_t frames, int in_kernel)
+snd_pcm_sframes_t snd_pcm_oss_readv3(struct snd_pcm_substream *substream, void **bufs, snd_pcm_uframes_t frames)
{
struct snd_pcm_runtime *runtime = substream->runtime;
int ret;
@@ -1313,19 +1283,13 @@ snd_pcm_sframes_t snd_pcm_oss_readv3(struct snd_pcm_substream *substream, void *
if (ret < 0)
break;
}
- if (in_kernel) {
- mm_segment_t fs;
- fs = snd_enter_user();
- ret = snd_pcm_lib_readv(substream, (void __user **)bufs, frames);
- snd_leave_user(fs);
- } else {
- ret = snd_pcm_lib_readv(substream, (void __user **)bufs, frames);
- }
+ ret = snd_pcm_kernel_readv(substream, bufs, frames);
if (ret != -EPIPE && ret != -ESTRPIPE)
break;
}
return ret;
}
+#endif /* CONFIG_SND_PCM_OSS_PLUGINS */
static ssize_t snd_pcm_oss_write2(struct snd_pcm_substream *substream, const char *buf, size_t bytes, int in_kernel)
{
@@ -1650,27 +1614,10 @@ static int snd_pcm_oss_sync(struct snd_pcm_oss_file *pcm_oss_file)
size = runtime->control->appl_ptr % runtime->period_size;
if (size > 0) {
size = runtime->period_size - size;
- if (runtime->access == SNDRV_PCM_ACCESS_RW_INTERLEAVED) {
- size = (runtime->frame_bits * size) / 8;
- while (size > 0) {
- mm_segment_t fs;
- size_t size1 = size < runtime->oss.period_bytes ? size : runtime->oss.period_bytes;
- size -= size1;
- size1 *= 8;
- size1 /= runtime->sample_bits;
- snd_pcm_format_set_silence(runtime->format,
- runtime->oss.buffer,
- size1);
- size1 /= runtime->channels; /* frames */
- fs = snd_enter_user();
- snd_pcm_lib_write(substream, (void __force __user *)runtime->oss.buffer, size1);
- snd_leave_user(fs);
- }
- } else if (runtime->access == SNDRV_PCM_ACCESS_RW_NONINTERLEAVED) {
- void __user *buffers[runtime->channels];
- memset(buffers, 0, runtime->channels * sizeof(void *));
- snd_pcm_lib_writev(substream, buffers, size);
- }
+ if (runtime->access == SNDRV_PCM_ACCESS_RW_INTERLEAVED)
+ snd_pcm_lib_write(substream, NULL, size);
+ else if (runtime->access == SNDRV_PCM_ACCESS_RW_NONINTERLEAVED)
+ snd_pcm_lib_writev(substream, NULL, size);
}
mutex_unlock(&runtime->oss.params_lock);
/*
@@ -1780,7 +1727,7 @@ static int snd_pcm_oss_get_formats(struct snd_pcm_oss_file *pcm_oss_file)
int direct;
struct snd_pcm_hw_params *params;
unsigned int formats = 0;
- struct snd_mask format_mask;
+ const struct snd_mask *format_mask;
int fmt;
if ((err = snd_pcm_oss_get_active_substream(pcm_oss_file, &substream)) < 0)
@@ -1802,12 +1749,12 @@ static int snd_pcm_oss_get_formats(struct snd_pcm_oss_file *pcm_oss_file)
return -ENOMEM;
_snd_pcm_hw_params_any(params);
err = snd_pcm_hw_refine(substream, params);
- format_mask = *hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT);
+ format_mask = hw_param_mask_c(params, SNDRV_PCM_HW_PARAM_FORMAT);
kfree(params);
if (err < 0)
return err;
for (fmt = 0; fmt < 32; ++fmt) {
- if (snd_mask_test(&format_mask, fmt)) {
+ if (snd_mask_test(format_mask, fmt)) {
int f = snd_pcm_oss_format_to(fmt);
if (f >= 0)
formats |= f;
diff --git a/sound/core/oss/pcm_plugin.c b/sound/core/oss/pcm_plugin.c
index 727ac44..cadc937 100644
--- a/sound/core/oss/pcm_plugin.c
+++ b/sound/core/oss/pcm_plugin.c
@@ -266,7 +266,8 @@ snd_pcm_sframes_t snd_pcm_plug_slave_size(struct snd_pcm_substream *plug, snd_pc
return frames;
}
-static int snd_pcm_plug_formats(struct snd_mask *mask, snd_pcm_format_t format)
+static int snd_pcm_plug_formats(const struct snd_mask *mask,
+ snd_pcm_format_t format)
{
struct snd_mask formats = *mask;
u64 linfmts = (SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S8 |
@@ -309,7 +310,7 @@ static snd_pcm_format_t preferred_formats[] = {
};
snd_pcm_format_t snd_pcm_plug_slave_format(snd_pcm_format_t format,
- struct snd_mask *format_mask)
+ const struct snd_mask *format_mask)
{
int i;
diff --git a/sound/core/oss/pcm_plugin.h b/sound/core/oss/pcm_plugin.h
index a5035c2..c9cd29d 100644
--- a/sound/core/oss/pcm_plugin.h
+++ b/sound/core/oss/pcm_plugin.h
@@ -126,7 +126,7 @@ int snd_pcm_plug_format_plugins(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *slave_params);
snd_pcm_format_t snd_pcm_plug_slave_format(snd_pcm_format_t format,
- struct snd_mask *format_mask);
+ const struct snd_mask *format_mask);
int snd_pcm_plugin_append(struct snd_pcm_plugin *plugin);
@@ -162,17 +162,15 @@ snd_pcm_sframes_t snd_pcm_oss_write3(struct snd_pcm_substream *substream,
snd_pcm_sframes_t snd_pcm_oss_read3(struct snd_pcm_substream *substream,
char *ptr, snd_pcm_uframes_t size, int in_kernel);
snd_pcm_sframes_t snd_pcm_oss_writev3(struct snd_pcm_substream *substream,
- void **bufs, snd_pcm_uframes_t frames,
- int in_kernel);
+ void **bufs, snd_pcm_uframes_t frames);
snd_pcm_sframes_t snd_pcm_oss_readv3(struct snd_pcm_substream *substream,
- void **bufs, snd_pcm_uframes_t frames,
- int in_kernel);
+ void **bufs, snd_pcm_uframes_t frames);
#else
static inline snd_pcm_sframes_t snd_pcm_plug_client_size(struct snd_pcm_substream *handle, snd_pcm_uframes_t drv_size) { return drv_size; }
static inline snd_pcm_sframes_t snd_pcm_plug_slave_size(struct snd_pcm_substream *handle, snd_pcm_uframes_t clt_size) { return clt_size; }
-static inline int snd_pcm_plug_slave_format(int format, struct snd_mask *format_mask) { return format; }
+static inline int snd_pcm_plug_slave_format(int format, const struct snd_mask *format_mask) { return format; }
#endif
diff --git a/sound/core/pcm.c b/sound/core/pcm.c
index 8e980aa..4b32904 100644
--- a/sound/core/pcm.c
+++ b/sound/core/pcm.c
@@ -31,13 +31,17 @@
#include <sound/control.h>
#include <sound/info.h>
+#include "pcm_local.h"
+
MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>, Abramo Bagnara <abramo@alsa-project.org>");
MODULE_DESCRIPTION("Midlevel PCM code for ALSA.");
MODULE_LICENSE("GPL");
static LIST_HEAD(snd_pcm_devices);
-static LIST_HEAD(snd_pcm_notify_list);
static DEFINE_MUTEX(register_mutex);
+#if IS_ENABLED(CONFIG_SND_PCM_OSS)
+static LIST_HEAD(snd_pcm_notify_list);
+#endif
static int snd_pcm_free(struct snd_pcm *pcm);
static int snd_pcm_dev_free(struct snd_device *device);
@@ -884,16 +888,23 @@ static void snd_pcm_free_stream(struct snd_pcm_str * pstr)
put_device(&pstr->dev);
}
+#if IS_ENABLED(CONFIG_SND_PCM_OSS)
+#define pcm_call_notify(pcm, call) \
+ do { \
+ struct snd_pcm_notify *_notify; \
+ list_for_each_entry(_notify, &snd_pcm_notify_list, list) \
+ _notify->call(pcm); \
+ } while (0)
+#else
+#define pcm_call_notify(pcm, call) do {} while (0)
+#endif
+
static int snd_pcm_free(struct snd_pcm *pcm)
{
- struct snd_pcm_notify *notify;
-
if (!pcm)
return 0;
- if (!pcm->internal) {
- list_for_each_entry(notify, &snd_pcm_notify_list, list)
- notify->n_unregister(pcm);
- }
+ if (!pcm->internal)
+ pcm_call_notify(pcm, n_unregister);
if (pcm->private_free)
pcm->private_free(pcm);
snd_pcm_lib_preallocate_free_for_all(pcm);
@@ -1069,7 +1080,6 @@ static int snd_pcm_dev_register(struct snd_device *device)
{
int cidx, err;
struct snd_pcm_substream *substream;
- struct snd_pcm_notify *notify;
struct snd_pcm *pcm;
if (snd_BUG_ON(!device || !device->device_data))
@@ -1107,8 +1117,7 @@ static int snd_pcm_dev_register(struct snd_device *device)
snd_pcm_timer_init(substream);
}
- list_for_each_entry(notify, &snd_pcm_notify_list, list)
- notify->n_register(pcm);
+ pcm_call_notify(pcm, n_register);
unlock:
mutex_unlock(&register_mutex);
@@ -1118,7 +1127,6 @@ static int snd_pcm_dev_register(struct snd_device *device)
static int snd_pcm_dev_disconnect(struct snd_device *device)
{
struct snd_pcm *pcm = device->device_data;
- struct snd_pcm_notify *notify;
struct snd_pcm_substream *substream;
int cidx;
@@ -1138,8 +1146,7 @@ static int snd_pcm_dev_disconnect(struct snd_device *device)
}
}
if (!pcm->internal) {
- list_for_each_entry(notify, &snd_pcm_notify_list, list)
- notify->n_disconnect(pcm);
+ pcm_call_notify(pcm, n_disconnect);
}
for (cidx = 0; cidx < 2; cidx++) {
if (!pcm->internal)
@@ -1151,6 +1158,7 @@ static int snd_pcm_dev_disconnect(struct snd_device *device)
return 0;
}
+#if IS_ENABLED(CONFIG_SND_PCM_OSS)
/**
* snd_pcm_notify - Add/remove the notify list
* @notify: PCM notify list
@@ -1183,6 +1191,7 @@ int snd_pcm_notify(struct snd_pcm_notify *notify, int nfree)
return 0;
}
EXPORT_SYMBOL(snd_pcm_notify);
+#endif /* CONFIG_SND_PCM_OSS */
#ifdef CONFIG_SND_PROC_FS
/*
diff --git a/sound/core/pcm_compat.c b/sound/core/pcm_compat.c
index 1f64ab0..8a0f8d5 100644
--- a/sound/core/pcm_compat.c
+++ b/sound/core/pcm_compat.c
@@ -27,17 +27,13 @@ static int snd_pcm_ioctl_delay_compat(struct snd_pcm_substream *substream,
s32 __user *src)
{
snd_pcm_sframes_t delay;
- mm_segment_t fs;
- int err;
- fs = snd_enter_user();
- err = snd_pcm_delay(substream, &delay);
- snd_leave_user(fs);
- if (err < 0)
- return err;
+ delay = snd_pcm_delay(substream);
+ if (delay < 0)
+ return delay;
if (put_user(delay, src))
return -EFAULT;
- return err;
+ return 0;
}
static int snd_pcm_ioctl_rewind_compat(struct snd_pcm_substream *substream,
diff --git a/sound/core/pcm_drm_eld.c b/sound/core/pcm_drm_eld.c
index e70379f..9881d08 100644
--- a/sound/core/pcm_drm_eld.c
+++ b/sound/core/pcm_drm_eld.c
@@ -29,13 +29,13 @@ static int eld_limit_rates(struct snd_pcm_hw_params *params,
struct snd_pcm_hw_rule *rule)
{
struct snd_interval *r = hw_param_interval(params, rule->var);
- struct snd_interval *c;
+ const struct snd_interval *c;
unsigned int rate_mask = 7, i;
const u8 *sad, *eld = rule->private;
sad = drm_eld_sad(eld);
if (sad) {
- c = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
+ c = hw_param_interval_c(params, SNDRV_PCM_HW_PARAM_CHANNELS);
for (i = drm_eld_sad_count(eld); i > 0; i--, sad += 3) {
unsigned max_channels = sad_max_channels(sad);
@@ -57,7 +57,7 @@ static int eld_limit_channels(struct snd_pcm_hw_params *params,
struct snd_pcm_hw_rule *rule)
{
struct snd_interval *c = hw_param_interval(params, rule->var);
- struct snd_interval *r;
+ const struct snd_interval *r;
struct snd_interval t = { .min = 1, .max = 2, .integer = 1, };
unsigned int i;
const u8 *sad, *eld = rule->private;
@@ -67,7 +67,7 @@ static int eld_limit_channels(struct snd_pcm_hw_params *params,
unsigned int rate_mask = 0;
/* Convert the rate interval to a mask */
- r = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
+ r = hw_param_interval_c(params, SNDRV_PCM_HW_PARAM_RATE);
for (i = 0; i < ARRAY_SIZE(eld_rates); i++)
if (r->min <= eld_rates[i] && r->max >= eld_rates[i])
rate_mask |= BIT(i);
diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c
index 5088d4b..95b8ef1 100644
--- a/sound/core/pcm_lib.c
+++ b/sound/core/pcm_lib.c
@@ -33,6 +33,8 @@
#include <sound/pcm_params.h>
#include <sound/timer.h>
+#include "pcm_local.h"
+
#ifdef CONFIG_SND_PCM_XRUN_DEBUG
#define CREATE_TRACE_POINTS
#include "pcm_trace.h"
@@ -42,6 +44,9 @@
#define trace_hw_ptr_error(substream, reason)
#endif
+static int fill_silence_frames(struct snd_pcm_substream *substream,
+ snd_pcm_uframes_t off, snd_pcm_uframes_t frames);
+
/*
* fill ring buffer with silence
* runtime->silence_start: starting pointer to silence area
@@ -55,6 +60,7 @@ void snd_pcm_playback_silence(struct snd_pcm_substream *substream, snd_pcm_ufram
{
struct snd_pcm_runtime *runtime = substream->runtime;
snd_pcm_uframes_t frames, ofs, transfer;
+ int err;
if (runtime->silence_size < runtime->boundary) {
snd_pcm_sframes_t noise_dist, n;
@@ -107,33 +113,8 @@ void snd_pcm_playback_silence(struct snd_pcm_substream *substream, snd_pcm_ufram
ofs = runtime->silence_start % runtime->buffer_size;
while (frames > 0) {
transfer = ofs + frames > runtime->buffer_size ? runtime->buffer_size - ofs : frames;
- if (runtime->access == SNDRV_PCM_ACCESS_RW_INTERLEAVED ||
- runtime->access == SNDRV_PCM_ACCESS_MMAP_INTERLEAVED) {
- if (substream->ops->silence) {
- int err;
- err = substream->ops->silence(substream, -1, ofs, transfer);
- snd_BUG_ON(err < 0);
- } else {
- char *hwbuf = runtime->dma_area + frames_to_bytes(runtime, ofs);
- snd_pcm_format_set_silence(runtime->format, hwbuf, transfer * runtime->channels);
- }
- } else {
- unsigned int c;
- unsigned int channels = runtime->channels;
- if (substream->ops->silence) {
- for (c = 0; c < channels; ++c) {
- int err;
- err = substream->ops->silence(substream, c, ofs, transfer);
- snd_BUG_ON(err < 0);
- }
- } else {
- size_t dma_csize = runtime->dma_bytes / channels;
- for (c = 0; c < channels; ++c) {
- char *hwbuf = runtime->dma_area + (c * dma_csize) + samples_to_bytes(runtime, ofs);
- snd_pcm_format_set_silence(runtime->format, hwbuf, transfer);
- }
- }
- }
+ err = fill_silence_frames(substream, ofs, transfer);
+ snd_BUG_ON(err < 0);
runtime->silence_filled += transfer;
frames -= transfer;
ofs = 0;
@@ -1415,7 +1396,8 @@ static int snd_pcm_hw_rule_msbits(struct snd_pcm_hw_params *params,
unsigned int l = (unsigned long) rule->private;
int width = l & 0xffff;
unsigned int msbits = l >> 16;
- struct snd_interval *i = hw_param_interval(params, SNDRV_PCM_HW_PARAM_SAMPLE_BITS);
+ const struct snd_interval *i =
+ hw_param_interval_c(params, SNDRV_PCM_HW_PARAM_SAMPLE_BITS);
if (!snd_interval_single(i))
return 0;
@@ -1733,7 +1715,7 @@ EXPORT_SYMBOL(snd_pcm_hw_param_last);
int snd_pcm_hw_params_choose(struct snd_pcm_substream *pcm,
struct snd_pcm_hw_params *params)
{
- static int vars[] = {
+ static const int vars[] = {
SNDRV_PCM_HW_PARAM_ACCESS,
SNDRV_PCM_HW_PARAM_FORMAT,
SNDRV_PCM_HW_PARAM_SUBFORMAT,
@@ -1744,7 +1726,8 @@ int snd_pcm_hw_params_choose(struct snd_pcm_substream *pcm,
SNDRV_PCM_HW_PARAM_TICK_TIME,
-1
};
- int err, *v;
+ const int *v;
+ int err;
for (v = vars; *v != -1; v++) {
if (*v != SNDRV_PCM_HW_PARAM_BUFFER_SIZE)
@@ -1985,296 +1968,260 @@ static int wait_for_avail(struct snd_pcm_substream *substream,
return err;
}
-static int snd_pcm_lib_write_transfer(struct snd_pcm_substream *substream,
- unsigned int hwoff,
- unsigned long data, unsigned int off,
- snd_pcm_uframes_t frames)
+typedef int (*pcm_transfer_f)(struct snd_pcm_substream *substream,
+ int channel, unsigned long hwoff,
+ void *buf, unsigned long bytes);
+
+typedef int (*pcm_copy_f)(struct snd_pcm_substream *, snd_pcm_uframes_t, void *,
+ snd_pcm_uframes_t, snd_pcm_uframes_t, pcm_transfer_f);
+
+/* calculate the target DMA-buffer position to be written/read */
+static void *get_dma_ptr(struct snd_pcm_runtime *runtime,
+ int channel, unsigned long hwoff)
{
- struct snd_pcm_runtime *runtime = substream->runtime;
- int err;
- char __user *buf = (char __user *) data + frames_to_bytes(runtime, off);
- if (substream->ops->copy) {
- if ((err = substream->ops->copy(substream, -1, hwoff, buf, frames)) < 0)
- return err;
- } else {
- char *hwbuf = runtime->dma_area + frames_to_bytes(runtime, hwoff);
- if (copy_from_user(hwbuf, buf, frames_to_bytes(runtime, frames)))
- return -EFAULT;
- }
+ return runtime->dma_area + hwoff +
+ channel * (runtime->dma_bytes / runtime->channels);
+}
+
+/* default copy_user ops for write; used for both interleaved and non- modes */
+static int default_write_copy(struct snd_pcm_substream *substream,
+ int channel, unsigned long hwoff,
+ void *buf, unsigned long bytes)
+{
+ if (copy_from_user(get_dma_ptr(substream->runtime, channel, hwoff),
+ (void __user *)buf, bytes))
+ return -EFAULT;
+ return 0;
+}
+
+/* default copy_kernel ops for write */
+static int default_write_copy_kernel(struct snd_pcm_substream *substream,
+ int channel, unsigned long hwoff,
+ void *buf, unsigned long bytes)
+{
+ memcpy(get_dma_ptr(substream->runtime, channel, hwoff), buf, bytes);
return 0;
}
-
-typedef int (*transfer_f)(struct snd_pcm_substream *substream, unsigned int hwoff,
- unsigned long data, unsigned int off,
- snd_pcm_uframes_t size);
-static snd_pcm_sframes_t snd_pcm_lib_write1(struct snd_pcm_substream *substream,
- unsigned long data,
- snd_pcm_uframes_t size,
- int nonblock,
- transfer_f transfer)
+/* fill silence instead of copy data; called as a transfer helper
+ * from __snd_pcm_lib_write() or directly from noninterleaved_copy() when
+ * a NULL buffer is passed
+ */
+static int fill_silence(struct snd_pcm_substream *substream, int channel,
+ unsigned long hwoff, void *buf, unsigned long bytes)
{
struct snd_pcm_runtime *runtime = substream->runtime;
- snd_pcm_uframes_t xfer = 0;
- snd_pcm_uframes_t offset = 0;
- snd_pcm_uframes_t avail;
- int err = 0;
- if (size == 0)
+ if (substream->stream != SNDRV_PCM_STREAM_PLAYBACK)
return 0;
+ if (substream->ops->fill_silence)
+ return substream->ops->fill_silence(substream, channel,
+ hwoff, bytes);
- snd_pcm_stream_lock_irq(substream);
- switch (runtime->status->state) {
- case SNDRV_PCM_STATE_PREPARED:
- case SNDRV_PCM_STATE_RUNNING:
- case SNDRV_PCM_STATE_PAUSED:
- break;
- case SNDRV_PCM_STATE_XRUN:
- err = -EPIPE;
- goto _end_unlock;
- case SNDRV_PCM_STATE_SUSPENDED:
- err = -ESTRPIPE;
- goto _end_unlock;
- default:
- err = -EBADFD;
- goto _end_unlock;
- }
-
- runtime->twake = runtime->control->avail_min ? : 1;
- if (runtime->status->state == SNDRV_PCM_STATE_RUNNING)
- snd_pcm_update_hw_ptr(substream);
- avail = snd_pcm_playback_avail(runtime);
- while (size > 0) {
- snd_pcm_uframes_t frames, appl_ptr, appl_ofs;
- snd_pcm_uframes_t cont;
- if (!avail) {
- if (nonblock) {
- err = -EAGAIN;
- goto _end_unlock;
- }
- runtime->twake = min_t(snd_pcm_uframes_t, size,
- runtime->control->avail_min ? : 1);
- err = wait_for_avail(substream, &avail);
- if (err < 0)
- goto _end_unlock;
- }
- frames = size > avail ? avail : size;
- cont = runtime->buffer_size - runtime->control->appl_ptr % runtime->buffer_size;
- if (frames > cont)
- frames = cont;
- if (snd_BUG_ON(!frames)) {
- runtime->twake = 0;
- snd_pcm_stream_unlock_irq(substream);
- return -EINVAL;
- }
- appl_ptr = runtime->control->appl_ptr;
- appl_ofs = appl_ptr % runtime->buffer_size;
- snd_pcm_stream_unlock_irq(substream);
- err = transfer(substream, appl_ofs, data, offset, frames);
- snd_pcm_stream_lock_irq(substream);
- if (err < 0)
- goto _end_unlock;
- switch (runtime->status->state) {
- case SNDRV_PCM_STATE_XRUN:
- err = -EPIPE;
- goto _end_unlock;
- case SNDRV_PCM_STATE_SUSPENDED:
- err = -ESTRPIPE;
- goto _end_unlock;
- default:
- break;
- }
- appl_ptr += frames;
- if (appl_ptr >= runtime->boundary)
- appl_ptr -= runtime->boundary;
- runtime->control->appl_ptr = appl_ptr;
- if (substream->ops->ack)
- substream->ops->ack(substream);
-
- offset += frames;
- size -= frames;
- xfer += frames;
- avail -= frames;
- if (runtime->status->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)
- goto _end_unlock;
- }
- }
- _end_unlock:
- runtime->twake = 0;
- if (xfer > 0 && err >= 0)
- snd_pcm_update_state(substream, runtime);
- snd_pcm_stream_unlock_irq(substream);
- return xfer > 0 ? (snd_pcm_sframes_t)xfer : err;
+ snd_pcm_format_set_silence(runtime->format,
+ get_dma_ptr(runtime, channel, hwoff),
+ bytes_to_samples(runtime, bytes));
+ return 0;
}
-/* sanity-check for read/write methods */
-static int pcm_sanity_check(struct snd_pcm_substream *substream)
+/* default copy_user ops for read; used for both interleaved and non- modes */
+static int default_read_copy(struct snd_pcm_substream *substream,
+ int channel, unsigned long hwoff,
+ void *buf, unsigned long bytes)
{
- struct snd_pcm_runtime *runtime;
- if (PCM_RUNTIME_CHECK(substream))
- return -ENXIO;
- runtime = substream->runtime;
- if (snd_BUG_ON(!substream->ops->copy && !runtime->dma_area))
- return -EINVAL;
- if (runtime->status->state == SNDRV_PCM_STATE_OPEN)
- return -EBADFD;
+ if (copy_to_user((void __user *)buf,
+ get_dma_ptr(substream->runtime, channel, hwoff),
+ bytes))
+ return -EFAULT;
return 0;
}
-snd_pcm_sframes_t snd_pcm_lib_write(struct snd_pcm_substream *substream, const void __user *buf, snd_pcm_uframes_t size)
+/* default copy_kernel ops for read */
+static int default_read_copy_kernel(struct snd_pcm_substream *substream,
+ int channel, unsigned long hwoff,
+ void *buf, unsigned long bytes)
{
- struct snd_pcm_runtime *runtime;
- int nonblock;
- int err;
+ memcpy(buf, get_dma_ptr(substream->runtime, channel, hwoff), bytes);
+ return 0;
+}
- err = pcm_sanity_check(substream);
- if (err < 0)
- return err;
- runtime = substream->runtime;
- nonblock = !!(substream->f_flags & O_NONBLOCK);
+/* call transfer function with the converted pointers and sizes;
+ * for interleaved mode, it's one shot for all samples
+ */
+static int interleaved_copy(struct snd_pcm_substream *substream,
+ snd_pcm_uframes_t hwoff, void *data,
+ snd_pcm_uframes_t off,
+ snd_pcm_uframes_t frames,
+ pcm_transfer_f transfer)
+{
+ struct snd_pcm_runtime *runtime = substream->runtime;
- if (runtime->access != SNDRV_PCM_ACCESS_RW_INTERLEAVED &&
- runtime->channels > 1)
- return -EINVAL;
- return snd_pcm_lib_write1(substream, (unsigned long)buf, size, nonblock,
- snd_pcm_lib_write_transfer);
+ /* convert to bytes */
+ hwoff = frames_to_bytes(runtime, hwoff);
+ off = frames_to_bytes(runtime, off);
+ frames = frames_to_bytes(runtime, frames);
+ return transfer(substream, 0, hwoff, data + off, frames);
}
-EXPORT_SYMBOL(snd_pcm_lib_write);
-
-static int snd_pcm_lib_writev_transfer(struct snd_pcm_substream *substream,
- unsigned int hwoff,
- unsigned long data, unsigned int off,
- snd_pcm_uframes_t frames)
+/* call transfer function with the converted pointers and sizes for each
+ * non-interleaved channel; when buffer is NULL, silencing instead of copying
+ */
+static int noninterleaved_copy(struct snd_pcm_substream *substream,
+ snd_pcm_uframes_t hwoff, void *data,
+ snd_pcm_uframes_t off,
+ snd_pcm_uframes_t frames,
+ pcm_transfer_f transfer)
{
struct snd_pcm_runtime *runtime = substream->runtime;
- int err;
- void __user **bufs = (void __user **)data;
int channels = runtime->channels;
- int c;
- if (substream->ops->copy) {
- if (snd_BUG_ON(!substream->ops->silence))
- return -EINVAL;
- for (c = 0; c < channels; ++c, ++bufs) {
- if (*bufs == NULL) {
- if ((err = substream->ops->silence(substream, c, hwoff, frames)) < 0)
- return err;
- } else {
- char __user *buf = *bufs + samples_to_bytes(runtime, off);
- if ((err = substream->ops->copy(substream, c, hwoff, buf, frames)) < 0)
- return err;
- }
- }
- } else {
- /* default transfer behaviour */
- size_t dma_csize = runtime->dma_bytes / channels;
- for (c = 0; c < channels; ++c, ++bufs) {
- char *hwbuf = runtime->dma_area + (c * dma_csize) + samples_to_bytes(runtime, hwoff);
- if (*bufs == NULL) {
- snd_pcm_format_set_silence(runtime->format, hwbuf, frames);
- } else {
- char __user *buf = *bufs + samples_to_bytes(runtime, off);
- if (copy_from_user(hwbuf, buf, samples_to_bytes(runtime, frames)))
- return -EFAULT;
- }
- }
+ void **bufs = data;
+ int c, err;
+
+ /* convert to bytes; note that it's not frames_to_bytes() here.
+ * in non-interleaved mode, we copy for each channel, thus
+ * each copy is n_samples bytes x channels = whole frames.
+ */
+ off = samples_to_bytes(runtime, off);
+ frames = samples_to_bytes(runtime, frames);
+ hwoff = samples_to_bytes(runtime, hwoff);
+ for (c = 0; c < channels; ++c, ++bufs) {
+ if (!data || !*bufs)
+ err = fill_silence(substream, c, hwoff, NULL, frames);
+ else
+ err = transfer(substream, c, hwoff, *bufs + off,
+ frames);
+ if (err < 0)
+ return err;
}
return 0;
}
-
-snd_pcm_sframes_t snd_pcm_lib_writev(struct snd_pcm_substream *substream,
- void __user **bufs,
- snd_pcm_uframes_t frames)
+
+/* fill silence on the given buffer position;
+ * called from snd_pcm_playback_silence()
+ */
+static int fill_silence_frames(struct snd_pcm_substream *substream,
+ snd_pcm_uframes_t off, snd_pcm_uframes_t frames)
{
- struct snd_pcm_runtime *runtime;
- int nonblock;
- int err;
+ if (substream->runtime->access == SNDRV_PCM_ACCESS_RW_INTERLEAVED ||
+ substream->runtime->access == SNDRV_PCM_ACCESS_MMAP_INTERLEAVED)
+ return interleaved_copy(substream, off, NULL, 0, frames,
+ fill_silence);
+ else
+ return noninterleaved_copy(substream, off, NULL, 0, frames,
+ fill_silence);
+}
- err = pcm_sanity_check(substream);
- if (err < 0)
- return err;
+/* sanity-check for read/write methods */
+static int pcm_sanity_check(struct snd_pcm_substream *substream)
+{
+ struct snd_pcm_runtime *runtime;
+ if (PCM_RUNTIME_CHECK(substream))
+ return -ENXIO;
runtime = substream->runtime;
- nonblock = !!(substream->f_flags & O_NONBLOCK);
-
- if (runtime->access != SNDRV_PCM_ACCESS_RW_NONINTERLEAVED)
+ if (snd_BUG_ON(!substream->ops->copy_user && !runtime->dma_area))
return -EINVAL;
- return snd_pcm_lib_write1(substream, (unsigned long)bufs, frames,
- nonblock, snd_pcm_lib_writev_transfer);
+ if (runtime->status->state == SNDRV_PCM_STATE_OPEN)
+ return -EBADFD;
+ return 0;
}
-EXPORT_SYMBOL(snd_pcm_lib_writev);
-
-static int snd_pcm_lib_read_transfer(struct snd_pcm_substream *substream,
- unsigned int hwoff,
- unsigned long data, unsigned int off,
- snd_pcm_uframes_t frames)
+static int pcm_accessible_state(struct snd_pcm_runtime *runtime)
{
- struct snd_pcm_runtime *runtime = substream->runtime;
- int err;
- char __user *buf = (char __user *) data + frames_to_bytes(runtime, off);
- if (substream->ops->copy) {
- if ((err = substream->ops->copy(substream, -1, hwoff, buf, frames)) < 0)
- return err;
- } else {
- char *hwbuf = runtime->dma_area + frames_to_bytes(runtime, hwoff);
- if (copy_to_user(buf, hwbuf, frames_to_bytes(runtime, frames)))
- return -EFAULT;
+ switch (runtime->status->state) {
+ case SNDRV_PCM_STATE_PREPARED:
+ case SNDRV_PCM_STATE_RUNNING:
+ case SNDRV_PCM_STATE_PAUSED:
+ return 0;
+ case SNDRV_PCM_STATE_XRUN:
+ return -EPIPE;
+ case SNDRV_PCM_STATE_SUSPENDED:
+ return -ESTRPIPE;
+ default:
+ return -EBADFD;
}
- return 0;
}
-static snd_pcm_sframes_t snd_pcm_lib_read1(struct snd_pcm_substream *substream,
- unsigned long data,
- snd_pcm_uframes_t size,
- int nonblock,
- transfer_f transfer)
+/* the common loop for read/write data */
+snd_pcm_sframes_t __snd_pcm_lib_xfer(struct snd_pcm_substream *substream,
+ void *data, bool interleaved,
+ snd_pcm_uframes_t size, bool in_kernel)
{
struct snd_pcm_runtime *runtime = substream->runtime;
snd_pcm_uframes_t xfer = 0;
snd_pcm_uframes_t offset = 0;
snd_pcm_uframes_t avail;
- int err = 0;
+ pcm_copy_f writer;
+ pcm_transfer_f transfer;
+ bool nonblock;
+ bool is_playback;
+ int err;
+
+ err = pcm_sanity_check(substream);
+ if (err < 0)
+ return err;
+
+ is_playback = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
+ if (interleaved) {
+ if (runtime->access != SNDRV_PCM_ACCESS_RW_INTERLEAVED &&
+ runtime->channels > 1)
+ return -EINVAL;
+ writer = interleaved_copy;
+ } else {
+ if (runtime->access != SNDRV_PCM_ACCESS_RW_NONINTERLEAVED)
+ return -EINVAL;
+ writer = noninterleaved_copy;
+ }
+
+ if (!data) {
+ if (is_playback)
+ transfer = fill_silence;
+ else
+ return -EINVAL;
+ } else if (in_kernel) {
+ if (substream->ops->copy_kernel)
+ transfer = substream->ops->copy_kernel;
+ else
+ transfer = is_playback ?
+ default_write_copy_kernel : default_read_copy_kernel;
+ } else {
+ if (substream->ops->copy_user)
+ transfer = (pcm_transfer_f)substream->ops->copy_user;
+ else
+ transfer = is_playback ?
+ default_write_copy : default_read_copy;
+ }
if (size == 0)
return 0;
+ nonblock = !!(substream->f_flags & O_NONBLOCK);
+
snd_pcm_stream_lock_irq(substream);
- switch (runtime->status->state) {
- case SNDRV_PCM_STATE_PREPARED:
- if (size >= runtime->start_threshold) {
- err = snd_pcm_start(substream);
- if (err < 0)
- goto _end_unlock;
- }
- break;
- case SNDRV_PCM_STATE_DRAINING:
- case SNDRV_PCM_STATE_RUNNING:
- case SNDRV_PCM_STATE_PAUSED:
- break;
- case SNDRV_PCM_STATE_XRUN:
- err = -EPIPE;
- goto _end_unlock;
- case SNDRV_PCM_STATE_SUSPENDED:
- err = -ESTRPIPE;
- goto _end_unlock;
- default:
- err = -EBADFD;
+ err = pcm_accessible_state(runtime);
+ if (err < 0)
goto _end_unlock;
+
+ if (!is_playback &&
+ runtime->status->state == SNDRV_PCM_STATE_PREPARED &&
+ size >= runtime->start_threshold) {
+ err = snd_pcm_start(substream);
+ if (err < 0)
+ goto _end_unlock;
}
runtime->twake = runtime->control->avail_min ? : 1;
if (runtime->status->state == SNDRV_PCM_STATE_RUNNING)
snd_pcm_update_hw_ptr(substream);
- avail = snd_pcm_capture_avail(runtime);
+ if (is_playback)
+ avail = snd_pcm_playback_avail(runtime);
+ else
+ avail = snd_pcm_capture_avail(runtime);
while (size > 0) {
snd_pcm_uframes_t frames, appl_ptr, appl_ofs;
snd_pcm_uframes_t cont;
if (!avail) {
- if (runtime->status->state ==
- SNDRV_PCM_STATE_DRAINING) {
+ if (!is_playback &&
+ runtime->status->state == SNDRV_PCM_STATE_DRAINING) {
snd_pcm_stop(substream, SNDRV_PCM_STATE_SETUP);
goto _end_unlock;
}
@@ -2302,20 +2249,14 @@ static snd_pcm_sframes_t snd_pcm_lib_read1(struct snd_pcm_substream *substream,
appl_ptr = runtime->control->appl_ptr;
appl_ofs = appl_ptr % runtime->buffer_size;
snd_pcm_stream_unlock_irq(substream);
- err = transfer(substream, appl_ofs, data, offset, frames);
+ err = writer(substream, appl_ofs, data, offset, frames,
+ transfer);
snd_pcm_stream_lock_irq(substream);
if (err < 0)
goto _end_unlock;
- switch (runtime->status->state) {
- case SNDRV_PCM_STATE_XRUN:
- err = -EPIPE;
- goto _end_unlock;
- case SNDRV_PCM_STATE_SUSPENDED:
- err = -ESTRPIPE;
+ err = pcm_accessible_state(runtime);
+ if (err < 0)
goto _end_unlock;
- default:
- break;
- }
appl_ptr += frames;
if (appl_ptr >= runtime->boundary)
appl_ptr -= runtime->boundary;
@@ -2327,6 +2268,13 @@ static snd_pcm_sframes_t snd_pcm_lib_read1(struct snd_pcm_substream *substream,
size -= frames;
xfer += frames;
avail -= frames;
+ if (is_playback &&
+ runtime->status->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)
+ goto _end_unlock;
+ }
}
_end_unlock:
runtime->twake = 0;
@@ -2335,83 +2283,7 @@ static snd_pcm_sframes_t snd_pcm_lib_read1(struct snd_pcm_substream *substream,
snd_pcm_stream_unlock_irq(substream);
return xfer > 0 ? (snd_pcm_sframes_t)xfer : err;
}
-
-snd_pcm_sframes_t snd_pcm_lib_read(struct snd_pcm_substream *substream, void __user *buf, snd_pcm_uframes_t size)
-{
- struct snd_pcm_runtime *runtime;
- int nonblock;
- int err;
-
- err = pcm_sanity_check(substream);
- if (err < 0)
- return err;
- runtime = substream->runtime;
- nonblock = !!(substream->f_flags & O_NONBLOCK);
- if (runtime->access != SNDRV_PCM_ACCESS_RW_INTERLEAVED)
- return -EINVAL;
- return snd_pcm_lib_read1(substream, (unsigned long)buf, size, nonblock, snd_pcm_lib_read_transfer);
-}
-
-EXPORT_SYMBOL(snd_pcm_lib_read);
-
-static int snd_pcm_lib_readv_transfer(struct snd_pcm_substream *substream,
- unsigned int hwoff,
- unsigned long data, unsigned int off,
- snd_pcm_uframes_t frames)
-{
- struct snd_pcm_runtime *runtime = substream->runtime;
- int err;
- void __user **bufs = (void __user **)data;
- int channels = runtime->channels;
- int c;
- if (substream->ops->copy) {
- for (c = 0; c < channels; ++c, ++bufs) {
- char __user *buf;
- if (*bufs == NULL)
- continue;
- buf = *bufs + samples_to_bytes(runtime, off);
- if ((err = substream->ops->copy(substream, c, hwoff, buf, frames)) < 0)
- return err;
- }
- } else {
- snd_pcm_uframes_t dma_csize = runtime->dma_bytes / channels;
- for (c = 0; c < channels; ++c, ++bufs) {
- char *hwbuf;
- char __user *buf;
- if (*bufs == NULL)
- continue;
-
- hwbuf = runtime->dma_area + (c * dma_csize) + samples_to_bytes(runtime, hwoff);
- buf = *bufs + samples_to_bytes(runtime, off);
- if (copy_to_user(buf, hwbuf, samples_to_bytes(runtime, frames)))
- return -EFAULT;
- }
- }
- return 0;
-}
-
-snd_pcm_sframes_t snd_pcm_lib_readv(struct snd_pcm_substream *substream,
- void __user **bufs,
- snd_pcm_uframes_t frames)
-{
- struct snd_pcm_runtime *runtime;
- int nonblock;
- int err;
-
- err = pcm_sanity_check(substream);
- if (err < 0)
- return err;
- runtime = substream->runtime;
- if (runtime->status->state == SNDRV_PCM_STATE_OPEN)
- return -EBADFD;
-
- nonblock = !!(substream->f_flags & O_NONBLOCK);
- if (runtime->access != SNDRV_PCM_ACCESS_RW_NONINTERLEAVED)
- return -EINVAL;
- return snd_pcm_lib_read1(substream, (unsigned long)bufs, frames, nonblock, snd_pcm_lib_readv_transfer);
-}
-
-EXPORT_SYMBOL(snd_pcm_lib_readv);
+EXPORT_SYMBOL(__snd_pcm_lib_xfer);
/*
* standard channel mapping helpers
diff --git a/sound/core/pcm_local.h b/sound/core/pcm_local.h
new file mode 100644
index 0000000..34c66de
--- /dev/null
+++ b/sound/core/pcm_local.h
@@ -0,0 +1,51 @@
+/*
+ * pcm_local.h - a local header file for snd-pcm module.
+ *
+ * Copyright (c) Takashi Sakamoto <o-takashi@sakamocchi.jp>
+ *
+ * Licensed under the terms of the GNU General Public License, version 2.
+ */
+
+#ifndef __SOUND_CORE_PCM_LOCAL_H
+#define __SOUND_CORE_PCM_LOCAL_H
+
+extern const struct snd_pcm_hw_constraint_list snd_pcm_known_rates;
+
+void snd_interval_mul(const struct snd_interval *a,
+ const struct snd_interval *b, struct snd_interval *c);
+void snd_interval_div(const struct snd_interval *a,
+ const struct snd_interval *b, struct snd_interval *c);
+void snd_interval_muldivk(const struct snd_interval *a,
+ const struct snd_interval *b,
+ unsigned int k, struct snd_interval *c);
+void snd_interval_mulkdiv(const struct snd_interval *a, unsigned int k,
+ const struct snd_interval *b, struct snd_interval *c);
+
+int snd_pcm_hw_constraints_init(struct snd_pcm_substream *substream);
+int snd_pcm_hw_constraints_complete(struct snd_pcm_substream *substream);
+
+int snd_pcm_hw_params_choose(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params);
+
+int snd_pcm_hw_constraint_mask(struct snd_pcm_runtime *runtime,
+ snd_pcm_hw_param_t var, u_int32_t mask);
+
+int snd_pcm_update_state(struct snd_pcm_substream *substream,
+ struct snd_pcm_runtime *runtime);
+int snd_pcm_update_hw_ptr(struct snd_pcm_substream *substream);
+
+void snd_pcm_playback_silence(struct snd_pcm_substream *substream,
+ snd_pcm_uframes_t new_hw_ptr);
+
+#ifdef CONFIG_SND_PCM_TIMER
+void snd_pcm_timer_resolution_change(struct snd_pcm_substream *substream);
+void snd_pcm_timer_init(struct snd_pcm_substream *substream);
+void snd_pcm_timer_done(struct snd_pcm_substream *substream);
+#else
+static inline void
+snd_pcm_timer_resolution_change(struct snd_pcm_substream *substream) {}
+static inline void snd_pcm_timer_init(struct snd_pcm_substream *substream) {}
+static inline void snd_pcm_timer_done(struct snd_pcm_substream *substream) {}
+#endif
+
+#endif /* __SOUND_CORE_PCM_LOCAL_H */
diff --git a/sound/core/pcm_misc.c b/sound/core/pcm_misc.c
index 53dc373..dd8383e 100644
--- a/sound/core/pcm_misc.c
+++ b/sound/core/pcm_misc.c
@@ -23,6 +23,9 @@
#include <linux/export.h>
#include <sound/core.h>
#include <sound/pcm.h>
+
+#include "pcm_local.h"
+
#define SND_PCM_FORMAT_UNKNOWN (-1)
/* NOTE: "signed" prefix must be given below since the default char is
diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c
index 13dec5e..bf5d0f2 100644
--- a/sound/core/pcm_native.c
+++ b/sound/core/pcm_native.c
@@ -37,6 +37,8 @@
#include <sound/minors.h>
#include <linux/uio.h>
+#include "pcm_local.h"
+
/*
* Compatibility
*/
@@ -181,20 +183,6 @@ void snd_pcm_stream_unlock_irqrestore(struct snd_pcm_substream *substream,
}
EXPORT_SYMBOL_GPL(snd_pcm_stream_unlock_irqrestore);
-static inline mm_segment_t snd_enter_user(void)
-{
- mm_segment_t fs = get_fs();
- set_fs(get_ds());
- return fs;
-}
-
-static inline void snd_leave_user(mm_segment_t fs)
-{
- set_fs(fs);
-}
-
-
-
int snd_pcm_info(struct snd_pcm_substream *substream, struct snd_pcm_info *info)
{
struct snd_pcm_runtime *runtime;
@@ -1081,6 +1069,7 @@ static const struct action_ops snd_pcm_action_start = {
* @substream: the PCM substream instance
*
* Return: Zero if successful, or a negative error code.
+ * The stream lock must be acquired before calling this function.
*/
int snd_pcm_start(struct snd_pcm_substream *substream)
{
@@ -1088,6 +1077,13 @@ int snd_pcm_start(struct snd_pcm_substream *substream)
SNDRV_PCM_STATE_RUNNING);
}
+/* take the stream lock and start the streams */
+static int snd_pcm_start_lock_irq(struct snd_pcm_substream *substream)
+{
+ return snd_pcm_action_lock_irq(&snd_pcm_action_start, substream,
+ SNDRV_PCM_STATE_RUNNING);
+}
+
/*
* stop callbacks
*/
@@ -1940,7 +1936,8 @@ static int snd_pcm_hw_rule_format(struct snd_pcm_hw_params *params,
struct snd_pcm_hw_rule *rule)
{
unsigned int k;
- struct snd_interval *i = hw_param_interval(params, rule->deps[0]);
+ const struct snd_interval *i =
+ hw_param_interval_c(params, rule->deps[0]);
struct snd_mask m;
struct snd_mask *mask = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT);
snd_mask_any(&m);
@@ -1986,8 +1983,10 @@ static int snd_pcm_hw_rule_sample_bits(struct snd_pcm_hw_params *params,
#error "Change this table"
#endif
-static unsigned int rates[] = { 5512, 8000, 11025, 16000, 22050, 32000, 44100,
- 48000, 64000, 88200, 96000, 176400, 192000 };
+static const unsigned int rates[] = {
+ 5512, 8000, 11025, 16000, 22050, 32000, 44100,
+ 48000, 64000, 88200, 96000, 176400, 192000
+};
const struct snd_pcm_hw_constraint_list snd_pcm_known_rates = {
.count = ARRAY_SIZE(rates),
@@ -2428,50 +2427,105 @@ static int snd_pcm_release(struct inode *inode, struct file *file)
return 0;
}
-static snd_pcm_sframes_t snd_pcm_playback_rewind(struct snd_pcm_substream *substream,
- snd_pcm_uframes_t frames)
+/* check and update PCM state; return 0 or a negative error
+ * call this inside PCM lock
+ */
+static int do_pcm_hwsync(struct snd_pcm_substream *substream)
{
- struct snd_pcm_runtime *runtime = substream->runtime;
- snd_pcm_sframes_t appl_ptr;
- snd_pcm_sframes_t ret;
- snd_pcm_sframes_t hw_avail;
-
- if (frames == 0)
- return 0;
-
- snd_pcm_stream_lock_irq(substream);
- switch (runtime->status->state) {
- case SNDRV_PCM_STATE_PREPARED:
- break;
+ switch (substream->runtime->status->state) {
case SNDRV_PCM_STATE_DRAINING:
- case SNDRV_PCM_STATE_RUNNING:
- if (snd_pcm_update_hw_ptr(substream) >= 0)
- break;
+ if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
+ return -EBADFD;
/* Fall through */
- case SNDRV_PCM_STATE_XRUN:
- ret = -EPIPE;
- goto __end;
+ case SNDRV_PCM_STATE_RUNNING:
+ return snd_pcm_update_hw_ptr(substream);
+ case SNDRV_PCM_STATE_PREPARED:
+ case SNDRV_PCM_STATE_PAUSED:
+ return 0;
case SNDRV_PCM_STATE_SUSPENDED:
- ret = -ESTRPIPE;
- goto __end;
+ return -ESTRPIPE;
+ case SNDRV_PCM_STATE_XRUN:
+ return -EPIPE;
default:
- ret = -EBADFD;
- goto __end;
+ return -EBADFD;
}
+}
- hw_avail = snd_pcm_playback_hw_avail(runtime);
- if (hw_avail <= 0) {
- ret = 0;
- goto __end;
+/* update to the given appl_ptr and call ack callback if needed;
+ * when an error is returned, take back to the original value
+ */
+static int apply_appl_ptr(struct snd_pcm_substream *substream,
+ snd_pcm_uframes_t appl_ptr)
+{
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ snd_pcm_uframes_t old_appl_ptr = runtime->control->appl_ptr;
+ int ret;
+
+ runtime->control->appl_ptr = appl_ptr;
+ if (substream->ops->ack) {
+ ret = substream->ops->ack(substream);
+ if (ret < 0) {
+ runtime->control->appl_ptr = old_appl_ptr;
+ return ret;
+ }
}
- if (frames > (snd_pcm_uframes_t)hw_avail)
- frames = hw_avail;
+ return 0;
+}
+
+/* increase the appl_ptr; returns the processed frames or a negative error */
+static snd_pcm_sframes_t forward_appl_ptr(struct snd_pcm_substream *substream,
+ snd_pcm_uframes_t frames,
+ snd_pcm_sframes_t avail)
+{
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ snd_pcm_sframes_t appl_ptr;
+ int ret;
+
+ if (avail <= 0)
+ return 0;
+ if (frames > (snd_pcm_uframes_t)avail)
+ frames = avail;
+ appl_ptr = runtime->control->appl_ptr + frames;
+ if (appl_ptr >= (snd_pcm_sframes_t)runtime->boundary)
+ appl_ptr -= runtime->boundary;
+ ret = apply_appl_ptr(substream, appl_ptr);
+ return ret < 0 ? ret : frames;
+}
+
+/* decrease the appl_ptr; returns the processed frames or a negative error */
+static snd_pcm_sframes_t rewind_appl_ptr(struct snd_pcm_substream *substream,
+ snd_pcm_uframes_t frames,
+ snd_pcm_sframes_t avail)
+{
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ snd_pcm_sframes_t appl_ptr;
+ int ret;
+
+ if (avail <= 0)
+ return 0;
+ if (frames > (snd_pcm_uframes_t)avail)
+ frames = avail;
appl_ptr = runtime->control->appl_ptr - frames;
if (appl_ptr < 0)
appl_ptr += runtime->boundary;
- runtime->control->appl_ptr = appl_ptr;
- ret = frames;
- __end:
+ ret = apply_appl_ptr(substream, appl_ptr);
+ return ret < 0 ? ret : frames;
+}
+
+static snd_pcm_sframes_t snd_pcm_playback_rewind(struct snd_pcm_substream *substream,
+ snd_pcm_uframes_t frames)
+{
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ snd_pcm_sframes_t ret;
+
+ if (frames == 0)
+ return 0;
+
+ snd_pcm_stream_lock_irq(substream);
+ ret = do_pcm_hwsync(substream);
+ if (!ret)
+ ret = rewind_appl_ptr(substream, frames,
+ snd_pcm_playback_hw_avail(runtime));
snd_pcm_stream_unlock_irq(substream);
return ret;
}
@@ -2480,46 +2534,16 @@ static snd_pcm_sframes_t snd_pcm_capture_rewind(struct snd_pcm_substream *substr
snd_pcm_uframes_t frames)
{
struct snd_pcm_runtime *runtime = substream->runtime;
- snd_pcm_sframes_t appl_ptr;
snd_pcm_sframes_t ret;
- snd_pcm_sframes_t hw_avail;
if (frames == 0)
return 0;
snd_pcm_stream_lock_irq(substream);
- switch (runtime->status->state) {
- case SNDRV_PCM_STATE_PREPARED:
- case SNDRV_PCM_STATE_DRAINING:
- break;
- case SNDRV_PCM_STATE_RUNNING:
- if (snd_pcm_update_hw_ptr(substream) >= 0)
- break;
- /* Fall through */
- case SNDRV_PCM_STATE_XRUN:
- ret = -EPIPE;
- goto __end;
- case SNDRV_PCM_STATE_SUSPENDED:
- ret = -ESTRPIPE;
- goto __end;
- default:
- ret = -EBADFD;
- goto __end;
- }
-
- hw_avail = snd_pcm_capture_hw_avail(runtime);
- if (hw_avail <= 0) {
- ret = 0;
- goto __end;
- }
- if (frames > (snd_pcm_uframes_t)hw_avail)
- frames = hw_avail;
- appl_ptr = runtime->control->appl_ptr - frames;
- if (appl_ptr < 0)
- appl_ptr += runtime->boundary;
- runtime->control->appl_ptr = appl_ptr;
- ret = frames;
- __end:
+ ret = do_pcm_hwsync(substream);
+ if (!ret)
+ ret = rewind_appl_ptr(substream, frames,
+ snd_pcm_capture_hw_avail(runtime));
snd_pcm_stream_unlock_irq(substream);
return ret;
}
@@ -2528,47 +2552,16 @@ static snd_pcm_sframes_t snd_pcm_playback_forward(struct snd_pcm_substream *subs
snd_pcm_uframes_t frames)
{
struct snd_pcm_runtime *runtime = substream->runtime;
- snd_pcm_sframes_t appl_ptr;
snd_pcm_sframes_t ret;
- snd_pcm_sframes_t avail;
if (frames == 0)
return 0;
snd_pcm_stream_lock_irq(substream);
- switch (runtime->status->state) {
- case SNDRV_PCM_STATE_PREPARED:
- case SNDRV_PCM_STATE_PAUSED:
- break;
- case SNDRV_PCM_STATE_DRAINING:
- case SNDRV_PCM_STATE_RUNNING:
- if (snd_pcm_update_hw_ptr(substream) >= 0)
- break;
- /* Fall through */
- case SNDRV_PCM_STATE_XRUN:
- ret = -EPIPE;
- goto __end;
- case SNDRV_PCM_STATE_SUSPENDED:
- ret = -ESTRPIPE;
- goto __end;
- default:
- ret = -EBADFD;
- goto __end;
- }
-
- avail = snd_pcm_playback_avail(runtime);
- if (avail <= 0) {
- ret = 0;
- goto __end;
- }
- if (frames > (snd_pcm_uframes_t)avail)
- frames = avail;
- appl_ptr = runtime->control->appl_ptr + frames;
- if (appl_ptr >= (snd_pcm_sframes_t)runtime->boundary)
- appl_ptr -= runtime->boundary;
- runtime->control->appl_ptr = appl_ptr;
- ret = frames;
- __end:
+ ret = do_pcm_hwsync(substream);
+ if (!ret)
+ ret = forward_appl_ptr(substream, frames,
+ snd_pcm_playback_avail(runtime));
snd_pcm_stream_unlock_irq(substream);
return ret;
}
@@ -2577,123 +2570,47 @@ static snd_pcm_sframes_t snd_pcm_capture_forward(struct snd_pcm_substream *subst
snd_pcm_uframes_t frames)
{
struct snd_pcm_runtime *runtime = substream->runtime;
- snd_pcm_sframes_t appl_ptr;
snd_pcm_sframes_t ret;
- snd_pcm_sframes_t avail;
if (frames == 0)
return 0;
snd_pcm_stream_lock_irq(substream);
- switch (runtime->status->state) {
- case SNDRV_PCM_STATE_PREPARED:
- case SNDRV_PCM_STATE_DRAINING:
- case SNDRV_PCM_STATE_PAUSED:
- break;
- case SNDRV_PCM_STATE_RUNNING:
- if (snd_pcm_update_hw_ptr(substream) >= 0)
- break;
- /* Fall through */
- case SNDRV_PCM_STATE_XRUN:
- ret = -EPIPE;
- goto __end;
- case SNDRV_PCM_STATE_SUSPENDED:
- ret = -ESTRPIPE;
- goto __end;
- default:
- ret = -EBADFD;
- goto __end;
- }
-
- avail = snd_pcm_capture_avail(runtime);
- if (avail <= 0) {
- ret = 0;
- goto __end;
- }
- if (frames > (snd_pcm_uframes_t)avail)
- frames = avail;
- appl_ptr = runtime->control->appl_ptr + frames;
- if (appl_ptr >= (snd_pcm_sframes_t)runtime->boundary)
- appl_ptr -= runtime->boundary;
- runtime->control->appl_ptr = appl_ptr;
- ret = frames;
- __end:
+ ret = do_pcm_hwsync(substream);
+ if (!ret)
+ ret = forward_appl_ptr(substream, frames,
+ snd_pcm_capture_avail(runtime));
snd_pcm_stream_unlock_irq(substream);
return ret;
}
static int snd_pcm_hwsync(struct snd_pcm_substream *substream)
{
- struct snd_pcm_runtime *runtime = substream->runtime;
int err;
snd_pcm_stream_lock_irq(substream);
- switch (runtime->status->state) {
- case SNDRV_PCM_STATE_DRAINING:
- if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
- goto __badfd;
- /* Fall through */
- case SNDRV_PCM_STATE_RUNNING:
- if ((err = snd_pcm_update_hw_ptr(substream)) < 0)
- break;
- /* Fall through */
- case SNDRV_PCM_STATE_PREPARED:
- err = 0;
- break;
- case SNDRV_PCM_STATE_SUSPENDED:
- err = -ESTRPIPE;
- break;
- case SNDRV_PCM_STATE_XRUN:
- err = -EPIPE;
- break;
- default:
- __badfd:
- err = -EBADFD;
- break;
- }
+ err = do_pcm_hwsync(substream);
snd_pcm_stream_unlock_irq(substream);
return err;
}
-static int snd_pcm_delay(struct snd_pcm_substream *substream,
- snd_pcm_sframes_t __user *res)
+static snd_pcm_sframes_t snd_pcm_delay(struct snd_pcm_substream *substream)
{
struct snd_pcm_runtime *runtime = substream->runtime;
int err;
snd_pcm_sframes_t n = 0;
snd_pcm_stream_lock_irq(substream);
- switch (runtime->status->state) {
- case SNDRV_PCM_STATE_DRAINING:
- if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
- goto __badfd;
- /* Fall through */
- case SNDRV_PCM_STATE_RUNNING:
- if ((err = snd_pcm_update_hw_ptr(substream)) < 0)
- break;
- /* Fall through */
- case SNDRV_PCM_STATE_PREPARED:
- case SNDRV_PCM_STATE_SUSPENDED:
- err = 0;
+ err = do_pcm_hwsync(substream);
+ if (!err) {
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
n = snd_pcm_playback_hw_avail(runtime);
else
n = snd_pcm_capture_avail(runtime);
n += runtime->delay;
- break;
- case SNDRV_PCM_STATE_XRUN:
- err = -EPIPE;
- break;
- default:
- __badfd:
- err = -EBADFD;
- break;
}
snd_pcm_stream_unlock_irq(substream);
- if (!err)
- if (put_user(n, res))
- err = -EFAULT;
- return err;
+ return err < 0 ? err : n;
}
static int snd_pcm_sync_ptr(struct snd_pcm_substream *substream,
@@ -2718,10 +2635,15 @@ static int snd_pcm_sync_ptr(struct snd_pcm_substream *substream,
return err;
}
snd_pcm_stream_lock_irq(substream);
- if (!(sync_ptr.flags & SNDRV_PCM_SYNC_PTR_APPL))
- control->appl_ptr = sync_ptr.c.control.appl_ptr;
- else
+ if (!(sync_ptr.flags & SNDRV_PCM_SYNC_PTR_APPL)) {
+ err = apply_appl_ptr(substream, sync_ptr.c.control.appl_ptr);
+ if (err < 0) {
+ snd_pcm_stream_unlock_irq(substream);
+ return err;
+ }
+ } else {
sync_ptr.c.control.appl_ptr = control->appl_ptr;
+ }
if (!(sync_ptr.flags & SNDRV_PCM_SYNC_PTR_AVAIL_MIN))
control->avail_min = sync_ptr.c.control.avail_min;
else
@@ -2781,7 +2703,7 @@ static int snd_pcm_common_ioctl1(struct file *file,
case SNDRV_PCM_IOCTL_RESET:
return snd_pcm_reset(substream);
case SNDRV_PCM_IOCTL_START:
- return snd_pcm_action_lock_irq(&snd_pcm_action_start, substream, SNDRV_PCM_STATE_RUNNING);
+ return snd_pcm_start_lock_irq(substream);
case SNDRV_PCM_IOCTL_LINK:
return snd_pcm_link(substream, (int)(unsigned long) arg);
case SNDRV_PCM_IOCTL_UNLINK:
@@ -2793,7 +2715,16 @@ static int snd_pcm_common_ioctl1(struct file *file,
case SNDRV_PCM_IOCTL_HWSYNC:
return snd_pcm_hwsync(substream);
case SNDRV_PCM_IOCTL_DELAY:
- return snd_pcm_delay(substream, arg);
+ {
+ snd_pcm_sframes_t delay = snd_pcm_delay(substream);
+ snd_pcm_sframes_t __user *res = arg;
+
+ if (delay < 0)
+ return delay;
+ if (put_user(delay, res))
+ return -EFAULT;
+ return 0;
+ }
case SNDRV_PCM_IOCTL_SYNC_PTR:
return snd_pcm_sync_ptr(substream, arg);
#ifdef CONFIG_SND_SUPPORT_OLD_API
@@ -3007,30 +2938,55 @@ static long snd_pcm_capture_ioctl(struct file *file, unsigned int cmd,
(void __user *)arg);
}
+/**
+ * snd_pcm_kernel_ioctl - Execute PCM ioctl in the kernel-space
+ * @substream: PCM substream
+ * @cmd: IOCTL cmd
+ * @arg: IOCTL argument
+ *
+ * The function is provided primarily for OSS layer and USB gadget drivers,
+ * and it allows only the limited set of ioctls (hw_params, sw_params,
+ * prepare, start, drain, drop, forward).
+ */
int snd_pcm_kernel_ioctl(struct snd_pcm_substream *substream,
unsigned int cmd, void *arg)
{
- mm_segment_t fs;
- int result;
+ snd_pcm_uframes_t *frames = arg;
+ snd_pcm_sframes_t result;
- fs = snd_enter_user();
- switch (substream->stream) {
- case SNDRV_PCM_STREAM_PLAYBACK:
- result = snd_pcm_playback_ioctl1(NULL, substream, cmd,
- (void __user *)arg);
- break;
- case SNDRV_PCM_STREAM_CAPTURE:
- result = snd_pcm_capture_ioctl1(NULL, substream, cmd,
- (void __user *)arg);
- break;
+ switch (cmd) {
+ case SNDRV_PCM_IOCTL_FORWARD:
+ {
+ /* provided only for OSS; capture-only and no value returned */
+ if (substream->stream != SNDRV_PCM_STREAM_CAPTURE)
+ return -EINVAL;
+ result = snd_pcm_capture_forward(substream, *frames);
+ return result < 0 ? result : 0;
+ }
+ case SNDRV_PCM_IOCTL_HW_PARAMS:
+ return snd_pcm_hw_params(substream, arg);
+ case SNDRV_PCM_IOCTL_SW_PARAMS:
+ return snd_pcm_sw_params(substream, arg);
+ case SNDRV_PCM_IOCTL_PREPARE:
+ return snd_pcm_prepare(substream, NULL);
+ case SNDRV_PCM_IOCTL_START:
+ return snd_pcm_start_lock_irq(substream);
+ case SNDRV_PCM_IOCTL_DRAIN:
+ return snd_pcm_drain(substream, NULL);
+ case SNDRV_PCM_IOCTL_DROP:
+ return snd_pcm_drop(substream);
+ case SNDRV_PCM_IOCTL_DELAY:
+ {
+ result = snd_pcm_delay(substream);
+ if (result < 0)
+ return result;
+ *frames = result;
+ return 0;
+ }
default:
- result = -EINVAL;
- break;
+ return -EINVAL;
}
- snd_leave_user(fs);
- return result;
}
-
EXPORT_SYMBOL(snd_pcm_kernel_ioctl);
static ssize_t snd_pcm_read(struct file *file, char __user *buf, size_t count,
diff --git a/sound/core/pcm_timer.c b/sound/core/pcm_timer.c
index 20ecd8f..11389f1 100644
--- a/sound/core/pcm_timer.c
+++ b/sound/core/pcm_timer.c
@@ -25,6 +25,8 @@
#include <sound/pcm.h>
#include <sound/timer.h>
+#include "pcm_local.h"
+
/*
* Timer functions
*/
@@ -33,8 +35,8 @@ void snd_pcm_timer_resolution_change(struct snd_pcm_substream *substream)
{
unsigned long rate, mult, fsize, l, post;
struct snd_pcm_runtime *runtime = substream->runtime;
-
- mult = 1000000000;
+
+ mult = 1000000000;
rate = runtime->rate;
if (snd_BUG_ON(!rate))
return;
@@ -65,7 +67,7 @@ void snd_pcm_timer_resolution_change(struct snd_pcm_substream *substream)
static unsigned long snd_pcm_timer_resolution(struct snd_timer * timer)
{
struct snd_pcm_substream *substream;
-
+
substream = timer->private_data;
return substream->runtime ? substream->runtime->timer_resolution : 0;
}
@@ -73,7 +75,7 @@ static unsigned long snd_pcm_timer_resolution(struct snd_timer * timer)
static int snd_pcm_timer_start(struct snd_timer * timer)
{
struct snd_pcm_substream *substream;
-
+
substream = snd_timer_chip(timer);
substream->timer_running = 1;
return 0;
@@ -82,7 +84,7 @@ static int snd_pcm_timer_start(struct snd_timer * timer)
static int snd_pcm_timer_stop(struct snd_timer * timer)
{
struct snd_pcm_substream *substream;
-
+
substream = snd_timer_chip(timer);
substream->timer_running = 0;
return 0;
@@ -112,7 +114,7 @@ void snd_pcm_timer_init(struct snd_pcm_substream *substream)
{
struct snd_timer_id tid;
struct snd_timer *timer;
-
+
tid.dev_sclass = SNDRV_TIMER_SCLASS_NONE;
tid.dev_class = SNDRV_TIMER_CLASS_PCM;
tid.card = substream->pcm->card->number;
diff --git a/sound/drivers/dummy.c b/sound/drivers/dummy.c
index 172dacd..dd5ed03 100644
--- a/sound/drivers/dummy.c
+++ b/sound/drivers/dummy.c
@@ -644,15 +644,22 @@ static int alloc_fake_buffer(void)
}
static int dummy_pcm_copy(struct snd_pcm_substream *substream,
- int channel, snd_pcm_uframes_t pos,
- void __user *dst, snd_pcm_uframes_t count)
+ int channel, unsigned long pos,
+ void __user *dst, unsigned long bytes)
+{
+ return 0; /* do nothing */
+}
+
+static int dummy_pcm_copy_kernel(struct snd_pcm_substream *substream,
+ int channel, unsigned long pos,
+ void *dst, unsigned long bytes)
{
return 0; /* do nothing */
}
static int dummy_pcm_silence(struct snd_pcm_substream *substream,
- int channel, snd_pcm_uframes_t pos,
- snd_pcm_uframes_t count)
+ int channel, unsigned long pos,
+ unsigned long bytes)
{
return 0; /* do nothing */
}
@@ -683,8 +690,9 @@ static struct snd_pcm_ops dummy_pcm_ops_no_buf = {
.prepare = dummy_pcm_prepare,
.trigger = dummy_pcm_trigger,
.pointer = dummy_pcm_pointer,
- .copy = dummy_pcm_copy,
- .silence = dummy_pcm_silence,
+ .copy_user = dummy_pcm_copy,
+ .copy_kernel = dummy_pcm_copy_kernel,
+ .fill_silence = dummy_pcm_silence,
.page = dummy_pcm_page,
};
diff --git a/sound/drivers/opl3/opl3_oss.c b/sound/drivers/opl3/opl3_oss.c
index c1cb249..22c3e4b 100644
--- a/sound/drivers/opl3/opl3_oss.c
+++ b/sound/drivers/opl3/opl3_oss.c
@@ -27,20 +27,6 @@ static int snd_opl3_ioctl_seq_oss(struct snd_seq_oss_arg *arg, unsigned int cmd,
static int snd_opl3_load_patch_seq_oss(struct snd_seq_oss_arg *arg, int format, const char __user *buf, int offs, int count);
static int snd_opl3_reset_seq_oss(struct snd_seq_oss_arg *arg);
-/* */
-
-static inline mm_segment_t snd_enter_user(void)
-{
- mm_segment_t fs = get_fs();
- set_fs(get_ds());
- return fs;
-}
-
-static inline void snd_leave_user(mm_segment_t fs)
-{
- set_fs(fs);
-}
-
/* operators */
extern struct snd_midi_op opl3_ops;
diff --git a/sound/drivers/opl4/opl4_lib.c b/sound/drivers/opl4/opl4_lib.c
index 89c7aa0..240656e 100644
--- a/sound/drivers/opl4/opl4_lib.c
+++ b/sound/drivers/opl4/opl4_lib.c
@@ -153,7 +153,7 @@ static int snd_opl4_detect(struct snd_opl4 *opl4)
return 0;
}
-#if defined(CONFIG_SND_SEQUENCER) || (defined(MODULE) && defined(CONFIG_SND_SEQUENCER_MODULE))
+#if IS_REACHABLE(CONFIG_SND_SEQUENCER)
static void snd_opl4_seq_dev_free(struct snd_seq_device *seq_dev)
{
struct snd_opl4 *opl4 = seq_dev->private_data;
@@ -249,7 +249,7 @@ int snd_opl4_create(struct snd_card *card,
snd_opl4_create_mixer(opl4);
snd_opl4_create_proc(opl4);
-#if defined(CONFIG_SND_SEQUENCER) || (defined(MODULE) && defined(CONFIG_SND_SEQUENCER_MODULE))
+#if IS_REACHABLE(CONFIG_SND_SEQUENCER)
opl4->seq_client = -1;
if (opl4->hardware < OPL3_HW_OPL4_ML)
snd_opl4_create_seq_dev(opl4, seq_device);
diff --git a/sound/drivers/opl4/opl4_local.h b/sound/drivers/opl4/opl4_local.h
index 9a41bde..d5bac93 100644
--- a/sound/drivers/opl4/opl4_local.h
+++ b/sound/drivers/opl4/opl4_local.h
@@ -184,7 +184,7 @@ struct snd_opl4 {
#endif
struct mutex access_mutex;
-#if defined(CONFIG_SND_SEQUENCER) || defined(CONFIG_SND_SEQUENCER_MODULE)
+#if IS_REACHABLE(CONFIG_SND_SEQUENCER)
int used;
int seq_dev_num;
diff --git a/sound/drivers/vx/vx_mixer.c b/sound/drivers/vx/vx_mixer.c
index be9477e..98a41ac 100644
--- a/sound/drivers/vx/vx_mixer.c
+++ b/sound/drivers/vx/vx_mixer.c
@@ -455,7 +455,7 @@ static int vx_output_level_put(struct snd_kcontrol *kcontrol, struct snd_ctl_ele
return 0;
}
-static struct snd_kcontrol_new vx_control_output_level = {
+static const struct snd_kcontrol_new vx_control_output_level = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
SNDRV_CTL_ELEM_ACCESS_TLV_READ),
@@ -514,7 +514,7 @@ static int vx_audio_src_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_v
return 0;
}
-static struct snd_kcontrol_new vx_control_audio_src = {
+static const struct snd_kcontrol_new vx_control_audio_src = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Capture Source",
.info = vx_audio_src_info,
@@ -558,7 +558,7 @@ static int vx_clock_mode_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_
return 0;
}
-static struct snd_kcontrol_new vx_control_clock_mode = {
+static const struct snd_kcontrol_new vx_control_clock_mode = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Clock Mode",
.info = vx_clock_mode_info,
@@ -717,7 +717,7 @@ static int vx_monitor_sw_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_
static const DECLARE_TLV_DB_SCALE(db_scale_audio_gain, -10975, 25, 0);
-static struct snd_kcontrol_new vx_control_audio_gain = {
+static const struct snd_kcontrol_new vx_control_audio_gain = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
SNDRV_CTL_ELEM_ACCESS_TLV_READ),
@@ -727,14 +727,14 @@ static struct snd_kcontrol_new vx_control_audio_gain = {
.put = vx_audio_gain_put,
.tlv = { .p = db_scale_audio_gain },
};
-static struct snd_kcontrol_new vx_control_output_switch = {
+static const struct snd_kcontrol_new vx_control_output_switch = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "PCM Playback Switch",
.info = vx_audio_sw_info,
.get = vx_audio_sw_get,
.put = vx_audio_sw_put
};
-static struct snd_kcontrol_new vx_control_monitor_gain = {
+static const struct snd_kcontrol_new vx_control_monitor_gain = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Monitoring Volume",
.access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
@@ -744,7 +744,7 @@ static struct snd_kcontrol_new vx_control_monitor_gain = {
.put = vx_audio_monitor_put,
.tlv = { .p = db_scale_audio_gain },
};
-static struct snd_kcontrol_new vx_control_monitor_switch = {
+static const struct snd_kcontrol_new vx_control_monitor_switch = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Monitoring Switch",
.info = vx_audio_sw_info, /* shared */
@@ -805,7 +805,7 @@ static int vx_iec958_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_valu
return 0;
}
-static struct snd_kcontrol_new vx_control_iec958_mask = {
+static const struct snd_kcontrol_new vx_control_iec958_mask = {
.access = SNDRV_CTL_ELEM_ACCESS_READ,
.iface = SNDRV_CTL_ELEM_IFACE_PCM,
.name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,MASK),
@@ -813,7 +813,7 @@ static struct snd_kcontrol_new vx_control_iec958_mask = {
.get = vx_iec958_mask_get,
};
-static struct snd_kcontrol_new vx_control_iec958 = {
+static const struct snd_kcontrol_new vx_control_iec958 = {
.iface = SNDRV_CTL_ELEM_IFACE_PCM,
.name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT),
.info = vx_iec958_info,
@@ -878,7 +878,7 @@ static int vx_saturation_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_
return 0;
}
-static struct snd_kcontrol_new vx_control_vu_meter = {
+static const struct snd_kcontrol_new vx_control_vu_meter = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
/* name will be filled later */
@@ -886,7 +886,7 @@ static struct snd_kcontrol_new vx_control_vu_meter = {
.get = vx_vu_meter_get,
};
-static struct snd_kcontrol_new vx_control_peak_meter = {
+static const struct snd_kcontrol_new vx_control_peak_meter = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
/* name will be filled later */
@@ -894,7 +894,7 @@ static struct snd_kcontrol_new vx_control_peak_meter = {
.get = vx_peak_meter_get,
};
-static struct snd_kcontrol_new vx_control_saturation = {
+static const struct snd_kcontrol_new vx_control_saturation = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Input Saturation",
.access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
diff --git a/sound/firewire/amdtp-am824.c b/sound/firewire/amdtp-am824.c
index bebddc6..23ccddb 100644
--- a/sound/firewire/amdtp-am824.c
+++ b/sound/firewire/amdtp-am824.c
@@ -38,10 +38,6 @@ struct amdtp_am824 {
u8 pcm_positions[AM824_MAX_CHANNELS_FOR_PCM];
u8 midi_position;
- void (*transfer_samples)(struct amdtp_stream *s,
- struct snd_pcm_substream *pcm,
- __be32 *buffer, unsigned int frames);
-
unsigned int frame_multiplier;
};
@@ -177,32 +173,6 @@ static void write_pcm_s32(struct amdtp_stream *s,
}
}
-static void write_pcm_s16(struct amdtp_stream *s,
- struct snd_pcm_substream *pcm,
- __be32 *buffer, unsigned int frames)
-{
- struct amdtp_am824 *p = s->protocol;
- struct snd_pcm_runtime *runtime = pcm->runtime;
- unsigned int channels, remaining_frames, i, c;
- const u16 *src;
-
- channels = p->pcm_channels;
- src = (void *)runtime->dma_area +
- frames_to_bytes(runtime, s->pcm_buffer_pointer);
- remaining_frames = runtime->buffer_size - s->pcm_buffer_pointer;
-
- for (i = 0; i < frames; ++i) {
- for (c = 0; c < channels; ++c) {
- buffer[p->pcm_positions[c]] =
- cpu_to_be32((*src << 8) | 0x42000000);
- src++;
- }
- buffer += s->data_block_quadlets;
- if (--remaining_frames == 0)
- src = (void *)runtime->dma_area;
- }
-}
-
static void read_pcm_s32(struct amdtp_stream *s,
struct snd_pcm_substream *pcm,
__be32 *buffer, unsigned int frames)
@@ -242,43 +212,6 @@ static void write_pcm_silence(struct amdtp_stream *s,
}
/**
- * amdtp_am824_set_pcm_format - set the PCM format
- * @s: the AMDTP stream to configure
- * @format: the format of the ALSA PCM device
- *
- * The sample format must be set after the other parameters (rate/PCM channels/
- * MIDI) and before the stream is started, and must not be changed while the
- * stream is running.
- */
-void amdtp_am824_set_pcm_format(struct amdtp_stream *s, snd_pcm_format_t format)
-{
- struct amdtp_am824 *p = s->protocol;
-
- if (WARN_ON(amdtp_stream_pcm_running(s)))
- return;
-
- switch (format) {
- default:
- WARN_ON(1);
- /* fall through */
- case SNDRV_PCM_FORMAT_S16:
- if (s->direction == AMDTP_OUT_STREAM) {
- p->transfer_samples = write_pcm_s16;
- break;
- }
- WARN_ON(1);
- /* fall through */
- case SNDRV_PCM_FORMAT_S32:
- if (s->direction == AMDTP_OUT_STREAM)
- p->transfer_samples = write_pcm_s32;
- else
- p->transfer_samples = read_pcm_s32;
- break;
- }
-}
-EXPORT_SYMBOL_GPL(amdtp_am824_set_pcm_format);
-
-/**
* amdtp_am824_add_pcm_hw_constraints - add hw constraints for PCM substream
* @s: the AMDTP stream for AM824 data block, must be initialized.
* @runtime: the PCM substream runtime
@@ -407,7 +340,7 @@ static unsigned int process_rx_data_blocks(struct amdtp_stream *s, __be32 *buffe
unsigned int pcm_frames;
if (pcm) {
- p->transfer_samples(s, pcm, buffer, data_blocks);
+ write_pcm_s32(s, pcm, buffer, data_blocks);
pcm_frames = data_blocks * p->frame_multiplier;
} else {
write_pcm_silence(s, buffer, data_blocks);
@@ -428,7 +361,7 @@ static unsigned int process_tx_data_blocks(struct amdtp_stream *s, __be32 *buffe
unsigned int pcm_frames;
if (pcm) {
- p->transfer_samples(s, pcm, buffer, data_blocks);
+ read_pcm_s32(s, pcm, buffer, data_blocks);
pcm_frames = data_blocks * p->frame_multiplier;
} else {
pcm_frames = 0;
diff --git a/sound/firewire/amdtp-am824.h b/sound/firewire/amdtp-am824.h
index 73b07b3..b56e61f 100644
--- a/sound/firewire/amdtp-am824.h
+++ b/sound/firewire/amdtp-am824.h
@@ -8,8 +8,7 @@
#define AM824_IN_PCM_FORMAT_BITS SNDRV_PCM_FMTBIT_S32
-#define AM824_OUT_PCM_FORMAT_BITS (SNDRV_PCM_FMTBIT_S16 | \
- SNDRV_PCM_FMTBIT_S32)
+#define AM824_OUT_PCM_FORMAT_BITS SNDRV_PCM_FMTBIT_S32
/*
* This module supports maximum 64 PCM channels for one PCM stream
@@ -41,9 +40,6 @@ void amdtp_am824_set_midi_position(struct amdtp_stream *s,
int amdtp_am824_add_pcm_hw_constraints(struct amdtp_stream *s,
struct snd_pcm_runtime *runtime);
-void amdtp_am824_set_pcm_format(struct amdtp_stream *s,
- snd_pcm_format_t format);
-
void amdtp_am824_midi_trigger(struct amdtp_stream *s, unsigned int port,
struct snd_rawmidi_substream *midi);
diff --git a/sound/firewire/amdtp-stream.c b/sound/firewire/amdtp-stream.c
index 9e6f54f..4316d9d 100644
--- a/sound/firewire/amdtp-stream.c
+++ b/sound/firewire/amdtp-stream.c
@@ -929,6 +929,25 @@ unsigned long amdtp_stream_pcm_pointer(struct amdtp_stream *s)
EXPORT_SYMBOL(amdtp_stream_pcm_pointer);
/**
+ * amdtp_stream_pcm_ack - acknowledge queued PCM frames
+ * @s: the AMDTP stream that transfers the PCM frames
+ *
+ * Returns zero always.
+ */
+int amdtp_stream_pcm_ack(struct amdtp_stream *s)
+{
+ /*
+ * Process isochronous packets for recent isochronous cycle to handle
+ * queued PCM frames.
+ */
+ if (amdtp_stream_running(s))
+ fw_iso_context_flush_completions(s->context);
+
+ return 0;
+}
+EXPORT_SYMBOL(amdtp_stream_pcm_ack);
+
+/**
* amdtp_stream_update - update the stream after a bus reset
* @s: the AMDTP stream
*/
diff --git a/sound/firewire/amdtp-stream.h b/sound/firewire/amdtp-stream.h
index 7e88317..6d613f2 100644
--- a/sound/firewire/amdtp-stream.h
+++ b/sound/firewire/amdtp-stream.h
@@ -168,6 +168,7 @@ int amdtp_stream_add_pcm_hw_constraints(struct amdtp_stream *s,
void amdtp_stream_pcm_prepare(struct amdtp_stream *s);
unsigned long amdtp_stream_pcm_pointer(struct amdtp_stream *s);
+int amdtp_stream_pcm_ack(struct amdtp_stream *s);
void amdtp_stream_pcm_abort(struct amdtp_stream *s);
extern const unsigned int amdtp_syt_intervals[CIP_SFC_COUNT];
diff --git a/sound/firewire/bebob/bebob_maudio.c b/sound/firewire/bebob/bebob_maudio.c
index 07e5abd..d10208f 100644
--- a/sound/firewire/bebob/bebob_maudio.c
+++ b/sound/firewire/bebob/bebob_maudio.c
@@ -396,7 +396,7 @@ static int special_clk_ctl_put(struct snd_kcontrol *kctl,
return err;
}
-static struct snd_kcontrol_new special_clk_ctl = {
+static const struct snd_kcontrol_new special_clk_ctl = {
.name = "Clock Source",
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
@@ -429,7 +429,7 @@ static int special_sync_ctl_get(struct snd_kcontrol *kctl,
return 0;
}
-static struct snd_kcontrol_new special_sync_ctl = {
+static const struct snd_kcontrol_new special_sync_ctl = {
.name = "Sync Status",
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.access = SNDRV_CTL_ELEM_ACCESS_READ,
@@ -521,7 +521,7 @@ end:
mutex_unlock(&bebob->mutex);
return err;
}
-static struct snd_kcontrol_new special_dig_in_iface_ctl = {
+static const struct snd_kcontrol_new special_dig_in_iface_ctl = {
.name = "Digital Input Interface",
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
@@ -577,7 +577,7 @@ static int special_dig_out_iface_ctl_set(struct snd_kcontrol *kctl,
mutex_unlock(&bebob->mutex);
return err;
}
-static struct snd_kcontrol_new special_dig_out_iface_ctl = {
+static const struct snd_kcontrol_new special_dig_out_iface_ctl = {
.name = "Digital Output Interface",
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
diff --git a/sound/firewire/bebob/bebob_pcm.c b/sound/firewire/bebob/bebob_pcm.c
index 9e27eb8..657e15a 100644
--- a/sound/firewire/bebob/bebob_pcm.c
+++ b/sound/firewire/bebob/bebob_pcm.c
@@ -224,8 +224,6 @@ pcm_capture_hw_params(struct snd_pcm_substream *substream,
mutex_unlock(&bebob->mutex);
}
- amdtp_am824_set_pcm_format(&bebob->tx_stream, params_format(hw_params));
-
return 0;
}
static int
@@ -246,8 +244,6 @@ pcm_playback_hw_params(struct snd_pcm_substream *substream,
mutex_unlock(&bebob->mutex);
}
- amdtp_am824_set_pcm_format(&bebob->rx_stream, params_format(hw_params));
-
return 0;
}
@@ -359,6 +355,20 @@ pcm_playback_pointer(struct snd_pcm_substream *sbstrm)
return amdtp_stream_pcm_pointer(&bebob->rx_stream);
}
+static int pcm_capture_ack(struct snd_pcm_substream *substream)
+{
+ struct snd_bebob *bebob = substream->private_data;
+
+ return amdtp_stream_pcm_ack(&bebob->tx_stream);
+}
+
+static int pcm_playback_ack(struct snd_pcm_substream *substream)
+{
+ struct snd_bebob *bebob = substream->private_data;
+
+ return amdtp_stream_pcm_ack(&bebob->rx_stream);
+}
+
int snd_bebob_create_pcm_devices(struct snd_bebob *bebob)
{
static const struct snd_pcm_ops capture_ops = {
@@ -370,6 +380,7 @@ int snd_bebob_create_pcm_devices(struct snd_bebob *bebob)
.prepare = pcm_capture_prepare,
.trigger = pcm_capture_trigger,
.pointer = pcm_capture_pointer,
+ .ack = pcm_capture_ack,
.page = snd_pcm_lib_get_vmalloc_page,
};
static const struct snd_pcm_ops playback_ops = {
@@ -381,6 +392,7 @@ int snd_bebob_create_pcm_devices(struct snd_bebob *bebob)
.prepare = pcm_playback_prepare,
.trigger = pcm_playback_trigger,
.pointer = pcm_playback_pointer,
+ .ack = pcm_playback_ack,
.page = snd_pcm_lib_get_vmalloc_page,
.mmap = snd_pcm_lib_mmap_vmalloc,
};
diff --git a/sound/firewire/dice/dice-pcm.c b/sound/firewire/dice/dice-pcm.c
index 6074fe1..2dda746 100644
--- a/sound/firewire/dice/dice-pcm.c
+++ b/sound/firewire/dice/dice-pcm.c
@@ -146,7 +146,6 @@ static int capture_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *hw_params)
{
struct snd_dice *dice = substream->private_data;
- struct amdtp_stream *stream = &dice->tx_stream[substream->pcm->device];
int err;
err = snd_pcm_lib_alloc_vmalloc_buffer(substream,
@@ -160,15 +159,12 @@ static int capture_hw_params(struct snd_pcm_substream *substream,
mutex_unlock(&dice->mutex);
}
- amdtp_am824_set_pcm_format(stream, params_format(hw_params));
-
return 0;
}
static int playback_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *hw_params)
{
struct snd_dice *dice = substream->private_data;
- struct amdtp_stream *stream = &dice->rx_stream[substream->pcm->device];
int err;
err = snd_pcm_lib_alloc_vmalloc_buffer(substream,
@@ -182,8 +178,6 @@ static int playback_hw_params(struct snd_pcm_substream *substream,
mutex_unlock(&dice->mutex);
}
- amdtp_am824_set_pcm_format(stream, params_format(hw_params));
-
return 0;
}
@@ -300,6 +294,22 @@ static snd_pcm_uframes_t playback_pointer(struct snd_pcm_substream *substream)
return amdtp_stream_pcm_pointer(stream);
}
+static int capture_ack(struct snd_pcm_substream *substream)
+{
+ struct snd_dice *dice = substream->private_data;
+ struct amdtp_stream *stream = &dice->tx_stream[substream->pcm->device];
+
+ return amdtp_stream_pcm_ack(stream);
+}
+
+static int playback_ack(struct snd_pcm_substream *substream)
+{
+ struct snd_dice *dice = substream->private_data;
+ struct amdtp_stream *stream = &dice->rx_stream[substream->pcm->device];
+
+ return amdtp_stream_pcm_ack(stream);
+}
+
int snd_dice_create_pcm(struct snd_dice *dice)
{
static const struct snd_pcm_ops capture_ops = {
@@ -311,6 +321,7 @@ int snd_dice_create_pcm(struct snd_dice *dice)
.prepare = capture_prepare,
.trigger = capture_trigger,
.pointer = capture_pointer,
+ .ack = capture_ack,
.page = snd_pcm_lib_get_vmalloc_page,
.mmap = snd_pcm_lib_mmap_vmalloc,
};
@@ -323,6 +334,7 @@ int snd_dice_create_pcm(struct snd_dice *dice)
.prepare = playback_prepare,
.trigger = playback_trigger,
.pointer = playback_pointer,
+ .ack = playback_ack,
.page = snd_pcm_lib_get_vmalloc_page,
.mmap = snd_pcm_lib_mmap_vmalloc,
};
diff --git a/sound/firewire/digi00x/amdtp-dot.c b/sound/firewire/digi00x/amdtp-dot.c
index a468854..1453c34 100644
--- a/sound/firewire/digi00x/amdtp-dot.c
+++ b/sound/firewire/digi00x/amdtp-dot.c
@@ -48,10 +48,6 @@ struct amdtp_dot {
struct snd_rawmidi_substream *midi[MAX_MIDI_PORTS];
int midi_fifo_used[MAX_MIDI_PORTS];
int midi_fifo_limit;
-
- void (*transfer_samples)(struct amdtp_stream *s,
- struct snd_pcm_substream *pcm,
- __be32 *buffer, unsigned int frames);
};
/*
@@ -173,32 +169,6 @@ static void write_pcm_s32(struct amdtp_stream *s, struct snd_pcm_substream *pcm,
}
}
-static void write_pcm_s16(struct amdtp_stream *s, struct snd_pcm_substream *pcm,
- __be32 *buffer, unsigned int frames)
-{
- struct amdtp_dot *p = s->protocol;
- struct snd_pcm_runtime *runtime = pcm->runtime;
- unsigned int channels, remaining_frames, i, c;
- const u16 *src;
-
- channels = p->pcm_channels;
- src = (void *)runtime->dma_area +
- frames_to_bytes(runtime, s->pcm_buffer_pointer);
- remaining_frames = runtime->buffer_size - s->pcm_buffer_pointer;
-
- buffer++;
- for (i = 0; i < frames; ++i) {
- for (c = 0; c < channels; ++c) {
- buffer[c] = cpu_to_be32((*src << 8) | 0x40000000);
- dot_encode_step(&p->state, &buffer[c]);
- src++;
- }
- buffer += s->data_block_quadlets;
- if (--remaining_frames == 0)
- src = (void *)runtime->dma_area;
- }
-}
-
static void read_pcm_s32(struct amdtp_stream *s, struct snd_pcm_substream *pcm,
__be32 *buffer, unsigned int frames)
{
@@ -351,33 +321,6 @@ int amdtp_dot_add_pcm_hw_constraints(struct amdtp_stream *s,
return amdtp_stream_add_pcm_hw_constraints(s, runtime);
}
-void amdtp_dot_set_pcm_format(struct amdtp_stream *s, snd_pcm_format_t format)
-{
- struct amdtp_dot *p = s->protocol;
-
- if (WARN_ON(amdtp_stream_pcm_running(s)))
- return;
-
- switch (format) {
- default:
- WARN_ON(1);
- /* fall through */
- case SNDRV_PCM_FORMAT_S16:
- if (s->direction == AMDTP_OUT_STREAM) {
- p->transfer_samples = write_pcm_s16;
- break;
- }
- WARN_ON(1);
- /* fall through */
- case SNDRV_PCM_FORMAT_S32:
- if (s->direction == AMDTP_OUT_STREAM)
- p->transfer_samples = write_pcm_s32;
- else
- p->transfer_samples = read_pcm_s32;
- break;
- }
-}
-
void amdtp_dot_midi_trigger(struct amdtp_stream *s, unsigned int port,
struct snd_rawmidi_substream *midi)
{
@@ -392,13 +335,12 @@ static unsigned int process_tx_data_blocks(struct amdtp_stream *s,
unsigned int data_blocks,
unsigned int *syt)
{
- struct amdtp_dot *p = (struct amdtp_dot *)s->protocol;
struct snd_pcm_substream *pcm;
unsigned int pcm_frames;
pcm = ACCESS_ONCE(s->pcm);
if (pcm) {
- p->transfer_samples(s, pcm, buffer, data_blocks);
+ read_pcm_s32(s, pcm, buffer, data_blocks);
pcm_frames = data_blocks;
} else {
pcm_frames = 0;
@@ -414,13 +356,12 @@ static unsigned int process_rx_data_blocks(struct amdtp_stream *s,
unsigned int data_blocks,
unsigned int *syt)
{
- struct amdtp_dot *p = (struct amdtp_dot *)s->protocol;
struct snd_pcm_substream *pcm;
unsigned int pcm_frames;
pcm = ACCESS_ONCE(s->pcm);
if (pcm) {
- p->transfer_samples(s, pcm, buffer, data_blocks);
+ write_pcm_s32(s, pcm, buffer, data_blocks);
pcm_frames = data_blocks;
} else {
write_pcm_silence(s, buffer, data_blocks);
diff --git a/sound/firewire/digi00x/digi00x-pcm.c b/sound/firewire/digi00x/digi00x-pcm.c
index 68d1c52..f76cf5e 100644
--- a/sound/firewire/digi00x/digi00x-pcm.c
+++ b/sound/firewire/digi00x/digi00x-pcm.c
@@ -88,8 +88,7 @@ static int pcm_init_hw_params(struct snd_dg00x *dg00x,
substream->runtime->hw.formats = SNDRV_PCM_FMTBIT_S32;
s = &dg00x->tx_stream;
} else {
- substream->runtime->hw.formats = SNDRV_PCM_FMTBIT_S16 |
- SNDRV_PCM_FMTBIT_S32;
+ substream->runtime->hw.formats = SNDRV_PCM_FMTBIT_S32;
s = &dg00x->rx_stream;
}
@@ -184,8 +183,6 @@ static int pcm_capture_hw_params(struct snd_pcm_substream *substream,
mutex_unlock(&dg00x->mutex);
}
- amdtp_dot_set_pcm_format(&dg00x->tx_stream, params_format(hw_params));
-
return 0;
}
@@ -206,8 +203,6 @@ static int pcm_playback_hw_params(struct snd_pcm_substream *substream,
mutex_unlock(&dg00x->mutex);
}
- amdtp_dot_set_pcm_format(&dg00x->rx_stream, params_format(hw_params));
-
return 0;
}
@@ -329,6 +324,20 @@ static snd_pcm_uframes_t pcm_playback_pointer(struct snd_pcm_substream *sbstrm)
return amdtp_stream_pcm_pointer(&dg00x->rx_stream);
}
+static int pcm_capture_ack(struct snd_pcm_substream *substream)
+{
+ struct snd_dg00x *dg00x = substream->private_data;
+
+ return amdtp_stream_pcm_ack(&dg00x->tx_stream);
+}
+
+static int pcm_playback_ack(struct snd_pcm_substream *substream)
+{
+ struct snd_dg00x *dg00x = substream->private_data;
+
+ return amdtp_stream_pcm_ack(&dg00x->rx_stream);
+}
+
int snd_dg00x_create_pcm_devices(struct snd_dg00x *dg00x)
{
static const struct snd_pcm_ops capture_ops = {
@@ -340,6 +349,7 @@ int snd_dg00x_create_pcm_devices(struct snd_dg00x *dg00x)
.prepare = pcm_capture_prepare,
.trigger = pcm_capture_trigger,
.pointer = pcm_capture_pointer,
+ .ack = pcm_capture_ack,
.page = snd_pcm_lib_get_vmalloc_page,
};
static const struct snd_pcm_ops playback_ops = {
@@ -351,6 +361,7 @@ int snd_dg00x_create_pcm_devices(struct snd_dg00x *dg00x)
.prepare = pcm_playback_prepare,
.trigger = pcm_playback_trigger,
.pointer = pcm_playback_pointer,
+ .ack = pcm_playback_ack,
.page = snd_pcm_lib_get_vmalloc_page,
.mmap = snd_pcm_lib_mmap_vmalloc,
};
diff --git a/sound/firewire/digi00x/digi00x.h b/sound/firewire/digi00x/digi00x.h
index 1275a50..4dd1bbf 100644
--- a/sound/firewire/digi00x/digi00x.h
+++ b/sound/firewire/digi00x/digi00x.h
@@ -121,7 +121,6 @@ int amdtp_dot_set_parameters(struct amdtp_stream *s, unsigned int rate,
void amdtp_dot_reset(struct amdtp_stream *s);
int amdtp_dot_add_pcm_hw_constraints(struct amdtp_stream *s,
struct snd_pcm_runtime *runtime);
-void amdtp_dot_set_pcm_format(struct amdtp_stream *s, snd_pcm_format_t format);
void amdtp_dot_midi_trigger(struct amdtp_stream *s, unsigned int port,
struct snd_rawmidi_substream *midi);
diff --git a/sound/firewire/fireface/ff-midi.c b/sound/firewire/fireface/ff-midi.c
index 29ee0a7..949ee56 100644
--- a/sound/firewire/fireface/ff-midi.c
+++ b/sound/firewire/fireface/ff-midi.c
@@ -74,18 +74,6 @@ static void midi_playback_trigger(struct snd_rawmidi_substream *substream,
spin_unlock_irqrestore(&ff->lock, flags);
}
-static struct snd_rawmidi_ops midi_capture_ops = {
- .open = midi_capture_open,
- .close = midi_capture_close,
- .trigger = midi_capture_trigger,
-};
-
-static struct snd_rawmidi_ops midi_playback_ops = {
- .open = midi_playback_open,
- .close = midi_playback_close,
- .trigger = midi_playback_trigger,
-};
-
static void set_midi_substream_names(struct snd_rawmidi_str *stream,
const char *const name)
{
@@ -99,6 +87,16 @@ static void set_midi_substream_names(struct snd_rawmidi_str *stream,
int snd_ff_create_midi_devices(struct snd_ff *ff)
{
+ static const struct snd_rawmidi_ops midi_capture_ops = {
+ .open = midi_capture_open,
+ .close = midi_capture_close,
+ .trigger = midi_capture_trigger,
+ };
+ static const struct snd_rawmidi_ops midi_playback_ops = {
+ .open = midi_playback_open,
+ .close = midi_playback_close,
+ .trigger = midi_playback_trigger,
+ };
struct snd_rawmidi *rmidi;
struct snd_rawmidi_str *stream;
int err;
diff --git a/sound/firewire/fireface/ff-pcm.c b/sound/firewire/fireface/ff-pcm.c
index 93cee19..ad974b5 100644
--- a/sound/firewire/fireface/ff-pcm.c
+++ b/sound/firewire/fireface/ff-pcm.c
@@ -365,33 +365,47 @@ static snd_pcm_uframes_t pcm_playback_pointer(struct snd_pcm_substream *sbstrm)
return amdtp_stream_pcm_pointer(&ff->rx_stream);
}
-static struct snd_pcm_ops pcm_capture_ops = {
- .open = pcm_open,
- .close = pcm_close,
- .ioctl = snd_pcm_lib_ioctl,
- .hw_params = pcm_capture_hw_params,
- .hw_free = pcm_capture_hw_free,
- .prepare = pcm_capture_prepare,
- .trigger = pcm_capture_trigger,
- .pointer = pcm_capture_pointer,
- .page = snd_pcm_lib_get_vmalloc_page,
-};
-
-static struct snd_pcm_ops pcm_playback_ops = {
- .open = pcm_open,
- .close = pcm_close,
- .ioctl = snd_pcm_lib_ioctl,
- .hw_params = pcm_playback_hw_params,
- .hw_free = pcm_playback_hw_free,
- .prepare = pcm_playback_prepare,
- .trigger = pcm_playback_trigger,
- .pointer = pcm_playback_pointer,
- .page = snd_pcm_lib_get_vmalloc_page,
- .mmap = snd_pcm_lib_mmap_vmalloc,
-};
+static int pcm_capture_ack(struct snd_pcm_substream *substream)
+{
+ struct snd_ff *ff = substream->private_data;
+
+ return amdtp_stream_pcm_ack(&ff->tx_stream);
+}
+
+static int pcm_playback_ack(struct snd_pcm_substream *substream)
+{
+ struct snd_ff *ff = substream->private_data;
+
+ return amdtp_stream_pcm_ack(&ff->rx_stream);
+}
int snd_ff_create_pcm_devices(struct snd_ff *ff)
{
+ static const struct snd_pcm_ops pcm_capture_ops = {
+ .open = pcm_open,
+ .close = pcm_close,
+ .ioctl = snd_pcm_lib_ioctl,
+ .hw_params = pcm_capture_hw_params,
+ .hw_free = pcm_capture_hw_free,
+ .prepare = pcm_capture_prepare,
+ .trigger = pcm_capture_trigger,
+ .pointer = pcm_capture_pointer,
+ .ack = pcm_capture_ack,
+ .page = snd_pcm_lib_get_vmalloc_page,
+ };
+ static const struct snd_pcm_ops pcm_playback_ops = {
+ .open = pcm_open,
+ .close = pcm_close,
+ .ioctl = snd_pcm_lib_ioctl,
+ .hw_params = pcm_playback_hw_params,
+ .hw_free = pcm_playback_hw_free,
+ .prepare = pcm_playback_prepare,
+ .trigger = pcm_playback_trigger,
+ .pointer = pcm_playback_pointer,
+ .ack = pcm_playback_ack,
+ .page = snd_pcm_lib_get_vmalloc_page,
+ .mmap = snd_pcm_lib_mmap_vmalloc,
+ };
struct snd_pcm *pcm;
int err;
diff --git a/sound/firewire/fireworks/fireworks_pcm.c b/sound/firewire/fireworks/fireworks_pcm.c
index 9171702..346e264 100644
--- a/sound/firewire/fireworks/fireworks_pcm.c
+++ b/sound/firewire/fireworks/fireworks_pcm.c
@@ -257,8 +257,6 @@ static int pcm_capture_hw_params(struct snd_pcm_substream *substream,
mutex_unlock(&efw->mutex);
}
- amdtp_am824_set_pcm_format(&efw->tx_stream, params_format(hw_params));
-
return 0;
}
static int pcm_playback_hw_params(struct snd_pcm_substream *substream,
@@ -278,8 +276,6 @@ static int pcm_playback_hw_params(struct snd_pcm_substream *substream,
mutex_unlock(&efw->mutex);
}
- amdtp_am824_set_pcm_format(&efw->rx_stream, params_format(hw_params));
-
return 0;
}
@@ -383,6 +379,20 @@ static snd_pcm_uframes_t pcm_playback_pointer(struct snd_pcm_substream *sbstrm)
return amdtp_stream_pcm_pointer(&efw->rx_stream);
}
+static int pcm_capture_ack(struct snd_pcm_substream *substream)
+{
+ struct snd_efw *efw = substream->private_data;
+
+ return amdtp_stream_pcm_ack(&efw->tx_stream);
+}
+
+static int pcm_playback_ack(struct snd_pcm_substream *substream)
+{
+ struct snd_efw *efw = substream->private_data;
+
+ return amdtp_stream_pcm_ack(&efw->rx_stream);
+}
+
int snd_efw_create_pcm_devices(struct snd_efw *efw)
{
static const struct snd_pcm_ops capture_ops = {
@@ -394,6 +404,7 @@ int snd_efw_create_pcm_devices(struct snd_efw *efw)
.prepare = pcm_capture_prepare,
.trigger = pcm_capture_trigger,
.pointer = pcm_capture_pointer,
+ .ack = pcm_capture_ack,
.page = snd_pcm_lib_get_vmalloc_page,
};
static const struct snd_pcm_ops playback_ops = {
@@ -405,6 +416,7 @@ int snd_efw_create_pcm_devices(struct snd_efw *efw)
.prepare = pcm_playback_prepare,
.trigger = pcm_playback_trigger,
.pointer = pcm_playback_pointer,
+ .ack = pcm_playback_ack,
.page = snd_pcm_lib_get_vmalloc_page,
.mmap = snd_pcm_lib_mmap_vmalloc,
};
diff --git a/sound/firewire/motu/motu-pcm.c b/sound/firewire/motu/motu-pcm.c
index 94558f3..e3ef89c 100644
--- a/sound/firewire/motu/motu-pcm.c
+++ b/sound/firewire/motu/motu-pcm.c
@@ -356,6 +356,20 @@ static snd_pcm_uframes_t playback_pointer(struct snd_pcm_substream *substream)
return amdtp_stream_pcm_pointer(&motu->rx_stream);
}
+static int capture_ack(struct snd_pcm_substream *substream)
+{
+ struct snd_motu *motu = substream->private_data;
+
+ return amdtp_stream_pcm_ack(&motu->tx_stream);
+}
+
+static int playback_ack(struct snd_pcm_substream *substream)
+{
+ struct snd_motu *motu = substream->private_data;
+
+ return amdtp_stream_pcm_ack(&motu->rx_stream);
+}
+
int snd_motu_create_pcm_devices(struct snd_motu *motu)
{
static struct snd_pcm_ops capture_ops = {
@@ -367,6 +381,7 @@ int snd_motu_create_pcm_devices(struct snd_motu *motu)
.prepare = capture_prepare,
.trigger = capture_trigger,
.pointer = capture_pointer,
+ .ack = capture_ack,
.page = snd_pcm_lib_get_vmalloc_page,
.mmap = snd_pcm_lib_mmap_vmalloc,
};
@@ -379,6 +394,7 @@ int snd_motu_create_pcm_devices(struct snd_motu *motu)
.prepare = playback_prepare,
.trigger = playback_trigger,
.pointer = playback_pointer,
+ .ack = playback_ack,
.page = snd_pcm_lib_get_vmalloc_page,
.mmap = snd_pcm_lib_mmap_vmalloc,
};
diff --git a/sound/firewire/oxfw/oxfw-pcm.c b/sound/firewire/oxfw/oxfw-pcm.c
index f3530f8..bc1a3a3 100644
--- a/sound/firewire/oxfw/oxfw-pcm.c
+++ b/sound/firewire/oxfw/oxfw-pcm.c
@@ -244,8 +244,6 @@ static int pcm_capture_hw_params(struct snd_pcm_substream *substream,
mutex_unlock(&oxfw->mutex);
}
- amdtp_am824_set_pcm_format(&oxfw->tx_stream, params_format(hw_params));
-
return 0;
}
static int pcm_playback_hw_params(struct snd_pcm_substream *substream,
@@ -265,8 +263,6 @@ static int pcm_playback_hw_params(struct snd_pcm_substream *substream,
mutex_unlock(&oxfw->mutex);
}
- amdtp_am824_set_pcm_format(&oxfw->rx_stream, params_format(hw_params));
-
return 0;
}
@@ -386,6 +382,20 @@ static snd_pcm_uframes_t pcm_playback_pointer(struct snd_pcm_substream *sbstm)
return amdtp_stream_pcm_pointer(&oxfw->rx_stream);
}
+static int pcm_capture_ack(struct snd_pcm_substream *substream)
+{
+ struct snd_oxfw *oxfw = substream->private_data;
+
+ return amdtp_stream_pcm_ack(&oxfw->tx_stream);
+}
+
+static int pcm_playback_ack(struct snd_pcm_substream *substream)
+{
+ struct snd_oxfw *oxfw = substream->private_data;
+
+ return amdtp_stream_pcm_ack(&oxfw->rx_stream);
+}
+
int snd_oxfw_create_pcm(struct snd_oxfw *oxfw)
{
static const struct snd_pcm_ops capture_ops = {
@@ -397,6 +407,7 @@ int snd_oxfw_create_pcm(struct snd_oxfw *oxfw)
.prepare = pcm_capture_prepare,
.trigger = pcm_capture_trigger,
.pointer = pcm_capture_pointer,
+ .ack = pcm_capture_ack,
.page = snd_pcm_lib_get_vmalloc_page,
.mmap = snd_pcm_lib_mmap_vmalloc,
};
@@ -409,6 +420,7 @@ int snd_oxfw_create_pcm(struct snd_oxfw *oxfw)
.prepare = pcm_playback_prepare,
.trigger = pcm_playback_trigger,
.pointer = pcm_playback_pointer,
+ .ack = pcm_playback_ack,
.page = snd_pcm_lib_get_vmalloc_page,
.mmap = snd_pcm_lib_mmap_vmalloc,
};
diff --git a/sound/firewire/tascam/amdtp-tascam.c b/sound/firewire/tascam/amdtp-tascam.c
index 9dd0fcc..6aff1fc 100644
--- a/sound/firewire/tascam/amdtp-tascam.c
+++ b/sound/firewire/tascam/amdtp-tascam.c
@@ -14,10 +14,6 @@
struct amdtp_tscm {
unsigned int pcm_channels;
-
- void (*transfer_samples)(struct amdtp_stream *s,
- struct snd_pcm_substream *pcm,
- __be32 *buffer, unsigned int frames);
};
int amdtp_tscm_set_parameters(struct amdtp_stream *s, unsigned int rate)
@@ -62,31 +58,6 @@ static void write_pcm_s32(struct amdtp_stream *s,
}
}
-static void write_pcm_s16(struct amdtp_stream *s,
- struct snd_pcm_substream *pcm,
- __be32 *buffer, unsigned int frames)
-{
- struct amdtp_tscm *p = s->protocol;
- struct snd_pcm_runtime *runtime = pcm->runtime;
- unsigned int channels, remaining_frames, i, c;
- const u16 *src;
-
- channels = p->pcm_channels;
- src = (void *)runtime->dma_area +
- frames_to_bytes(runtime, s->pcm_buffer_pointer);
- remaining_frames = runtime->buffer_size - s->pcm_buffer_pointer;
-
- for (i = 0; i < frames; ++i) {
- for (c = 0; c < channels; ++c) {
- buffer[c] = cpu_to_be32(*src << 16);
- src++;
- }
- buffer += s->data_block_quadlets;
- if (--remaining_frames == 0)
- src = (void *)runtime->dma_area;
- }
-}
-
static void read_pcm_s32(struct amdtp_stream *s,
struct snd_pcm_substream *pcm,
__be32 *buffer, unsigned int frames)
@@ -146,44 +117,16 @@ int amdtp_tscm_add_pcm_hw_constraints(struct amdtp_stream *s,
return amdtp_stream_add_pcm_hw_constraints(s, runtime);
}
-void amdtp_tscm_set_pcm_format(struct amdtp_stream *s, snd_pcm_format_t format)
-{
- struct amdtp_tscm *p = s->protocol;
-
- if (WARN_ON(amdtp_stream_pcm_running(s)))
- return;
-
- switch (format) {
- default:
- WARN_ON(1);
- /* fall through */
- case SNDRV_PCM_FORMAT_S16:
- if (s->direction == AMDTP_OUT_STREAM) {
- p->transfer_samples = write_pcm_s16;
- break;
- }
- WARN_ON(1);
- /* fall through */
- case SNDRV_PCM_FORMAT_S32:
- if (s->direction == AMDTP_OUT_STREAM)
- p->transfer_samples = write_pcm_s32;
- else
- p->transfer_samples = read_pcm_s32;
- break;
- }
-}
-
static unsigned int process_tx_data_blocks(struct amdtp_stream *s,
__be32 *buffer,
unsigned int data_blocks,
unsigned int *syt)
{
- struct amdtp_tscm *p = (struct amdtp_tscm *)s->protocol;
struct snd_pcm_substream *pcm;
pcm = ACCESS_ONCE(s->pcm);
if (data_blocks > 0 && pcm)
- p->transfer_samples(s, pcm, buffer, data_blocks);
+ read_pcm_s32(s, pcm, buffer, data_blocks);
/* A place holder for control messages. */
@@ -195,7 +138,6 @@ static unsigned int process_rx_data_blocks(struct amdtp_stream *s,
unsigned int data_blocks,
unsigned int *syt)
{
- struct amdtp_tscm *p = (struct amdtp_tscm *)s->protocol;
struct snd_pcm_substream *pcm;
/* This field is not used. */
@@ -203,7 +145,7 @@ static unsigned int process_rx_data_blocks(struct amdtp_stream *s,
pcm = ACCESS_ONCE(s->pcm);
if (pcm)
- p->transfer_samples(s, pcm, buffer, data_blocks);
+ write_pcm_s32(s, pcm, buffer, data_blocks);
else
write_pcm_silence(s, buffer, data_blocks);
diff --git a/sound/firewire/tascam/tascam-pcm.c b/sound/firewire/tascam/tascam-pcm.c
index f5dd6ce..3c4482a 100644
--- a/sound/firewire/tascam/tascam-pcm.c
+++ b/sound/firewire/tascam/tascam-pcm.c
@@ -48,8 +48,7 @@ static int pcm_init_hw_params(struct snd_tscm *tscm,
stream = &tscm->tx_stream;
pcm_channels = tscm->spec->pcm_capture_analog_channels;
} else {
- runtime->hw.formats =
- SNDRV_PCM_FMTBIT_S16 | SNDRV_PCM_FMTBIT_S32;
+ runtime->hw.formats = SNDRV_PCM_FMTBIT_S32;
stream = &tscm->rx_stream;
pcm_channels = tscm->spec->pcm_playback_analog_channels;
}
@@ -125,8 +124,6 @@ static int pcm_capture_hw_params(struct snd_pcm_substream *substream,
mutex_unlock(&tscm->mutex);
}
- amdtp_tscm_set_pcm_format(&tscm->tx_stream, params_format(hw_params));
-
return 0;
}
@@ -147,8 +144,6 @@ static int pcm_playback_hw_params(struct snd_pcm_substream *substream,
mutex_unlock(&tscm->mutex);
}
- amdtp_tscm_set_pcm_format(&tscm->rx_stream, params_format(hw_params));
-
return 0;
}
@@ -268,6 +263,20 @@ static snd_pcm_uframes_t pcm_playback_pointer(struct snd_pcm_substream *sbstrm)
return amdtp_stream_pcm_pointer(&tscm->rx_stream);
}
+static int pcm_capture_ack(struct snd_pcm_substream *substream)
+{
+ struct snd_tscm *tscm = substream->private_data;
+
+ return amdtp_stream_pcm_ack(&tscm->tx_stream);
+}
+
+static int pcm_playback_ack(struct snd_pcm_substream *substream)
+{
+ struct snd_tscm *tscm = substream->private_data;
+
+ return amdtp_stream_pcm_ack(&tscm->rx_stream);
+}
+
int snd_tscm_create_pcm_devices(struct snd_tscm *tscm)
{
static const struct snd_pcm_ops capture_ops = {
@@ -279,6 +288,7 @@ int snd_tscm_create_pcm_devices(struct snd_tscm *tscm)
.prepare = pcm_capture_prepare,
.trigger = pcm_capture_trigger,
.pointer = pcm_capture_pointer,
+ .ack = pcm_capture_ack,
.page = snd_pcm_lib_get_vmalloc_page,
};
static const struct snd_pcm_ops playback_ops = {
@@ -290,6 +300,7 @@ int snd_tscm_create_pcm_devices(struct snd_tscm *tscm)
.prepare = pcm_playback_prepare,
.trigger = pcm_playback_trigger,
.pointer = pcm_playback_pointer,
+ .ack = pcm_playback_ack,
.page = snd_pcm_lib_get_vmalloc_page,
.mmap = snd_pcm_lib_mmap_vmalloc,
};
diff --git a/sound/firewire/tascam/tascam.h b/sound/firewire/tascam/tascam.h
index 08ecfae..a5bd167 100644
--- a/sound/firewire/tascam/tascam.h
+++ b/sound/firewire/tascam/tascam.h
@@ -131,7 +131,6 @@ int amdtp_tscm_init(struct amdtp_stream *s, struct fw_unit *unit,
int amdtp_tscm_set_parameters(struct amdtp_stream *s, unsigned int rate);
int amdtp_tscm_add_pcm_hw_constraints(struct amdtp_stream *s,
struct snd_pcm_runtime *runtime);
-void amdtp_tscm_set_pcm_format(struct amdtp_stream *s, snd_pcm_format_t format);
int snd_tscm_stream_get_rate(struct snd_tscm *tscm, unsigned int *rate);
int snd_tscm_stream_get_clock(struct snd_tscm *tscm,
diff --git a/sound/i2c/other/ak4113.c b/sound/i2c/other/ak4113.c
index 2183e9e..4099e60 100644
--- a/sound/i2c/other/ak4113.c
+++ b/sound/i2c/other/ak4113.c
@@ -199,12 +199,11 @@ static int snd_ak4113_in_error_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct ak4113 *chip = snd_kcontrol_chip(kcontrol);
- long *ptr;
spin_lock_irq(&chip->lock);
- ptr = (long *)(((char *)chip) + kcontrol->private_value);
- ucontrol->value.integer.value[0] = *ptr;
- *ptr = 0;
+ ucontrol->value.integer.value[0] =
+ chip->errors[kcontrol->private_value];
+ chip->errors[kcontrol->private_value] = 0;
spin_unlock_irq(&chip->lock);
return 0;
}
@@ -373,7 +372,7 @@ static struct snd_kcontrol_new snd_ak4113_iec958_controls[] = {
SNDRV_CTL_ELEM_ACCESS_VOLATILE,
.info = snd_ak4113_in_error_info,
.get = snd_ak4113_in_error_get,
- .private_value = offsetof(struct ak4113, parity_errors),
+ .private_value = AK4113_PARITY_ERRORS,
},
{
.iface = SNDRV_CTL_ELEM_IFACE_PCM,
@@ -382,7 +381,7 @@ static struct snd_kcontrol_new snd_ak4113_iec958_controls[] = {
SNDRV_CTL_ELEM_ACCESS_VOLATILE,
.info = snd_ak4113_in_error_info,
.get = snd_ak4113_in_error_get,
- .private_value = offsetof(struct ak4113, v_bit_errors),
+ .private_value = AK4113_V_BIT_ERRORS,
},
{
.iface = SNDRV_CTL_ELEM_IFACE_PCM,
@@ -391,7 +390,7 @@ static struct snd_kcontrol_new snd_ak4113_iec958_controls[] = {
SNDRV_CTL_ELEM_ACCESS_VOLATILE,
.info = snd_ak4113_in_error_info,
.get = snd_ak4113_in_error_get,
- .private_value = offsetof(struct ak4113, ccrc_errors),
+ .private_value = AK4113_CCRC_ERRORS,
},
{
.iface = SNDRV_CTL_ELEM_IFACE_PCM,
@@ -400,7 +399,7 @@ static struct snd_kcontrol_new snd_ak4113_iec958_controls[] = {
SNDRV_CTL_ELEM_ACCESS_VOLATILE,
.info = snd_ak4113_in_error_info,
.get = snd_ak4113_in_error_get,
- .private_value = offsetof(struct ak4113, qcrc_errors),
+ .private_value = AK4113_QCRC_ERRORS,
},
{
.iface = SNDRV_CTL_ELEM_IFACE_PCM,
@@ -551,13 +550,13 @@ int snd_ak4113_check_rate_and_errors(struct ak4113 *ak4113, unsigned int flags)
rcs2 = reg_read(ak4113, AK4113_REG_RCS2);
spin_lock_irqsave(&ak4113->lock, _flags);
if (rcs0 & AK4113_PAR)
- ak4113->parity_errors++;
+ ak4113->errors[AK4113_PARITY_ERRORS]++;
if (rcs0 & AK4113_V)
- ak4113->v_bit_errors++;
+ ak4113->errors[AK4113_V_BIT_ERRORS]++;
if (rcs2 & AK4113_CCRC)
- ak4113->ccrc_errors++;
+ ak4113->errors[AK4113_CCRC_ERRORS]++;
if (rcs2 & AK4113_QCRC)
- ak4113->qcrc_errors++;
+ ak4113->errors[AK4113_QCRC_ERRORS]++;
c0 = (ak4113->rcs0 & (AK4113_QINT | AK4113_CINT | AK4113_STC |
AK4113_AUDION | AK4113_AUTO | AK4113_UNLCK)) ^
(rcs0 & (AK4113_QINT | AK4113_CINT | AK4113_STC |
diff --git a/sound/i2c/other/ak4114.c b/sound/i2c/other/ak4114.c
index d53c9bb..7fb1aeb 100644
--- a/sound/i2c/other/ak4114.c
+++ b/sound/i2c/other/ak4114.c
@@ -194,12 +194,11 @@ static int snd_ak4114_in_error_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct ak4114 *chip = snd_kcontrol_chip(kcontrol);
- long *ptr;
spin_lock_irq(&chip->lock);
- ptr = (long *)(((char *)chip) + kcontrol->private_value);
- ucontrol->value.integer.value[0] = *ptr;
- *ptr = 0;
+ ucontrol->value.integer.value[0] =
+ chip->errors[kcontrol->private_value];
+ chip->errors[kcontrol->private_value] = 0;
spin_unlock_irq(&chip->lock);
return 0;
}
@@ -341,7 +340,7 @@ static struct snd_kcontrol_new snd_ak4114_iec958_controls[] = {
.access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
.info = snd_ak4114_in_error_info,
.get = snd_ak4114_in_error_get,
- .private_value = offsetof(struct ak4114, parity_errors),
+ .private_value = AK4114_PARITY_ERRORS,
},
{
.iface = SNDRV_CTL_ELEM_IFACE_PCM,
@@ -349,7 +348,7 @@ static struct snd_kcontrol_new snd_ak4114_iec958_controls[] = {
.access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
.info = snd_ak4114_in_error_info,
.get = snd_ak4114_in_error_get,
- .private_value = offsetof(struct ak4114, v_bit_errors),
+ .private_value = AK4114_V_BIT_ERRORS,
},
{
.iface = SNDRV_CTL_ELEM_IFACE_PCM,
@@ -357,7 +356,7 @@ static struct snd_kcontrol_new snd_ak4114_iec958_controls[] = {
.access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
.info = snd_ak4114_in_error_info,
.get = snd_ak4114_in_error_get,
- .private_value = offsetof(struct ak4114, ccrc_errors),
+ .private_value = AK4114_CCRC_ERRORS,
},
{
.iface = SNDRV_CTL_ELEM_IFACE_PCM,
@@ -365,7 +364,7 @@ static struct snd_kcontrol_new snd_ak4114_iec958_controls[] = {
.access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
.info = snd_ak4114_in_error_info,
.get = snd_ak4114_in_error_get,
- .private_value = offsetof(struct ak4114, qcrc_errors),
+ .private_value = AK4114_QCRC_ERRORS,
},
{
.iface = SNDRV_CTL_ELEM_IFACE_PCM,
@@ -581,13 +580,13 @@ int snd_ak4114_check_rate_and_errors(struct ak4114 *ak4114, unsigned int flags)
rcs0 = reg_read(ak4114, AK4114_REG_RCS0);
spin_lock_irqsave(&ak4114->lock, _flags);
if (rcs0 & AK4114_PAR)
- ak4114->parity_errors++;
+ ak4114->errors[AK4114_PARITY_ERRORS]++;
if (rcs1 & AK4114_V)
- ak4114->v_bit_errors++;
+ ak4114->errors[AK4114_V_BIT_ERRORS]++;
if (rcs1 & AK4114_CCRC)
- ak4114->ccrc_errors++;
+ ak4114->errors[AK4114_CCRC_ERRORS]++;
if (rcs1 & AK4114_QCRC)
- ak4114->qcrc_errors++;
+ ak4114->errors[AK4114_QCRC_ERRORS]++;
c0 = (ak4114->rcs0 & (AK4114_QINT | AK4114_CINT | AK4114_PEM | AK4114_AUDION | AK4114_AUTO | AK4114_UNLCK)) ^
(rcs0 & (AK4114_QINT | AK4114_CINT | AK4114_PEM | AK4114_AUDION | AK4114_AUTO | AK4114_UNLCK));
c1 = (ak4114->rcs1 & 0xf0) ^ (rcs1 & 0xf0);
diff --git a/sound/i2c/other/ak4117.c b/sound/i2c/other/ak4117.c
index 0702f05..3ab099f 100644
--- a/sound/i2c/other/ak4117.c
+++ b/sound/i2c/other/ak4117.c
@@ -168,12 +168,11 @@ static int snd_ak4117_in_error_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct ak4117 *chip = snd_kcontrol_chip(kcontrol);
- long *ptr;
spin_lock_irq(&chip->lock);
- ptr = (long *)(((char *)chip) + kcontrol->private_value);
- ucontrol->value.integer.value[0] = *ptr;
- *ptr = 0;
+ ucontrol->value.integer.value[0] =
+ chip->errors[kcontrol->private_value];
+ chip->errors[kcontrol->private_value] = 0;
spin_unlock_irq(&chip->lock);
return 0;
}
@@ -328,7 +327,7 @@ static struct snd_kcontrol_new snd_ak4117_iec958_controls[] = {
.access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
.info = snd_ak4117_in_error_info,
.get = snd_ak4117_in_error_get,
- .private_value = offsetof(struct ak4117, parity_errors),
+ .private_value = AK4117_PARITY_ERRORS,
},
{
.iface = SNDRV_CTL_ELEM_IFACE_PCM,
@@ -336,7 +335,7 @@ static struct snd_kcontrol_new snd_ak4117_iec958_controls[] = {
.access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
.info = snd_ak4117_in_error_info,
.get = snd_ak4117_in_error_get,
- .private_value = offsetof(struct ak4117, v_bit_errors),
+ .private_value = AK4117_V_BIT_ERRORS,
},
{
.iface = SNDRV_CTL_ELEM_IFACE_PCM,
@@ -344,7 +343,7 @@ static struct snd_kcontrol_new snd_ak4117_iec958_controls[] = {
.access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
.info = snd_ak4117_in_error_info,
.get = snd_ak4117_in_error_get,
- .private_value = offsetof(struct ak4117, ccrc_errors),
+ .private_value = AK4117_CCRC_ERRORS,
},
{
.iface = SNDRV_CTL_ELEM_IFACE_PCM,
@@ -352,7 +351,7 @@ static struct snd_kcontrol_new snd_ak4117_iec958_controls[] = {
.access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
.info = snd_ak4117_in_error_info,
.get = snd_ak4117_in_error_get,
- .private_value = offsetof(struct ak4117, qcrc_errors),
+ .private_value = AK4117_QCRC_ERRORS,
},
{
.iface = SNDRV_CTL_ELEM_IFACE_PCM,
@@ -470,13 +469,13 @@ int snd_ak4117_check_rate_and_errors(struct ak4117 *ak4117, unsigned int flags)
// printk(KERN_DEBUG "AK IRQ: rcs0 = 0x%x, rcs1 = 0x%x, rcs2 = 0x%x\n", rcs0, rcs1, rcs2);
spin_lock_irqsave(&ak4117->lock, _flags);
if (rcs0 & AK4117_PAR)
- ak4117->parity_errors++;
+ ak4117->errors[AK4117_PARITY_ERRORS]++;
if (rcs0 & AK4117_V)
- ak4117->v_bit_errors++;
+ ak4117->errors[AK4117_V_BIT_ERRORS]++;
if (rcs2 & AK4117_CCRC)
- ak4117->ccrc_errors++;
+ ak4117->errors[AK4117_CCRC_ERRORS]++;
if (rcs2 & AK4117_QCRC)
- ak4117->qcrc_errors++;
+ ak4117->errors[AK4117_QCRC_ERRORS]++;
c0 = (ak4117->rcs0 & (AK4117_QINT | AK4117_CINT | AK4117_STC | AK4117_AUDION | AK4117_AUTO | AK4117_UNLCK)) ^
(rcs0 & (AK4117_QINT | AK4117_CINT | AK4117_STC | AK4117_AUDION | AK4117_AUTO | AK4117_UNLCK));
c1 = (ak4117->rcs1 & (AK4117_DTSCD | AK4117_NPCM | AK4117_PEM | 0x0f)) ^
diff --git a/sound/isa/cmi8328.c b/sound/isa/cmi8328.c
index 8e1756c..d09e456 100644
--- a/sound/isa/cmi8328.c
+++ b/sound/isa/cmi8328.c
@@ -26,7 +26,7 @@ MODULE_AUTHOR("Ondrej Zary <linux@rainbow-software.org>");
MODULE_DESCRIPTION("C-Media CMI8328");
MODULE_LICENSE("GPL");
-#if defined(CONFIG_GAMEPORT) || defined(CONFIG_GAMEPORT_MODULE)
+#if IS_ENABLED(CONFIG_GAMEPORT)
#define SUPPORT_JOYSTICK 1
#endif
diff --git a/sound/isa/gus/gus_main.c b/sound/isa/gus/gus_main.c
index 4490ee4..3cf9b13 100644
--- a/sound/isa/gus/gus_main.c
+++ b/sound/isa/gus/gus_main.c
@@ -82,7 +82,7 @@ static int snd_gus_joystick_put(struct snd_kcontrol *kcontrol, struct snd_ctl_el
return change;
}
-static struct snd_kcontrol_new snd_gus_joystick_control = {
+static const struct snd_kcontrol_new snd_gus_joystick_control = {
.iface = SNDRV_CTL_ELEM_IFACE_CARD,
.name = "Joystick Speed",
.info = snd_gus_joystick_info,
diff --git a/sound/isa/gus/gus_pcm.c b/sound/isa/gus/gus_pcm.c
index 0650599..b9f6dcb 100644
--- a/sound/isa/gus/gus_pcm.c
+++ b/sound/isa/gus/gus_pcm.c
@@ -61,8 +61,6 @@ struct gus_pcm_private {
int final_volume;
};
-static int snd_gf1_pcm_use_dma = 1;
-
static void snd_gf1_pcm_block_change_ack(struct snd_gus_card * gus, void *private_data)
{
struct gus_pcm_private *pcmp = private_data;
@@ -355,66 +353,83 @@ static int snd_gf1_pcm_poke_block(struct snd_gus_card *gus, unsigned char *buf,
return 0;
}
-static int snd_gf1_pcm_playback_copy(struct snd_pcm_substream *substream,
- int voice,
- snd_pcm_uframes_t pos,
- void __user *src,
- snd_pcm_uframes_t count)
+static int get_bpos(struct gus_pcm_private *pcmp, int voice, unsigned int pos,
+ unsigned int len)
{
- struct snd_pcm_runtime *runtime = substream->runtime;
- struct gus_pcm_private *pcmp = runtime->private_data;
- unsigned int bpos, len;
-
- bpos = samples_to_bytes(runtime, pos) + (voice * (pcmp->dma_size / 2));
- len = samples_to_bytes(runtime, count);
+ unsigned int bpos = pos + (voice * (pcmp->dma_size / 2));
if (snd_BUG_ON(bpos > pcmp->dma_size))
return -EIO;
if (snd_BUG_ON(bpos + len > pcmp->dma_size))
return -EIO;
+ return bpos;
+}
+
+static int playback_copy_ack(struct snd_pcm_substream *substream,
+ unsigned int bpos, unsigned int len)
+{
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct gus_pcm_private *pcmp = runtime->private_data;
+ struct snd_gus_card *gus = pcmp->gus;
+ int w16, invert;
+
+ if (len > 32)
+ return snd_gf1_pcm_block_change(substream, bpos,
+ pcmp->memory + bpos, len);
+
+ w16 = (snd_pcm_format_width(runtime->format) == 16);
+ invert = snd_pcm_format_unsigned(runtime->format);
+ return snd_gf1_pcm_poke_block(gus, runtime->dma_area + bpos,
+ pcmp->memory + bpos, len, w16, invert);
+}
+
+static int snd_gf1_pcm_playback_copy(struct snd_pcm_substream *substream,
+ int voice, unsigned long pos,
+ void __user *src, unsigned long count)
+{
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct gus_pcm_private *pcmp = runtime->private_data;
+ unsigned int len = count;
+ int bpos;
+
+ bpos = get_bpos(pcmp, voice, pos, len);
+ if (bpos < 0)
+ return pos;
if (copy_from_user(runtime->dma_area + bpos, src, len))
return -EFAULT;
- if (snd_gf1_pcm_use_dma && len > 32) {
- return snd_gf1_pcm_block_change(substream, bpos, pcmp->memory + bpos, len);
- } else {
- struct snd_gus_card *gus = pcmp->gus;
- int err, w16, invert;
+ return playback_copy_ack(substream, bpos, len);
+}
- w16 = (snd_pcm_format_width(runtime->format) == 16);
- invert = snd_pcm_format_unsigned(runtime->format);
- if ((err = snd_gf1_pcm_poke_block(gus, runtime->dma_area + bpos, pcmp->memory + bpos, len, w16, invert)) < 0)
- return err;
- }
- return 0;
+static int snd_gf1_pcm_playback_copy_kernel(struct snd_pcm_substream *substream,
+ int voice, unsigned long pos,
+ void *src, unsigned long count)
+{
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct gus_pcm_private *pcmp = runtime->private_data;
+ unsigned int len = count;
+ int bpos;
+
+ bpos = get_bpos(pcmp, voice, pos, len);
+ if (bpos < 0)
+ return pos;
+ memcpy(runtime->dma_area + bpos, src, len);
+ return playback_copy_ack(substream, bpos, len);
}
static int snd_gf1_pcm_playback_silence(struct snd_pcm_substream *substream,
- int voice,
- snd_pcm_uframes_t pos,
- snd_pcm_uframes_t count)
+ int voice, unsigned long pos,
+ unsigned long count)
{
struct snd_pcm_runtime *runtime = substream->runtime;
struct gus_pcm_private *pcmp = runtime->private_data;
- unsigned int bpos, len;
+ unsigned int len = count;
+ int bpos;
- bpos = samples_to_bytes(runtime, pos) + (voice * (pcmp->dma_size / 2));
- len = samples_to_bytes(runtime, count);
- if (snd_BUG_ON(bpos > pcmp->dma_size))
- return -EIO;
- if (snd_BUG_ON(bpos + len > pcmp->dma_size))
- return -EIO;
- snd_pcm_format_set_silence(runtime->format, runtime->dma_area + bpos, count);
- if (snd_gf1_pcm_use_dma && len > 32) {
- return snd_gf1_pcm_block_change(substream, bpos, pcmp->memory + bpos, len);
- } else {
- struct snd_gus_card *gus = pcmp->gus;
- int err, w16, invert;
-
- w16 = (snd_pcm_format_width(runtime->format) == 16);
- invert = snd_pcm_format_unsigned(runtime->format);
- if ((err = snd_gf1_pcm_poke_block(gus, runtime->dma_area + bpos, pcmp->memory + bpos, len, w16, invert)) < 0)
- return err;
- }
- return 0;
+ bpos = get_bpos(pcmp, voice, pos, len);
+ if (bpos < 0)
+ return pos;
+ snd_pcm_format_set_silence(runtime->format, runtime->dma_area + bpos,
+ bytes_to_samples(runtime, count));
+ return playback_copy_ack(substream, bpos, len);
}
static int snd_gf1_pcm_playback_hw_params(struct snd_pcm_substream *substream,
@@ -809,7 +824,7 @@ static int snd_gf1_pcm_volume_put(struct snd_kcontrol *kcontrol, struct snd_ctl_
return change;
}
-static struct snd_kcontrol_new snd_gf1_pcm_volume_control =
+static const struct snd_kcontrol_new snd_gf1_pcm_volume_control =
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "PCM Playback Volume",
@@ -818,7 +833,7 @@ static struct snd_kcontrol_new snd_gf1_pcm_volume_control =
.put = snd_gf1_pcm_volume_put
};
-static struct snd_kcontrol_new snd_gf1_pcm_volume_control1 =
+static const struct snd_kcontrol_new snd_gf1_pcm_volume_control1 =
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "GPCM Playback Volume",
@@ -836,8 +851,9 @@ static struct snd_pcm_ops snd_gf1_pcm_playback_ops = {
.prepare = snd_gf1_pcm_playback_prepare,
.trigger = snd_gf1_pcm_playback_trigger,
.pointer = snd_gf1_pcm_playback_pointer,
- .copy = snd_gf1_pcm_playback_copy,
- .silence = snd_gf1_pcm_playback_silence,
+ .copy_user = snd_gf1_pcm_playback_copy,
+ .copy_kernel = snd_gf1_pcm_playback_copy_kernel,
+ .fill_silence = snd_gf1_pcm_playback_silence,
};
static struct snd_pcm_ops snd_gf1_pcm_capture_ops = {
diff --git a/sound/isa/sb/emu8000.c b/sound/isa/sb/emu8000.c
index ec18070..0b5c4cf 100644
--- a/sound/isa/sb/emu8000.c
+++ b/sound/isa/sb/emu8000.c
@@ -1138,7 +1138,7 @@ snd_emu8000_new(struct snd_card *card, int index, long port, int seq_ports,
snd_emu8000_free(hw);
return err;
}
-#if defined(CONFIG_SND_SEQUENCER) || (defined(MODULE) && defined(CONFIG_SND_SEQUENCER_MODULE))
+#if IS_REACHABLE(CONFIG_SND_SEQUENCER)
if (snd_seq_device_new(card, index, SNDRV_SEQ_DEV_ID_EMU8000,
sizeof(struct snd_emu8000*), &awe) >= 0) {
strcpy(awe->name, "EMU-8000");
diff --git a/sound/isa/sb/emu8000_pcm.c b/sound/isa/sb/emu8000_pcm.c
index 32f234f..2ee8d67 100644
--- a/sound/isa/sb/emu8000_pcm.c
+++ b/sound/isa/sb/emu8000_pcm.c
@@ -422,143 +422,148 @@ do { \
return -EAGAIN;\
} while (0)
+enum {
+ COPY_USER, COPY_KERNEL, FILL_SILENCE,
+};
+
+#define GET_VAL(sval, buf, mode) \
+ do { \
+ switch (mode) { \
+ case FILL_SILENCE: \
+ sval = 0; \
+ break; \
+ case COPY_KERNEL: \
+ sval = *buf++; \
+ break; \
+ default: \
+ if (get_user(sval, (unsigned short __user *)buf)) \
+ return -EFAULT; \
+ buf++; \
+ break; \
+ } \
+ } while (0)
#ifdef USE_NONINTERLEAVE
+
+#define LOOP_WRITE(rec, offset, _buf, count, mode) \
+ do { \
+ struct snd_emu8000 *emu = (rec)->emu; \
+ unsigned short *buf = (unsigned short *)(_buf); \
+ snd_emu8000_write_wait(emu, 1); \
+ EMU8000_SMALW_WRITE(emu, offset); \
+ while (count > 0) { \
+ unsigned short sval; \
+ CHECK_SCHEDULER(); \
+ GET_VAL(sval, buf, mode); \
+ EMU8000_SMLD_WRITE(emu, sval); \
+ count--; \
+ } \
+ } while (0)
+
/* copy one channel block */
-static int emu8k_transfer_block(struct snd_emu8000 *emu, int offset, unsigned short *buf, int count)
+static int emu8k_pcm_copy(struct snd_pcm_substream *subs,
+ int voice, unsigned long pos,
+ void __user *src, unsigned long count)
{
- EMU8000_SMALW_WRITE(emu, offset);
- while (count > 0) {
- unsigned short sval;
- CHECK_SCHEDULER();
- if (get_user(sval, buf))
- return -EFAULT;
- EMU8000_SMLD_WRITE(emu, sval);
- buf++;
- count--;
- }
+ struct snd_emu8k_pcm *rec = subs->runtime->private_data;
+
+ /* convert to word unit */
+ pos = (pos << 1) + rec->loop_start[voice];
+ count <<= 1;
+ LOOP_WRITE(rec, pos, src, count, COPY_UESR);
return 0;
}
-static int emu8k_pcm_copy(struct snd_pcm_substream *subs,
- int voice,
- snd_pcm_uframes_t pos,
- void *src,
- snd_pcm_uframes_t count)
+static int emu8k_pcm_copy_kernel(struct snd_pcm_substream *subs,
+ int voice, unsigned long pos,
+ void *src, unsigned long count)
{
struct snd_emu8k_pcm *rec = subs->runtime->private_data;
- struct snd_emu8000 *emu = rec->emu;
-
- snd_emu8000_write_wait(emu, 1);
- if (voice == -1) {
- unsigned short *buf = src;
- int i, err;
- count /= rec->voices;
- for (i = 0; i < rec->voices; i++) {
- err = emu8k_transfer_block(emu, pos + rec->loop_start[i], buf, count);
- if (err < 0)
- return err;
- buf += count;
- }
- return 0;
- } else {
- return emu8k_transfer_block(emu, pos + rec->loop_start[voice], src, count);
- }
-}
-/* make a channel block silence */
-static int emu8k_silence_block(struct snd_emu8000 *emu, int offset, int count)
-{
- EMU8000_SMALW_WRITE(emu, offset);
- while (count > 0) {
- CHECK_SCHEDULER();
- EMU8000_SMLD_WRITE(emu, 0);
- count--;
- }
+ /* convert to word unit */
+ pos = (pos << 1) + rec->loop_start[voice];
+ count <<= 1;
+ LOOP_WRITE(rec, pos, src, count, COPY_KERNEL);
return 0;
}
+/* make a channel block silence */
static int emu8k_pcm_silence(struct snd_pcm_substream *subs,
- int voice,
- snd_pcm_uframes_t pos,
- snd_pcm_uframes_t count)
+ int voice, unsigned long pos, unsigned long count)
{
struct snd_emu8k_pcm *rec = subs->runtime->private_data;
- struct snd_emu8000 *emu = rec->emu;
-
- snd_emu8000_write_wait(emu, 1);
- if (voice == -1 && rec->voices == 1)
- voice = 0;
- if (voice == -1) {
- int err;
- err = emu8k_silence_block(emu, pos + rec->loop_start[0], count / 2);
- if (err < 0)
- return err;
- return emu8k_silence_block(emu, pos + rec->loop_start[1], count / 2);
- } else {
- return emu8k_silence_block(emu, pos + rec->loop_start[voice], count);
- }
+
+ /* convert to word unit */
+ pos = (pos << 1) + rec->loop_start[voice];
+ count <<= 1;
+ LOOP_WRITE(rec, pos, NULL, count, FILL_SILENCE);
+ return 0;
}
#else /* interleave */
+#define LOOP_WRITE(rec, pos, _buf, count, mode) \
+ do { \
+ struct snd_emu8000 *emu = rec->emu; \
+ unsigned short *buf = (unsigned short *)(_buf); \
+ snd_emu8000_write_wait(emu, 1); \
+ EMU8000_SMALW_WRITE(emu, pos + rec->loop_start[0]); \
+ if (rec->voices > 1) \
+ EMU8000_SMARW_WRITE(emu, pos + rec->loop_start[1]); \
+ while (count > 0) { \
+ unsigned short sval; \
+ CHECK_SCHEDULER(); \
+ GET_VAL(sval, buf, mode); \
+ EMU8000_SMLD_WRITE(emu, sval); \
+ if (rec->voices > 1) { \
+ CHECK_SCHEDULER(); \
+ GET_VAL(sval, buf, mode); \
+ EMU8000_SMRD_WRITE(emu, sval); \
+ } \
+ count--; \
+ } \
+ } while (0)
+
+
/*
* copy the interleaved data can be done easily by using
* DMA "left" and "right" channels on emu8k engine.
*/
static int emu8k_pcm_copy(struct snd_pcm_substream *subs,
- int voice,
- snd_pcm_uframes_t pos,
- void __user *src,
- snd_pcm_uframes_t count)
+ int voice, unsigned long pos,
+ void __user *src, unsigned long count)
{
struct snd_emu8k_pcm *rec = subs->runtime->private_data;
- struct snd_emu8000 *emu = rec->emu;
- unsigned short __user *buf = src;
- snd_emu8000_write_wait(emu, 1);
- EMU8000_SMALW_WRITE(emu, pos + rec->loop_start[0]);
- if (rec->voices > 1)
- EMU8000_SMARW_WRITE(emu, pos + rec->loop_start[1]);
-
- while (count-- > 0) {
- unsigned short sval;
- CHECK_SCHEDULER();
- if (get_user(sval, buf))
- return -EFAULT;
- EMU8000_SMLD_WRITE(emu, sval);
- buf++;
- if (rec->voices > 1) {
- CHECK_SCHEDULER();
- if (get_user(sval, buf))
- return -EFAULT;
- EMU8000_SMRD_WRITE(emu, sval);
- buf++;
- }
- }
+ /* convert to frames */
+ pos = bytes_to_frames(subs->runtime, pos);
+ count = bytes_to_frames(subs->runtime, count);
+ LOOP_WRITE(rec, pos, src, count, COPY_USER);
+ return 0;
+}
+
+static int emu8k_pcm_copy_kernel(struct snd_pcm_substream *subs,
+ int voice, unsigned long pos,
+ void *src, unsigned long count)
+{
+ struct snd_emu8k_pcm *rec = subs->runtime->private_data;
+
+ /* convert to frames */
+ pos = bytes_to_frames(subs->runtime, pos);
+ count = bytes_to_frames(subs->runtime, count);
+ LOOP_WRITE(rec, pos, src, count, COPY_KERNEL);
return 0;
}
static int emu8k_pcm_silence(struct snd_pcm_substream *subs,
- int voice,
- snd_pcm_uframes_t pos,
- snd_pcm_uframes_t count)
+ int voice, unsigned long pos, unsigned long count)
{
struct snd_emu8k_pcm *rec = subs->runtime->private_data;
- struct snd_emu8000 *emu = rec->emu;
- snd_emu8000_write_wait(emu, 1);
- EMU8000_SMALW_WRITE(emu, rec->loop_start[0] + pos);
- if (rec->voices > 1)
- EMU8000_SMARW_WRITE(emu, rec->loop_start[1] + pos);
- while (count-- > 0) {
- CHECK_SCHEDULER();
- EMU8000_SMLD_WRITE(emu, 0);
- if (rec->voices > 1) {
- CHECK_SCHEDULER();
- EMU8000_SMRD_WRITE(emu, 0);
- }
- }
+ /* convert to frames */
+ pos = bytes_to_frames(subs->runtime, pos);
+ count = bytes_to_frames(subs->runtime, count);
+ LOOP_WRITE(rec, pos, NULL, count, FILL_SILENCE);
return 0;
}
#endif
@@ -674,8 +679,9 @@ static struct snd_pcm_ops emu8k_pcm_ops = {
.prepare = emu8k_pcm_prepare,
.trigger = emu8k_pcm_trigger,
.pointer = emu8k_pcm_pointer,
- .copy = emu8k_pcm_copy,
- .silence = emu8k_pcm_silence,
+ .copy_user = emu8k_pcm_copy,
+ .copy_kernel = emu8k_pcm_copy_kernel,
+ .fill_silence = emu8k_pcm_silence,
};
diff --git a/sound/isa/sb/sb16.c b/sound/isa/sb/sb16.c
index 3b2e4f4..31ab09b 100644
--- a/sound/isa/sb/sb16.c
+++ b/sound/isa/sb/sb16.c
@@ -62,7 +62,7 @@ MODULE_SUPPORTED_DEVICE("{{Creative Labs,SB AWE 32},"
#define SNDRV_DEBUG_IRQ
#endif
-#if defined(SNDRV_SBAWE) && (defined(CONFIG_SND_SEQUENCER) || (defined(MODULE) && defined(CONFIG_SND_SEQUENCER_MODULE)))
+#if defined(SNDRV_SBAWE) && IS_REACHABLE(CONFIG_SND_SEQUENCER)
#define SNDRV_SBAWE_EMU8000
#endif
diff --git a/sound/isa/sb/sb16_csp.c b/sound/isa/sb/sb16_csp.c
index 48da227..fa5780b 100644
--- a/sound/isa/sb/sb16_csp.c
+++ b/sound/isa/sb/sb16_csp.c
@@ -1029,7 +1029,7 @@ static int snd_sb_qsound_space_put(struct snd_kcontrol *kcontrol, struct snd_ctl
return change;
}
-static struct snd_kcontrol_new snd_sb_qsound_switch = {
+static const struct snd_kcontrol_new snd_sb_qsound_switch = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "3D Control - Switch",
.info = snd_sb_qsound_switch_info,
@@ -1037,7 +1037,7 @@ static struct snd_kcontrol_new snd_sb_qsound_switch = {
.put = snd_sb_qsound_switch_put
};
-static struct snd_kcontrol_new snd_sb_qsound_space = {
+static const struct snd_kcontrol_new snd_sb_qsound_space = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "3D Control - Space",
.info = snd_sb_qsound_space_info,
diff --git a/sound/isa/sb/sb16_main.c b/sound/isa/sb/sb16_main.c
index 8b2d6c6..4be1350 100644
--- a/sound/isa/sb/sb16_main.c
+++ b/sound/isa/sb/sb16_main.c
@@ -737,7 +737,7 @@ static int snd_sb16_dma_control_put(struct snd_kcontrol *kcontrol, struct snd_ct
return change;
}
-static struct snd_kcontrol_new snd_sb16_dma_control = {
+static const struct snd_kcontrol_new snd_sb16_dma_control = {
.iface = SNDRV_CTL_ELEM_IFACE_CARD,
.name = "16-bit DMA Allocation",
.info = snd_sb16_dma_control_info,
diff --git a/sound/isa/sscape.c b/sound/isa/sscape.c
index 54f5758a..1cd2908 100644
--- a/sound/isa/sscape.c
+++ b/sound/isa/sscape.c
@@ -671,7 +671,7 @@ __skip_change:
return change;
}
-static struct snd_kcontrol_new midi_mixer_ctl = {
+static const struct snd_kcontrol_new midi_mixer_ctl = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "MIDI",
.info = sscape_midi_info,
diff --git a/sound/mips/hal2.c b/sound/mips/hal2.c
index 00fc924..6505deb 100644
--- a/sound/mips/hal2.c
+++ b/sound/mips/hal2.c
@@ -264,7 +264,7 @@ static int hal2_gain_put(struct snd_kcontrol *kcontrol,
return old != new;
}
-static struct snd_kcontrol_new hal2_ctrl_headphone = {
+static const struct snd_kcontrol_new hal2_ctrl_headphone = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Headphone Playback Volume",
.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
@@ -274,7 +274,7 @@ static struct snd_kcontrol_new hal2_ctrl_headphone = {
.put = hal2_gain_put,
};
-static struct snd_kcontrol_new hal2_ctrl_mic = {
+static const struct snd_kcontrol_new hal2_ctrl_mic = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Mic Capture Volume",
.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
@@ -616,10 +616,9 @@ static int hal2_playback_ack(struct snd_pcm_substream *substream)
struct hal2_codec *dac = &hal2->dac;
dac->pcm_indirect.hw_queue_size = H2_BUF_SIZE / 2;
- snd_pcm_indirect_playback_transfer(substream,
- &dac->pcm_indirect,
- hal2_playback_transfer);
- return 0;
+ return snd_pcm_indirect_playback_transfer(substream,
+ &dac->pcm_indirect,
+ hal2_playback_transfer);
}
static int hal2_capture_open(struct snd_pcm_substream *substream)
@@ -707,10 +706,9 @@ static int hal2_capture_ack(struct snd_pcm_substream *substream)
struct snd_hal2 *hal2 = snd_pcm_substream_chip(substream);
struct hal2_codec *adc = &hal2->adc;
- snd_pcm_indirect_capture_transfer(substream,
- &adc->pcm_indirect,
- hal2_capture_transfer);
- return 0;
+ return snd_pcm_indirect_capture_transfer(substream,
+ &adc->pcm_indirect,
+ hal2_capture_transfer);
}
static struct snd_pcm_ops hal2_playback_ops = {
diff --git a/sound/mips/sgio2audio.c b/sound/mips/sgio2audio.c
index f07aa39..0ebc1c3 100644
--- a/sound/mips/sgio2audio.c
+++ b/sound/mips/sgio2audio.c
@@ -230,7 +230,7 @@ static int sgio2audio_source_put(struct snd_kcontrol *kcontrol,
}
/* dac1/pcm0 mixer control */
-static struct snd_kcontrol_new sgio2audio_ctrl_pcm0 = {
+static const struct snd_kcontrol_new sgio2audio_ctrl_pcm0 = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "PCM Playback Volume",
.index = 0,
@@ -242,7 +242,7 @@ static struct snd_kcontrol_new sgio2audio_ctrl_pcm0 = {
};
/* dac2/pcm1 mixer control */
-static struct snd_kcontrol_new sgio2audio_ctrl_pcm1 = {
+static const struct snd_kcontrol_new sgio2audio_ctrl_pcm1 = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "PCM Playback Volume",
.index = 1,
@@ -254,7 +254,7 @@ static struct snd_kcontrol_new sgio2audio_ctrl_pcm1 = {
};
/* record level mixer control */
-static struct snd_kcontrol_new sgio2audio_ctrl_reclevel = {
+static const struct snd_kcontrol_new sgio2audio_ctrl_reclevel = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Capture Volume",
.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
@@ -265,7 +265,7 @@ static struct snd_kcontrol_new sgio2audio_ctrl_reclevel = {
};
/* record level source control */
-static struct snd_kcontrol_new sgio2audio_ctrl_recsource = {
+static const struct snd_kcontrol_new sgio2audio_ctrl_recsource = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Capture Source",
.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
@@ -275,7 +275,7 @@ static struct snd_kcontrol_new sgio2audio_ctrl_recsource = {
};
/* line mixer control */
-static struct snd_kcontrol_new sgio2audio_ctrl_line = {
+static const struct snd_kcontrol_new sgio2audio_ctrl_line = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Line Playback Volume",
.index = 0,
@@ -287,7 +287,7 @@ static struct snd_kcontrol_new sgio2audio_ctrl_line = {
};
/* cd mixer control */
-static struct snd_kcontrol_new sgio2audio_ctrl_cd = {
+static const struct snd_kcontrol_new sgio2audio_ctrl_cd = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Line Playback Volume",
.index = 1,
@@ -299,7 +299,7 @@ static struct snd_kcontrol_new sgio2audio_ctrl_cd = {
};
/* mic mixer control */
-static struct snd_kcontrol_new sgio2audio_ctrl_mic = {
+static const struct snd_kcontrol_new sgio2audio_ctrl_mic = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Mic Playback Volume",
.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
diff --git a/sound/pci/cs4281.c b/sound/pci/cs4281.c
index f870697..ee7ba4b 100644
--- a/sound/pci/cs4281.c
+++ b/sound/pci/cs4281.c
@@ -1296,7 +1296,7 @@ static void snd_cs4281_free_gameport(struct cs4281 *chip)
#else
static inline int snd_cs4281_create_gameport(struct cs4281 *chip) { return -ENOSYS; }
static inline void snd_cs4281_free_gameport(struct cs4281 *chip) { }
-#endif /* CONFIG_GAMEPORT || (MODULE && CONFIG_GAMEPORT_MODULE) */
+#endif /* IS_REACHABLE(CONFIG_GAMEPORT) */
static int snd_cs4281_free(struct cs4281 *chip)
{
diff --git a/sound/pci/cs46xx/cs46xx_lib.c b/sound/pci/cs46xx/cs46xx_lib.c
index e4cf318..ae2aad5 100644
--- a/sound/pci/cs46xx/cs46xx_lib.c
+++ b/sound/pci/cs46xx/cs46xx_lib.c
@@ -887,8 +887,8 @@ static int snd_cs46xx_playback_transfer(struct snd_pcm_substream *substream)
{
struct snd_pcm_runtime *runtime = substream->runtime;
struct snd_cs46xx_pcm * cpcm = runtime->private_data;
- snd_pcm_indirect_playback_transfer(substream, &cpcm->pcm_rec, snd_cs46xx_pb_trans_copy);
- return 0;
+ return snd_pcm_indirect_playback_transfer(substream, &cpcm->pcm_rec,
+ snd_cs46xx_pb_trans_copy);
}
static void snd_cs46xx_cp_trans_copy(struct snd_pcm_substream *substream,
@@ -903,8 +903,8 @@ static void snd_cs46xx_cp_trans_copy(struct snd_pcm_substream *substream,
static int snd_cs46xx_capture_transfer(struct snd_pcm_substream *substream)
{
struct snd_cs46xx *chip = snd_pcm_substream_chip(substream);
- snd_pcm_indirect_capture_transfer(substream, &chip->capt.pcm_rec, snd_cs46xx_cp_trans_copy);
- return 0;
+ return snd_pcm_indirect_capture_transfer(substream, &chip->capt.pcm_rec,
+ snd_cs46xx_cp_trans_copy);
}
static snd_pcm_uframes_t snd_cs46xx_playback_direct_pointer(struct snd_pcm_substream *substream)
@@ -2371,7 +2371,7 @@ static int snd_cs46xx_front_dup_put(struct snd_kcontrol *kcontrol,
ucontrol->value.integer.value[0] ? 0 : 0x200);
}
-static struct snd_kcontrol_new snd_cs46xx_front_dup_ctl = {
+static const struct snd_kcontrol_new snd_cs46xx_front_dup_ctl = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Duplicate Front",
.info = snd_mixer_boolean_info,
diff --git a/sound/pci/emu10k1/emufx.c b/sound/pci/emu10k1/emufx.c
index 56fc47b..dc58595 100644
--- a/sound/pci/emu10k1/emufx.c
+++ b/sound/pci/emu10k1/emufx.c
@@ -311,21 +311,6 @@ static const u32 onoff_table[2] = {
};
/*
- */
-
-static inline mm_segment_t snd_enter_user(void)
-{
- mm_segment_t fs = get_fs();
- set_fs(get_ds());
- return fs;
-}
-
-static inline void snd_leave_user(mm_segment_t fs)
-{
- set_fs(fs);
-}
-
-/*
* controls
*/
@@ -538,7 +523,8 @@ unsigned int snd_emu10k1_efx_read(struct snd_emu10k1 *emu, unsigned int pc)
}
static int snd_emu10k1_gpr_poke(struct snd_emu10k1 *emu,
- struct snd_emu10k1_fx8010_code *icode)
+ struct snd_emu10k1_fx8010_code *icode,
+ bool in_kernel)
{
int gpr;
u32 val;
@@ -546,7 +532,9 @@ static int snd_emu10k1_gpr_poke(struct snd_emu10k1 *emu,
for (gpr = 0; gpr < (emu->audigy ? 0x200 : 0x100); gpr++) {
if (!test_bit(gpr, icode->gpr_valid))
continue;
- if (get_user(val, &icode->gpr_map[gpr]))
+ if (in_kernel)
+ val = *(u32 *)&icode->gpr_map[gpr];
+ else if (get_user(val, &icode->gpr_map[gpr]))
return -EFAULT;
snd_emu10k1_ptr_write(emu, emu->gpr_base + gpr, 0, val);
}
@@ -569,7 +557,8 @@ static int snd_emu10k1_gpr_peek(struct snd_emu10k1 *emu,
}
static int snd_emu10k1_tram_poke(struct snd_emu10k1 *emu,
- struct snd_emu10k1_fx8010_code *icode)
+ struct snd_emu10k1_fx8010_code *icode,
+ bool in_kernel)
{
int tram;
u32 addr, val;
@@ -577,9 +566,14 @@ static int snd_emu10k1_tram_poke(struct snd_emu10k1 *emu,
for (tram = 0; tram < (emu->audigy ? 0x100 : 0xa0); tram++) {
if (!test_bit(tram, icode->tram_valid))
continue;
- if (get_user(val, &icode->tram_data_map[tram]) ||
- get_user(addr, &icode->tram_addr_map[tram]))
- return -EFAULT;
+ if (in_kernel) {
+ val = *(u32 *)&icode->tram_data_map[tram];
+ addr = *(u32 *)&icode->tram_addr_map[tram];
+ } else {
+ if (get_user(val, &icode->tram_data_map[tram]) ||
+ get_user(addr, &icode->tram_addr_map[tram]))
+ return -EFAULT;
+ }
snd_emu10k1_ptr_write(emu, TANKMEMDATAREGBASE + tram, 0, val);
if (!emu->audigy) {
snd_emu10k1_ptr_write(emu, TANKMEMADDRREGBASE + tram, 0, addr);
@@ -615,16 +609,22 @@ static int snd_emu10k1_tram_peek(struct snd_emu10k1 *emu,
}
static int snd_emu10k1_code_poke(struct snd_emu10k1 *emu,
- struct snd_emu10k1_fx8010_code *icode)
+ struct snd_emu10k1_fx8010_code *icode,
+ bool in_kernel)
{
u32 pc, lo, hi;
for (pc = 0; pc < (emu->audigy ? 2*1024 : 2*512); pc += 2) {
if (!test_bit(pc / 2, icode->code_valid))
continue;
- if (get_user(lo, &icode->code[pc + 0]) ||
- get_user(hi, &icode->code[pc + 1]))
- return -EFAULT;
+ if (in_kernel) {
+ lo = *(u32 *)&icode->code[pc + 0];
+ hi = *(u32 *)&icode->code[pc + 1];
+ } else {
+ if (get_user(lo, &icode->code[pc + 0]) ||
+ get_user(hi, &icode->code[pc + 1]))
+ return -EFAULT;
+ }
snd_emu10k1_efx_write(emu, pc + 0, lo);
snd_emu10k1_efx_write(emu, pc + 1, hi);
}
@@ -665,14 +665,16 @@ snd_emu10k1_look_for_ctl(struct snd_emu10k1 *emu, struct snd_ctl_elem_id *id)
#define MAX_TLV_SIZE 256
-static unsigned int *copy_tlv(const unsigned int __user *_tlv)
+static unsigned int *copy_tlv(const unsigned int __user *_tlv, bool in_kernel)
{
unsigned int data[2];
unsigned int *tlv;
if (!_tlv)
return NULL;
- if (copy_from_user(data, _tlv, sizeof(data)))
+ if (in_kernel)
+ memcpy(data, (void *)_tlv, sizeof(data));
+ else if (copy_from_user(data, _tlv, sizeof(data)))
return NULL;
if (data[1] >= MAX_TLV_SIZE)
return NULL;
@@ -680,7 +682,9 @@ static unsigned int *copy_tlv(const unsigned int __user *_tlv)
if (!tlv)
return NULL;
memcpy(tlv, data, sizeof(data));
- if (copy_from_user(tlv + 2, _tlv + 2, data[1])) {
+ if (in_kernel) {
+ memcpy(tlv + 2, (void *)(_tlv + 2), data[1]);
+ } else if (copy_from_user(tlv + 2, _tlv + 2, data[1])) {
kfree(tlv);
return NULL;
}
@@ -690,7 +694,7 @@ static unsigned int *copy_tlv(const unsigned int __user *_tlv)
static int copy_gctl(struct snd_emu10k1 *emu,
struct snd_emu10k1_fx8010_control_gpr *gctl,
struct snd_emu10k1_fx8010_control_gpr __user *_gctl,
- int idx)
+ int idx, bool in_kernel)
{
struct snd_emu10k1_fx8010_control_old_gpr __user *octl;
@@ -718,7 +722,8 @@ static int copy_gctl_to_user(struct snd_emu10k1 *emu,
}
static int snd_emu10k1_verify_controls(struct snd_emu10k1 *emu,
- struct snd_emu10k1_fx8010_code *icode)
+ struct snd_emu10k1_fx8010_code *icode,
+ bool in_kernel)
{
unsigned int i;
struct snd_ctl_elem_id __user *_id;
@@ -728,7 +733,9 @@ static int snd_emu10k1_verify_controls(struct snd_emu10k1 *emu,
for (i = 0, _id = icode->gpr_del_controls;
i < icode->gpr_del_control_count; i++, _id++) {
- if (copy_from_user(&id, _id, sizeof(id)))
+ if (in_kernel)
+ id = *(struct snd_ctl_elem_id *)_id;
+ else if (copy_from_user(&id, _id, sizeof(id)))
return -EFAULT;
if (snd_emu10k1_look_for_ctl(emu, &id) == NULL)
return -ENOENT;
@@ -738,7 +745,8 @@ static int snd_emu10k1_verify_controls(struct snd_emu10k1 *emu,
return -ENOMEM;
err = 0;
for (i = 0; i < icode->gpr_add_control_count; i++) {
- if (copy_gctl(emu, gctl, icode->gpr_add_controls, i)) {
+ if (copy_gctl(emu, gctl, icode->gpr_add_controls, i,
+ in_kernel)) {
err = -EFAULT;
goto __error;
}
@@ -759,7 +767,8 @@ static int snd_emu10k1_verify_controls(struct snd_emu10k1 *emu,
}
for (i = 0; i < icode->gpr_list_control_count; i++) {
/* FIXME: we need to check the WRITE access */
- if (copy_gctl(emu, gctl, icode->gpr_list_controls, i)) {
+ if (copy_gctl(emu, gctl, icode->gpr_list_controls, i,
+ in_kernel)) {
err = -EFAULT;
goto __error;
}
@@ -781,7 +790,8 @@ static void snd_emu10k1_ctl_private_free(struct snd_kcontrol *kctl)
}
static int snd_emu10k1_add_controls(struct snd_emu10k1 *emu,
- struct snd_emu10k1_fx8010_code *icode)
+ struct snd_emu10k1_fx8010_code *icode,
+ bool in_kernel)
{
unsigned int i, j;
struct snd_emu10k1_fx8010_control_gpr *gctl;
@@ -800,7 +810,8 @@ static int snd_emu10k1_add_controls(struct snd_emu10k1 *emu,
}
for (i = 0; i < icode->gpr_add_control_count; i++) {
- if (copy_gctl(emu, gctl, icode->gpr_add_controls, i)) {
+ if (copy_gctl(emu, gctl, icode->gpr_add_controls, i,
+ in_kernel)) {
err = -EFAULT;
goto __error;
}
@@ -821,7 +832,7 @@ static int snd_emu10k1_add_controls(struct snd_emu10k1 *emu,
knew.device = gctl->id.device;
knew.subdevice = gctl->id.subdevice;
knew.info = snd_emu10k1_gpr_ctl_info;
- knew.tlv.p = copy_tlv(gctl->tlv);
+ knew.tlv.p = copy_tlv(gctl->tlv, in_kernel);
if (knew.tlv.p)
knew.access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
SNDRV_CTL_ELEM_ACCESS_TLV_READ;
@@ -873,7 +884,8 @@ static int snd_emu10k1_add_controls(struct snd_emu10k1 *emu,
}
static int snd_emu10k1_del_controls(struct snd_emu10k1 *emu,
- struct snd_emu10k1_fx8010_code *icode)
+ struct snd_emu10k1_fx8010_code *icode,
+ bool in_kernel)
{
unsigned int i;
struct snd_ctl_elem_id id;
@@ -883,7 +895,9 @@ static int snd_emu10k1_del_controls(struct snd_emu10k1 *emu,
for (i = 0, _id = icode->gpr_del_controls;
i < icode->gpr_del_control_count; i++, _id++) {
- if (copy_from_user(&id, _id, sizeof(id)))
+ if (in_kernel)
+ id = *(struct snd_ctl_elem_id *)_id;
+ else if (copy_from_user(&id, _id, sizeof(id)))
return -EFAULT;
down_write(&card->controls_rwsem);
ctl = snd_emu10k1_look_for_ctl(emu, &id);
@@ -941,12 +955,14 @@ static int snd_emu10k1_list_controls(struct snd_emu10k1 *emu,
}
static int snd_emu10k1_icode_poke(struct snd_emu10k1 *emu,
- struct snd_emu10k1_fx8010_code *icode)
+ struct snd_emu10k1_fx8010_code *icode,
+ bool in_kernel)
{
int err = 0;
mutex_lock(&emu->fx8010.lock);
- if ((err = snd_emu10k1_verify_controls(emu, icode)) < 0)
+ err = snd_emu10k1_verify_controls(emu, icode, in_kernel);
+ if (err < 0)
goto __error;
strlcpy(emu->fx8010.name, icode->name, sizeof(emu->fx8010.name));
/* stop FX processor - this may be dangerous, but it's better to miss
@@ -956,11 +972,20 @@ static int snd_emu10k1_icode_poke(struct snd_emu10k1 *emu,
else
snd_emu10k1_ptr_write(emu, DBG, 0, emu->fx8010.dbg | EMU10K1_DBG_SINGLE_STEP);
/* ok, do the main job */
- if ((err = snd_emu10k1_del_controls(emu, icode)) < 0 ||
- (err = snd_emu10k1_gpr_poke(emu, icode)) < 0 ||
- (err = snd_emu10k1_tram_poke(emu, icode)) < 0 ||
- (err = snd_emu10k1_code_poke(emu, icode)) < 0 ||
- (err = snd_emu10k1_add_controls(emu, icode)) < 0)
+ err = snd_emu10k1_del_controls(emu, icode, in_kernel);
+ if (err < 0)
+ goto __error;
+ err = snd_emu10k1_gpr_poke(emu, icode, in_kernel);
+ if (err < 0)
+ goto __error;
+ err = snd_emu10k1_tram_poke(emu, icode, in_kernel);
+ if (err < 0)
+ goto __error;
+ err = snd_emu10k1_code_poke(emu, icode, in_kernel);
+ if (err < 0)
+ goto __error;
+ err = snd_emu10k1_add_controls(emu, icode, in_kernel);
+ if (err < 0)
goto __error;
/* start FX processor when the DSP code is updated */
if (emu->audigy)
@@ -1179,7 +1204,6 @@ static int _snd_emu10k1_audigy_init_efx(struct snd_emu10k1 *emu)
struct snd_emu10k1_fx8010_code *icode = NULL;
struct snd_emu10k1_fx8010_control_gpr *controls = NULL, *ctl;
u32 *gpr_map;
- mm_segment_t seg;
err = -ENOMEM;
icode = kzalloc(sizeof(*icode), GFP_KERNEL);
@@ -1739,13 +1763,11 @@ A_OP(icode, &ptr, iMAC0, A_GPR(var), A_GPR(var), A_GPR(vol), A_EXTIN(input))
while (ptr < 0x400)
A_OP(icode, &ptr, 0x0f, 0xc0, 0xc0, 0xcf, 0xc0);
- seg = snd_enter_user();
icode->gpr_add_control_count = nctl;
icode->gpr_add_controls = (struct snd_emu10k1_fx8010_control_gpr __user *)controls;
emu->support_tlv = 1; /* support TLV */
- err = snd_emu10k1_icode_poke(emu, icode);
+ err = snd_emu10k1_icode_poke(emu, icode, true);
emu->support_tlv = 0; /* clear again */
- snd_leave_user(seg);
__err:
kfree(controls);
@@ -1817,7 +1839,6 @@ static int _snd_emu10k1_init_efx(struct snd_emu10k1 *emu)
struct snd_emu10k1_fx8010_pcm_rec *ipcm = NULL;
struct snd_emu10k1_fx8010_control_gpr *controls = NULL, *ctl;
u32 *gpr_map;
- mm_segment_t seg;
err = -ENOMEM;
icode = kzalloc(sizeof(*icode), GFP_KERNEL);
@@ -2368,13 +2389,11 @@ static int _snd_emu10k1_init_efx(struct snd_emu10k1 *emu)
if ((err = snd_emu10k1_fx8010_tram_setup(emu, ipcm->buffer_size)) < 0)
goto __err;
- seg = snd_enter_user();
icode->gpr_add_control_count = i;
icode->gpr_add_controls = (struct snd_emu10k1_fx8010_control_gpr __user *)controls;
emu->support_tlv = 1; /* support TLV */
- err = snd_emu10k1_icode_poke(emu, icode);
+ err = snd_emu10k1_icode_poke(emu, icode, true);
emu->support_tlv = 0; /* clear again */
- snd_leave_user(seg);
if (err >= 0)
err = snd_emu10k1_ipcm_poke(emu, ipcm);
__err:
@@ -2537,7 +2556,7 @@ static int snd_emu10k1_fx8010_ioctl(struct snd_hwdep * hw, struct file *file, un
icode = memdup_user(argp, sizeof(*icode));
if (IS_ERR(icode))
return PTR_ERR(icode);
- res = snd_emu10k1_icode_poke(emu, icode);
+ res = snd_emu10k1_icode_poke(emu, icode, false);
kfree(icode);
return res;
case SNDRV_EMU10K1_IOCTL_CODE_PEEK:
diff --git a/sound/pci/emu10k1/emupcm.c b/sound/pci/emu10k1/emupcm.c
index ef1cf53..bdda29f 100644
--- a/sound/pci/emu10k1/emupcm.c
+++ b/sound/pci/emu10k1/emupcm.c
@@ -1632,8 +1632,8 @@ static int snd_emu10k1_fx8010_playback_transfer(struct snd_pcm_substream *substr
struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream);
struct snd_emu10k1_fx8010_pcm *pcm = &emu->fx8010.pcm[substream->number];
- snd_pcm_indirect_playback_transfer(substream, &pcm->pcm_rec, fx8010_pb_trans_copy);
- return 0;
+ return snd_pcm_indirect_playback_transfer(substream, &pcm->pcm_rec,
+ fx8010_pb_trans_copy);
}
static int snd_emu10k1_fx8010_playback_hw_params(struct snd_pcm_substream *substream,
diff --git a/sound/pci/es1938.c b/sound/pci/es1938.c
index e8d9430..a544cd5 100644
--- a/sound/pci/es1938.c
+++ b/sound/pci/es1938.c
@@ -839,15 +839,12 @@ static snd_pcm_uframes_t snd_es1938_playback_pointer(struct snd_pcm_substream *s
}
static int snd_es1938_capture_copy(struct snd_pcm_substream *substream,
- int channel,
- snd_pcm_uframes_t pos,
- void __user *dst,
- snd_pcm_uframes_t count)
+ int channel, unsigned long pos,
+ void __user *dst, unsigned long count)
{
struct snd_pcm_runtime *runtime = substream->runtime;
struct es1938 *chip = snd_pcm_substream_chip(substream);
- pos <<= chip->dma1_shift;
- count <<= chip->dma1_shift;
+
if (snd_BUG_ON(pos + count > chip->dma1_size))
return -EINVAL;
if (pos + count < chip->dma1_size) {
@@ -856,12 +853,31 @@ static int snd_es1938_capture_copy(struct snd_pcm_substream *substream,
} else {
if (copy_to_user(dst, runtime->dma_area + pos + 1, count - 1))
return -EFAULT;
- if (put_user(runtime->dma_area[0], ((unsigned char __user *)dst) + count - 1))
+ if (put_user(runtime->dma_area[0],
+ ((unsigned char __user *)dst) + count - 1))
return -EFAULT;
}
return 0;
}
+static int snd_es1938_capture_copy_kernel(struct snd_pcm_substream *substream,
+ int channel, unsigned long pos,
+ void *dst, unsigned long count)
+{
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct es1938 *chip = snd_pcm_substream_chip(substream);
+
+ if (snd_BUG_ON(pos + count > chip->dma1_size))
+ return -EINVAL;
+ if (pos + count < chip->dma1_size) {
+ memcpy(dst, runtime->dma_area + pos + 1, count);
+ } else {
+ memcpy(dst, runtime->dma_area + pos + 1, count - 1);
+ runtime->dma_area[0] = *((unsigned char *)dst + count - 1);
+ }
+ return 0;
+}
+
/*
* buffer management
*/
@@ -1012,7 +1028,8 @@ static const struct snd_pcm_ops snd_es1938_capture_ops = {
.prepare = snd_es1938_capture_prepare,
.trigger = snd_es1938_capture_trigger,
.pointer = snd_es1938_capture_pointer,
- .copy = snd_es1938_capture_copy,
+ .copy_user = snd_es1938_capture_copy,
+ .copy_kernel = snd_es1938_capture_copy_kernel,
};
static int snd_es1938_new_pcm(struct es1938 *chip, int device)
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c
index 70bb365..821aad3 100644
--- a/sound/pci/hda/hda_codec.c
+++ b/sound/pci/hda/hda_codec.c
@@ -19,13 +19,11 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include <linux/mm.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/slab.h>
#include <linux/mutex.h>
#include <linux/module.h>
-#include <linux/async.h>
#include <linux/pm.h>
#include <linux/pm_runtime.h>
#include <sound/core.h>
@@ -1477,18 +1475,8 @@ int snd_hda_mixer_amp_volume_put(struct snd_kcontrol *kcontrol,
}
EXPORT_SYMBOL_GPL(snd_hda_mixer_amp_volume_put);
-/**
- * snd_hda_mixer_amp_volume_put - TLV callback for a standard AMP mixer volume
- * @kcontrol: ctl element
- * @op_flag: operation flag
- * @size: byte size of input TLV
- * @_tlv: TLV data
- *
- * The control element is supposed to have the private_value field
- * set up via HDA_COMPOSE_AMP_VAL*() or related macros.
- */
-int snd_hda_mixer_amp_tlv(struct snd_kcontrol *kcontrol, int op_flag,
- unsigned int size, unsigned int __user *_tlv)
+/* inquiry the amp caps and convert to TLV */
+static void get_ctl_amp_tlv(struct snd_kcontrol *kcontrol, unsigned int *tlv)
{
struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
hda_nid_t nid = get_amp_nid(kcontrol);
@@ -1497,8 +1485,6 @@ int snd_hda_mixer_amp_tlv(struct snd_kcontrol *kcontrol, int op_flag,
bool min_mute = get_amp_min_mute(kcontrol);
u32 caps, val1, val2;
- if (size < 4 * sizeof(unsigned int))
- return -ENOMEM;
caps = query_amp_caps(codec, nid, dir);
val2 = (caps & AC_AMPCAP_STEP_SIZE) >> AC_AMPCAP_STEP_SIZE_SHIFT;
val2 = (val2 + 1) * 25;
@@ -1507,13 +1493,31 @@ int snd_hda_mixer_amp_tlv(struct snd_kcontrol *kcontrol, int op_flag,
val1 = ((int)val1) * ((int)val2);
if (min_mute || (caps & AC_AMPCAP_MIN_MUTE))
val2 |= TLV_DB_SCALE_MUTE;
- if (put_user(SNDRV_CTL_TLVT_DB_SCALE, _tlv))
- return -EFAULT;
- if (put_user(2 * sizeof(unsigned int), _tlv + 1))
- return -EFAULT;
- if (put_user(val1, _tlv + 2))
- return -EFAULT;
- if (put_user(val2, _tlv + 3))
+ tlv[0] = SNDRV_CTL_TLVT_DB_SCALE;
+ tlv[1] = 2 * sizeof(unsigned int);
+ tlv[2] = val1;
+ tlv[3] = val2;
+}
+
+/**
+ * snd_hda_mixer_amp_tlv - TLV callback for a standard AMP mixer volume
+ * @kcontrol: ctl element
+ * @op_flag: operation flag
+ * @size: byte size of input TLV
+ * @_tlv: TLV data
+ *
+ * The control element is supposed to have the private_value field
+ * set up via HDA_COMPOSE_AMP_VAL*() or related macros.
+ */
+int snd_hda_mixer_amp_tlv(struct snd_kcontrol *kcontrol, int op_flag,
+ unsigned int size, unsigned int __user *_tlv)
+{
+ unsigned int tlv[4];
+
+ if (size < 4 * sizeof(unsigned int))
+ return -ENOMEM;
+ get_ctl_amp_tlv(kcontrol, tlv);
+ if (copy_to_user(_tlv, tlv, sizeof(tlv)))
return -EFAULT;
return 0;
}
@@ -1807,13 +1811,10 @@ static int get_kctl_0dB_offset(struct hda_codec *codec,
const int *tlv = NULL;
int val = -1;
- if (kctl->vd[0].access & SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK) {
- /* FIXME: set_fs() hack for obtaining user-space TLV data */
- mm_segment_t fs = get_fs();
- set_fs(get_ds());
- if (!kctl->tlv.c(kctl, 0, sizeof(_tlv), _tlv))
- tlv = _tlv;
- set_fs(fs);
+ if ((kctl->vd[0].access & SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK) &&
+ kctl->tlv.c == snd_hda_mixer_amp_tlv) {
+ get_ctl_amp_tlv(kctl, _tlv);
+ tlv = _tlv;
} else if (kctl->vd[0].access & SNDRV_CTL_ELEM_ACCESS_TLV_READ)
tlv = kctl->tlv.p;
if (tlv && tlv[0] == SNDRV_CTL_TLVT_DB_SCALE) {
@@ -2118,196 +2119,6 @@ int snd_hda_mixer_amp_switch_put(struct snd_kcontrol *kcontrol,
EXPORT_SYMBOL_GPL(snd_hda_mixer_amp_switch_put);
/*
- * bound volume controls
- *
- * bind multiple volumes (# indices, from 0)
- */
-
-#define AMP_VAL_IDX_SHIFT 19
-#define AMP_VAL_IDX_MASK (0x0f<<19)
-
-/**
- * snd_hda_mixer_bind_switch_get - Get callback for a bound volume control
- * @kcontrol: ctl element
- * @ucontrol: pointer to get/store the data
- *
- * The control element is supposed to have the private_value field
- * set up via HDA_BIND_MUTE*() macros.
- */
-int snd_hda_mixer_bind_switch_get(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
- unsigned long pval;
- int err;
-
- mutex_lock(&codec->control_mutex);
- pval = kcontrol->private_value;
- kcontrol->private_value = pval & ~AMP_VAL_IDX_MASK; /* index 0 */
- err = snd_hda_mixer_amp_switch_get(kcontrol, ucontrol);
- kcontrol->private_value = pval;
- mutex_unlock(&codec->control_mutex);
- return err;
-}
-EXPORT_SYMBOL_GPL(snd_hda_mixer_bind_switch_get);
-
-/**
- * snd_hda_mixer_bind_switch_put - Put callback for a bound volume control
- * @kcontrol: ctl element
- * @ucontrol: pointer to get/store the data
- *
- * The control element is supposed to have the private_value field
- * set up via HDA_BIND_MUTE*() macros.
- */
-int snd_hda_mixer_bind_switch_put(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
- unsigned long pval;
- int i, indices, err = 0, change = 0;
-
- mutex_lock(&codec->control_mutex);
- pval = kcontrol->private_value;
- indices = (pval & AMP_VAL_IDX_MASK) >> AMP_VAL_IDX_SHIFT;
- for (i = 0; i < indices; i++) {
- kcontrol->private_value = (pval & ~AMP_VAL_IDX_MASK) |
- (i << AMP_VAL_IDX_SHIFT);
- err = snd_hda_mixer_amp_switch_put(kcontrol, ucontrol);
- if (err < 0)
- break;
- change |= err;
- }
- kcontrol->private_value = pval;
- mutex_unlock(&codec->control_mutex);
- return err < 0 ? err : change;
-}
-EXPORT_SYMBOL_GPL(snd_hda_mixer_bind_switch_put);
-
-/**
- * snd_hda_mixer_bind_ctls_info - Info callback for a generic bound control
- * @kcontrol: referred ctl element
- * @uinfo: pointer to get/store the data
- *
- * The control element is supposed to have the private_value field
- * set up via HDA_BIND_VOL() or HDA_BIND_SW() macros.
- */
-int snd_hda_mixer_bind_ctls_info(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_info *uinfo)
-{
- struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
- struct hda_bind_ctls *c;
- int err;
-
- mutex_lock(&codec->control_mutex);
- c = (struct hda_bind_ctls *)kcontrol->private_value;
- kcontrol->private_value = *c->values;
- err = c->ops->info(kcontrol, uinfo);
- kcontrol->private_value = (long)c;
- mutex_unlock(&codec->control_mutex);
- return err;
-}
-EXPORT_SYMBOL_GPL(snd_hda_mixer_bind_ctls_info);
-
-/**
- * snd_hda_mixer_bind_ctls_get - Get callback for a generic bound control
- * @kcontrol: ctl element
- * @ucontrol: pointer to get/store the data
- *
- * The control element is supposed to have the private_value field
- * set up via HDA_BIND_VOL() or HDA_BIND_SW() macros.
- */
-int snd_hda_mixer_bind_ctls_get(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
- struct hda_bind_ctls *c;
- int err;
-
- mutex_lock(&codec->control_mutex);
- c = (struct hda_bind_ctls *)kcontrol->private_value;
- kcontrol->private_value = *c->values;
- err = c->ops->get(kcontrol, ucontrol);
- kcontrol->private_value = (long)c;
- mutex_unlock(&codec->control_mutex);
- return err;
-}
-EXPORT_SYMBOL_GPL(snd_hda_mixer_bind_ctls_get);
-
-/**
- * snd_hda_mixer_bind_ctls_put - Put callback for a generic bound control
- * @kcontrol: ctl element
- * @ucontrol: pointer to get/store the data
- *
- * The control element is supposed to have the private_value field
- * set up via HDA_BIND_VOL() or HDA_BIND_SW() macros.
- */
-int snd_hda_mixer_bind_ctls_put(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
- struct hda_bind_ctls *c;
- unsigned long *vals;
- int err = 0, change = 0;
-
- mutex_lock(&codec->control_mutex);
- c = (struct hda_bind_ctls *)kcontrol->private_value;
- for (vals = c->values; *vals; vals++) {
- kcontrol->private_value = *vals;
- err = c->ops->put(kcontrol, ucontrol);
- if (err < 0)
- break;
- change |= err;
- }
- kcontrol->private_value = (long)c;
- mutex_unlock(&codec->control_mutex);
- return err < 0 ? err : change;
-}
-EXPORT_SYMBOL_GPL(snd_hda_mixer_bind_ctls_put);
-
-/**
- * snd_hda_mixer_bind_tlv - TLV callback for a generic bound control
- * @kcontrol: ctl element
- * @op_flag: operation flag
- * @size: byte size of input TLV
- * @tlv: TLV data
- *
- * The control element is supposed to have the private_value field
- * set up via HDA_BIND_VOL() macro.
- */
-int snd_hda_mixer_bind_tlv(struct snd_kcontrol *kcontrol, int op_flag,
- unsigned int size, unsigned int __user *tlv)
-{
- struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
- struct hda_bind_ctls *c;
- int err;
-
- mutex_lock(&codec->control_mutex);
- c = (struct hda_bind_ctls *)kcontrol->private_value;
- kcontrol->private_value = *c->values;
- err = c->ops->tlv(kcontrol, op_flag, size, tlv);
- kcontrol->private_value = (long)c;
- mutex_unlock(&codec->control_mutex);
- return err;
-}
-EXPORT_SYMBOL_GPL(snd_hda_mixer_bind_tlv);
-
-struct hda_ctl_ops snd_hda_bind_vol = {
- .info = snd_hda_mixer_amp_volume_info,
- .get = snd_hda_mixer_amp_volume_get,
- .put = snd_hda_mixer_amp_volume_put,
- .tlv = snd_hda_mixer_amp_tlv
-};
-EXPORT_SYMBOL_GPL(snd_hda_bind_vol);
-
-struct hda_ctl_ops snd_hda_bind_sw = {
- .info = snd_hda_mixer_amp_switch_info,
- .get = snd_hda_mixer_amp_switch_get,
- .put = snd_hda_mixer_amp_switch_put,
- .tlv = snd_hda_mixer_amp_tlv
-};
-EXPORT_SYMBOL_GPL(snd_hda_bind_sw);
-
-/*
* SPDIF out controls
*/
diff --git a/sound/pci/hda/hda_generic.c b/sound/pci/hda/hda_generic.c
index 2842c82..557ecfc 100644
--- a/sound/pci/hda/hda_generic.c
+++ b/sound/pci/hda/hda_generic.c
@@ -948,6 +948,8 @@ static void resume_path_from_idx(struct hda_codec *codec, int path_idx)
static int hda_gen_mixer_mute_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol);
+static int hda_gen_bind_mute_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol);
static int hda_gen_bind_mute_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol);
@@ -970,7 +972,7 @@ static const struct snd_kcontrol_new control_templates[] = {
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.info = snd_hda_mixer_amp_switch_info,
- .get = snd_hda_mixer_bind_switch_get,
+ .get = hda_gen_bind_mute_get,
.put = hda_gen_bind_mute_put, /* replaced */
.private_value = HDA_COMPOSE_AMP_VAL(0, 3, 0, 0),
},
@@ -1101,11 +1103,51 @@ static int hda_gen_mixer_mute_put(struct snd_kcontrol *kcontrol,
return snd_hda_mixer_amp_switch_put(kcontrol, ucontrol);
}
+/*
+ * Bound mute controls
+ */
+#define AMP_VAL_IDX_SHIFT 19
+#define AMP_VAL_IDX_MASK (0x0f<<19)
+
+static int hda_gen_bind_mute_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+ unsigned long pval;
+ int err;
+
+ mutex_lock(&codec->control_mutex);
+ pval = kcontrol->private_value;
+ kcontrol->private_value = pval & ~AMP_VAL_IDX_MASK; /* index 0 */
+ err = snd_hda_mixer_amp_switch_get(kcontrol, ucontrol);
+ kcontrol->private_value = pval;
+ mutex_unlock(&codec->control_mutex);
+ return err;
+}
+
static int hda_gen_bind_mute_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
+ struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+ unsigned long pval;
+ int i, indices, err = 0, change = 0;
+
sync_auto_mute_bits(kcontrol, ucontrol);
- return snd_hda_mixer_bind_switch_put(kcontrol, ucontrol);
+
+ mutex_lock(&codec->control_mutex);
+ pval = kcontrol->private_value;
+ indices = (pval & AMP_VAL_IDX_MASK) >> AMP_VAL_IDX_SHIFT;
+ for (i = 0; i < indices; i++) {
+ kcontrol->private_value = (pval & ~AMP_VAL_IDX_MASK) |
+ (i << AMP_VAL_IDX_SHIFT);
+ err = snd_hda_mixer_amp_switch_put(kcontrol, ucontrol);
+ if (err < 0)
+ break;
+ change |= err;
+ }
+ kcontrol->private_value = pval;
+ mutex_unlock(&codec->control_mutex);
+ return err < 0 ? err : change;
}
/* any ctl assigned to the path with the given index? */
diff --git a/sound/pci/hda/hda_local.h b/sound/pci/hda/hda_local.h
index d0e066e..5b5c324 100644
--- a/sound/pci/hda/hda_local.h
+++ b/sound/pci/hda/hda_local.h
@@ -178,67 +178,6 @@ void snd_hda_sync_vmaster_hook(struct hda_vmaster_mute_hook *hook);
#define HDA_AMP_UNMUTE 0x00
#define HDA_AMP_VOLMASK 0x7f
-/* mono switch binding multiple inputs */
-#define HDA_BIND_MUTE_MONO(xname, nid, channel, indices, direction) \
- { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = 0, \
- .info = snd_hda_mixer_amp_switch_info, \
- .get = snd_hda_mixer_bind_switch_get, \
- .put = snd_hda_mixer_bind_switch_put, \
- .private_value = HDA_COMPOSE_AMP_VAL(nid, channel, indices, direction) }
-
-/* stereo switch binding multiple inputs */
-#define HDA_BIND_MUTE(xname,nid,indices,dir) \
- HDA_BIND_MUTE_MONO(xname,nid,3,indices,dir)
-
-int snd_hda_mixer_bind_switch_get(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol);
-int snd_hda_mixer_bind_switch_put(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol);
-
-/* more generic bound controls */
-struct hda_ctl_ops {
- snd_kcontrol_info_t *info;
- snd_kcontrol_get_t *get;
- snd_kcontrol_put_t *put;
- snd_kcontrol_tlv_rw_t *tlv;
-};
-
-extern struct hda_ctl_ops snd_hda_bind_vol; /* for bind-volume with TLV */
-extern struct hda_ctl_ops snd_hda_bind_sw; /* for bind-switch */
-
-struct hda_bind_ctls {
- struct hda_ctl_ops *ops;
- unsigned long values[];
-};
-
-int snd_hda_mixer_bind_ctls_info(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_info *uinfo);
-int snd_hda_mixer_bind_ctls_get(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol);
-int snd_hda_mixer_bind_ctls_put(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol);
-int snd_hda_mixer_bind_tlv(struct snd_kcontrol *kcontrol, int op_flag,
- unsigned int size, unsigned int __user *tlv);
-
-#define HDA_BIND_VOL(xname, bindrec) \
- { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
- .name = xname, \
- .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |\
- SNDRV_CTL_ELEM_ACCESS_TLV_READ |\
- SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK,\
- .info = snd_hda_mixer_bind_ctls_info,\
- .get = snd_hda_mixer_bind_ctls_get,\
- .put = snd_hda_mixer_bind_ctls_put,\
- .tlv = { .c = snd_hda_mixer_bind_tlv },\
- .private_value = (long) (bindrec) }
-#define HDA_BIND_SW(xname, bindrec) \
- { .iface = SNDRV_CTL_ELEM_IFACE_MIXER,\
- .name = xname, \
- .info = snd_hda_mixer_bind_ctls_info,\
- .get = snd_hda_mixer_bind_ctls_get,\
- .put = snd_hda_mixer_bind_ctls_put,\
- .private_value = (long) (bindrec) }
-
/*
* SPDIF I/O
*/
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index cbeebc0..5ef2413 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -2575,18 +2575,37 @@ static int patch_alc262(struct hda_codec *codec)
* ALC268
*/
/* bind Beep switches of both NID 0x0f and 0x10 */
-static const struct hda_bind_ctls alc268_bind_beep_sw = {
- .ops = &snd_hda_bind_sw,
- .values = {
- HDA_COMPOSE_AMP_VAL(0x0f, 3, 1, HDA_INPUT),
- HDA_COMPOSE_AMP_VAL(0x10, 3, 1, HDA_INPUT),
- 0
- },
-};
+static int alc268_beep_switch_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+ unsigned long pval;
+ int err;
+
+ mutex_lock(&codec->control_mutex);
+ pval = kcontrol->private_value;
+ kcontrol->private_value = (pval & ~0xff) | 0x0f;
+ err = snd_hda_mixer_amp_switch_put(kcontrol, ucontrol);
+ if (err >= 0) {
+ kcontrol->private_value = (pval & ~0xff) | 0x10;
+ err = snd_hda_mixer_amp_switch_put(kcontrol, ucontrol);
+ }
+ kcontrol->private_value = pval;
+ mutex_unlock(&codec->control_mutex);
+ return err;
+}
static const struct snd_kcontrol_new alc268_beep_mixer[] = {
HDA_CODEC_VOLUME("Beep Playback Volume", 0x1d, 0x0, HDA_INPUT),
- HDA_BIND_SW("Beep Playback Switch", &alc268_bind_beep_sw),
+ {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "Beep Playback Switch",
+ .subdevice = HDA_SUBDEV_AMP_FLAG,
+ .info = snd_hda_mixer_amp_switch_info,
+ .get = snd_hda_mixer_amp_switch_get,
+ .put = alc268_beep_switch_put,
+ .private_value = HDA_COMPOSE_AMP_VAL(0x0f, 3, 1, HDA_INPUT)
+ },
{ }
};
diff --git a/sound/pci/ice1712/ice1712.c b/sound/pci/ice1712/ice1712.c
index 1d8612c..6b650ab 100644
--- a/sound/pci/ice1712/ice1712.c
+++ b/sound/pci/ice1712/ice1712.c
@@ -1401,7 +1401,7 @@ static struct snd_kcontrol_new snd_ice1712_multi_playback_ctrls[] = {
},
};
-static struct snd_kcontrol_new snd_ice1712_multi_capture_analog_switch = {
+static const struct snd_kcontrol_new snd_ice1712_multi_capture_analog_switch = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "H/W Multi Capture Switch",
.info = snd_ice1712_pro_mixer_switch_info,
@@ -1420,7 +1420,7 @@ static const struct snd_kcontrol_new snd_ice1712_multi_capture_spdif_switch = {
.count = 2,
};
-static struct snd_kcontrol_new snd_ice1712_multi_capture_analog_volume = {
+static const struct snd_kcontrol_new snd_ice1712_multi_capture_analog_volume = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
SNDRV_CTL_ELEM_ACCESS_TLV_READ),
@@ -2165,7 +2165,7 @@ static int snd_ice1712_pro_route_spdif_put(struct snd_kcontrol *kcontrol,
return change;
}
-static struct snd_kcontrol_new snd_ice1712_mixer_pro_analog_route = {
+static const struct snd_kcontrol_new snd_ice1712_mixer_pro_analog_route = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "H/W Playback Route",
.info = snd_ice1712_pro_route_info,
diff --git a/sound/pci/ice1712/ice1724.c b/sound/pci/ice1712/ice1724.c
index 9cd6e55..7851881 100644
--- a/sound/pci/ice1712/ice1724.c
+++ b/sound/pci/ice1712/ice1724.c
@@ -2142,7 +2142,7 @@ static int snd_vt1724_pro_route_spdif_put(struct snd_kcontrol *kcontrol,
digital_route_shift(idx));
}
-static struct snd_kcontrol_new snd_vt1724_mixer_pro_analog_route =
+static const struct snd_kcontrol_new snd_vt1724_mixer_pro_analog_route =
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "H/W Playback Route",
diff --git a/sound/pci/korg1212/korg1212.c b/sound/pci/korg1212/korg1212.c
index 1e25095..b28fe49 100644
--- a/sound/pci/korg1212/korg1212.c
+++ b/sound/pci/korg1212/korg1212.c
@@ -1299,13 +1299,21 @@ static int snd_korg1212_silence(struct snd_korg1212 *korg1212, int pos, int coun
return 0;
}
-static int snd_korg1212_copy_to(struct snd_korg1212 *korg1212, void __user *dst, int pos, int count, int offset, int size)
+static int snd_korg1212_copy_to(struct snd_pcm_substream *substream,
+ void __user *dst, int pos, int count,
+ bool in_kernel)
{
- struct KorgAudioFrame * src = korg1212->recordDataBufsPtr[0].bufferData + pos;
- int i, rc;
-
- K1212_DEBUG_PRINTK_VERBOSE("K1212_DEBUG: snd_korg1212_copy_to pos=%d offset=%d size=%d\n",
- pos, offset, size);
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct snd_korg1212 *korg1212 = snd_pcm_substream_chip(substream);
+ struct KorgAudioFrame *src;
+ int i, size;
+
+ pos = bytes_to_frames(runtime, pos);
+ count = bytes_to_frames(runtime, count);
+ size = korg1212->channels * 2;
+ src = korg1212->recordDataBufsPtr[0].bufferData + pos;
+ K1212_DEBUG_PRINTK_VERBOSE("K1212_DEBUG: snd_korg1212_copy_to pos=%d size=%d count=%d\n",
+ pos, size, count);
if (snd_BUG_ON(pos + count > K1212_MAX_SAMPLES))
return -EINVAL;
@@ -1317,11 +1325,10 @@ static int snd_korg1212_copy_to(struct snd_korg1212 *korg1212, void __user *dst,
return -EFAULT;
}
#endif
- rc = copy_to_user(dst + offset, src, size);
- if (rc) {
- K1212_DEBUG_PRINTK("K1212_DEBUG: snd_korg1212_copy_to USER EFAULT src=%p dst=%p iter=%d\n", src, dst, i);
+ if (in_kernel)
+ memcpy((void *)dst, src, size);
+ else if (copy_to_user(dst, src, size))
return -EFAULT;
- }
src++;
dst += size;
}
@@ -1329,13 +1336,22 @@ static int snd_korg1212_copy_to(struct snd_korg1212 *korg1212, void __user *dst,
return 0;
}
-static int snd_korg1212_copy_from(struct snd_korg1212 *korg1212, void __user *src, int pos, int count, int offset, int size)
+static int snd_korg1212_copy_from(struct snd_pcm_substream *substream,
+ void __user *src, int pos, int count,
+ bool in_kernel)
{
- struct KorgAudioFrame * dst = korg1212->playDataBufsPtr[0].bufferData + pos;
- int i, rc;
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct snd_korg1212 *korg1212 = snd_pcm_substream_chip(substream);
+ struct KorgAudioFrame *dst;
+ int i, size;
- K1212_DEBUG_PRINTK_VERBOSE("K1212_DEBUG: snd_korg1212_copy_from pos=%d offset=%d size=%d count=%d\n",
- pos, offset, size, count);
+ pos = bytes_to_frames(runtime, pos);
+ count = bytes_to_frames(runtime, count);
+ size = korg1212->channels * 2;
+ dst = korg1212->playDataBufsPtr[0].bufferData + pos;
+
+ K1212_DEBUG_PRINTK_VERBOSE("K1212_DEBUG: snd_korg1212_copy_from pos=%d size=%d count=%d\n",
+ pos, size, count);
if (snd_BUG_ON(pos + count > K1212_MAX_SAMPLES))
return -EINVAL;
@@ -1348,11 +1364,10 @@ static int snd_korg1212_copy_from(struct snd_korg1212 *korg1212, void __user *sr
return -EFAULT;
}
#endif
- rc = copy_from_user((void*) dst + offset, src, size);
- if (rc) {
- K1212_DEBUG_PRINTK("K1212_DEBUG: snd_korg1212_copy_from USER EFAULT src=%p dst=%p iter=%d\n", src, dst, i);
+ if (in_kernel)
+ memcpy((void *)dst, src, size);
+ else if (copy_from_user(dst, src, size))
return -EFAULT;
- }
dst++;
src += size;
}
@@ -1640,45 +1655,46 @@ static snd_pcm_uframes_t snd_korg1212_capture_pointer(struct snd_pcm_substream *
}
static int snd_korg1212_playback_copy(struct snd_pcm_substream *substream,
- int channel, /* not used (interleaved data) */
- snd_pcm_uframes_t pos,
- void __user *src,
- snd_pcm_uframes_t count)
+ int channel, unsigned long pos,
+ void __user *src, unsigned long count)
{
- struct snd_korg1212 *korg1212 = snd_pcm_substream_chip(substream);
-
- K1212_DEBUG_PRINTK_VERBOSE("K1212_DEBUG: snd_korg1212_playback_copy [%s] %ld %ld\n",
- stateName[korg1212->cardState], pos, count);
-
- return snd_korg1212_copy_from(korg1212, src, pos, count, 0, korg1212->channels * 2);
+ return snd_korg1212_copy_from(substream, src, pos, count, false);
+}
+static int snd_korg1212_playback_copy_kernel(struct snd_pcm_substream *substream,
+ int channel, unsigned long pos,
+ void *src, unsigned long count)
+{
+ return snd_korg1212_copy_from(substream, (void __user *)src,
+ pos, count, true);
}
static int snd_korg1212_playback_silence(struct snd_pcm_substream *substream,
int channel, /* not used (interleaved data) */
- snd_pcm_uframes_t pos,
- snd_pcm_uframes_t count)
+ unsigned long pos,
+ unsigned long count)
{
+ struct snd_pcm_runtime *runtime = substream->runtime;
struct snd_korg1212 *korg1212 = snd_pcm_substream_chip(substream);
- K1212_DEBUG_PRINTK_VERBOSE("K1212_DEBUG: snd_korg1212_playback_silence [%s]\n",
- stateName[korg1212->cardState]);
-
- return snd_korg1212_silence(korg1212, pos, count, 0, korg1212->channels * 2);
+ return snd_korg1212_silence(korg1212, bytes_to_frames(runtime, pos),
+ bytes_to_frames(runtime, count),
+ 0, korg1212->channels * 2);
}
static int snd_korg1212_capture_copy(struct snd_pcm_substream *substream,
- int channel, /* not used (interleaved data) */
- snd_pcm_uframes_t pos,
- void __user *dst,
- snd_pcm_uframes_t count)
+ int channel, unsigned long pos,
+ void __user *dst, unsigned long count)
{
- struct snd_korg1212 *korg1212 = snd_pcm_substream_chip(substream);
-
- K1212_DEBUG_PRINTK_VERBOSE("K1212_DEBUG: snd_korg1212_capture_copy [%s] %ld %ld\n",
- stateName[korg1212->cardState], pos, count);
+ return snd_korg1212_copy_to(substream, dst, pos, count, false);
+}
- return snd_korg1212_copy_to(korg1212, dst, pos, count, 0, korg1212->channels * 2);
+static int snd_korg1212_capture_copy_kernel(struct snd_pcm_substream *substream,
+ int channel, unsigned long pos,
+ void *dst, unsigned long count)
+{
+ return snd_korg1212_copy_to(substream, (void __user *)dst,
+ pos, count, true);
}
static const struct snd_pcm_ops snd_korg1212_playback_ops = {
@@ -1689,8 +1705,9 @@ static const struct snd_pcm_ops snd_korg1212_playback_ops = {
.prepare = snd_korg1212_prepare,
.trigger = snd_korg1212_trigger,
.pointer = snd_korg1212_playback_pointer,
- .copy = snd_korg1212_playback_copy,
- .silence = snd_korg1212_playback_silence,
+ .copy_user = snd_korg1212_playback_copy,
+ .copy_kernel = snd_korg1212_playback_copy_kernel,
+ .fill_silence = snd_korg1212_playback_silence,
};
static const struct snd_pcm_ops snd_korg1212_capture_ops = {
@@ -1701,7 +1718,8 @@ static const struct snd_pcm_ops snd_korg1212_capture_ops = {
.prepare = snd_korg1212_prepare,
.trigger = snd_korg1212_trigger,
.pointer = snd_korg1212_capture_pointer,
- .copy = snd_korg1212_capture_copy,
+ .copy_user = snd_korg1212_capture_copy,
+ .copy_kernel = snd_korg1212_capture_copy_kernel,
};
/*
diff --git a/sound/pci/mixart/mixart_mixer.c b/sound/pci/mixart/mixart_mixer.c
index 4a4616a..2b9496a 100644
--- a/sound/pci/mixart/mixart_mixer.c
+++ b/sound/pci/mixart/mixart_mixer.c
@@ -404,7 +404,7 @@ static int mixart_analog_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_e
static const DECLARE_TLV_DB_SCALE(db_scale_analog, -9600, 50, 0);
-static struct snd_kcontrol_new mixart_control_analog_level = {
+static const struct snd_kcontrol_new mixart_control_analog_level = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
SNDRV_CTL_ELEM_ACCESS_TLV_READ),
@@ -897,7 +897,7 @@ static int mixart_pcm_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem
static const DECLARE_TLV_DB_SCALE(db_scale_digital, -10950, 50, 0);
-static struct snd_kcontrol_new snd_mixart_pcm_vol =
+static const struct snd_kcontrol_new snd_mixart_pcm_vol =
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
@@ -951,7 +951,7 @@ static int mixart_pcm_sw_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_
return changed;
}
-static struct snd_kcontrol_new mixart_control_pcm_switch = {
+static const struct snd_kcontrol_new mixart_control_pcm_switch = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
/* name will be filled later */
.count = MIXART_PLAYBACK_STREAMS,
diff --git a/sound/pci/nm256/nm256.c b/sound/pci/nm256/nm256.c
index 103fe31..63f0985d 100644
--- a/sound/pci/nm256/nm256.c
+++ b/sound/pci/nm256/nm256.c
@@ -695,53 +695,68 @@ snd_nm256_capture_pointer(struct snd_pcm_substream *substream)
*/
static int
snd_nm256_playback_silence(struct snd_pcm_substream *substream,
- int channel, /* not used (interleaved data) */
- snd_pcm_uframes_t pos,
- snd_pcm_uframes_t count)
+ int channel, unsigned long pos, unsigned long count)
{
struct snd_pcm_runtime *runtime = substream->runtime;
struct nm256_stream *s = runtime->private_data;
- count = frames_to_bytes(runtime, count);
- pos = frames_to_bytes(runtime, pos);
+
memset_io(s->bufptr + pos, 0, count);
return 0;
}
static int
snd_nm256_playback_copy(struct snd_pcm_substream *substream,
- int channel, /* not used (interleaved data) */
- snd_pcm_uframes_t pos,
- void __user *src,
- snd_pcm_uframes_t count)
+ int channel, unsigned long pos,
+ void __user *src, unsigned long count)
{
struct snd_pcm_runtime *runtime = substream->runtime;
struct nm256_stream *s = runtime->private_data;
- count = frames_to_bytes(runtime, count);
- pos = frames_to_bytes(runtime, pos);
+
if (copy_from_user_toio(s->bufptr + pos, src, count))
return -EFAULT;
return 0;
}
+static int
+snd_nm256_playback_copy_kernel(struct snd_pcm_substream *substream,
+ int channel, unsigned long pos,
+ void *src, unsigned long count)
+{
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct nm256_stream *s = runtime->private_data;
+
+ memcpy_toio(s->bufptr + pos, src, count);
+ return 0;
+}
+
/*
* copy to user
*/
static int
snd_nm256_capture_copy(struct snd_pcm_substream *substream,
- int channel, /* not used (interleaved data) */
- snd_pcm_uframes_t pos,
- void __user *dst,
- snd_pcm_uframes_t count)
+ int channel, unsigned long pos,
+ void __user *dst, unsigned long count)
{
struct snd_pcm_runtime *runtime = substream->runtime;
struct nm256_stream *s = runtime->private_data;
- count = frames_to_bytes(runtime, count);
- pos = frames_to_bytes(runtime, pos);
+
if (copy_to_user_fromio(dst, s->bufptr + pos, count))
return -EFAULT;
return 0;
}
+static int
+snd_nm256_capture_copy_kernel(struct snd_pcm_substream *substream,
+ int channel, unsigned long pos,
+ void *dst, unsigned long count)
+{
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct nm256_stream *s = runtime->private_data;
+
+ memcpy_fromio(dst, s->bufptr + pos, count);
+ return 0;
+}
+
#endif /* !__i386__ */
@@ -911,8 +926,9 @@ static const struct snd_pcm_ops snd_nm256_playback_ops = {
.trigger = snd_nm256_playback_trigger,
.pointer = snd_nm256_playback_pointer,
#ifndef __i386__
- .copy = snd_nm256_playback_copy,
- .silence = snd_nm256_playback_silence,
+ .copy_user = snd_nm256_playback_copy,
+ .copy_kernel = snd_nm256_playback_copy_kernel,
+ .fill_silence = snd_nm256_playback_silence,
#endif
.mmap = snd_pcm_lib_mmap_iomem,
};
@@ -926,7 +942,8 @@ static const struct snd_pcm_ops snd_nm256_capture_ops = {
.trigger = snd_nm256_capture_trigger,
.pointer = snd_nm256_capture_pointer,
#ifndef __i386__
- .copy = snd_nm256_capture_copy,
+ .copy_user = snd_nm256_capture_copy,
+ .copy_kernel = snd_nm256_capture_copy_kernel,
#endif
.mmap = snd_pcm_lib_mmap_iomem,
};
diff --git a/sound/pci/rme32.c b/sound/pci/rme32.c
index 96d15db..67d48c8 100644
--- a/sound/pci/rme32.c
+++ b/sound/pci/rme32.c
@@ -254,39 +254,46 @@ static inline unsigned int snd_rme32_pcm_byteptr(struct rme32 * rme32)
}
/* silence callback for halfduplex mode */
-static int snd_rme32_playback_silence(struct snd_pcm_substream *substream, int channel, /* not used (interleaved data) */
- snd_pcm_uframes_t pos,
- snd_pcm_uframes_t count)
+static int snd_rme32_playback_silence(struct snd_pcm_substream *substream,
+ int channel, unsigned long pos,
+ unsigned long count)
{
struct rme32 *rme32 = snd_pcm_substream_chip(substream);
- count <<= rme32->playback_frlog;
- pos <<= rme32->playback_frlog;
+
memset_io(rme32->iobase + RME32_IO_DATA_BUFFER + pos, 0, count);
return 0;
}
/* copy callback for halfduplex mode */
-static int snd_rme32_playback_copy(struct snd_pcm_substream *substream, int channel, /* not used (interleaved data) */
- snd_pcm_uframes_t pos,
- void __user *src, snd_pcm_uframes_t count)
+static int snd_rme32_playback_copy(struct snd_pcm_substream *substream,
+ int channel, unsigned long pos,
+ void __user *src, unsigned long count)
{
struct rme32 *rme32 = snd_pcm_substream_chip(substream);
- count <<= rme32->playback_frlog;
- pos <<= rme32->playback_frlog;
+
if (copy_from_user_toio(rme32->iobase + RME32_IO_DATA_BUFFER + pos,
- src, count))
+ src, count))
return -EFAULT;
return 0;
}
+static int snd_rme32_playback_copy_kernel(struct snd_pcm_substream *substream,
+ int channel, unsigned long pos,
+ void *src, unsigned long count)
+{
+ struct rme32 *rme32 = snd_pcm_substream_chip(substream);
+
+ memcpy_toio(rme32->iobase + RME32_IO_DATA_BUFFER + pos, src, count);
+ return 0;
+}
+
/* copy callback for halfduplex mode */
-static int snd_rme32_capture_copy(struct snd_pcm_substream *substream, int channel, /* not used (interleaved data) */
- snd_pcm_uframes_t pos,
- void __user *dst, snd_pcm_uframes_t count)
+static int snd_rme32_capture_copy(struct snd_pcm_substream *substream,
+ int channel, unsigned long pos,
+ void __user *dst, unsigned long count)
{
struct rme32 *rme32 = snd_pcm_substream_chip(substream);
- count <<= rme32->capture_frlog;
- pos <<= rme32->capture_frlog;
+
if (copy_to_user_fromio(dst,
rme32->iobase + RME32_IO_DATA_BUFFER + pos,
count))
@@ -294,6 +301,16 @@ static int snd_rme32_capture_copy(struct snd_pcm_substream *substream, int chann
return 0;
}
+static int snd_rme32_capture_copy_kernel(struct snd_pcm_substream *substream,
+ int channel, unsigned long pos,
+ void *dst, unsigned long count)
+{
+ struct rme32 *rme32 = snd_pcm_substream_chip(substream);
+
+ memcpy_fromio(dst, rme32->iobase + RME32_IO_DATA_BUFFER + pos, count);
+ return 0;
+}
+
/*
* SPDIF I/O capabilities (half-duplex mode)
*/
@@ -1157,9 +1174,8 @@ static int snd_rme32_playback_fd_ack(struct snd_pcm_substream *substream)
if (rme32->running & (1 << SNDRV_PCM_STREAM_CAPTURE))
rec->hw_queue_size -= cprec->hw_ready;
spin_unlock(&rme32->lock);
- snd_pcm_indirect_playback_transfer(substream, rec,
- snd_rme32_pb_trans_copy);
- return 0;
+ return snd_pcm_indirect_playback_transfer(substream, rec,
+ snd_rme32_pb_trans_copy);
}
static void snd_rme32_cp_trans_copy(struct snd_pcm_substream *substream,
@@ -1174,9 +1190,8 @@ static void snd_rme32_cp_trans_copy(struct snd_pcm_substream *substream,
static int snd_rme32_capture_fd_ack(struct snd_pcm_substream *substream)
{
struct rme32 *rme32 = snd_pcm_substream_chip(substream);
- snd_pcm_indirect_capture_transfer(substream, &rme32->capture_pcm,
- snd_rme32_cp_trans_copy);
- return 0;
+ return snd_pcm_indirect_capture_transfer(substream, &rme32->capture_pcm,
+ snd_rme32_cp_trans_copy);
}
static snd_pcm_uframes_t
@@ -1205,8 +1220,9 @@ static const struct snd_pcm_ops snd_rme32_playback_spdif_ops = {
.prepare = snd_rme32_playback_prepare,
.trigger = snd_rme32_pcm_trigger,
.pointer = snd_rme32_playback_pointer,
- .copy = snd_rme32_playback_copy,
- .silence = snd_rme32_playback_silence,
+ .copy_user = snd_rme32_playback_copy,
+ .copy_kernel = snd_rme32_playback_copy_kernel,
+ .fill_silence = snd_rme32_playback_silence,
.mmap = snd_pcm_lib_mmap_iomem,
};
@@ -1219,7 +1235,8 @@ static const struct snd_pcm_ops snd_rme32_capture_spdif_ops = {
.prepare = snd_rme32_capture_prepare,
.trigger = snd_rme32_pcm_trigger,
.pointer = snd_rme32_capture_pointer,
- .copy = snd_rme32_capture_copy,
+ .copy_user = snd_rme32_capture_copy,
+ .copy_kernel = snd_rme32_capture_copy_kernel,
.mmap = snd_pcm_lib_mmap_iomem,
};
@@ -1231,8 +1248,9 @@ static const struct snd_pcm_ops snd_rme32_playback_adat_ops = {
.prepare = snd_rme32_playback_prepare,
.trigger = snd_rme32_pcm_trigger,
.pointer = snd_rme32_playback_pointer,
- .copy = snd_rme32_playback_copy,
- .silence = snd_rme32_playback_silence,
+ .copy_user = snd_rme32_playback_copy,
+ .copy_kernel = snd_rme32_playback_copy_kernel,
+ .fill_silence = snd_rme32_playback_silence,
.mmap = snd_pcm_lib_mmap_iomem,
};
@@ -1244,7 +1262,8 @@ static const struct snd_pcm_ops snd_rme32_capture_adat_ops = {
.prepare = snd_rme32_capture_prepare,
.trigger = snd_rme32_pcm_trigger,
.pointer = snd_rme32_capture_pointer,
- .copy = snd_rme32_capture_copy,
+ .copy_user = snd_rme32_capture_copy,
+ .copy_kernel = snd_rme32_capture_copy_kernel,
.mmap = snd_pcm_lib_mmap_iomem,
};
diff --git a/sound/pci/rme96.c b/sound/pci/rme96.c
index 05b9da3..24f1349 100644
--- a/sound/pci/rme96.c
+++ b/sound/pci/rme96.c
@@ -327,13 +327,10 @@ snd_rme96_capture_ptr(struct rme96 *rme96)
static int
snd_rme96_playback_silence(struct snd_pcm_substream *substream,
- int channel, /* not used (interleaved data) */
- snd_pcm_uframes_t pos,
- snd_pcm_uframes_t count)
+ int channel, unsigned long pos, unsigned long count)
{
struct rme96 *rme96 = snd_pcm_substream_chip(substream);
- count <<= rme96->playback_frlog;
- pos <<= rme96->playback_frlog;
+
memset_io(rme96->iobase + RME96_IO_PLAY_BUFFER + pos,
0, count);
return 0;
@@ -341,32 +338,49 @@ snd_rme96_playback_silence(struct snd_pcm_substream *substream,
static int
snd_rme96_playback_copy(struct snd_pcm_substream *substream,
- int channel, /* not used (interleaved data) */
- snd_pcm_uframes_t pos,
- void __user *src,
- snd_pcm_uframes_t count)
+ int channel, unsigned long pos,
+ void __user *src, unsigned long count)
{
struct rme96 *rme96 = snd_pcm_substream_chip(substream);
- count <<= rme96->playback_frlog;
- pos <<= rme96->playback_frlog;
- return copy_from_user_toio(rme96->iobase + RME96_IO_PLAY_BUFFER + pos, src,
- count);
+
+ return copy_from_user_toio(rme96->iobase + RME96_IO_PLAY_BUFFER + pos,
+ src, count);
+}
+
+static int
+snd_rme96_playback_copy_kernel(struct snd_pcm_substream *substream,
+ int channel, unsigned long pos,
+ void *src, unsigned long count)
+{
+ struct rme96 *rme96 = snd_pcm_substream_chip(substream);
+
+ memcpy_toio(rme96->iobase + RME96_IO_PLAY_BUFFER + pos, src, count);
+ return 0;
}
static int
snd_rme96_capture_copy(struct snd_pcm_substream *substream,
- int channel, /* not used (interleaved data) */
- snd_pcm_uframes_t pos,
- void __user *dst,
- snd_pcm_uframes_t count)
+ int channel, unsigned long pos,
+ void __user *dst, unsigned long count)
{
struct rme96 *rme96 = snd_pcm_substream_chip(substream);
- count <<= rme96->capture_frlog;
- pos <<= rme96->capture_frlog;
- return copy_to_user_fromio(dst, rme96->iobase + RME96_IO_REC_BUFFER + pos,
+
+ return copy_to_user_fromio(dst,
+ rme96->iobase + RME96_IO_REC_BUFFER + pos,
count);
}
+static int
+snd_rme96_capture_copy_kernel(struct snd_pcm_substream *substream,
+ int channel, unsigned long pos,
+ void *dst, unsigned long count)
+{
+ struct rme96 *rme96 = snd_pcm_substream_chip(substream);
+
+ memcpy_fromio(dst, rme96->iobase + RME96_IO_REC_BUFFER + pos, count);
+ return 0;
+}
+
/*
* Digital output capabilities (S/PDIF)
*/
@@ -1513,8 +1527,9 @@ static const struct snd_pcm_ops snd_rme96_playback_spdif_ops = {
.prepare = snd_rme96_playback_prepare,
.trigger = snd_rme96_playback_trigger,
.pointer = snd_rme96_playback_pointer,
- .copy = snd_rme96_playback_copy,
- .silence = snd_rme96_playback_silence,
+ .copy_user = snd_rme96_playback_copy,
+ .copy_kernel = snd_rme96_playback_copy_kernel,
+ .fill_silence = snd_rme96_playback_silence,
.mmap = snd_pcm_lib_mmap_iomem,
};
@@ -1526,7 +1541,8 @@ static const struct snd_pcm_ops snd_rme96_capture_spdif_ops = {
.prepare = snd_rme96_capture_prepare,
.trigger = snd_rme96_capture_trigger,
.pointer = snd_rme96_capture_pointer,
- .copy = snd_rme96_capture_copy,
+ .copy_user = snd_rme96_capture_copy,
+ .copy_kernel = snd_rme96_capture_copy_kernel,
.mmap = snd_pcm_lib_mmap_iomem,
};
@@ -1538,8 +1554,9 @@ static const struct snd_pcm_ops snd_rme96_playback_adat_ops = {
.prepare = snd_rme96_playback_prepare,
.trigger = snd_rme96_playback_trigger,
.pointer = snd_rme96_playback_pointer,
- .copy = snd_rme96_playback_copy,
- .silence = snd_rme96_playback_silence,
+ .copy_user = snd_rme96_playback_copy,
+ .copy_kernel = snd_rme96_playback_copy_kernel,
+ .fill_silence = snd_rme96_playback_silence,
.mmap = snd_pcm_lib_mmap_iomem,
};
@@ -1551,7 +1568,8 @@ static const struct snd_pcm_ops snd_rme96_capture_adat_ops = {
.prepare = snd_rme96_capture_prepare,
.trigger = snd_rme96_capture_trigger,
.pointer = snd_rme96_capture_pointer,
- .copy = snd_rme96_capture_copy,
+ .copy_user = snd_rme96_capture_copy,
+ .copy_kernel = snd_rme96_capture_copy_kernel,
.mmap = snd_pcm_lib_mmap_iomem,
};
diff --git a/sound/pci/rme9652/hdsp.c b/sound/pci/rme9652/hdsp.c
index fc0face..b000096 100644
--- a/sound/pci/rme9652/hdsp.c
+++ b/sound/pci/rme9652/hdsp.c
@@ -3913,42 +3913,73 @@ static char *hdsp_channel_buffer_location(struct hdsp *hdsp,
return hdsp->playback_buffer + (mapped_channel * HDSP_CHANNEL_BUFFER_BYTES);
}
-static int snd_hdsp_playback_copy(struct snd_pcm_substream *substream, int channel,
- snd_pcm_uframes_t pos, void __user *src, snd_pcm_uframes_t count)
+static int snd_hdsp_playback_copy(struct snd_pcm_substream *substream,
+ int channel, unsigned long pos,
+ void __user *src, unsigned long count)
{
struct hdsp *hdsp = snd_pcm_substream_chip(substream);
char *channel_buf;
- if (snd_BUG_ON(pos + count > HDSP_CHANNEL_BUFFER_BYTES / 4))
+ if (snd_BUG_ON(pos + count > HDSP_CHANNEL_BUFFER_BYTES))
return -EINVAL;
channel_buf = hdsp_channel_buffer_location (hdsp, substream->pstr->stream, channel);
if (snd_BUG_ON(!channel_buf))
return -EIO;
- if (copy_from_user(channel_buf + pos * 4, src, count * 4))
+ if (copy_from_user(channel_buf + pos, src, count))
return -EFAULT;
- return count;
+ return 0;
}
-static int snd_hdsp_capture_copy(struct snd_pcm_substream *substream, int channel,
- snd_pcm_uframes_t pos, void __user *dst, snd_pcm_uframes_t count)
+static int snd_hdsp_playback_copy_kernel(struct snd_pcm_substream *substream,
+ int channel, unsigned long pos,
+ void *src, unsigned long count)
{
struct hdsp *hdsp = snd_pcm_substream_chip(substream);
char *channel_buf;
- if (snd_BUG_ON(pos + count > HDSP_CHANNEL_BUFFER_BYTES / 4))
+ channel_buf = hdsp_channel_buffer_location(hdsp, substream->pstr->stream, channel);
+ if (snd_BUG_ON(!channel_buf))
+ return -EIO;
+ memcpy(channel_buf + pos, src, count);
+ return 0;
+}
+
+static int snd_hdsp_capture_copy(struct snd_pcm_substream *substream,
+ int channel, unsigned long pos,
+ void __user *dst, unsigned long count)
+{
+ struct hdsp *hdsp = snd_pcm_substream_chip(substream);
+ char *channel_buf;
+
+ if (snd_BUG_ON(pos + count > HDSP_CHANNEL_BUFFER_BYTES))
return -EINVAL;
channel_buf = hdsp_channel_buffer_location (hdsp, substream->pstr->stream, channel);
if (snd_BUG_ON(!channel_buf))
return -EIO;
- if (copy_to_user(dst, channel_buf + pos * 4, count * 4))
+ if (copy_to_user(dst, channel_buf + pos, count))
return -EFAULT;
- return count;
+ return 0;
}
-static int snd_hdsp_hw_silence(struct snd_pcm_substream *substream, int channel,
- snd_pcm_uframes_t pos, snd_pcm_uframes_t count)
+static int snd_hdsp_capture_copy_kernel(struct snd_pcm_substream *substream,
+ int channel, unsigned long pos,
+ void *dst, unsigned long count)
+{
+ struct hdsp *hdsp = snd_pcm_substream_chip(substream);
+ char *channel_buf;
+
+ channel_buf = hdsp_channel_buffer_location(hdsp, substream->pstr->stream, channel);
+ if (snd_BUG_ON(!channel_buf))
+ return -EIO;
+ memcpy(dst, channel_buf + pos, count);
+ return 0;
+}
+
+static int snd_hdsp_hw_silence(struct snd_pcm_substream *substream,
+ int channel, unsigned long pos,
+ unsigned long count)
{
struct hdsp *hdsp = snd_pcm_substream_chip(substream);
char *channel_buf;
@@ -3956,8 +3987,8 @@ static int snd_hdsp_hw_silence(struct snd_pcm_substream *substream, int channel,
channel_buf = hdsp_channel_buffer_location (hdsp, substream->pstr->stream, channel);
if (snd_BUG_ON(!channel_buf))
return -EIO;
- memset(channel_buf + pos * 4, 0, count * 4);
- return count;
+ memset(channel_buf + pos, 0, count);
+ return 0;
}
static int snd_hdsp_reset(struct snd_pcm_substream *substream)
@@ -4869,8 +4900,9 @@ static const struct snd_pcm_ops snd_hdsp_playback_ops = {
.prepare = snd_hdsp_prepare,
.trigger = snd_hdsp_trigger,
.pointer = snd_hdsp_hw_pointer,
- .copy = snd_hdsp_playback_copy,
- .silence = snd_hdsp_hw_silence,
+ .copy_user = snd_hdsp_playback_copy,
+ .copy_kernel = snd_hdsp_playback_copy_kernel,
+ .fill_silence = snd_hdsp_hw_silence,
};
static const struct snd_pcm_ops snd_hdsp_capture_ops = {
@@ -4881,7 +4913,8 @@ static const struct snd_pcm_ops snd_hdsp_capture_ops = {
.prepare = snd_hdsp_prepare,
.trigger = snd_hdsp_trigger,
.pointer = snd_hdsp_hw_pointer,
- .copy = snd_hdsp_capture_copy,
+ .copy_user = snd_hdsp_capture_copy,
+ .copy_kernel = snd_hdsp_capture_copy_kernel,
};
static int snd_hdsp_create_hwdep(struct snd_card *card, struct hdsp *hdsp)
diff --git a/sound/pci/rme9652/rme9652.c b/sound/pci/rme9652/rme9652.c
index 55172c6..59684bf 100644
--- a/sound/pci/rme9652/rme9652.c
+++ b/sound/pci/rme9652/rme9652.c
@@ -1883,13 +1883,14 @@ static char *rme9652_channel_buffer_location(struct snd_rme9652 *rme9652,
}
}
-static int snd_rme9652_playback_copy(struct snd_pcm_substream *substream, int channel,
- snd_pcm_uframes_t pos, void __user *src, snd_pcm_uframes_t count)
+static int snd_rme9652_playback_copy(struct snd_pcm_substream *substream,
+ int channel, unsigned long pos,
+ void __user *src, unsigned long count)
{
struct snd_rme9652 *rme9652 = snd_pcm_substream_chip(substream);
char *channel_buf;
- if (snd_BUG_ON(pos + count > RME9652_CHANNEL_BUFFER_BYTES / 4))
+ if (snd_BUG_ON(pos + count > RME9652_CHANNEL_BUFFER_BYTES))
return -EINVAL;
channel_buf = rme9652_channel_buffer_location (rme9652,
@@ -1897,18 +1898,35 @@ static int snd_rme9652_playback_copy(struct snd_pcm_substream *substream, int ch
channel);
if (snd_BUG_ON(!channel_buf))
return -EIO;
- if (copy_from_user(channel_buf + pos * 4, src, count * 4))
+ if (copy_from_user(channel_buf + pos, src, count))
return -EFAULT;
- return count;
+ return 0;
}
-static int snd_rme9652_capture_copy(struct snd_pcm_substream *substream, int channel,
- snd_pcm_uframes_t pos, void __user *dst, snd_pcm_uframes_t count)
+static int snd_rme9652_playback_copy_kernel(struct snd_pcm_substream *substream,
+ int channel, unsigned long pos,
+ void *src, unsigned long count)
{
struct snd_rme9652 *rme9652 = snd_pcm_substream_chip(substream);
char *channel_buf;
- if (snd_BUG_ON(pos + count > RME9652_CHANNEL_BUFFER_BYTES / 4))
+ channel_buf = rme9652_channel_buffer_location(rme9652,
+ substream->pstr->stream,
+ channel);
+ if (snd_BUG_ON(!channel_buf))
+ return -EIO;
+ memcpy(channel_buf + pos, src, count);
+ return 0;
+}
+
+static int snd_rme9652_capture_copy(struct snd_pcm_substream *substream,
+ int channel, unsigned long pos,
+ void __user *dst, unsigned long count)
+{
+ struct snd_rme9652 *rme9652 = snd_pcm_substream_chip(substream);
+ char *channel_buf;
+
+ if (snd_BUG_ON(pos + count > RME9652_CHANNEL_BUFFER_BYTES))
return -EINVAL;
channel_buf = rme9652_channel_buffer_location (rme9652,
@@ -1916,13 +1934,30 @@ static int snd_rme9652_capture_copy(struct snd_pcm_substream *substream, int cha
channel);
if (snd_BUG_ON(!channel_buf))
return -EIO;
- if (copy_to_user(dst, channel_buf + pos * 4, count * 4))
+ if (copy_to_user(dst, channel_buf + pos, count))
return -EFAULT;
- return count;
+ return 0;
}
-static int snd_rme9652_hw_silence(struct snd_pcm_substream *substream, int channel,
- snd_pcm_uframes_t pos, snd_pcm_uframes_t count)
+static int snd_rme9652_capture_copy_kernel(struct snd_pcm_substream *substream,
+ int channel, unsigned long pos,
+ void *dst, unsigned long count)
+{
+ struct snd_rme9652 *rme9652 = snd_pcm_substream_chip(substream);
+ char *channel_buf;
+
+ channel_buf = rme9652_channel_buffer_location(rme9652,
+ substream->pstr->stream,
+ channel);
+ if (snd_BUG_ON(!channel_buf))
+ return -EIO;
+ memcpy(dst, channel_buf + pos, count);
+ return 0;
+}
+
+static int snd_rme9652_hw_silence(struct snd_pcm_substream *substream,
+ int channel, unsigned long pos,
+ unsigned long count)
{
struct snd_rme9652 *rme9652 = snd_pcm_substream_chip(substream);
char *channel_buf;
@@ -1932,8 +1967,8 @@ static int snd_rme9652_hw_silence(struct snd_pcm_substream *substream, int chann
channel);
if (snd_BUG_ON(!channel_buf))
return -EIO;
- memset(channel_buf + pos * 4, 0, count * 4);
- return count;
+ memset(channel_buf + pos, 0, count);
+ return 0;
}
static int snd_rme9652_reset(struct snd_pcm_substream *substream)
@@ -2376,8 +2411,9 @@ static const struct snd_pcm_ops snd_rme9652_playback_ops = {
.prepare = snd_rme9652_prepare,
.trigger = snd_rme9652_trigger,
.pointer = snd_rme9652_hw_pointer,
- .copy = snd_rme9652_playback_copy,
- .silence = snd_rme9652_hw_silence,
+ .copy_user = snd_rme9652_playback_copy,
+ .copy_kernel = snd_rme9652_playback_copy_kernel,
+ .fill_silence = snd_rme9652_hw_silence,
};
static const struct snd_pcm_ops snd_rme9652_capture_ops = {
@@ -2388,7 +2424,8 @@ static const struct snd_pcm_ops snd_rme9652_capture_ops = {
.prepare = snd_rme9652_prepare,
.trigger = snd_rme9652_trigger,
.pointer = snd_rme9652_hw_pointer,
- .copy = snd_rme9652_capture_copy,
+ .copy_user = snd_rme9652_capture_copy,
+ .copy_kernel = snd_rme9652_capture_copy_kernel,
};
static int snd_rme9652_create_pcm(struct snd_card *card,
diff --git a/sound/pci/vx222/vx222.c b/sound/pci/vx222/vx222.c
index ecbaf47..5586184 100644
--- a/sound/pci/vx222/vx222.c
+++ b/sound/pci/vx222/vx222.c
@@ -116,7 +116,7 @@ static struct snd_vx_hardware vx222_mic_hw = {
*/
static int snd_vx222_free(struct vx_core *chip)
{
- struct snd_vx222 *vx = (struct snd_vx222 *)chip;
+ struct snd_vx222 *vx = to_vx222(chip);
if (chip->irq >= 0)
free_irq(chip->irq, (void*)chip);
@@ -158,7 +158,7 @@ static int snd_vx222_create(struct snd_card *card, struct pci_dev *pci,
pci_disable_device(pci);
return -ENOMEM;
}
- vx = (struct snd_vx222 *)chip;
+ vx = to_vx222(chip);
vx->pci = pci;
if ((err = pci_request_regions(pci, CARD_NAME)) < 0) {
diff --git a/sound/pci/vx222/vx222.h b/sound/pci/vx222/vx222.h
index 2f0d78f..cae355c 100644
--- a/sound/pci/vx222/vx222.h
+++ b/sound/pci/vx222/vx222.h
@@ -39,6 +39,8 @@ struct snd_vx222 {
int mic_level; /* mic level for vx222 mic */
};
+#define to_vx222(x) container_of(x, struct snd_vx222, core)
+
/* we use a lookup table with 148 values, see vx_mixer.c */
#define VX2_AKM_LEVEL_MAX 0x93
diff --git a/sound/pci/vx222/vx222_ops.c b/sound/pci/vx222/vx222_ops.c
index 7df1663..d4298af 100644
--- a/sound/pci/vx222/vx222_ops.c
+++ b/sound/pci/vx222/vx222_ops.c
@@ -86,7 +86,7 @@ static int vx2_reg_index[VX_REG_MAX] = {
static inline unsigned long vx2_reg_addr(struct vx_core *_chip, int reg)
{
- struct snd_vx222 *chip = (struct snd_vx222 *)_chip;
+ struct snd_vx222 *chip = to_vx222(_chip);
return chip->port[vx2_reg_index[reg]] + vx2_reg_offset[reg];
}
@@ -159,7 +159,7 @@ static void vx2_outl(struct vx_core *chip, int offset, unsigned int val)
static void vx2_reset_dsp(struct vx_core *_chip)
{
- struct snd_vx222 *chip = (struct snd_vx222 *)_chip;
+ struct snd_vx222 *chip = to_vx222(_chip);
/* set the reset dsp bit to 0 */
vx_outl(chip, CDSP, chip->regCDSP & ~VX_CDSP_DSP_RESET_MASK);
@@ -174,7 +174,7 @@ static void vx2_reset_dsp(struct vx_core *_chip)
static int vx2_test_xilinx(struct vx_core *_chip)
{
- struct snd_vx222 *chip = (struct snd_vx222 *)_chip;
+ struct snd_vx222 *chip = to_vx222(_chip);
unsigned int data;
dev_dbg(_chip->card->dev, "testing xilinx...\n");
@@ -479,7 +479,7 @@ static int vx2_test_and_ack(struct vx_core *chip)
*/
static void vx2_validate_irq(struct vx_core *_chip, int enable)
{
- struct snd_vx222 *chip = (struct snd_vx222 *)_chip;
+ struct snd_vx222 *chip = to_vx222(_chip);
/* Set the interrupt enable bit to 1 in CDSP register */
if (enable) {
@@ -730,7 +730,7 @@ static void vx2_old_write_codec_bit(struct vx_core *chip, int codec, unsigned in
*/
static void vx2_reset_codec(struct vx_core *_chip)
{
- struct snd_vx222 *chip = (struct snd_vx222 *)_chip;
+ struct snd_vx222 *chip = to_vx222(_chip);
/* Set the reset CODEC bit to 0. */
vx_outl(chip, CDSP, chip->regCDSP &~ VX_CDSP_CODEC_RESET_MASK);
@@ -772,7 +772,7 @@ static void vx2_reset_codec(struct vx_core *_chip)
*/
static void vx2_change_audio_source(struct vx_core *_chip, int src)
{
- struct snd_vx222 *chip = (struct snd_vx222 *)_chip;
+ struct snd_vx222 *chip = to_vx222(_chip);
switch (src) {
case VX_AUDIO_SRC_DIGITAL:
@@ -791,7 +791,7 @@ static void vx2_change_audio_source(struct vx_core *_chip, int src)
*/
static void vx2_set_clock_source(struct vx_core *_chip, int source)
{
- struct snd_vx222 *chip = (struct snd_vx222 *)_chip;
+ struct snd_vx222 *chip = to_vx222(_chip);
if (source == INTERNAL_QUARTZ)
chip->regCFG &= ~VX_CFG_CLOCKIN_SEL_MASK;
@@ -805,7 +805,7 @@ static void vx2_set_clock_source(struct vx_core *_chip, int source)
*/
static void vx2_reset_board(struct vx_core *_chip, int cold_reset)
{
- struct snd_vx222 *chip = (struct snd_vx222 *)_chip;
+ struct snd_vx222 *chip = to_vx222(_chip);
/* initialize the register values */
chip->regCDSP = VX_CDSP_CODEC_RESET_MASK | VX_CDSP_DSP_RESET_MASK ;
@@ -878,7 +878,7 @@ static int vx_input_level_info(struct snd_kcontrol *kcontrol, struct snd_ctl_ele
static int vx_input_level_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
struct vx_core *_chip = snd_kcontrol_chip(kcontrol);
- struct snd_vx222 *chip = (struct snd_vx222 *)_chip;
+ struct snd_vx222 *chip = to_vx222(_chip);
mutex_lock(&_chip->mixer_mutex);
ucontrol->value.integer.value[0] = chip->input_level[0];
ucontrol->value.integer.value[1] = chip->input_level[1];
@@ -889,7 +889,7 @@ static int vx_input_level_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem
static int vx_input_level_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
struct vx_core *_chip = snd_kcontrol_chip(kcontrol);
- struct snd_vx222 *chip = (struct snd_vx222 *)_chip;
+ struct snd_vx222 *chip = to_vx222(_chip);
if (ucontrol->value.integer.value[0] < 0 ||
ucontrol->value.integer.value[0] > MIC_LEVEL_MAX)
return -EINVAL;
@@ -922,7 +922,7 @@ static int vx_mic_level_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_
static int vx_mic_level_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
struct vx_core *_chip = snd_kcontrol_chip(kcontrol);
- struct snd_vx222 *chip = (struct snd_vx222 *)_chip;
+ struct snd_vx222 *chip = to_vx222(_chip);
ucontrol->value.integer.value[0] = chip->mic_level;
return 0;
}
@@ -930,7 +930,7 @@ static int vx_mic_level_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_v
static int vx_mic_level_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
struct vx_core *_chip = snd_kcontrol_chip(kcontrol);
- struct snd_vx222 *chip = (struct snd_vx222 *)_chip;
+ struct snd_vx222 *chip = to_vx222(_chip);
if (ucontrol->value.integer.value[0] < 0 ||
ucontrol->value.integer.value[0] > MIC_LEVEL_MAX)
return -EINVAL;
@@ -973,7 +973,7 @@ static const struct snd_kcontrol_new vx_control_mic_level = {
static int vx2_add_mic_controls(struct vx_core *_chip)
{
- struct snd_vx222 *chip = (struct snd_vx222 *)_chip;
+ struct snd_vx222 *chip = to_vx222(_chip);
int err;
if (_chip->type != VX_TYPE_MIC)
diff --git a/sound/pcmcia/vx/vxp_mixer.c b/sound/pcmcia/vx/vxp_mixer.c
index a4a6642..304b153 100644
--- a/sound/pcmcia/vx/vxp_mixer.c
+++ b/sound/pcmcia/vx/vxp_mixer.c
@@ -43,7 +43,7 @@ static int vx_mic_level_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_
static int vx_mic_level_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
struct vx_core *_chip = snd_kcontrol_chip(kcontrol);
- struct snd_vxpocket *chip = (struct snd_vxpocket *)_chip;
+ struct snd_vxpocket *chip = to_vxpocket(_chip);
ucontrol->value.integer.value[0] = chip->mic_level;
return 0;
}
@@ -51,7 +51,7 @@ static int vx_mic_level_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_v
static int vx_mic_level_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
struct vx_core *_chip = snd_kcontrol_chip(kcontrol);
- struct snd_vxpocket *chip = (struct snd_vxpocket *)_chip;
+ struct snd_vxpocket *chip = to_vxpocket(_chip);
unsigned int val = ucontrol->value.integer.value[0];
if (val > MIC_LEVEL_MAX)
@@ -69,7 +69,7 @@ static int vx_mic_level_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_v
static const DECLARE_TLV_DB_SCALE(db_scale_mic, -21, 3, 0);
-static struct snd_kcontrol_new vx_control_mic_level = {
+static const struct snd_kcontrol_new vx_control_mic_level = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
SNDRV_CTL_ELEM_ACCESS_TLV_READ),
@@ -88,7 +88,7 @@ static struct snd_kcontrol_new vx_control_mic_level = {
static int vx_mic_boost_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
struct vx_core *_chip = snd_kcontrol_chip(kcontrol);
- struct snd_vxpocket *chip = (struct snd_vxpocket *)_chip;
+ struct snd_vxpocket *chip = to_vxpocket(_chip);
ucontrol->value.integer.value[0] = chip->mic_level;
return 0;
}
@@ -96,7 +96,7 @@ static int vx_mic_boost_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_v
static int vx_mic_boost_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
struct vx_core *_chip = snd_kcontrol_chip(kcontrol);
- struct snd_vxpocket *chip = (struct snd_vxpocket *)_chip;
+ struct snd_vxpocket *chip = to_vxpocket(_chip);
int val = !!ucontrol->value.integer.value[0];
mutex_lock(&_chip->mixer_mutex);
if (chip->mic_level != val) {
@@ -109,7 +109,7 @@ static int vx_mic_boost_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_v
return 0;
}
-static struct snd_kcontrol_new vx_control_mic_boost = {
+static const struct snd_kcontrol_new vx_control_mic_boost = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Mic Boost",
.info = vx_mic_boost_info,
@@ -120,7 +120,7 @@ static struct snd_kcontrol_new vx_control_mic_boost = {
int vxp_add_mic_controls(struct vx_core *_chip)
{
- struct snd_vxpocket *chip = (struct snd_vxpocket *)_chip;
+ struct snd_vxpocket *chip = to_vxpocket(_chip);
int err;
/* mute input levels */
diff --git a/sound/pcmcia/vx/vxp_ops.c b/sound/pcmcia/vx/vxp_ops.c
index 5f97791..8cde402 100644
--- a/sound/pcmcia/vx/vxp_ops.c
+++ b/sound/pcmcia/vx/vxp_ops.c
@@ -50,7 +50,7 @@ static int vxp_reg_offset[VX_REG_MAX] = {
static inline unsigned long vxp_reg_addr(struct vx_core *_chip, int reg)
{
- struct snd_vxpocket *chip = (struct snd_vxpocket *)_chip;
+ struct snd_vxpocket *chip = to_vxpocket(_chip);
return chip->port + vxp_reg_offset[reg];
}
@@ -110,7 +110,7 @@ static int vx_check_magic(struct vx_core *chip)
static void vxp_reset_dsp(struct vx_core *_chip)
{
- struct snd_vxpocket *chip = (struct snd_vxpocket *)_chip;
+ struct snd_vxpocket *chip = to_vxpocket(_chip);
/* set the reset dsp bit to 1 */
vx_outb(chip, CDSP, chip->regCDSP | VXP_CDSP_DSP_RESET_MASK);
@@ -128,7 +128,7 @@ static void vxp_reset_dsp(struct vx_core *_chip)
*/
static void vxp_reset_codec(struct vx_core *_chip)
{
- struct snd_vxpocket *chip = (struct snd_vxpocket *)_chip;
+ struct snd_vxpocket *chip = to_vxpocket(_chip);
/* Set the reset CODEC bit to 1. */
vx_outb(chip, CDSP, chip->regCDSP | VXP_CDSP_CODEC_RESET_MASK);
@@ -147,7 +147,7 @@ static void vxp_reset_codec(struct vx_core *_chip)
*/
static int vxp_load_xilinx_binary(struct vx_core *_chip, const struct firmware *fw)
{
- struct snd_vxpocket *chip = (struct snd_vxpocket *)_chip;
+ struct snd_vxpocket *chip = to_vxpocket(_chip);
unsigned int i;
int c;
int regCSUER, regRUER;
@@ -280,7 +280,7 @@ static int vxp_load_dsp(struct vx_core *vx, int index, const struct firmware *fw
*/
static int vxp_test_and_ack(struct vx_core *_chip)
{
- struct snd_vxpocket *chip = (struct snd_vxpocket *)_chip;
+ struct snd_vxpocket *chip = to_vxpocket(_chip);
/* not booted yet? */
if (! (_chip->chip_status & VX_STAT_XILINX_LOADED))
@@ -307,7 +307,7 @@ static int vxp_test_and_ack(struct vx_core *_chip)
*/
static void vxp_validate_irq(struct vx_core *_chip, int enable)
{
- struct snd_vxpocket *chip = (struct snd_vxpocket *)_chip;
+ struct snd_vxpocket *chip = to_vxpocket(_chip);
/* Set the interrupt enable bit to 1 in CDSP register */
if (enable)
@@ -323,7 +323,7 @@ static void vxp_validate_irq(struct vx_core *_chip, int enable)
*/
static void vx_setup_pseudo_dma(struct vx_core *_chip, int do_write)
{
- struct snd_vxpocket *chip = (struct snd_vxpocket *)_chip;
+ struct snd_vxpocket *chip = to_vxpocket(_chip);
/* Interrupt mode and HREQ pin enabled for host transmit / receive data transfers */
vx_outb(chip, ICR, do_write ? ICR_TREQ : ICR_RREQ);
@@ -343,7 +343,7 @@ static void vx_setup_pseudo_dma(struct vx_core *_chip, int do_write)
*/
static void vx_release_pseudo_dma(struct vx_core *_chip)
{
- struct snd_vxpocket *chip = (struct snd_vxpocket *)_chip;
+ struct snd_vxpocket *chip = to_vxpocket(_chip);
/* Disable DMA and 16-bit accesses */
chip->regDIALOG &= ~(VXP_DLG_DMAWRITE_SEL_MASK|
@@ -403,7 +403,7 @@ static void vxp_dma_write(struct vx_core *chip, struct snd_pcm_runtime *runtime,
static void vxp_dma_read(struct vx_core *chip, struct snd_pcm_runtime *runtime,
struct vx_pipe *pipe, int count)
{
- struct snd_vxpocket *pchip = (struct snd_vxpocket *)chip;
+ struct snd_vxpocket *pchip = to_vxpocket(chip);
long port = vxp_reg_addr(chip, VX_DMA);
int offset = pipe->hw_ptr;
unsigned short *addr = (unsigned short *)(runtime->dma_area + offset);
@@ -467,7 +467,7 @@ static void vxp_write_codec_reg(struct vx_core *chip, int codec, unsigned int da
*/
void vx_set_mic_boost(struct vx_core *chip, int boost)
{
- struct snd_vxpocket *pchip = (struct snd_vxpocket *)chip;
+ struct snd_vxpocket *pchip = to_vxpocket(chip);
if (chip->chip_status & VX_STAT_IS_STALE)
return;
@@ -509,7 +509,7 @@ static int vx_compute_mic_level(int level)
*/
void vx_set_mic_level(struct vx_core *chip, int level)
{
- struct snd_vxpocket *pchip = (struct snd_vxpocket *)chip;
+ struct snd_vxpocket *pchip = to_vxpocket(chip);
if (chip->chip_status & VX_STAT_IS_STALE)
return;
@@ -528,7 +528,7 @@ void vx_set_mic_level(struct vx_core *chip, int level)
*/
static void vxp_change_audio_source(struct vx_core *_chip, int src)
{
- struct snd_vxpocket *chip = (struct snd_vxpocket *)_chip;
+ struct snd_vxpocket *chip = to_vxpocket(_chip);
switch (src) {
case VX_AUDIO_SRC_DIGITAL:
@@ -568,7 +568,7 @@ static void vxp_change_audio_source(struct vx_core *_chip, int src)
*/
static void vxp_set_clock_source(struct vx_core *_chip, int source)
{
- struct snd_vxpocket *chip = (struct snd_vxpocket *)_chip;
+ struct snd_vxpocket *chip = to_vxpocket(_chip);
if (source == INTERNAL_QUARTZ)
chip->regCDSP &= ~VXP_CDSP_CLOCKIN_SEL_MASK;
@@ -583,7 +583,7 @@ static void vxp_set_clock_source(struct vx_core *_chip, int source)
*/
static void vxp_reset_board(struct vx_core *_chip, int cold_reset)
{
- struct snd_vxpocket *chip = (struct snd_vxpocket *)_chip;
+ struct snd_vxpocket *chip = to_vxpocket(_chip);
chip->regCDSP = 0;
chip->regDIALOG = 0;
diff --git a/sound/pcmcia/vx/vxpocket.c b/sound/pcmcia/vx/vxpocket.c
index b16f42d..ca0d19e 100644
--- a/sound/pcmcia/vx/vxpocket.c
+++ b/sound/pcmcia/vx/vxpocket.c
@@ -155,7 +155,7 @@ static int snd_vxpocket_new(struct snd_card *card, int ibl,
}
chip->ibl.size = ibl;
- vxp = (struct snd_vxpocket *)chip;
+ vxp = to_vxpocket(chip);
vxp->p_dev = link;
link->priv = chip;
@@ -187,7 +187,7 @@ static int snd_vxpocket_assign_resources(struct vx_core *chip, int port, int irq
{
int err;
struct snd_card *card = chip->card;
- struct snd_vxpocket *vxp = (struct snd_vxpocket *)chip;
+ struct snd_vxpocket *vxp = to_vxpocket(chip);
snd_printdd(KERN_DEBUG "vxpocket assign resources: port = 0x%x, irq = %d\n", port, irq);
vxp->port = port;
diff --git a/sound/pcmcia/vx/vxpocket.h b/sound/pcmcia/vx/vxpocket.h
index 13d658c..26f4255 100644
--- a/sound/pcmcia/vx/vxpocket.h
+++ b/sound/pcmcia/vx/vxpocket.h
@@ -43,6 +43,8 @@ struct snd_vxpocket {
struct pcmcia_device *p_dev;
};
+#define to_vxpocket(x) container_of(x, struct snd_vxpocket, core)
+
extern struct snd_vx_ops snd_vxpocket_ops;
void vx_set_mic_boost(struct vx_core *chip, int boost);
diff --git a/sound/ppc/awacs.c b/sound/ppc/awacs.c
index 1468e4b..d1e4ef1 100644
--- a/sound/ppc/awacs.c
+++ b/sound/ppc/awacs.c
@@ -514,7 +514,7 @@ static struct snd_kcontrol_new snd_pmac_awacs_amp_vol[] = {
},
};
-static struct snd_kcontrol_new snd_pmac_awacs_amp_hp_sw = {
+static const struct snd_kcontrol_new snd_pmac_awacs_amp_hp_sw = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Headphone Playback Switch",
.info = snd_pmac_boolean_stereo_info,
@@ -523,7 +523,7 @@ static struct snd_kcontrol_new snd_pmac_awacs_amp_hp_sw = {
.private_value = AMP_CH_HD,
};
-static struct snd_kcontrol_new snd_pmac_awacs_amp_spk_sw = {
+static const struct snd_kcontrol_new snd_pmac_awacs_amp_spk_sw = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Speaker Playback Switch",
.info = snd_pmac_boolean_stereo_info,
diff --git a/sound/ppc/beep.c b/sound/ppc/beep.c
index d3524f9..f19eb3e 100644
--- a/sound/ppc/beep.c
+++ b/sound/ppc/beep.c
@@ -206,7 +206,7 @@ static int snd_pmac_put_beep(struct snd_kcontrol *kcontrol,
return oval != chip->beep->volume;
}
-static struct snd_kcontrol_new snd_pmac_beep_mixer = {
+static const struct snd_kcontrol_new snd_pmac_beep_mixer = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Beep Playback Volume",
.info = snd_pmac_info_beep,
diff --git a/sound/ppc/tumbler.c b/sound/ppc/tumbler.c
index 58ee808..0779a29 100644
--- a/sound/ppc/tumbler.c
+++ b/sound/ppc/tumbler.c
@@ -897,7 +897,7 @@ static struct snd_kcontrol_new snapper_mixers[] = {
},
};
-static struct snd_kcontrol_new tumbler_hp_sw = {
+static const struct snd_kcontrol_new tumbler_hp_sw = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Headphone Playback Switch",
.info = snd_pmac_boolean_mono_info,
@@ -905,7 +905,7 @@ static struct snd_kcontrol_new tumbler_hp_sw = {
.put = tumbler_put_mute_switch,
.private_value = TUMBLER_MUTE_HP,
};
-static struct snd_kcontrol_new tumbler_speaker_sw = {
+static const struct snd_kcontrol_new tumbler_speaker_sw = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Speaker Playback Switch",
.info = snd_pmac_boolean_mono_info,
@@ -913,7 +913,7 @@ static struct snd_kcontrol_new tumbler_speaker_sw = {
.put = tumbler_put_mute_switch,
.private_value = TUMBLER_MUTE_AMP,
};
-static struct snd_kcontrol_new tumbler_lineout_sw = {
+static const struct snd_kcontrol_new tumbler_lineout_sw = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Line Out Playback Switch",
.info = snd_pmac_boolean_mono_info,
@@ -921,7 +921,7 @@ static struct snd_kcontrol_new tumbler_lineout_sw = {
.put = tumbler_put_mute_switch,
.private_value = TUMBLER_MUTE_LINE,
};
-static struct snd_kcontrol_new tumbler_drc_sw = {
+static const struct snd_kcontrol_new tumbler_drc_sw = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "DRC Switch",
.info = snd_pmac_boolean_mono_info,
diff --git a/sound/sh/aica.c b/sound/sh/aica.c
index fbbc252..ab4802d 100644
--- a/sound/sh/aica.c
+++ b/sound/sh/aica.c
@@ -535,7 +535,7 @@ static int aica_pcmvolume_put(struct snd_kcontrol *kcontrol,
return 1;
}
-static struct snd_kcontrol_new snd_aica_pcmswitch_control = {
+static const struct snd_kcontrol_new snd_aica_pcmswitch_control = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "PCM Playback Switch",
.index = 0,
@@ -544,7 +544,7 @@ static struct snd_kcontrol_new snd_aica_pcmswitch_control = {
.put = aica_pcmswitch_put
};
-static struct snd_kcontrol_new snd_aica_pcmvolume_control = {
+static const struct snd_kcontrol_new snd_aica_pcmvolume_control = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "PCM Playback Volume",
.index = 0,
diff --git a/sound/sh/sh_dac_audio.c b/sound/sh/sh_dac_audio.c
index 461b310..c1e00ed 100644
--- a/sound/sh/sh_dac_audio.c
+++ b/sound/sh/sh_dac_audio.c
@@ -184,23 +184,36 @@ static int snd_sh_dac_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
return 0;
}
-static int snd_sh_dac_pcm_copy(struct snd_pcm_substream *substream, int channel,
- snd_pcm_uframes_t pos, void __user *src, snd_pcm_uframes_t count)
+static int snd_sh_dac_pcm_copy(struct snd_pcm_substream *substream,
+ int channel, unsigned long pos,
+ void __user *src, unsigned long count)
{
/* channel is not used (interleaved data) */
struct snd_sh_dac *chip = snd_pcm_substream_chip(substream);
struct snd_pcm_runtime *runtime = substream->runtime;
- ssize_t b_count = frames_to_bytes(runtime , count);
- ssize_t b_pos = frames_to_bytes(runtime , pos);
- if (count < 0)
- return -EINVAL;
+ if (copy_from_user_toio(chip->data_buffer + pos, src, count))
+ return -EFAULT;
+ chip->buffer_end = chip->data_buffer + pos + count;
- if (!count)
- return 0;
+ if (chip->empty) {
+ chip->empty = 0;
+ dac_audio_start_timer(chip);
+ }
+
+ return 0;
+}
- memcpy_toio(chip->data_buffer + b_pos, src, b_count);
- chip->buffer_end = chip->data_buffer + b_pos + b_count;
+static int snd_sh_dac_pcm_copy_kernel(struct snd_pcm_substream *substream,
+ int channel, unsigned long pos,
+ void *src, unsigned long count)
+{
+ /* channel is not used (interleaved data) */
+ struct snd_sh_dac *chip = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
+
+ memcpy_toio(chip->data_buffer + pos, src, count);
+ chip->buffer_end = chip->data_buffer + pos + count;
if (chip->empty) {
chip->empty = 0;
@@ -211,23 +224,15 @@ static int snd_sh_dac_pcm_copy(struct snd_pcm_substream *substream, int channel,
}
static int snd_sh_dac_pcm_silence(struct snd_pcm_substream *substream,
- int channel, snd_pcm_uframes_t pos,
- snd_pcm_uframes_t count)
+ int channel, unsigned long pos,
+ unsigned long count)
{
/* channel is not used (interleaved data) */
struct snd_sh_dac *chip = snd_pcm_substream_chip(substream);
struct snd_pcm_runtime *runtime = substream->runtime;
- ssize_t b_count = frames_to_bytes(runtime , count);
- ssize_t b_pos = frames_to_bytes(runtime , pos);
-
- if (count < 0)
- return -EINVAL;
-
- if (!count)
- return 0;
- memset_io(chip->data_buffer + b_pos, 0, b_count);
- chip->buffer_end = chip->data_buffer + b_pos + b_count;
+ memset_io(chip->data_buffer + pos, 0, count);
+ chip->buffer_end = chip->data_buffer + pos + count;
if (chip->empty) {
chip->empty = 0;
@@ -256,8 +261,9 @@ static struct snd_pcm_ops snd_sh_dac_pcm_ops = {
.prepare = snd_sh_dac_pcm_prepare,
.trigger = snd_sh_dac_pcm_trigger,
.pointer = snd_sh_dac_pcm_pointer,
- .copy = snd_sh_dac_pcm_copy,
- .silence = snd_sh_dac_pcm_silence,
+ .copy_user = snd_sh_dac_pcm_copy,
+ .copy_kernel = snd_sh_dac_pcm_copy_kernel,
+ .fill_silence = snd_sh_dac_pcm_silence,
.mmap = snd_pcm_lib_mmap_iomem,
};
diff --git a/sound/soc/blackfin/bf5xx-ac97-pcm.c b/sound/soc/blackfin/bf5xx-ac97-pcm.c
index 02ad260..913e292 100644
--- a/sound/soc/blackfin/bf5xx-ac97-pcm.c
+++ b/sound/soc/blackfin/bf5xx-ac97-pcm.c
@@ -279,23 +279,33 @@ static int bf5xx_pcm_mmap(struct snd_pcm_substream *substream,
return 0 ;
}
#else
-static int bf5xx_pcm_copy(struct snd_pcm_substream *substream, int channel,
- snd_pcm_uframes_t pos,
- void __user *buf, snd_pcm_uframes_t count)
+static int bf5xx_pcm_copy(struct snd_pcm_substream *substream,
+ int channel, unsigned long pos,
+ void *buf, unsigned long count)
{
struct snd_pcm_runtime *runtime = substream->runtime;
unsigned int chan_mask = ac97_chan_mask[runtime->channels - 1];
+ struct ac97_frame *dst;
+
pr_debug("%s copy pos:0x%lx count:0x%lx\n",
substream->stream ? "Capture" : "Playback", pos, count);
+ dst = (struct ac97_frame *)runtime->dma_area +
+ bytes_to_frames(runtime, pos);
+ count = bytes_to_frames(runtime, count);
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
- bf5xx_pcm_to_ac97((struct ac97_frame *)runtime->dma_area + pos,
- (__u16 *)buf, count, chan_mask);
+ bf5xx_pcm_to_ac97(dst, buf, count, chan_mask);
else
- bf5xx_ac97_to_pcm((struct ac97_frame *)runtime->dma_area + pos,
- (__u16 *)buf, count);
+ bf5xx_ac97_to_pcm(dst, buf, count);
return 0;
}
+
+static int bf5xx_pcm_copy_user(struct snd_pcm_substream *substream,
+ int channel, unsigned long pos,
+ void __user *buf, unsigned long count)
+{
+ return bf5xx_pcm_copy(substream, channel, pos, (void *)buf, count);
+}
#endif
static struct snd_pcm_ops bf5xx_pcm_ac97_ops = {
@@ -309,7 +319,8 @@ static struct snd_pcm_ops bf5xx_pcm_ac97_ops = {
#if defined(CONFIG_SND_BF5XX_MMAP_SUPPORT)
.mmap = bf5xx_pcm_mmap,
#else
- .copy = bf5xx_pcm_copy,
+ .copy_user = bf5xx_pcm_copy_user,
+ .copy_kernel = bf5xx_pcm_copy,
#endif
};
diff --git a/sound/soc/blackfin/bf5xx-i2s-pcm.c b/sound/soc/blackfin/bf5xx-i2s-pcm.c
index 6cba211d..470d99a 100644
--- a/sound/soc/blackfin/bf5xx-i2s-pcm.c
+++ b/sound/soc/blackfin/bf5xx-i2s-pcm.c
@@ -225,8 +225,9 @@ static int bf5xx_pcm_mmap(struct snd_pcm_substream *substream,
return 0 ;
}
-static int bf5xx_pcm_copy(struct snd_pcm_substream *substream, int channel,
- snd_pcm_uframes_t pos, void *buf, snd_pcm_uframes_t count)
+static int bf5xx_pcm_copy(struct snd_pcm_substream *substream,
+ int channel, unsigned long pos,
+ void *buf, unsigned long count)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_pcm_runtime *runtime = substream->runtime;
@@ -238,6 +239,8 @@ static int bf5xx_pcm_copy(struct snd_pcm_substream *substream, int channel,
dma_data = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
if (dma_data->tdm_mode) {
+ pos = bytes_to_frames(runtime, pos);
+ count = bytes_to_frames(runtime, count);
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
src = buf;
dst = runtime->dma_area;
@@ -269,21 +272,29 @@ static int bf5xx_pcm_copy(struct snd_pcm_substream *substream, int channel,
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
src = buf;
dst = runtime->dma_area;
- dst += frames_to_bytes(runtime, pos);
+ dst += pos;
} else {
src = runtime->dma_area;
- src += frames_to_bytes(runtime, pos);
+ src += pos;
dst = buf;
}
- memcpy(dst, src, frames_to_bytes(runtime, count));
+ memcpy(dst, src, count);
}
return 0;
}
+static int bf5xx_pcm_copy_user(struct snd_pcm_substream *substream,
+ int channel, unsigned long pos,
+ void __user *buf, unsigned long count)
+{
+ return bf5xx_pcm_copy(substream, channel, pos, (void *)buf, count);
+}
+
static int bf5xx_pcm_silence(struct snd_pcm_substream *substream,
- int channel, snd_pcm_uframes_t pos, snd_pcm_uframes_t count)
+ int channel, unsigned long pos,
+ unsigned long count)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_pcm_runtime *runtime = substream->runtime;
@@ -295,11 +306,11 @@ static int bf5xx_pcm_silence(struct snd_pcm_substream *substream,
dma_data = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
if (dma_data->tdm_mode) {
- offset = pos * 8 * sample_size;
- samples = count * 8;
+ offset = bytes_to_frames(runtime, pos) * 8 * sample_size;
+ samples = bytes_to_frames(runtime, count) * 8;
} else {
- offset = frames_to_bytes(runtime, pos);
- samples = count * runtime->channels;
+ offset = pos;
+ samples = bytes_to_samples(runtime, count);
}
snd_pcm_format_set_silence(runtime->format, buf + offset, samples);
@@ -316,8 +327,9 @@ static struct snd_pcm_ops bf5xx_pcm_i2s_ops = {
.trigger = bf5xx_pcm_trigger,
.pointer = bf5xx_pcm_pointer,
.mmap = bf5xx_pcm_mmap,
- .copy = bf5xx_pcm_copy,
- .silence = bf5xx_pcm_silence,
+ .copy_user = bf5xx_pcm_copy_user,
+ .copy_kernel = bf5xx_pcm_copy,
+ .fill_silence = bf5xx_pcm_silence,
};
static int bf5xx_pcm_i2s_new(struct snd_soc_pcm_runtime *rtd)
diff --git a/sound/soc/sh/siu_dai.c b/sound/soc/sh/siu_dai.c
index 76b2ab8..4a22aad 100644
--- a/sound/soc/sh/siu_dai.c
+++ b/sound/soc/sh/siu_dai.c
@@ -441,7 +441,7 @@ static int siu_dai_put_volume(struct snd_kcontrol *kctrl,
return 0;
}
-static struct snd_kcontrol_new playback_controls = {
+static const struct snd_kcontrol_new playback_controls = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "PCM Playback Volume",
.index = 0,
@@ -451,7 +451,7 @@ static struct snd_kcontrol_new playback_controls = {
.private_value = VOLUME_PLAYBACK,
};
-static struct snd_kcontrol_new capture_controls = {
+static const struct snd_kcontrol_new capture_controls = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "PCM Capture Volume",
.index = 0,
diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c
index efc5831..dcc5ece 100644
--- a/sound/soc/soc-pcm.c
+++ b/sound/soc/soc-pcm.c
@@ -2743,8 +2743,9 @@ int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num)
if (platform->driver->ops) {
rtd->ops.ack = platform->driver->ops->ack;
- rtd->ops.copy = platform->driver->ops->copy;
- rtd->ops.silence = platform->driver->ops->silence;
+ rtd->ops.copy_user = platform->driver->ops->copy_user;
+ rtd->ops.copy_kernel = platform->driver->ops->copy_kernel;
+ rtd->ops.fill_silence = platform->driver->ops->fill_silence;
rtd->ops.page = platform->driver->ops->page;
rtd->ops.mmap = platform->driver->ops->mmap;
}
diff --git a/sound/usb/Kconfig b/sound/usb/Kconfig
index a452ad7..f61b566 100644
--- a/sound/usb/Kconfig
+++ b/sound/usb/Kconfig
@@ -91,7 +91,7 @@ config SND_USB_CAIAQ_INPUT
config SND_USB_US122L
tristate "Tascam US-122L USB driver"
- depends on X86
+ depends on X86 || COMPILE_TEST
select SND_HWDEP
select SND_RAWMIDI
help
diff --git a/sound/usb/mixer_quirks.c b/sound/usb/mixer_quirks.c
index 4fa0053..e3d1dec 100644
--- a/sound/usb/mixer_quirks.c
+++ b/sound/usb/mixer_quirks.c
@@ -362,7 +362,7 @@ static int snd_audigy2nx_led_resume(struct usb_mixer_elem_list *list)
}
/* name and private_value are set dynamically */
-static struct snd_kcontrol_new snd_audigy2nx_control = {
+static const struct snd_kcontrol_new snd_audigy2nx_control = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.info = snd_audigy2nx_led_info,
.get = snd_audigy2nx_led_get,
diff --git a/sound/usb/usx2y/us122l.c b/sound/usb/usx2y/us122l.c
index e118bdc..a33e31b2 100644
--- a/sound/usb/usx2y/us122l.c
+++ b/sound/usb/usx2y/us122l.c
@@ -46,8 +46,10 @@ MODULE_PARM_DESC(id, "ID string for "NAME_ALLCAPS".");
module_param_array(enable, bool, NULL, 0444);
MODULE_PARM_DESC(enable, "Enable "NAME_ALLCAPS".");
-static int snd_us122l_card_used[SNDRV_CARDS];
+/* driver_info flags */
+#define US122L_FLAG_US144 BIT(0)
+static int snd_us122l_card_used[SNDRV_CARDS];
static int us122l_create_usbmidi(struct snd_card *card)
{
@@ -198,8 +200,7 @@ static int usb_stream_hwdep_open(struct snd_hwdep *hw, struct file *file)
if (!us122l->first)
us122l->first = file;
- if (us122l->dev->descriptor.idProduct == USB_ID_US144 ||
- us122l->dev->descriptor.idProduct == USB_ID_US144MKII) {
+ if (us122l->is_us144) {
iface = usb_ifnum_to_if(us122l->dev, 0);
usb_autopm_get_interface(iface);
}
@@ -214,8 +215,7 @@ static int usb_stream_hwdep_release(struct snd_hwdep *hw, struct file *file)
struct usb_interface *iface;
snd_printdd(KERN_DEBUG "%p %p\n", hw, file);
- if (us122l->dev->descriptor.idProduct == USB_ID_US144 ||
- us122l->dev->descriptor.idProduct == USB_ID_US144MKII) {
+ if (us122l->is_us144) {
iface = usb_ifnum_to_if(us122l->dev, 0);
usb_autopm_put_interface(iface);
}
@@ -483,8 +483,7 @@ static bool us122l_create_card(struct snd_card *card)
int err;
struct us122l *us122l = US122L(card);
- if (us122l->dev->descriptor.idProduct == USB_ID_US144 ||
- us122l->dev->descriptor.idProduct == USB_ID_US144MKII) {
+ if (us122l->is_us144) {
err = usb_set_interface(us122l->dev, 0, 1);
if (err) {
snd_printk(KERN_ERR "usb_set_interface error \n");
@@ -503,8 +502,7 @@ static bool us122l_create_card(struct snd_card *card)
if (!us122l_start(us122l, 44100, 256))
return false;
- if (us122l->dev->descriptor.idProduct == USB_ID_US144 ||
- us122l->dev->descriptor.idProduct == USB_ID_US144MKII)
+ if (us122l->is_us144)
err = us144_create_usbmidi(card);
else
err = us122l_create_usbmidi(card);
@@ -536,7 +534,8 @@ static void snd_us122l_free(struct snd_card *card)
static int usx2y_create_card(struct usb_device *device,
struct usb_interface *intf,
- struct snd_card **cardp)
+ struct snd_card **cardp,
+ unsigned long flags)
{
int dev;
struct snd_card *card;
@@ -556,6 +555,7 @@ static int usx2y_create_card(struct usb_device *device,
US122L(card)->dev = device;
mutex_init(&US122L(card)->mutex);
init_waitqueue_head(&US122L(card)->sk.sleep);
+ US122L(card)->is_us144 = flags & US122L_FLAG_US144;
INIT_LIST_HEAD(&US122L(card)->midi_list);
strcpy(card->driver, "USB "NAME_ALLCAPS"");
sprintf(card->shortname, "TASCAM "NAME_ALLCAPS"");
@@ -579,7 +579,7 @@ static int us122l_usb_probe(struct usb_interface *intf,
struct snd_card *card;
int err;
- err = usx2y_create_card(device, intf, &card);
+ err = usx2y_create_card(device, intf, &card, device_id->driver_info);
if (err < 0)
return err;
@@ -607,9 +607,8 @@ static int snd_us122l_probe(struct usb_interface *intf,
struct snd_card *card;
int err;
- if ((device->descriptor.idProduct == USB_ID_US144 ||
- device->descriptor.idProduct == USB_ID_US144MKII)
- && device->speed == USB_SPEED_HIGH) {
+ if (id->driver_info & US122L_FLAG_US144 &&
+ device->speed == USB_SPEED_HIGH) {
snd_printk(KERN_ERR "disable ehci-hcd to run US-144 \n");
return -ENODEV;
}
@@ -703,8 +702,7 @@ static int snd_us122l_resume(struct usb_interface *intf)
mutex_lock(&us122l->mutex);
/* needed, doesn't restart without: */
- if (us122l->dev->descriptor.idProduct == USB_ID_US144 ||
- us122l->dev->descriptor.idProduct == USB_ID_US144MKII) {
+ if (us122l->is_us144) {
err = usb_set_interface(us122l->dev, 0, 1);
if (err) {
snd_printk(KERN_ERR "usb_set_interface error \n");
@@ -747,7 +745,8 @@ static struct usb_device_id snd_us122l_usb_id_table[] = {
{ /* US-144 only works at USB1.1! Disable module ehci-hcd. */
.match_flags = USB_DEVICE_ID_MATCH_DEVICE,
.idVendor = 0x0644,
- .idProduct = USB_ID_US144
+ .idProduct = USB_ID_US144,
+ .driver_info = US122L_FLAG_US144
},
{
.match_flags = USB_DEVICE_ID_MATCH_DEVICE,
@@ -757,7 +756,8 @@ static struct usb_device_id snd_us122l_usb_id_table[] = {
{
.match_flags = USB_DEVICE_ID_MATCH_DEVICE,
.idVendor = 0x0644,
- .idProduct = USB_ID_US144MKII
+ .idProduct = USB_ID_US144MKII,
+ .driver_info = US122L_FLAG_US144
},
{ /* terminator */ }
};
diff --git a/sound/usb/usx2y/us122l.h b/sound/usb/usx2y/us122l.h
index f263b3f..3e2a2d0 100644
--- a/sound/usb/usx2y/us122l.h
+++ b/sound/usb/usx2y/us122l.h
@@ -16,6 +16,8 @@ struct us122l {
struct list_head midi_list;
atomic_t mmap_count;
+
+ bool is_us144;
};
OpenPOWER on IntegriCloud