mirror of
https://github.com/S3NEO/android_kernel_samsung_msm8226.git
synced 2024-11-07 03:47:13 +00:00
Merge branch 'topic/core-cleanup' into for-linus
This commit is contained in:
commit
3374cd1abd
26 changed files with 831 additions and 494 deletions
|
@ -5518,34 +5518,41 @@ struct _snd_pcm_runtime {
|
|||
]]>
|
||||
</programlisting>
|
||||
</informalexample>
|
||||
|
||||
For the raw data, <structfield>size</structfield> field must be
|
||||
set properly. This specifies the maximum size of the proc file access.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
The callback is much more complicated than the text-file
|
||||
version. You need to use a low-level I/O functions such as
|
||||
The read/write callbacks of raw mode are more direct than the text mode.
|
||||
You need to use a low-level I/O functions such as
|
||||
<function>copy_from/to_user()</function> to transfer the
|
||||
data.
|
||||
|
||||
<informalexample>
|
||||
<programlisting>
|
||||
<![CDATA[
|
||||
static long my_file_io_read(struct snd_info_entry *entry,
|
||||
static ssize_t my_file_io_read(struct snd_info_entry *entry,
|
||||
void *file_private_data,
|
||||
struct file *file,
|
||||
char *buf,
|
||||
unsigned long count,
|
||||
unsigned long pos)
|
||||
size_t count,
|
||||
loff_t pos)
|
||||
{
|
||||
long size = count;
|
||||
if (pos + size > local_max_size)
|
||||
size = local_max_size - pos;
|
||||
if (copy_to_user(buf, local_data + pos, size))
|
||||
if (copy_to_user(buf, local_data + pos, count))
|
||||
return -EFAULT;
|
||||
return size;
|
||||
return count;
|
||||
}
|
||||
]]>
|
||||
</programlisting>
|
||||
</informalexample>
|
||||
|
||||
If the size of the info entry has been set up properly,
|
||||
<structfield>count</structfield> and <structfield>pos</structfield> are
|
||||
guaranteed to fit within 0 and the given size.
|
||||
You don't have to check the range in the callbacks unless any
|
||||
other condition is required.
|
||||
|
||||
</para>
|
||||
|
||||
</chapter>
|
||||
|
|
|
@ -51,18 +51,18 @@ struct snd_info_entry_ops {
|
|||
unsigned short mode, void **file_private_data);
|
||||
int (*release)(struct snd_info_entry *entry,
|
||||
unsigned short mode, void *file_private_data);
|
||||
long (*read)(struct snd_info_entry *entry, void *file_private_data,
|
||||
struct file *file, char __user *buf,
|
||||
unsigned long count, unsigned long pos);
|
||||
long (*write)(struct snd_info_entry *entry, void *file_private_data,
|
||||
struct file *file, const char __user *buf,
|
||||
unsigned long count, unsigned long pos);
|
||||
long long (*llseek)(struct snd_info_entry *entry,
|
||||
void *file_private_data, struct file *file,
|
||||
long long offset, int orig);
|
||||
unsigned int(*poll)(struct snd_info_entry *entry,
|
||||
void *file_private_data, struct file *file,
|
||||
poll_table *wait);
|
||||
ssize_t (*read)(struct snd_info_entry *entry, void *file_private_data,
|
||||
struct file *file, char __user *buf,
|
||||
size_t count, loff_t pos);
|
||||
ssize_t (*write)(struct snd_info_entry *entry, void *file_private_data,
|
||||
struct file *file, const char __user *buf,
|
||||
size_t count, loff_t pos);
|
||||
loff_t (*llseek)(struct snd_info_entry *entry,
|
||||
void *file_private_data, struct file *file,
|
||||
loff_t offset, int orig);
|
||||
unsigned int (*poll)(struct snd_info_entry *entry,
|
||||
void *file_private_data, struct file *file,
|
||||
poll_table *wait);
|
||||
int (*ioctl)(struct snd_info_entry *entry, void *file_private_data,
|
||||
struct file *file, unsigned int cmd, unsigned long arg);
|
||||
int (*mmap)(struct snd_info_entry *entry, void *file_private_data,
|
||||
|
|
|
@ -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.
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
break;
|
||||
case SNDRV_INFO_CONTENT_DATA:
|
||||
if (entry->c.ops->llseek) {
|
||||
ret = entry->c.ops->llseek(entry,
|
||||
data->file_private_data,
|
||||
file, offset, orig);
|
||||
goto out;
|
||||
}
|
||||
break;
|
||||
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;
|
||||
}
|
||||
ret = -ENXIO;
|
||||
out:
|
||||
unlock_kernel();
|
||||
if (entry->content == SNDRV_INFO_CONTENT_DATA)
|
||||
size = entry->size;
|
||||
else
|
||||
size = 0;
|
||||
switch (orig) {
|
||||
case SEEK_SET:
|
||||
break;
|
||||
case SEEK_CUR:
|
||||
offset += file->f_pos;
|
||||
break;
|
||||
case SEEK_END:
|
||||
if (!size)
|
||||
goto out;
|
||||
offset += size;
|
||||
break;
|
||||
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)
|
||||
|
|
|
@ -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,
|
||||
};
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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 =
|
|||
.write = snd_rawmidi_write,
|
||||
.open = snd_rawmidi_open,
|
||||
.release = snd_rawmidi_release,
|
||||
.llseek = no_llseek,
|
||||
.poll = snd_rawmidi_poll,
|
||||
.unlocked_ioctl = snd_rawmidi_ioctl,
|
||||
.compat_ioctl = snd_rawmidi_ioctl_compat,
|
||||
|
|
|
@ -318,6 +318,11 @@ static int snd_seq_open(struct inode *inode, struct file *file)
|
|||
int c, mode; /* client id */
|
||||
struct snd_seq_client *client;
|
||||
struct snd_seq_user_client *user;
|
||||
int err;
|
||||
|
||||
err = nonseekable_open(inode, file);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
if (mutex_lock_interruptible(®ister_mutex))
|
||||
return -ERESTARTSYS;
|
||||
|
@ -2550,6 +2555,7 @@ static const struct file_operations snd_seq_f_ops =
|
|||
.write = snd_seq_write,
|
||||
.open = snd_seq_open,
|
||||
.release = snd_seq_release,
|
||||
.llseek = no_llseek,
|
||||
.poll = snd_seq_poll,
|
||||
.unlocked_ioctl = snd_seq_ioctl,
|
||||
.compat_ioctl = snd_seq_ioctl_compat,
|
||||
|
|
|
@ -120,7 +120,29 @@ void *snd_lookup_minor_data(unsigned int minor, int type)
|
|||
|
||||
EXPORT_SYMBOL(snd_lookup_minor_data);
|
||||
|
||||
static int __snd_open(struct inode *inode, struct file *file)
|
||||
#ifdef CONFIG_MODULES
|
||||
static struct snd_minor *autoload_device(unsigned int minor)
|
||||
{
|
||||
int dev;
|
||||
mutex_unlock(&sound_mutex); /* release lock temporarily */
|
||||
dev = SNDRV_MINOR_DEVICE(minor);
|
||||
if (dev == SNDRV_MINOR_CONTROL) {
|
||||
/* /dev/aloadC? */
|
||||
int card = SNDRV_MINOR_CARD(minor);
|
||||
if (snd_cards[card] == NULL)
|
||||
snd_request_card(card);
|
||||
} else if (dev == SNDRV_MINOR_GLOBAL) {
|
||||
/* /dev/aloadSEQ */
|
||||
snd_request_other(minor);
|
||||
}
|
||||
mutex_lock(&sound_mutex); /* reacuire lock */
|
||||
return snd_minors[minor];
|
||||
}
|
||||
#else /* !CONFIG_MODULES */
|
||||
#define autoload_device(minor) NULL
|
||||
#endif /* CONFIG_MODULES */
|
||||
|
||||
static int snd_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
unsigned int minor = iminor(inode);
|
||||
struct snd_minor *mptr = NULL;
|
||||
|
@ -129,55 +151,36 @@ static int __snd_open(struct inode *inode, struct file *file)
|
|||
|
||||
if (minor >= ARRAY_SIZE(snd_minors))
|
||||
return -ENODEV;
|
||||
mutex_lock(&sound_mutex);
|
||||
mptr = snd_minors[minor];
|
||||
if (mptr == NULL) {
|
||||
#ifdef CONFIG_MODULES
|
||||
int dev = SNDRV_MINOR_DEVICE(minor);
|
||||
if (dev == SNDRV_MINOR_CONTROL) {
|
||||
/* /dev/aloadC? */
|
||||
int card = SNDRV_MINOR_CARD(minor);
|
||||
if (snd_cards[card] == NULL)
|
||||
snd_request_card(card);
|
||||
} else if (dev == SNDRV_MINOR_GLOBAL) {
|
||||
/* /dev/aloadSEQ */
|
||||
snd_request_other(minor);
|
||||
}
|
||||
#ifndef CONFIG_SND_DYNAMIC_MINORS
|
||||
/* /dev/snd/{controlC?,seq} */
|
||||
mptr = snd_minors[minor];
|
||||
if (mptr == NULL)
|
||||
#endif
|
||||
#endif
|
||||
mptr = autoload_device(minor);
|
||||
if (!mptr) {
|
||||
mutex_unlock(&sound_mutex);
|
||||
return -ENODEV;
|
||||
}
|
||||
}
|
||||
old_fops = file->f_op;
|
||||
file->f_op = fops_get(mptr->f_ops);
|
||||
if (file->f_op == NULL) {
|
||||
file->f_op = old_fops;
|
||||
return -ENODEV;
|
||||
err = -ENODEV;
|
||||
}
|
||||
if (file->f_op->open)
|
||||
mutex_unlock(&sound_mutex);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
if (file->f_op->open) {
|
||||
err = file->f_op->open(inode, file);
|
||||
if (err) {
|
||||
fops_put(file->f_op);
|
||||
file->f_op = fops_get(old_fops);
|
||||
if (err) {
|
||||
fops_put(file->f_op);
|
||||
file->f_op = fops_get(old_fops);
|
||||
}
|
||||
}
|
||||
fops_put(old_fops);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
/* BKL pushdown: nasty #ifdef avoidance wrapper */
|
||||
static int snd_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
int ret;
|
||||
|
||||
lock_kernel();
|
||||
ret = __snd_open(inode, file);
|
||||
unlock_kernel();
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct file_operations snd_fops =
|
||||
{
|
||||
.owner = THIS_MODULE,
|
||||
|
|
|
@ -1238,6 +1238,11 @@ static void snd_timer_user_tinterrupt(struct snd_timer_instance *timeri,
|
|||
static int snd_timer_user_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
struct snd_timer_user *tu;
|
||||
int err;
|
||||
|
||||
err = nonseekable_open(inode, file);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
tu = kzalloc(sizeof(*tu), GFP_KERNEL);
|
||||
if (tu == NULL)
|
||||
|
@ -1922,6 +1927,7 @@ static const struct file_operations snd_timer_f_ops =
|
|||
.read = snd_timer_user_read,
|
||||
.open = snd_timer_user_open,
|
||||
.release = snd_timer_user_release,
|
||||
.llseek = no_llseek,
|
||||
.poll = snd_timer_user_poll,
|
||||
.unlocked_ioctl = snd_timer_user_ioctl,
|
||||
.compat_ioctl = snd_timer_user_ioctl_compat,
|
||||
|
|
|
@ -49,77 +49,45 @@ static int snd_opl4_mem_proc_release(struct snd_info_entry *entry,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static long snd_opl4_mem_proc_read(struct snd_info_entry *entry, void *file_private_data,
|
||||
struct file *file, char __user *_buf,
|
||||
unsigned long count, unsigned long pos)
|
||||
static ssize_t snd_opl4_mem_proc_read(struct snd_info_entry *entry,
|
||||
void *file_private_data,
|
||||
struct file *file, char __user *_buf,
|
||||
size_t count, loff_t pos)
|
||||
{
|
||||
struct snd_opl4 *opl4 = entry->private_data;
|
||||
long size;
|
||||
char* buf;
|
||||
|
||||
size = count;
|
||||
if (pos + size > entry->size)
|
||||
size = entry->size - pos;
|
||||
if (size > 0) {
|
||||
buf = vmalloc(size);
|
||||
if (!buf)
|
||||
return -ENOMEM;
|
||||
snd_opl4_read_memory(opl4, buf, pos, size);
|
||||
if (copy_to_user(_buf, buf, size)) {
|
||||
vfree(buf);
|
||||
return -EFAULT;
|
||||
}
|
||||
buf = vmalloc(count);
|
||||
if (!buf)
|
||||
return -ENOMEM;
|
||||
snd_opl4_read_memory(opl4, buf, pos, count);
|
||||
if (copy_to_user(_buf, buf, count)) {
|
||||
vfree(buf);
|
||||
return size;
|
||||
return -EFAULT;
|
||||
}
|
||||
return 0;
|
||||
vfree(buf);
|
||||
return count;
|
||||
}
|
||||
|
||||
static long snd_opl4_mem_proc_write(struct snd_info_entry *entry, void *file_private_data,
|
||||
struct file *file, const char __user *_buf,
|
||||
unsigned long count, unsigned long pos)
|
||||
static ssize_t snd_opl4_mem_proc_write(struct snd_info_entry *entry,
|
||||
void *file_private_data,
|
||||
struct file *file,
|
||||
const char __user *_buf,
|
||||
size_t count, loff_t pos)
|
||||
{
|
||||
struct snd_opl4 *opl4 = entry->private_data;
|
||||
long size;
|
||||
char *buf;
|
||||
|
||||
size = count;
|
||||
if (pos + size > entry->size)
|
||||
size = entry->size - pos;
|
||||
if (size > 0) {
|
||||
buf = vmalloc(size);
|
||||
if (!buf)
|
||||
return -ENOMEM;
|
||||
if (copy_from_user(buf, _buf, size)) {
|
||||
vfree(buf);
|
||||
return -EFAULT;
|
||||
}
|
||||
snd_opl4_write_memory(opl4, buf, pos, size);
|
||||
buf = vmalloc(count);
|
||||
if (!buf)
|
||||
return -ENOMEM;
|
||||
if (copy_from_user(buf, _buf, count)) {
|
||||
vfree(buf);
|
||||
return size;
|
||||
return -EFAULT;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static long long snd_opl4_mem_proc_llseek(struct snd_info_entry *entry, void *file_private_data,
|
||||
struct file *file, long long offset, int orig)
|
||||
{
|
||||
switch (orig) {
|
||||
case SEEK_SET:
|
||||
file->f_pos = offset;
|
||||
break;
|
||||
case SEEK_CUR:
|
||||
file->f_pos += offset;
|
||||
break;
|
||||
case SEEK_END: /* offset is negative */
|
||||
file->f_pos = entry->size + offset;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
if (file->f_pos > entry->size)
|
||||
file->f_pos = entry->size;
|
||||
return file->f_pos;
|
||||
snd_opl4_write_memory(opl4, buf, pos, count);
|
||||
vfree(buf);
|
||||
return count;
|
||||
}
|
||||
|
||||
static struct snd_info_entry_ops snd_opl4_mem_proc_ops = {
|
||||
|
@ -127,7 +95,6 @@ static struct snd_info_entry_ops snd_opl4_mem_proc_ops = {
|
|||
.release = snd_opl4_mem_proc_release,
|
||||
.read = snd_opl4_mem_proc_read,
|
||||
.write = snd_opl4_mem_proc_write,
|
||||
.llseek = snd_opl4_mem_proc_llseek,
|
||||
};
|
||||
|
||||
int snd_opl4_create_proc(struct snd_opl4 *opl4)
|
||||
|
|
|
@ -31,52 +31,21 @@ struct gus_proc_private {
|
|||
struct snd_gus_card * gus;
|
||||
};
|
||||
|
||||
static long snd_gf1_mem_proc_dump(struct snd_info_entry *entry, void *file_private_data,
|
||||
struct file *file, char __user *buf,
|
||||
unsigned long count, unsigned long pos)
|
||||
static ssize_t snd_gf1_mem_proc_dump(struct snd_info_entry *entry,
|
||||
void *file_private_data,
|
||||
struct file *file, char __user *buf,
|
||||
size_t count, loff_t pos)
|
||||
{
|
||||
long size;
|
||||
struct gus_proc_private *priv = entry->private_data;
|
||||
struct snd_gus_card *gus = priv->gus;
|
||||
int err;
|
||||
|
||||
size = count;
|
||||
if (pos + size > priv->size)
|
||||
size = (long)priv->size - pos;
|
||||
if (size > 0) {
|
||||
if ((err = snd_gus_dram_read(gus, buf, pos, size, priv->rom)) < 0)
|
||||
return err;
|
||||
return size;
|
||||
}
|
||||
return 0;
|
||||
err = snd_gus_dram_read(gus, buf, pos, count, priv->rom);
|
||||
if (err < 0)
|
||||
return err;
|
||||
return count;
|
||||
}
|
||||
|
||||
static long long snd_gf1_mem_proc_llseek(struct snd_info_entry *entry,
|
||||
void *private_file_data,
|
||||
struct file *file,
|
||||
long long offset,
|
||||
int orig)
|
||||
{
|
||||
struct gus_proc_private *priv = entry->private_data;
|
||||
|
||||
switch (orig) {
|
||||
case SEEK_SET:
|
||||
file->f_pos = offset;
|
||||
break;
|
||||
case SEEK_CUR:
|
||||
file->f_pos += offset;
|
||||
break;
|
||||
case SEEK_END: /* offset is negative */
|
||||
file->f_pos = priv->size + offset;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
if (file->f_pos > priv->size)
|
||||
file->f_pos = priv->size;
|
||||
return file->f_pos;
|
||||
}
|
||||
|
||||
static void snd_gf1_mem_proc_free(struct snd_info_entry *entry)
|
||||
{
|
||||
struct gus_proc_private *priv = entry->private_data;
|
||||
|
@ -85,7 +54,6 @@ static void snd_gf1_mem_proc_free(struct snd_info_entry *entry)
|
|||
|
||||
static struct snd_info_entry_ops snd_gf1_mem_proc_ops = {
|
||||
.read = snd_gf1_mem_proc_dump,
|
||||
.llseek = snd_gf1_mem_proc_llseek,
|
||||
};
|
||||
|
||||
int snd_gf1_mem_proc_init(struct snd_gus_card * gus)
|
||||
|
|
|
@ -1139,40 +1139,28 @@ static void snd_cs4281_proc_read(struct snd_info_entry *entry,
|
|||
snd_iprintf(buffer, "Spurious end IRQs : %u\n", chip->spurious_dtc_irq);
|
||||
}
|
||||
|
||||
static long snd_cs4281_BA0_read(struct snd_info_entry *entry,
|
||||
void *file_private_data,
|
||||
struct file *file, char __user *buf,
|
||||
unsigned long count, unsigned long pos)
|
||||
static ssize_t snd_cs4281_BA0_read(struct snd_info_entry *entry,
|
||||
void *file_private_data,
|
||||
struct file *file, char __user *buf,
|
||||
size_t count, loff_t pos)
|
||||
{
|
||||
long size;
|
||||
struct cs4281 *chip = entry->private_data;
|
||||
|
||||
size = count;
|
||||
if (pos + size > CS4281_BA0_SIZE)
|
||||
size = (long)CS4281_BA0_SIZE - pos;
|
||||
if (size > 0) {
|
||||
if (copy_to_user_fromio(buf, chip->ba0 + pos, size))
|
||||
return -EFAULT;
|
||||
}
|
||||
return size;
|
||||
if (copy_to_user_fromio(buf, chip->ba0 + pos, count))
|
||||
return -EFAULT;
|
||||
return count;
|
||||
}
|
||||
|
||||
static long snd_cs4281_BA1_read(struct snd_info_entry *entry,
|
||||
void *file_private_data,
|
||||
struct file *file, char __user *buf,
|
||||
unsigned long count, unsigned long pos)
|
||||
static ssize_t snd_cs4281_BA1_read(struct snd_info_entry *entry,
|
||||
void *file_private_data,
|
||||
struct file *file, char __user *buf,
|
||||
size_t count, loff_t pos)
|
||||
{
|
||||
long size;
|
||||
struct cs4281 *chip = entry->private_data;
|
||||
|
||||
size = count;
|
||||
if (pos + size > CS4281_BA1_SIZE)
|
||||
size = (long)CS4281_BA1_SIZE - pos;
|
||||
if (size > 0) {
|
||||
if (copy_to_user_fromio(buf, chip->ba1 + pos, size))
|
||||
return -EFAULT;
|
||||
}
|
||||
return size;
|
||||
if (copy_to_user_fromio(buf, chip->ba1 + pos, count))
|
||||
return -EFAULT;
|
||||
return count;
|
||||
}
|
||||
|
||||
static struct snd_info_entry_ops snd_cs4281_proc_ops_BA0 = {
|
||||
|
|
|
@ -2657,21 +2657,16 @@ static inline void snd_cs46xx_remove_gameport(struct snd_cs46xx *chip) { }
|
|||
* proc interface
|
||||
*/
|
||||
|
||||
static long snd_cs46xx_io_read(struct snd_info_entry *entry, void *file_private_data,
|
||||
struct file *file, char __user *buf,
|
||||
unsigned long count, unsigned long pos)
|
||||
static ssize_t snd_cs46xx_io_read(struct snd_info_entry *entry,
|
||||
void *file_private_data,
|
||||
struct file *file, char __user *buf,
|
||||
size_t count, loff_t pos)
|
||||
{
|
||||
long size;
|
||||
struct snd_cs46xx_region *region = entry->private_data;
|
||||
|
||||
size = count;
|
||||
if (pos + (size_t)size > region->size)
|
||||
size = region->size - pos;
|
||||
if (size > 0) {
|
||||
if (copy_to_user_fromio(buf, region->remap_addr + pos, size))
|
||||
return -EFAULT;
|
||||
}
|
||||
return size;
|
||||
if (copy_to_user_fromio(buf, region->remap_addr + pos, count))
|
||||
return -EFAULT;
|
||||
return count;
|
||||
}
|
||||
|
||||
static struct snd_info_entry_ops snd_cs46xx_proc_io_ops = {
|
||||
|
|
|
@ -341,15 +341,17 @@ static void snd_emu10k1_proc_acode_read(struct snd_info_entry *entry,
|
|||
#define TOTAL_SIZE_CODE (0x200*8)
|
||||
#define A_TOTAL_SIZE_CODE (0x400*8)
|
||||
|
||||
static long snd_emu10k1_fx8010_read(struct snd_info_entry *entry,
|
||||
void *file_private_data,
|
||||
struct file *file, char __user *buf,
|
||||
unsigned long count, unsigned long pos)
|
||||
static ssize_t snd_emu10k1_fx8010_read(struct snd_info_entry *entry,
|
||||
void *file_private_data,
|
||||
struct file *file, char __user *buf,
|
||||
size_t count, loff_t pos)
|
||||
{
|
||||
long size;
|
||||
struct snd_emu10k1 *emu = entry->private_data;
|
||||
unsigned int offset;
|
||||
int tram_addr = 0;
|
||||
unsigned int *tmp;
|
||||
long res;
|
||||
unsigned int idx;
|
||||
|
||||
if (!strcmp(entry->name, "fx8010_tram_addr")) {
|
||||
offset = TANKMEMADDRREGBASE;
|
||||
|
@ -361,30 +363,25 @@ static long snd_emu10k1_fx8010_read(struct snd_info_entry *entry,
|
|||
} else {
|
||||
offset = emu->audigy ? A_FXGPREGBASE : FXGPREGBASE;
|
||||
}
|
||||
size = count;
|
||||
if (pos + size > entry->size)
|
||||
size = (long)entry->size - pos;
|
||||
if (size > 0) {
|
||||
unsigned int *tmp;
|
||||
long res;
|
||||
unsigned int idx;
|
||||
if ((tmp = kmalloc(size + 8, GFP_KERNEL)) == NULL)
|
||||
return -ENOMEM;
|
||||
for (idx = 0; idx < ((pos & 3) + size + 3) >> 2; idx++)
|
||||
if (tram_addr && emu->audigy) {
|
||||
tmp[idx] = snd_emu10k1_ptr_read(emu, offset + idx + (pos >> 2), 0) >> 11;
|
||||
tmp[idx] |= snd_emu10k1_ptr_read(emu, 0x100 + idx + (pos >> 2), 0) << 20;
|
||||
} else
|
||||
tmp[idx] = snd_emu10k1_ptr_read(emu, offset + idx + (pos >> 2), 0);
|
||||
if (copy_to_user(buf, ((char *)tmp) + (pos & 3), size))
|
||||
res = -EFAULT;
|
||||
else {
|
||||
res = size;
|
||||
|
||||
tmp = kmalloc(count + 8, GFP_KERNEL);
|
||||
if (!tmp)
|
||||
return -ENOMEM;
|
||||
for (idx = 0; idx < ((pos & 3) + count + 3) >> 2; idx++) {
|
||||
unsigned int val;
|
||||
val = snd_emu10k1_ptr_read(emu, offset + idx + (pos >> 2), 0);
|
||||
if (tram_addr && emu->audigy) {
|
||||
val >>= 11;
|
||||
val |= snd_emu10k1_ptr_read(emu, 0x100 + idx + (pos >> 2), 0) << 20;
|
||||
}
|
||||
kfree(tmp);
|
||||
return res;
|
||||
tmp[idx] = val;
|
||||
}
|
||||
return 0;
|
||||
if (copy_to_user(buf, ((char *)tmp) + (pos & 3), count))
|
||||
res = -EFAULT;
|
||||
else
|
||||
res = count;
|
||||
kfree(tmp);
|
||||
return res;
|
||||
}
|
||||
|
||||
static void snd_emu10k1_proc_voices_read(struct snd_info_entry *entry,
|
||||
|
|
|
@ -1956,11 +1956,10 @@ static int __devinit aureon_add_controls(struct snd_ice1712 *ice)
|
|||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* initialize the chip
|
||||
* reset the chip
|
||||
*/
|
||||
static int __devinit aureon_init(struct snd_ice1712 *ice)
|
||||
static int aureon_reset(struct snd_ice1712 *ice)
|
||||
{
|
||||
static const unsigned short wm_inits_aureon[] = {
|
||||
/* These come first to reduce init pop noise */
|
||||
|
@ -2047,30 +2046,10 @@ static int __devinit aureon_init(struct snd_ice1712 *ice)
|
|||
0x0605, /* slave, 24bit, MSB on second OSCLK, SDOUT for right channel when OLRCK is high */
|
||||
(unsigned short)-1
|
||||
};
|
||||
struct aureon_spec *spec;
|
||||
unsigned int tmp;
|
||||
const unsigned short *p;
|
||||
int err, i;
|
||||
|
||||
spec = kzalloc(sizeof(*spec), GFP_KERNEL);
|
||||
if (!spec)
|
||||
return -ENOMEM;
|
||||
ice->spec = spec;
|
||||
|
||||
if (ice->eeprom.subvendor == VT1724_SUBDEVICE_AUREON51_SKY) {
|
||||
ice->num_total_dacs = 6;
|
||||
ice->num_total_adcs = 2;
|
||||
} else {
|
||||
/* aureon 7.1 and prodigy 7.1 */
|
||||
ice->num_total_dacs = 8;
|
||||
ice->num_total_adcs = 2;
|
||||
}
|
||||
|
||||
/* to remeber the register values of CS8415 */
|
||||
ice->akm = kzalloc(sizeof(struct snd_akm4xxx), GFP_KERNEL);
|
||||
if (!ice->akm)
|
||||
return -ENOMEM;
|
||||
ice->akm_codecs = 1;
|
||||
int err;
|
||||
struct aureon_spec *spec = ice->spec;
|
||||
|
||||
err = aureon_ac97_init(ice);
|
||||
if (err != 0)
|
||||
|
@ -2118,6 +2097,61 @@ static int __devinit aureon_init(struct snd_ice1712 *ice)
|
|||
/* initialize PCA9554 pin directions & set default input */
|
||||
aureon_pca9554_write(ice, PCA9554_DIR, 0x00);
|
||||
aureon_pca9554_write(ice, PCA9554_OUT, 0x00); /* internal AUX */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* suspend/resume
|
||||
*/
|
||||
#ifdef CONFIG_PM
|
||||
static int aureon_resume(struct snd_ice1712 *ice)
|
||||
{
|
||||
struct aureon_spec *spec = ice->spec;
|
||||
int err, i;
|
||||
|
||||
err = aureon_reset(ice);
|
||||
if (err != 0)
|
||||
return err;
|
||||
|
||||
/* workaround for poking volume with alsamixer after resume:
|
||||
* just set stored volume again */
|
||||
for (i = 0; i < ice->num_total_dacs; i++)
|
||||
wm_set_vol(ice, i, spec->vol[i], spec->master[i % 2]);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* initialize the chip
|
||||
*/
|
||||
static int __devinit aureon_init(struct snd_ice1712 *ice)
|
||||
{
|
||||
struct aureon_spec *spec;
|
||||
int i, err;
|
||||
|
||||
spec = kzalloc(sizeof(*spec), GFP_KERNEL);
|
||||
if (!spec)
|
||||
return -ENOMEM;
|
||||
ice->spec = spec;
|
||||
|
||||
if (ice->eeprom.subvendor == VT1724_SUBDEVICE_AUREON51_SKY) {
|
||||
ice->num_total_dacs = 6;
|
||||
ice->num_total_adcs = 2;
|
||||
} else {
|
||||
/* aureon 7.1 and prodigy 7.1 */
|
||||
ice->num_total_dacs = 8;
|
||||
ice->num_total_adcs = 2;
|
||||
}
|
||||
|
||||
/* to remeber the register values of CS8415 */
|
||||
ice->akm = kzalloc(sizeof(struct snd_akm4xxx), GFP_KERNEL);
|
||||
if (!ice->akm)
|
||||
return -ENOMEM;
|
||||
ice->akm_codecs = 1;
|
||||
|
||||
err = aureon_reset(ice);
|
||||
if (err != 0)
|
||||
return err;
|
||||
|
||||
spec->master[0] = WM_VOL_MUTE;
|
||||
spec->master[1] = WM_VOL_MUTE;
|
||||
|
@ -2126,6 +2160,11 @@ static int __devinit aureon_init(struct snd_ice1712 *ice)
|
|||
wm_set_vol(ice, i, spec->vol[i], spec->master[i % 2]);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
ice->pm_resume = aureon_resume;
|
||||
ice->pm_suspend_enabled = 1;
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -1102,73 +1102,17 @@ static int snd_mixart_free(struct mixart_mgr *mgr)
|
|||
/*
|
||||
* proc interface
|
||||
*/
|
||||
static long long snd_mixart_BA0_llseek(struct snd_info_entry *entry,
|
||||
void *private_file_data,
|
||||
struct file *file,
|
||||
long long offset,
|
||||
int orig)
|
||||
{
|
||||
offset = offset & ~3; /* 4 bytes aligned */
|
||||
|
||||
switch(orig) {
|
||||
case SEEK_SET:
|
||||
file->f_pos = offset;
|
||||
break;
|
||||
case SEEK_CUR:
|
||||
file->f_pos += offset;
|
||||
break;
|
||||
case SEEK_END: /* offset is negative */
|
||||
file->f_pos = MIXART_BA0_SIZE + offset;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
if(file->f_pos > MIXART_BA0_SIZE)
|
||||
file->f_pos = MIXART_BA0_SIZE;
|
||||
return file->f_pos;
|
||||
}
|
||||
|
||||
static long long snd_mixart_BA1_llseek(struct snd_info_entry *entry,
|
||||
void *private_file_data,
|
||||
struct file *file,
|
||||
long long offset,
|
||||
int orig)
|
||||
{
|
||||
offset = offset & ~3; /* 4 bytes aligned */
|
||||
|
||||
switch(orig) {
|
||||
case SEEK_SET:
|
||||
file->f_pos = offset;
|
||||
break;
|
||||
case SEEK_CUR:
|
||||
file->f_pos += offset;
|
||||
break;
|
||||
case SEEK_END: /* offset is negative */
|
||||
file->f_pos = MIXART_BA1_SIZE + offset;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
if(file->f_pos > MIXART_BA1_SIZE)
|
||||
file->f_pos = MIXART_BA1_SIZE;
|
||||
return file->f_pos;
|
||||
}
|
||||
|
||||
/*
|
||||
mixart_BA0 proc interface for BAR 0 - read callback
|
||||
*/
|
||||
static long snd_mixart_BA0_read(struct snd_info_entry *entry, void *file_private_data,
|
||||
struct file *file, char __user *buf,
|
||||
unsigned long count, unsigned long pos)
|
||||
static ssize_t snd_mixart_BA0_read(struct snd_info_entry *entry,
|
||||
void *file_private_data,
|
||||
struct file *file, char __user *buf,
|
||||
size_t count, loff_t pos)
|
||||
{
|
||||
struct mixart_mgr *mgr = entry->private_data;
|
||||
unsigned long maxsize;
|
||||
|
||||
if (pos >= MIXART_BA0_SIZE)
|
||||
return 0;
|
||||
maxsize = MIXART_BA0_SIZE - pos;
|
||||
if (count > maxsize)
|
||||
count = maxsize;
|
||||
count = count & ~3; /* make sure the read size is a multiple of 4 bytes */
|
||||
if (copy_to_user_fromio(buf, MIXART_MEM(mgr, pos), count))
|
||||
return -EFAULT;
|
||||
|
@ -1178,18 +1122,13 @@ static long snd_mixart_BA0_read(struct snd_info_entry *entry, void *file_private
|
|||
/*
|
||||
mixart_BA1 proc interface for BAR 1 - read callback
|
||||
*/
|
||||
static long snd_mixart_BA1_read(struct snd_info_entry *entry, void *file_private_data,
|
||||
struct file *file, char __user *buf,
|
||||
unsigned long count, unsigned long pos)
|
||||
static ssize_t snd_mixart_BA1_read(struct snd_info_entry *entry,
|
||||
void *file_private_data,
|
||||
struct file *file, char __user *buf,
|
||||
size_t count, loff_t pos)
|
||||
{
|
||||
struct mixart_mgr *mgr = entry->private_data;
|
||||
unsigned long maxsize;
|
||||
|
||||
if (pos > MIXART_BA1_SIZE)
|
||||
return 0;
|
||||
maxsize = MIXART_BA1_SIZE - pos;
|
||||
if (count > maxsize)
|
||||
count = maxsize;
|
||||
count = count & ~3; /* make sure the read size is a multiple of 4 bytes */
|
||||
if (copy_to_user_fromio(buf, MIXART_REG(mgr, pos), count))
|
||||
return -EFAULT;
|
||||
|
@ -1198,12 +1137,10 @@ static long snd_mixart_BA1_read(struct snd_info_entry *entry, void *file_private
|
|||
|
||||
static struct snd_info_entry_ops snd_mixart_proc_ops_BA0 = {
|
||||
.read = snd_mixart_BA0_read,
|
||||
.llseek = snd_mixart_BA0_llseek
|
||||
};
|
||||
|
||||
static struct snd_info_entry_ops snd_mixart_proc_ops_BA1 = {
|
||||
.read = snd_mixart_BA1_read,
|
||||
.llseek = snd_mixart_BA1_llseek
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
#include <linux/kmod.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/string.h>
|
||||
#include <sound/core.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/irq.h>
|
||||
|
@ -46,6 +47,8 @@
|
|||
#define DBG(fmt...)
|
||||
#endif
|
||||
|
||||
#define IS_G4DA (of_machine_is_compatible("PowerMac3,4"))
|
||||
|
||||
/* i2c address for tumbler */
|
||||
#define TAS_I2C_ADDR 0x34
|
||||
|
||||
|
@ -243,6 +246,7 @@ static int tumbler_set_master_volume(struct pmac_tumbler *mix)
|
|||
snd_printk(KERN_ERR "failed to set volume \n");
|
||||
return -EINVAL;
|
||||
}
|
||||
DBG("(I) succeeded to set volume (%u, %u)\n", left_vol, right_vol);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -353,6 +357,7 @@ static int tumbler_set_drc(struct pmac_tumbler *mix)
|
|||
snd_printk(KERN_ERR "failed to set DRC\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
DBG("(I) succeeded to set DRC (%u, %u)\n", val[0], val[1]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -389,6 +394,7 @@ static int snapper_set_drc(struct pmac_tumbler *mix)
|
|||
snd_printk(KERN_ERR "failed to set DRC\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
DBG("(I) succeeded to set DRC (%u, %u)\n", val[0], val[1]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1134,7 +1140,8 @@ static long tumbler_find_device(const char *device, const char *platform,
|
|||
gp->inactive_val = (*base) ? 0x4 : 0x5;
|
||||
} else {
|
||||
const u32 *prop = NULL;
|
||||
gp->active_state = 0;
|
||||
gp->active_state = IS_G4DA
|
||||
&& !strncmp(device, "keywest-gpio1", 13);
|
||||
gp->active_val = 0x4;
|
||||
gp->inactive_val = 0x5;
|
||||
/* Here are some crude hacks to extract the GPIO polarity and
|
||||
|
@ -1312,6 +1319,9 @@ static int __devinit tumbler_init(struct snd_pmac *chip)
|
|||
if (irq <= NO_IRQ)
|
||||
irq = tumbler_find_device("line-output-detect",
|
||||
NULL, &mix->line_detect, 1);
|
||||
if (IS_G4DA && irq <= NO_IRQ)
|
||||
irq = tumbler_find_device("keywest-gpio16",
|
||||
NULL, &mix->line_detect, 1);
|
||||
mix->lineout_irq = irq;
|
||||
|
||||
tumbler_reset_audio(chip);
|
||||
|
|
|
@ -65,6 +65,7 @@ config SND_USB_CAIAQ
|
|||
* Native Instruments Audio 8 DJ
|
||||
* Native Instruments Guitar Rig Session I/O
|
||||
* Native Instruments Guitar Rig mobile
|
||||
* Native Instruments Traktor Kontrol X1
|
||||
|
||||
To compile this driver as a module, choose M here: the module
|
||||
will be called snd-usb-caiaq.
|
||||
|
|
|
@ -35,33 +35,41 @@ static int control_info(struct snd_kcontrol *kcontrol,
|
|||
struct snd_usb_caiaqdev *dev = caiaqdev(chip->card);
|
||||
int pos = kcontrol->private_value;
|
||||
int is_intval = pos & CNT_INTVAL;
|
||||
unsigned int id = dev->chip.usb_id;
|
||||
int maxval = 63;
|
||||
|
||||
uinfo->count = 1;
|
||||
pos &= ~CNT_INTVAL;
|
||||
|
||||
if (id == USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AUDIO8DJ)
|
||||
&& (pos == 0)) {
|
||||
/* current input mode of A8DJ */
|
||||
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
|
||||
uinfo->value.integer.min = 0;
|
||||
uinfo->value.integer.max = 2;
|
||||
return 0;
|
||||
}
|
||||
switch (dev->chip.usb_id) {
|
||||
case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AUDIO8DJ):
|
||||
if (pos == 0) {
|
||||
/* current input mode of A8DJ */
|
||||
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
|
||||
uinfo->value.integer.min = 0;
|
||||
uinfo->value.integer.max = 2;
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
|
||||
if (id == USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AUDIO4DJ)
|
||||
&& (pos == 0)) {
|
||||
/* current input mode of A4DJ */
|
||||
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
|
||||
uinfo->value.integer.min = 0;
|
||||
uinfo->value.integer.max = 1;
|
||||
return 0;
|
||||
case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AUDIO4DJ):
|
||||
if (pos == 0) {
|
||||
/* current input mode of A4DJ */
|
||||
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
|
||||
uinfo->value.integer.min = 0;
|
||||
uinfo->value.integer.max = 1;
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_TRAKTORKONTROLX1):
|
||||
maxval = 127;
|
||||
break;
|
||||
}
|
||||
|
||||
if (is_intval) {
|
||||
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
|
||||
uinfo->value.integer.min = 0;
|
||||
uinfo->value.integer.max = 64;
|
||||
uinfo->value.integer.max = maxval;
|
||||
} else {
|
||||
uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
|
||||
uinfo->value.integer.min = 0;
|
||||
|
@ -102,9 +110,10 @@ static int control_put(struct snd_kcontrol *kcontrol,
|
|||
struct snd_usb_audio *chip = snd_kcontrol_chip(kcontrol);
|
||||
struct snd_usb_caiaqdev *dev = caiaqdev(chip->card);
|
||||
int pos = kcontrol->private_value;
|
||||
unsigned char cmd = EP1_CMD_WRITE_IO;
|
||||
|
||||
if (dev->chip.usb_id ==
|
||||
USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AUDIO4DJ)) {
|
||||
switch (dev->chip.usb_id) {
|
||||
case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AUDIO4DJ): {
|
||||
/* A4DJ has only one control */
|
||||
/* do not expose hardware input mode 0 */
|
||||
dev->control_state[0] = ucontrol->value.integer.value[0] + 1;
|
||||
|
@ -113,10 +122,15 @@ static int control_put(struct snd_kcontrol *kcontrol,
|
|||
return 1;
|
||||
}
|
||||
|
||||
case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_TRAKTORKONTROLX1):
|
||||
cmd = EP1_CMD_DIMM_LEDS;
|
||||
break;
|
||||
}
|
||||
|
||||
if (pos & CNT_INTVAL) {
|
||||
dev->control_state[pos & ~CNT_INTVAL]
|
||||
= ucontrol->value.integer.value[0];
|
||||
snd_usb_caiaq_send_command(dev, EP1_CMD_WRITE_IO,
|
||||
snd_usb_caiaq_send_command(dev, cmd,
|
||||
dev->control_state, sizeof(dev->control_state));
|
||||
} else {
|
||||
if (ucontrol->value.integer.value[0])
|
||||
|
@ -124,7 +138,7 @@ static int control_put(struct snd_kcontrol *kcontrol,
|
|||
else
|
||||
dev->control_state[pos / 8] &= ~(1 << (pos % 8));
|
||||
|
||||
snd_usb_caiaq_send_command(dev, EP1_CMD_WRITE_IO,
|
||||
snd_usb_caiaq_send_command(dev, cmd,
|
||||
dev->control_state, sizeof(dev->control_state));
|
||||
}
|
||||
|
||||
|
@ -273,6 +287,43 @@ static struct caiaq_controller a4dj_controller[] = {
|
|||
{ "Current input mode", 0 | CNT_INTVAL }
|
||||
};
|
||||
|
||||
static struct caiaq_controller kontrolx1_controller[] = {
|
||||
{ "LED FX A: ON", 7 | CNT_INTVAL },
|
||||
{ "LED FX A: 1", 6 | CNT_INTVAL },
|
||||
{ "LED FX A: 2", 5 | CNT_INTVAL },
|
||||
{ "LED FX A: 3", 4 | CNT_INTVAL },
|
||||
{ "LED FX B: ON", 3 | CNT_INTVAL },
|
||||
{ "LED FX B: 1", 2 | CNT_INTVAL },
|
||||
{ "LED FX B: 2", 1 | CNT_INTVAL },
|
||||
{ "LED FX B: 3", 0 | CNT_INTVAL },
|
||||
|
||||
{ "LED Hotcue", 28 | CNT_INTVAL },
|
||||
{ "LED Shift (white)", 29 | CNT_INTVAL },
|
||||
{ "LED Shift (green)", 30 | CNT_INTVAL },
|
||||
|
||||
{ "LED Deck A: FX1", 24 | CNT_INTVAL },
|
||||
{ "LED Deck A: FX2", 25 | CNT_INTVAL },
|
||||
{ "LED Deck A: IN", 17 | CNT_INTVAL },
|
||||
{ "LED Deck A: OUT", 16 | CNT_INTVAL },
|
||||
{ "LED Deck A: < BEAT", 19 | CNT_INTVAL },
|
||||
{ "LED Deck A: BEAT >", 18 | CNT_INTVAL },
|
||||
{ "LED Deck A: CUE/ABS", 21 | CNT_INTVAL },
|
||||
{ "LED Deck A: CUP/REL", 20 | CNT_INTVAL },
|
||||
{ "LED Deck A: PLAY", 23 | CNT_INTVAL },
|
||||
{ "LED Deck A: SYNC", 22 | CNT_INTVAL },
|
||||
|
||||
{ "LED Deck B: FX1", 26 | CNT_INTVAL },
|
||||
{ "LED Deck B: FX2", 27 | CNT_INTVAL },
|
||||
{ "LED Deck B: IN", 15 | CNT_INTVAL },
|
||||
{ "LED Deck B: OUT", 14 | CNT_INTVAL },
|
||||
{ "LED Deck B: < BEAT", 13 | CNT_INTVAL },
|
||||
{ "LED Deck B: BEAT >", 12 | CNT_INTVAL },
|
||||
{ "LED Deck B: CUE/ABS", 11 | CNT_INTVAL },
|
||||
{ "LED Deck B: CUP/REL", 10 | CNT_INTVAL },
|
||||
{ "LED Deck B: PLAY", 9 | CNT_INTVAL },
|
||||
{ "LED Deck B: SYNC", 8 | CNT_INTVAL },
|
||||
};
|
||||
|
||||
static int __devinit add_controls(struct caiaq_controller *c, int num,
|
||||
struct snd_usb_caiaqdev *dev)
|
||||
{
|
||||
|
@ -321,10 +372,16 @@ int __devinit snd_usb_caiaq_control_init(struct snd_usb_caiaqdev *dev)
|
|||
ret = add_controls(a8dj_controller,
|
||||
ARRAY_SIZE(a8dj_controller), dev);
|
||||
break;
|
||||
|
||||
case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AUDIO4DJ):
|
||||
ret = add_controls(a4dj_controller,
|
||||
ARRAY_SIZE(a4dj_controller), dev);
|
||||
break;
|
||||
|
||||
case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_TRAKTORKONTROLX1):
|
||||
ret = add_controls(kontrolx1_controller,
|
||||
ARRAY_SIZE(kontrolx1_controller), dev);
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
|
|
@ -47,7 +47,8 @@ MODULE_SUPPORTED_DEVICE("{{Native Instruments, RigKontrol2},"
|
|||
"{Native Instruments, Audio 4 DJ},"
|
||||
"{Native Instruments, Audio 8 DJ},"
|
||||
"{Native Instruments, Session I/O},"
|
||||
"{Native Instruments, GuitarRig mobile}");
|
||||
"{Native Instruments, GuitarRig mobile}"
|
||||
"{Native Instruments, Traktor Kontrol X1}");
|
||||
|
||||
static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-max */
|
||||
static char* id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* Id for this card */
|
||||
|
@ -128,6 +129,11 @@ static struct usb_device_id snd_usb_id_table[] = {
|
|||
.idVendor = USB_VID_NATIVEINSTRUMENTS,
|
||||
.idProduct = USB_PID_AUDIO2DJ
|
||||
},
|
||||
{
|
||||
.match_flags = USB_DEVICE_ID_MATCH_DEVICE,
|
||||
.idVendor = USB_VID_NATIVEINSTRUMENTS,
|
||||
.idProduct = USB_PID_TRAKTORKONTROLX1
|
||||
},
|
||||
{ /* terminator */ }
|
||||
};
|
||||
|
||||
|
|
|
@ -5,18 +5,20 @@
|
|||
|
||||
#define USB_VID_NATIVEINSTRUMENTS 0x17cc
|
||||
|
||||
#define USB_PID_RIGKONTROL2 0x1969
|
||||
#define USB_PID_RIGKONTROL3 0x1940
|
||||
#define USB_PID_KORECONTROLLER 0x4711
|
||||
#define USB_PID_KORECONTROLLER2 0x4712
|
||||
#define USB_PID_AK1 0x0815
|
||||
#define USB_PID_AUDIO2DJ 0x041c
|
||||
#define USB_PID_AUDIO4DJ 0x0839
|
||||
#define USB_PID_AUDIO8DJ 0x1978
|
||||
#define USB_PID_SESSIONIO 0x1915
|
||||
#define USB_PID_GUITARRIGMOBILE 0x0d8d
|
||||
#define USB_PID_RIGKONTROL2 0x1969
|
||||
#define USB_PID_RIGKONTROL3 0x1940
|
||||
#define USB_PID_KORECONTROLLER 0x4711
|
||||
#define USB_PID_KORECONTROLLER2 0x4712
|
||||
#define USB_PID_AK1 0x0815
|
||||
#define USB_PID_AUDIO2DJ 0x041c
|
||||
#define USB_PID_AUDIO4DJ 0x0839
|
||||
#define USB_PID_AUDIO8DJ 0x1978
|
||||
#define USB_PID_SESSIONIO 0x1915
|
||||
#define USB_PID_GUITARRIGMOBILE 0x0d8d
|
||||
#define USB_PID_TRAKTORKONTROLX1 0x2305
|
||||
|
||||
#define EP1_BUFSIZE 64
|
||||
#define EP4_BUFSIZE 512
|
||||
#define CAIAQ_USB_STR_LEN 0xff
|
||||
#define MAX_STREAMS 32
|
||||
|
||||
|
@ -104,6 +106,8 @@ struct snd_usb_caiaqdev {
|
|||
struct input_dev *input_dev;
|
||||
char phys[64]; /* physical device path */
|
||||
unsigned short keycode[64];
|
||||
struct urb *ep4_in_urb;
|
||||
unsigned char ep4_in_buf[EP4_BUFSIZE];
|
||||
#endif
|
||||
|
||||
/* ALSA */
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include <linux/init.h>
|
||||
#include <linux/usb.h>
|
||||
#include <linux/usb/input.h>
|
||||
#include <sound/core.h>
|
||||
#include <sound/pcm.h>
|
||||
|
||||
#include "device.h"
|
||||
|
@ -65,6 +66,8 @@ static unsigned short keycode_kore[] = {
|
|||
KEY_BRL_DOT5
|
||||
};
|
||||
|
||||
#define KONTROLX1_INPUTS 40
|
||||
|
||||
#define DEG90 (range / 2)
|
||||
#define DEG180 (range)
|
||||
#define DEG270 (DEG90 + DEG180)
|
||||
|
@ -162,6 +165,17 @@ static void snd_caiaq_input_read_analog(struct snd_usb_caiaqdev *dev,
|
|||
input_report_abs(input_dev, ABS_Z, (buf[4] << 8) | buf[5]);
|
||||
input_sync(input_dev);
|
||||
break;
|
||||
case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_TRAKTORKONTROLX1):
|
||||
input_report_abs(input_dev, ABS_HAT0X, (buf[8] << 8) | buf[9]);
|
||||
input_report_abs(input_dev, ABS_HAT0Y, (buf[4] << 8) | buf[5]);
|
||||
input_report_abs(input_dev, ABS_HAT1X, (buf[12] << 8) | buf[13]);
|
||||
input_report_abs(input_dev, ABS_HAT1Y, (buf[2] << 8) | buf[3]);
|
||||
input_report_abs(input_dev, ABS_HAT2X, (buf[15] << 8) | buf[15]);
|
||||
input_report_abs(input_dev, ABS_HAT2Y, (buf[0] << 8) | buf[1]);
|
||||
input_report_abs(input_dev, ABS_HAT3X, (buf[10] << 8) | buf[11]);
|
||||
input_report_abs(input_dev, ABS_HAT3Y, (buf[6] << 8) | buf[7]);
|
||||
input_sync(input_dev);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -201,7 +215,7 @@ static void snd_caiaq_input_read_erp(struct snd_usb_caiaqdev *dev,
|
|||
}
|
||||
|
||||
static void snd_caiaq_input_read_io(struct snd_usb_caiaqdev *dev,
|
||||
char *buf, unsigned int len)
|
||||
unsigned char *buf, unsigned int len)
|
||||
{
|
||||
struct input_dev *input_dev = dev->input_dev;
|
||||
unsigned short *keycode = input_dev->keycode;
|
||||
|
@ -218,15 +232,84 @@ static void snd_caiaq_input_read_io(struct snd_usb_caiaqdev *dev,
|
|||
input_report_key(input_dev, keycode[i],
|
||||
buf[i / 8] & (1 << (i % 8)));
|
||||
|
||||
if (dev->chip.usb_id ==
|
||||
USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_KORECONTROLLER) ||
|
||||
dev->chip.usb_id ==
|
||||
USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_KORECONTROLLER2))
|
||||
switch (dev->chip.usb_id) {
|
||||
case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_KORECONTROLLER):
|
||||
case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_KORECONTROLLER2):
|
||||
input_report_abs(dev->input_dev, ABS_MISC, 255 - buf[4]);
|
||||
break;
|
||||
case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_TRAKTORKONTROLX1):
|
||||
/* rotary encoders */
|
||||
input_report_abs(dev->input_dev, ABS_X, buf[5] & 0xf);
|
||||
input_report_abs(dev->input_dev, ABS_Y, buf[5] >> 4);
|
||||
input_report_abs(dev->input_dev, ABS_Z, buf[6] & 0xf);
|
||||
input_report_abs(dev->input_dev, ABS_MISC, buf[6] >> 4);
|
||||
break;
|
||||
}
|
||||
|
||||
input_sync(input_dev);
|
||||
}
|
||||
|
||||
static void snd_usb_caiaq_ep4_reply_dispatch(struct urb *urb)
|
||||
{
|
||||
struct snd_usb_caiaqdev *dev = urb->context;
|
||||
unsigned char *buf = urb->transfer_buffer;
|
||||
int ret;
|
||||
|
||||
if (urb->status || !dev || urb != dev->ep4_in_urb)
|
||||
return;
|
||||
|
||||
if (urb->actual_length < 24)
|
||||
goto requeue;
|
||||
|
||||
switch (dev->chip.usb_id) {
|
||||
case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_TRAKTORKONTROLX1):
|
||||
if (buf[0] & 0x3)
|
||||
snd_caiaq_input_read_io(dev, buf + 1, 7);
|
||||
|
||||
if (buf[0] & 0x4)
|
||||
snd_caiaq_input_read_analog(dev, buf + 8, 16);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
requeue:
|
||||
dev->ep4_in_urb->actual_length = 0;
|
||||
ret = usb_submit_urb(dev->ep4_in_urb, GFP_ATOMIC);
|
||||
if (ret < 0)
|
||||
log("unable to submit urb. OOM!?\n");
|
||||
}
|
||||
|
||||
static int snd_usb_caiaq_input_open(struct input_dev *idev)
|
||||
{
|
||||
struct snd_usb_caiaqdev *dev = input_get_drvdata(idev);
|
||||
|
||||
if (!dev)
|
||||
return -EINVAL;
|
||||
|
||||
switch (dev->chip.usb_id) {
|
||||
case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_TRAKTORKONTROLX1):
|
||||
if (usb_submit_urb(dev->ep4_in_urb, GFP_KERNEL) != 0)
|
||||
return -EIO;
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void snd_usb_caiaq_input_close(struct input_dev *idev)
|
||||
{
|
||||
struct snd_usb_caiaqdev *dev = input_get_drvdata(idev);
|
||||
|
||||
if (!dev)
|
||||
return;
|
||||
|
||||
switch (dev->chip.usb_id) {
|
||||
case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_TRAKTORKONTROLX1):
|
||||
usb_kill_urb(dev->ep4_in_urb);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void snd_usb_caiaq_input_dispatch(struct snd_usb_caiaqdev *dev,
|
||||
char *buf,
|
||||
unsigned int len)
|
||||
|
@ -251,7 +334,7 @@ int snd_usb_caiaq_input_init(struct snd_usb_caiaqdev *dev)
|
|||
{
|
||||
struct usb_device *usb_dev = dev->chip.dev;
|
||||
struct input_dev *input;
|
||||
int i, ret;
|
||||
int i, ret = 0;
|
||||
|
||||
input = input_allocate_device();
|
||||
if (!input)
|
||||
|
@ -265,7 +348,9 @@ int snd_usb_caiaq_input_init(struct snd_usb_caiaqdev *dev)
|
|||
usb_to_input_id(usb_dev, &input->id);
|
||||
input->dev.parent = &usb_dev->dev;
|
||||
|
||||
switch (dev->chip.usb_id) {
|
||||
input_set_drvdata(input, dev);
|
||||
|
||||
switch (dev->chip.usb_id) {
|
||||
case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_RIGKONTROL2):
|
||||
input->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
|
||||
input->absbit[0] = BIT_MASK(ABS_X) | BIT_MASK(ABS_Y) |
|
||||
|
@ -325,26 +410,73 @@ int snd_usb_caiaq_input_init(struct snd_usb_caiaqdev *dev)
|
|||
input_set_abs_params(input, ABS_Z, 0, 4096, 0, 10);
|
||||
input_set_abs_params(input, ABS_MISC, 0, 255, 0, 1);
|
||||
snd_usb_caiaq_set_auto_msg(dev, 1, 10, 5);
|
||||
break;
|
||||
case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_TRAKTORKONTROLX1):
|
||||
input->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
|
||||
input->absbit[0] = BIT_MASK(ABS_HAT0X) | BIT_MASK(ABS_HAT0Y) |
|
||||
BIT_MASK(ABS_HAT1X) | BIT_MASK(ABS_HAT1Y) |
|
||||
BIT_MASK(ABS_HAT2X) | BIT_MASK(ABS_HAT2Y) |
|
||||
BIT_MASK(ABS_HAT3X) | BIT_MASK(ABS_HAT3Y) |
|
||||
BIT_MASK(ABS_X) | BIT_MASK(ABS_Y) |
|
||||
BIT_MASK(ABS_Z);
|
||||
input->absbit[BIT_WORD(ABS_MISC)] |= BIT_MASK(ABS_MISC);
|
||||
BUILD_BUG_ON(sizeof(dev->keycode) < KONTROLX1_INPUTS);
|
||||
for (i = 0; i < KONTROLX1_INPUTS; i++)
|
||||
dev->keycode[i] = BTN_MISC + i;
|
||||
input->keycodemax = KONTROLX1_INPUTS;
|
||||
|
||||
/* analog potentiometers */
|
||||
input_set_abs_params(input, ABS_HAT0X, 0, 4096, 0, 10);
|
||||
input_set_abs_params(input, ABS_HAT0Y, 0, 4096, 0, 10);
|
||||
input_set_abs_params(input, ABS_HAT1X, 0, 4096, 0, 10);
|
||||
input_set_abs_params(input, ABS_HAT1Y, 0, 4096, 0, 10);
|
||||
input_set_abs_params(input, ABS_HAT2X, 0, 4096, 0, 10);
|
||||
input_set_abs_params(input, ABS_HAT2Y, 0, 4096, 0, 10);
|
||||
input_set_abs_params(input, ABS_HAT3X, 0, 4096, 0, 10);
|
||||
input_set_abs_params(input, ABS_HAT3Y, 0, 4096, 0, 10);
|
||||
|
||||
/* rotary encoders */
|
||||
input_set_abs_params(input, ABS_X, 0, 0xf, 0, 1);
|
||||
input_set_abs_params(input, ABS_Y, 0, 0xf, 0, 1);
|
||||
input_set_abs_params(input, ABS_Z, 0, 0xf, 0, 1);
|
||||
input_set_abs_params(input, ABS_MISC, 0, 0xf, 0, 1);
|
||||
|
||||
dev->ep4_in_urb = usb_alloc_urb(0, GFP_KERNEL);
|
||||
if (!dev->ep4_in_urb) {
|
||||
ret = -ENOMEM;
|
||||
goto exit_free_idev;
|
||||
}
|
||||
|
||||
usb_fill_bulk_urb(dev->ep4_in_urb, usb_dev,
|
||||
usb_rcvbulkpipe(usb_dev, 0x4),
|
||||
dev->ep4_in_buf, EP4_BUFSIZE,
|
||||
snd_usb_caiaq_ep4_reply_dispatch, dev);
|
||||
|
||||
snd_usb_caiaq_set_auto_msg(dev, 1, 10, 5);
|
||||
|
||||
break;
|
||||
default:
|
||||
/* no input methods supported on this device */
|
||||
input_free_device(input);
|
||||
return 0;
|
||||
goto exit_free_idev;
|
||||
}
|
||||
|
||||
input->open = snd_usb_caiaq_input_open;
|
||||
input->close = snd_usb_caiaq_input_close;
|
||||
input->keycode = dev->keycode;
|
||||
input->keycodesize = sizeof(unsigned short);
|
||||
for (i = 0; i < input->keycodemax; i++)
|
||||
__set_bit(dev->keycode[i], input->keybit);
|
||||
|
||||
ret = input_register_device(input);
|
||||
if (ret < 0) {
|
||||
input_free_device(input);
|
||||
return ret;
|
||||
}
|
||||
if (ret < 0)
|
||||
goto exit_free_idev;
|
||||
|
||||
dev->input_dev = input;
|
||||
return 0;
|
||||
|
||||
exit_free_idev:
|
||||
input_free_device(input);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void snd_usb_caiaq_input_free(struct snd_usb_caiaqdev *dev)
|
||||
|
@ -352,6 +484,10 @@ void snd_usb_caiaq_input_free(struct snd_usb_caiaqdev *dev)
|
|||
if (!dev || !dev->input_dev)
|
||||
return;
|
||||
|
||||
usb_kill_urb(dev->ep4_in_urb);
|
||||
usb_free_urb(dev->ep4_in_urb);
|
||||
dev->ep4_in_urb = NULL;
|
||||
|
||||
input_unregister_device(dev->input_dev);
|
||||
dev->input_dev = NULL;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue