summaryrefslogtreecommitdiffstats
path: root/sound
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2010-05-20 11:58:57 +0200
committerTakashi Iwai <tiwai@suse.de>2010-05-20 11:58:57 +0200
commit3374cd1abd478f767aaedf2c21d109596ff0fe72 (patch)
tree46b00a571ba5d86373bd9054fdccc5dc6e28e42f /sound
parente40152ee1e1c7a63f4777791863215e3faa37a86 (diff)
parent670ff6abd6caff406b217f8a828d6c03656535d8 (diff)
Merge branch 'topic/core-cleanup' into for-linus
Diffstat (limited to 'sound')
-rw-r--r--sound/atmel/Kconfig2
-rw-r--r--sound/atmel/ac97c.c355
-rw-r--r--sound/core/control.c5
-rw-r--r--sound/core/info.c74
-rw-r--r--sound/core/oss/mixer_oss.c5
-rw-r--r--sound/core/oss/pcm_oss.c5
-rw-r--r--sound/core/pcm_native.c19
-rw-r--r--sound/core/rawmidi.c5
-rw-r--r--sound/core/seq/seq_clientmgr.c6
-rw-r--r--sound/core/sound.c73
-rw-r--r--sound/core/timer.c6
-rw-r--r--sound/drivers/opl4/opl4_proc.c83
-rw-r--r--sound/isa/gus/gus_mem_proc.c48
-rw-r--r--sound/pci/cs4281.c40
-rw-r--r--sound/pci/cs46xx/cs46xx_lib.c19
-rw-r--r--sound/pci/emu10k1/emuproc.c51
-rw-r--r--sound/pci/ice1712/aureon.c89
-rw-r--r--sound/pci/mixart/mixart.c79
-rw-r--r--sound/ppc/tumbler.c12
-rw-r--r--sound/usb/Kconfig1
-rw-r--r--sound/usb/caiaq/control.c99
-rw-r--r--sound/usb/caiaq/device.c8
-rw-r--r--sound/usb/caiaq/device.h24
-rw-r--r--sound/usb/caiaq/input.c162
24 files changed, 800 insertions, 470 deletions
diff --git a/sound/atmel/Kconfig b/sound/atmel/Kconfig
index 6c228a91940d..94de43a096f1 100644
--- a/sound/atmel/Kconfig
+++ b/sound/atmel/Kconfig
@@ -12,7 +12,7 @@ config SND_ATMEL_AC97C
tristate "Atmel AC97 Controller (AC97C) driver"
select SND_PCM
select SND_AC97_CODEC
- depends on DW_DMAC && AVR32
+ depends on (DW_DMAC && AVR32) || ARCH_AT91
help
ALSA sound driver for the Atmel AC97 controller.
diff --git a/sound/atmel/ac97c.c b/sound/atmel/ac97c.c
index 0c0f8771656a..428121a7e705 100644
--- a/sound/atmel/ac97c.c
+++ b/sound/atmel/ac97c.c
@@ -13,6 +13,7 @@
#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>
#include <linux/module.h>
@@ -31,6 +32,10 @@
#include <linux/dw_dmac.h>
+#include <mach/cpu.h>
+#include <mach/hardware.h>
+#include <mach/gpio.h>
+
#include "ac97c.h"
enum {
@@ -63,6 +68,7 @@ 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;
void __iomem *regs;
@@ -242,10 +248,12 @@ static int atmel_ac97c_playback_hw_params(struct snd_pcm_substream *substream,
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_TX_READY, &chip->flags))
- dw_dma_cyclic_free(chip->dma.tx_chan);
-
+ 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);
@@ -266,9 +274,14 @@ static int atmel_ac97c_capture_hw_params(struct snd_pcm_substream *substream,
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_RX_READY, &chip->flags))
- dw_dma_cyclic_free(chip->dma.rx_chan);
+ if (cpu_is_at32ap7000()) {
+ 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_RX_READY, &chip->flags))
+ dw_dma_cyclic_free(chip->dma.rx_chan);
+ }
/* Set restrictions to params. */
mutex_lock(&opened_mutex);
@@ -282,16 +295,20 @@ static int atmel_ac97c_capture_hw_params(struct snd_pcm_substream *substream,
static int atmel_ac97c_playback_hw_free(struct snd_pcm_substream *substream)
{
struct atmel_ac97c *chip = snd_pcm_substream_chip(substream);
- if (test_and_clear_bit(DMA_TX_READY, &chip->flags))
- dw_dma_cyclic_free(chip->dma.tx_chan);
+ 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 (test_and_clear_bit(DMA_RX_READY, &chip->flags))
- dw_dma_cyclic_free(chip->dma.rx_chan);
+ 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);
}
@@ -299,9 +316,11 @@ static int atmel_ac97c_playback_prepare(struct snd_pcm_substream *substream)
{
struct atmel_ac97c *chip = snd_pcm_substream_chip(substream);
struct snd_pcm_runtime *runtime = substream->runtime;
+ int block_size = frames_to_bytes(runtime, runtime->period_size);
unsigned long word = ac97c_readl(chip, OCA);
int retval;
+ chip->playback_period = 0;
word &= ~(AC97C_CH_MASK(PCM_LEFT) | AC97C_CH_MASK(PCM_RIGHT));
/* assign channels to AC97C channel A */
@@ -320,11 +339,16 @@ static int atmel_ac97c_playback_prepare(struct snd_pcm_substream *substream)
ac97c_writel(chip, OCA, word);
/* configure sample format and size */
- word = AC97C_CMR_DMAEN | AC97C_CMR_SIZE_16;
+ word = ac97c_readl(chip, CAMR);
+ if (chip->opened <= 1)
+ word = AC97C_CMR_DMAEN | AC97C_CMR_SIZE_16;
+ else
+ word |= AC97C_CMR_DMAEN | AC97C_CMR_SIZE_16;
switch (runtime->format) {
case SNDRV_PCM_FORMAT_S16_LE:
- word |= AC97C_CMR_CEM_LITTLE;
+ if (cpu_is_at32ap7000())
+ word |= AC97C_CMR_CEM_LITTLE;
break;
case SNDRV_PCM_FORMAT_S16_BE: /* fall through */
word &= ~(AC97C_CMR_CEM_LITTLE);
@@ -363,9 +387,18 @@ 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 (!test_bit(DMA_TX_READY, &chip->flags))
- retval = atmel_ac97c_prepare_dma(chip, substream,
- DMA_TO_DEVICE);
+ if (cpu_is_at32ap7000()) {
+ if (!test_bit(DMA_TX_READY, &chip->flags))
+ retval = atmel_ac97c_prepare_dma(chip, substream,
+ DMA_TO_DEVICE);
+ } 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);
+ }
return retval;
}
@@ -374,9 +407,11 @@ static int atmel_ac97c_capture_prepare(struct snd_pcm_substream *substream)
{
struct atmel_ac97c *chip = snd_pcm_substream_chip(substream);
struct snd_pcm_runtime *runtime = substream->runtime;
+ int block_size = frames_to_bytes(runtime, runtime->period_size);
unsigned long word = ac97c_readl(chip, ICA);
int retval;
+ chip->capture_period = 0;
word &= ~(AC97C_CH_MASK(PCM_LEFT) | AC97C_CH_MASK(PCM_RIGHT));
/* assign channels to AC97C channel A */
@@ -395,11 +430,16 @@ static int atmel_ac97c_capture_prepare(struct snd_pcm_substream *substream)
ac97c_writel(chip, ICA, word);
/* configure sample format and size */
- word = AC97C_CMR_DMAEN | AC97C_CMR_SIZE_16;
+ word = ac97c_readl(chip, CAMR);
+ if (chip->opened <= 1)
+ word = AC97C_CMR_DMAEN | AC97C_CMR_SIZE_16;
+ else
+ word |= AC97C_CMR_DMAEN | AC97C_CMR_SIZE_16;
switch (runtime->format) {
case SNDRV_PCM_FORMAT_S16_LE:
- word |= AC97C_CMR_CEM_LITTLE;
+ if (cpu_is_at32ap7000())
+ word |= AC97C_CMR_CEM_LITTLE;
break;
case SNDRV_PCM_FORMAT_S16_BE: /* fall through */
word &= ~(AC97C_CMR_CEM_LITTLE);
@@ -438,9 +478,18 @@ 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 (!test_bit(DMA_RX_READY, &chip->flags))
- retval = atmel_ac97c_prepare_dma(chip, substream,
- DMA_FROM_DEVICE);
+ if (cpu_is_at32ap7000()) {
+ if (!test_bit(DMA_RX_READY, &chip->flags))
+ retval = atmel_ac97c_prepare_dma(chip, substream,
+ DMA_FROM_DEVICE);
+ } 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);
+ }
return retval;
}
@@ -449,7 +498,7 @@ static int
atmel_ac97c_playback_trigger(struct snd_pcm_substream *substream, int cmd)
{
struct atmel_ac97c *chip = snd_pcm_substream_chip(substream);
- unsigned long camr;
+ unsigned long camr, ptcr = 0;
int retval = 0;
camr = ac97c_readl(chip, CAMR);
@@ -458,15 +507,22 @@ 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:
- retval = dw_dma_cyclic_start(chip->dma.tx_chan);
- if (retval)
- goto out;
- camr |= AC97C_CMR_CENA;
+ if (cpu_is_at32ap7000()) {
+ retval = dw_dma_cyclic_start(chip->dma.tx_chan);
+ if (retval)
+ goto out;
+ } else {
+ 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:
- dw_dma_cyclic_stop(chip->dma.tx_chan);
+ if (cpu_is_at32ap7000())
+ dw_dma_cyclic_stop(chip->dma.tx_chan);
+ else
+ ptcr |= ATMEL_PDC_TXTDIS;
if (chip->opened <= 1)
camr &= ~AC97C_CMR_CENA;
break;
@@ -476,6 +532,8 @@ atmel_ac97c_playback_trigger(struct snd_pcm_substream *substream, int cmd)
}
ac97c_writel(chip, CAMR, camr);
+ if (!cpu_is_at32ap7000())
+ writel(ptcr, chip->regs + ATMEL_PDC_PTCR);
out:
return retval;
}
@@ -484,24 +542,32 @@ static int
atmel_ac97c_capture_trigger(struct snd_pcm_substream *substream, int cmd)
{
struct atmel_ac97c *chip = snd_pcm_substream_chip(substream);
- unsigned long camr;
+ unsigned long camr, ptcr = 0;
int retval = 0;
camr = ac97c_readl(chip, CAMR);
+ ptcr = readl(chip->regs + ATMEL_PDC_PTSR);
switch (cmd) {
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: /* fall through */
case SNDRV_PCM_TRIGGER_RESUME: /* fall through */
case SNDRV_PCM_TRIGGER_START:
- retval = dw_dma_cyclic_start(chip->dma.rx_chan);
- if (retval)
- goto out;
- camr |= AC97C_CMR_CENA;
+ if (cpu_is_at32ap7000()) {
+ retval = dw_dma_cyclic_start(chip->dma.rx_chan);
+ if (retval)
+ goto out;
+ } else {
+ 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:
- dw_dma_cyclic_stop(chip->dma.rx_chan);
+ if (cpu_is_at32ap7000())
+ dw_dma_cyclic_stop(chip->dma.rx_chan);
+ else
+ ptcr |= (ATMEL_PDC_RXTDIS);
if (chip->opened <= 1)
camr &= ~AC97C_CMR_CENA;
break;
@@ -511,6 +577,8 @@ atmel_ac97c_capture_trigger(struct snd_pcm_substream *substream, int cmd)
}
ac97c_writel(chip, CAMR, camr);
+ if (!cpu_is_at32ap7000())
+ writel(ptcr, chip->regs + ATMEL_PDC_PTCR);
out:
return retval;
}
@@ -523,7 +591,10 @@ atmel_ac97c_playback_pointer(struct snd_pcm_substream *substream)
snd_pcm_uframes_t frames;
unsigned long bytes;
- bytes = dw_dma_get_src_addr(chip->dma.tx_chan);
+ if (cpu_is_at32ap7000())
+ bytes = dw_dma_get_src_addr(chip->dma.tx_chan);
+ else
+ bytes = readl(chip->regs + ATMEL_PDC_TPR);
bytes -= runtime->dma_addr;
frames = bytes_to_frames(runtime, bytes);
@@ -540,7 +611,10 @@ atmel_ac97c_capture_pointer(struct snd_pcm_substream *substream)
snd_pcm_uframes_t frames;
unsigned long bytes;
- bytes = dw_dma_get_dst_addr(chip->dma.rx_chan);
+ if (cpu_is_at32ap7000())
+ bytes = dw_dma_get_dst_addr(chip->dma.rx_chan);
+ else
+ bytes = readl(chip->regs + ATMEL_PDC_RPR);
bytes -= runtime->dma_addr;
frames = bytes_to_frames(runtime, bytes);
@@ -578,8 +652,11 @@ static irqreturn_t atmel_ac97c_interrupt(int irq, void *dev)
u32 sr = ac97c_readl(chip, SR);
u32 casr = ac97c_readl(chip, CASR);
u32 cosr = ac97c_readl(chip, COSR);
+ u32 camr = ac97c_readl(chip, CAMR);
if (sr & AC97C_SR_CAEVT) {
+ struct snd_pcm_runtime *runtime;
+ int offset, next_period, block_size;
dev_info(&chip->pdev->dev, "channel A event%s%s%s%s%s%s\n",
casr & AC97C_CSR_OVRUN ? " OVRUN" : "",
casr & AC97C_CSR_RXRDY ? " RXRDY" : "",
@@ -587,6 +664,50 @@ 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);
+ }
+ }
retval = IRQ_HANDLED;
}
@@ -608,15 +729,50 @@ static irqreturn_t atmel_ac97c_interrupt(int irq, void *dev)
return retval;
}
+static struct ac97_pcm at91_ac97_pcm_defs[] __devinitdata = {
+ /* Playback */
+ {
+ .exclusive = 1,
+ .r = { {
+ .slots = ((1 << AC97_SLOT_PCM_LEFT)
+ | (1 << AC97_SLOT_PCM_RIGHT)),
+ } },
+ },
+ /* PCM in */
+ {
+ .stream = 1,
+ .exclusive = 1,
+ .r = { {
+ .slots = ((1 << AC97_SLOT_PCM_LEFT)
+ | (1 << AC97_SLOT_PCM_RIGHT)),
+ } }
+ },
+ /* Mic in */
+ {
+ .stream = 1,
+ .exclusive = 1,
+ .r = { {
+ .slots = (1<<AC97_SLOT_MIC),
+ } }
+ },
+};
+
static int __devinit atmel_ac97c_pcm_new(struct atmel_ac97c *chip)
{
struct snd_pcm *pcm;
struct snd_pcm_hardware hw = atmel_ac97c_hw;
- int capture, playback, retval;
+ int capture, playback, retval, err;
capture = test_bit(DMA_RX_CHAN_PRESENT, &chip->flags);
playback = test_bit(DMA_TX_CHAN_PRESENT, &chip->flags);
+ 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,
chip->pdev->id, playback, capture, &pcm);
if (retval)
@@ -775,7 +931,12 @@ static int __devinit atmel_ac97c_probe(struct platform_device *pdev)
return -ENXIO;
}
- pclk = clk_get(&pdev->dev, "pclk");
+ if (cpu_is_at32ap7000()) {
+ pclk = clk_get(&pdev->dev, "pclk");
+ } else {
+ pclk = clk_get(&pdev->dev, "ac97_clk");
+ }
+
if (IS_ERR(pclk)) {
dev_dbg(&pdev->dev, "no peripheral clock\n");
return PTR_ERR(pclk);
@@ -844,43 +1005,52 @@ static int __devinit atmel_ac97c_probe(struct platform_device *pdev)
goto err_ac97_bus;
}
- if (pdata->rx_dws.dma_dev) {
- struct dw_dma_slave *dws = &pdata->rx_dws;
- dma_cap_mask_t mask;
+ if (cpu_is_at32ap7000()) {
+ if (pdata->rx_dws.dma_dev) {
+ struct dw_dma_slave *dws = &pdata->rx_dws;
+ dma_cap_mask_t mask;
- dws->rx_reg = regs->start + AC97C_CARHR + 2;
+ dws->rx_reg = regs->start + AC97C_CARHR + 2;
- dma_cap_zero(mask);
- dma_cap_set(DMA_SLAVE, mask);
+ dma_cap_zero(mask);
+ dma_cap_set(DMA_SLAVE, mask);
- chip->dma.rx_chan = dma_request_channel(mask, filter, dws);
+ chip->dma.rx_chan = dma_request_channel(mask, filter,
+ dws);
- dev_info(&chip->pdev->dev, "using %s for DMA RX\n",
+ 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);
- }
+ set_bit(DMA_RX_CHAN_PRESENT, &chip->flags);
+ }
- if (pdata->tx_dws.dma_dev) {
- struct dw_dma_slave *dws = &pdata->tx_dws;
- dma_cap_mask_t mask;
+ if (pdata->tx_dws.dma_dev) {
+ struct dw_dma_slave *dws = &pdata->tx_dws;
+ dma_cap_mask_t mask;
- dws->tx_reg = regs->start + AC97C_CATHR + 2;
+ dws->tx_reg = regs->start + AC97C_CATHR + 2;
- dma_cap_zero(mask);
- dma_cap_set(DMA_SLAVE, mask);
+ dma_cap_zero(mask);
+ dma_cap_set(DMA_SLAVE, mask);
- chip->dma.tx_chan = dma_request_channel(mask, filter, dws);
+ chip->dma.tx_chan = dma_request_channel(mask, filter,
+ dws);
- dev_info(&chip->pdev->dev, "using %s for DMA TX\n",
+ 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);
- }
+ 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;
+ 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);
@@ -897,20 +1067,22 @@ static int __devinit atmel_ac97c_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, card);
- dev_info(&pdev->dev, "Atmel AC97 controller at 0x%p\n",
- chip->regs);
+ dev_info(&pdev->dev, "Atmel AC97 controller at 0x%p, irq = %d\n",
+ chip->regs, irq);
return 0;
err_dma:
- 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;
+ 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:
snd_card_set_dev(card, NULL);
@@ -934,10 +1106,12 @@ static int atmel_ac97c_suspend(struct platform_device *pdev, pm_message_t msg)
struct snd_card *card = platform_get_drvdata(pdev);
struct atmel_ac97c *chip = card->private_data;
- 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);
+ 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(chip->pclk);
return 0;
@@ -949,11 +1123,12 @@ static int atmel_ac97c_resume(struct platform_device *pdev)
struct atmel_ac97c *chip = card->private_data;
clk_enable(chip->pclk);
- 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);
-
+ 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;
}
#else
@@ -978,14 +1153,16 @@ static int __devexit atmel_ac97c_remove(struct platform_device *pdev)
iounmap(chip->regs);
free_irq(chip->irq, chip);
- 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;
+ 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_set_dev(card, NULL);
snd_card_free(card);
diff --git a/sound/core/control.c b/sound/core/control.c
index 439ce64f9d82..070aab490191 100644
--- a/sound/core/control.c
+++ b/sound/core/control.c
@@ -50,6 +50,10 @@ static int snd_ctl_open(struct inode *inode, struct file *file)
struct snd_ctl_file *ctl;
int err;
+ err = nonseekable_open(inode, file);
+ if (err < 0)
+ return err;
+
card = snd_lookup_minor_data(iminor(inode), SNDRV_DEVICE_TYPE_CONTROL);
if (!card) {
err = -ENODEV;
@@ -1388,6 +1392,7 @@ static const struct file_operations snd_ctl_f_ops =
.read = snd_ctl_read,
.open = snd_ctl_open,
.release = snd_ctl_release,
+ .llseek = no_llseek,
.poll = snd_ctl_poll,
.unlocked_ioctl = snd_ctl_ioctl,
.compat_ioctl = snd_ctl_ioctl_compat,
diff --git a/sound/core/info.c b/sound/core/info.c
index cc4a53d4b7f8..b70564ed8b37 100644
--- a/sound/core/info.c
+++ b/sound/core/info.c
@@ -164,40 +164,44 @@ static loff_t snd_info_entry_llseek(struct file *file, loff_t offset, int orig)
{
struct snd_info_private_data *data;
struct snd_info_entry *entry;
- loff_t ret;
+ loff_t ret = -EINVAL, size;
data = file->private_data;
entry = data->entry;
- lock_kernel();
- switch (entry->content) {
- case SNDRV_INFO_CONTENT_TEXT:
- switch (orig) {
- case SEEK_SET:
- file->f_pos = offset;
- ret = file->f_pos;
- goto out;
- case SEEK_CUR:
- file->f_pos += offset;
- ret = file->f_pos;
- goto out;
- case SEEK_END:
- default:
- ret = -EINVAL;
- goto out;
- }
+ mutex_lock(&entry->access);
+ if (entry->content == SNDRV_INFO_CONTENT_DATA &&
+ entry->c.ops->llseek) {
+ offset = entry->c.ops->llseek(entry,
+ data->file_private_data,
+ file, offset, orig);
+ goto out;
+ }
+ if (entry->content == SNDRV_INFO_CONTENT_DATA)
+ size = entry->size;
+ else
+ size = 0;
+ switch (orig) {
+ case SEEK_SET:
break;
- case SNDRV_INFO_CONTENT_DATA:
- if (entry->c.ops->llseek) {
- ret = entry->c.ops->llseek(entry,
- data->file_private_data,
- file, offset, orig);
+ case SEEK_CUR:
+ offset += file->f_pos;
+ break;
+ case SEEK_END:
+ if (!size)
goto out;
- }
+ offset += size;
break;
- }
- ret = -ENXIO;
-out:
- unlock_kernel();
+ default:
+ goto out;
+ }
+ if (offset < 0)
+ goto out;
+ if (size && offset > size)
+ offset = size;
+ file->f_pos = offset;
+ ret = offset;
+ out:
+ mutex_unlock(&entry->access);
return ret;
}
@@ -232,10 +236,15 @@ static ssize_t snd_info_entry_read(struct file *file, char __user *buffer,
return -EFAULT;
break;
case SNDRV_INFO_CONTENT_DATA:
- if (entry->c.ops->read)
+ if (pos >= entry->size)
+ return 0;
+ if (entry->c.ops->read) {
+ size = entry->size - pos;
+ size = min(count, size);
size = entry->c.ops->read(entry,
data->file_private_data,
- file, buffer, count, pos);
+ file, buffer, size, pos);
+ }
break;
}
if ((ssize_t) size > 0)
@@ -282,10 +291,13 @@ static ssize_t snd_info_entry_write(struct file *file, const char __user *buffer
size = count;
break;
case SNDRV_INFO_CONTENT_DATA:
- if (entry->c.ops->write)
+ if (entry->c.ops->write && count > 0) {
+ size_t maxsize = entry->size - pos;
+ count = min(count, maxsize);
size = entry->c.ops->write(entry,
data->file_private_data,
file, buffer, count, pos);
+ }
break;
}
if ((ssize_t) size > 0)
diff --git a/sound/core/oss/mixer_oss.c b/sound/core/oss/mixer_oss.c
index 54e2eb56e4c2..f50ebf20df96 100644
--- a/sound/core/oss/mixer_oss.c
+++ b/sound/core/oss/mixer_oss.c
@@ -43,6 +43,10 @@ static int snd_mixer_oss_open(struct inode *inode, struct file *file)
struct snd_mixer_oss_file *fmixer;
int err;
+ err = nonseekable_open(inode, file);
+ if (err < 0)
+ return err;
+
card = snd_lookup_oss_minor_data(iminor(inode),
SNDRV_OSS_DEVICE_TYPE_MIXER);
if (card == NULL)
@@ -397,6 +401,7 @@ static const struct file_operations snd_mixer_oss_f_ops =
.owner = THIS_MODULE,
.open = snd_mixer_oss_open,
.release = snd_mixer_oss_release,
+ .llseek = no_llseek,
.unlocked_ioctl = snd_mixer_oss_ioctl,
.compat_ioctl = snd_mixer_oss_ioctl_compat,
};
diff --git a/sound/core/oss/pcm_oss.c b/sound/core/oss/pcm_oss.c
index 82d4e3329b3d..5c8c7dff8ede 100644
--- a/sound/core/oss/pcm_oss.c
+++ b/sound/core/oss/pcm_oss.c
@@ -2379,6 +2379,10 @@ static int snd_pcm_oss_open(struct inode *inode, struct file *file)
int nonblock;
wait_queue_t wait;
+ err = nonseekable_open(inode, file);
+ if (err < 0)
+ return err;
+
pcm = snd_lookup_oss_minor_data(iminor(inode),
SNDRV_OSS_DEVICE_TYPE_PCM);
if (pcm == NULL) {
@@ -2977,6 +2981,7 @@ static const struct file_operations snd_pcm_oss_f_reg =
.write = snd_pcm_oss_write,
.open = snd_pcm_oss_open,
.release = snd_pcm_oss_release,
+ .llseek = no_llseek,
.poll = snd_pcm_oss_poll,
.unlocked_ioctl = snd_pcm_oss_ioctl,
.compat_ioctl = snd_pcm_oss_ioctl_compat,
diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c
index 20b5982c996b..b9517f38073c 100644
--- a/sound/core/pcm_native.c
+++ b/sound/core/pcm_native.c
@@ -2110,7 +2110,9 @@ static int snd_pcm_open_file(struct file *file,
static int snd_pcm_playback_open(struct inode *inode, struct file *file)
{
struct snd_pcm *pcm;
-
+ int err = nonseekable_open(inode, file);
+ if (err < 0)
+ return err;
pcm = snd_lookup_minor_data(iminor(inode),
SNDRV_DEVICE_TYPE_PCM_PLAYBACK);
return snd_pcm_open(file, pcm, SNDRV_PCM_STREAM_PLAYBACK);
@@ -2119,7 +2121,9 @@ static int snd_pcm_playback_open(struct inode *inode, struct file *file)
static int snd_pcm_capture_open(struct inode *inode, struct file *file)
{
struct snd_pcm *pcm;
-
+ int err = nonseekable_open(inode, file);
+ if (err < 0)
+ return err;
pcm = snd_lookup_minor_data(iminor(inode),
SNDRV_DEVICE_TYPE_PCM_CAPTURE);
return snd_pcm_open(file, pcm, SNDRV_PCM_STREAM_CAPTURE);
@@ -3310,18 +3314,13 @@ static int snd_pcm_fasync(int fd, struct file * file, int on)
struct snd_pcm_file * pcm_file;
struct snd_pcm_substream *substream;
struct snd_pcm_runtime *runtime;
- int err = -ENXIO;
- lock_kernel();
pcm_file = file->private_data;
substream = pcm_file->substream;
if (PCM_RUNTIME_CHECK(substream))
- goto out;
+ return -ENXIO;
runtime = substream->runtime;
- err = fasync_helper(fd, file, on, &runtime->fasync);
-out:
- unlock_kernel();
- return err;
+ return fasync_helper(fd, file, on, &runtime->fasync);
}
/*
@@ -3462,6 +3461,7 @@ const struct file_operations snd_pcm_f_ops[2] = {
.aio_write = snd_pcm_aio_write,
.open = snd_pcm_playback_open,
.release = snd_pcm_release,
+ .llseek = no_llseek,
.poll = snd_pcm_playback_poll,
.unlocked_ioctl = snd_pcm_playback_ioctl,
.compat_ioctl = snd_pcm_ioctl_compat,
@@ -3475,6 +3475,7 @@ const struct file_operations snd_pcm_f_ops[2] = {
.aio_read = snd_pcm_aio_read,
.open = snd_pcm_capture_open,
.release = snd_pcm_release,
+ .llseek = no_llseek,
.poll = snd_pcm_capture_poll,
.unlocked_ioctl = snd_pcm_capture_ioctl,
.compat_ioctl = snd_pcm_ioctl_compat,
diff --git a/sound/core/rawmidi.c b/sound/core/rawmidi.c
index 0f5a194695d9..eb68326c37d4 100644
--- a/sound/core/rawmidi.c
+++ b/sound/core/rawmidi.c
@@ -376,6 +376,10 @@ static int snd_rawmidi_open(struct inode *inode, struct file *file)
if ((file->f_flags & O_APPEND) && !(file->f_flags & O_NONBLOCK))
return -EINVAL; /* invalid combination */
+ err = nonseekable_open(inode, file);
+ if (err < 0)
+ return err;
+
if (maj == snd_major) {
rmidi = snd_lookup_minor_data(iminor(inode),
SNDRV_DEVICE_TYPE_RAWMIDI);
@@ -1391,6 +1395,7 @@ static const struct file_operations snd_rawmidi_f_ops =