aboutsummaryrefslogtreecommitdiff
path: root/drivers/media/video/saa7134
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/video/saa7134')
-rw-r--r--drivers/media/video/saa7134/Kconfig3
-rw-r--r--drivers/media/video/saa7134/Makefile7
-rw-r--r--drivers/media/video/saa7134/saa7134-alsa.c448
-rw-r--r--drivers/media/video/saa7134/saa7134-cards.c32
-rw-r--r--drivers/media/video/saa7134/saa7134-core.c121
-rw-r--r--drivers/media/video/saa7134/saa7134-input.c109
-rw-r--r--drivers/media/video/saa7134/saa7134-oss.c161
-rw-r--r--drivers/media/video/saa7134/saa7134.h2
8 files changed, 427 insertions, 456 deletions
diff --git a/drivers/media/video/saa7134/Kconfig b/drivers/media/video/saa7134/Kconfig
index 624e8808a51..7bdeabe638c 100644
--- a/drivers/media/video/saa7134/Kconfig
+++ b/drivers/media/video/saa7134/Kconfig
@@ -1,10 +1,11 @@
config VIDEO_SAA7134
tristate "Philips SAA7134 support"
- depends on VIDEO_DEV && PCI && I2C && SOUND
+ depends on VIDEO_DEV && PCI && I2C && SOUND && SND
select VIDEO_BUF
select VIDEO_IR
select VIDEO_TUNER
select CRC32
+ select SND_PCM_OSS
---help---
This is a video4linux driver for Philips SAA713x based
TV cards.
diff --git a/drivers/media/video/saa7134/Makefile b/drivers/media/video/saa7134/Makefile
index e0b28f0533a..4226b61cc61 100644
--- a/drivers/media/video/saa7134/Makefile
+++ b/drivers/media/video/saa7134/Makefile
@@ -1,10 +1,11 @@
saa7134-objs := saa7134-cards.o saa7134-core.o saa7134-i2c.o \
- saa7134-oss.o saa7134-ts.o saa7134-tvaudio.o \
- saa7134-vbi.o saa7134-video.o saa7134-input.o
+ saa7134-ts.o saa7134-tvaudio.o saa7134-vbi.o \
+ saa7134-video.o saa7134-input.o
obj-$(CONFIG_VIDEO_SAA7134) += saa7134.o saa7134-empress.o \
- saa6752hs.o saa7134-alsa.o
+ saa6752hs.o saa7134-alsa.o \
+ saa7134-oss.o
obj-$(CONFIG_VIDEO_SAA7134_DVB) += saa7134-dvb.o
EXTRA_CFLAGS += -I$(src)/..
diff --git a/drivers/media/video/saa7134/saa7134-alsa.c b/drivers/media/video/saa7134/saa7134-alsa.c
index 4f3c4235432..5707c666660 100644
--- a/drivers/media/video/saa7134/saa7134-alsa.c
+++ b/drivers/media/video/saa7134/saa7134-alsa.c
@@ -30,7 +30,9 @@
#include <sound/core.h>
#include <sound/control.h>
#include <sound/pcm.h>
+#include <sound/pcm_params.h>
#include <sound/initval.h>
+#include <linux/interrupt.h>
#include "saa7134.h"
#include "saa7134-reg.h"
@@ -56,6 +58,8 @@ static int enable[SNDRV_CARDS] = {1, [1 ... (SNDRV_CARDS - 1)] = 0};
module_param_array(index, int, NULL, 0444);
MODULE_PARM_DESC(index, "Index value for SAA7134 capture interface(s).");
+int position;
+
#define dprintk(fmt, arg...) if (debug) \
printk(KERN_DEBUG "%s/alsa: " fmt, dev->name , ## arg)
@@ -68,7 +72,7 @@ typedef struct snd_card_saa7134 {
int mixer_volume[MIXER_ADDR_LAST+1][2];
int capture_source[MIXER_ADDR_LAST+1][2];
struct pci_dev *pci;
- struct saa7134_dev *saadev;
+ struct saa7134_dev *dev;
unsigned long iobase;
int irq;
@@ -83,12 +87,10 @@ typedef struct snd_card_saa7134 {
*/
typedef struct snd_card_saa7134_pcm {
- struct saa7134_dev *saadev;
+ struct saa7134_dev *dev;
spinlock_t lock;
- unsigned int pcm_size; /* buffer size */
- unsigned int pcm_count; /* bytes per period */
- unsigned int pcm_bps; /* bytes per second */
+
snd_pcm_substream_t *substream;
} snd_card_saa7134_pcm_t;
@@ -100,13 +102,11 @@ static snd_card_t *snd_saa7134_cards[SNDRV_CARDS];
*
* Called when the capture device is released or the buffer overflows
*
- * - Copied verbatim from saa7134-oss's dsp_dma_stop. Can be dropped
- * if we just share dsp_dma_stop and use it here
+ * - Copied verbatim from saa7134-oss's dsp_dma_stop.
*
*/
static void saa7134_dma_stop(struct saa7134_dev *dev)
-
{
dev->dmasound.dma_blk = -1;
dev->dmasound.dma_running = 0;
@@ -118,8 +118,7 @@ static void saa7134_dma_stop(struct saa7134_dev *dev)
*
* Called when preparing the capture device for use
*
- * - Copied verbatim from saa7134-oss's dsp_dma_start. Can be dropped
- * if we just share dsp_dma_start and use it here
+ * - Copied verbatim from saa7134-oss's dsp_dma_start.
*
*/
@@ -170,9 +169,9 @@ void saa7134_irq_alsa_done(struct saa7134_dev *dev, unsigned long status)
if (dev->dmasound.read_count >= dev->dmasound.blksize * (dev->dmasound.blocks-2)) {
dprintk("irq: overrun [full=%d/%d] - Blocks in %d\n",dev->dmasound.read_count,
dev->dmasound.bufsize, dev->dmasound.blocks);
+ spin_unlock(&dev->slock);
snd_pcm_stop(dev->dmasound.substream,SNDRV_PCM_STATE_XRUN);
- saa7134_dma_stop(dev);
- goto done;
+ return;
}
/* next block addr */
@@ -194,6 +193,7 @@ void saa7134_irq_alsa_done(struct saa7134_dev *dev, unsigned long status)
snd_pcm_period_elapsed(dev->dmasound.substream);
spin_lock(&dev->slock);
}
+
done:
spin_unlock(&dev->slock);
@@ -209,7 +209,9 @@ void saa7134_irq_alsa_done(struct saa7134_dev *dev, unsigned long status)
static irqreturn_t saa7134_alsa_irq(int irq, void *dev_id, struct pt_regs *regs)
{
- struct saa7134_dev *dev = (struct saa7134_dev*) dev_id;
+ struct saa7134_dmasound *dmasound = dev_id;
+ struct saa7134_dev *dev = dmasound->priv_data;
+
unsigned long report, status;
int loop, handled = 0;
@@ -248,56 +250,23 @@ static int snd_card_saa7134_capture_trigger(snd_pcm_substream_t * substream,
int cmd)
{
snd_pcm_runtime_t *runtime = substream->runtime;
- snd_card_saa7134_pcm_t *saapcm = runtime->private_data;
- struct saa7134_dev *dev=saapcm->saadev;
+ snd_card_saa7134_pcm_t *pcm = runtime->private_data;
+ struct saa7134_dev *dev=pcm->dev;
int err = 0;
- spin_lock_irq(&dev->slock);
- if (cmd == SNDRV_PCM_TRIGGER_START) {
+ spin_lock(&dev->slock);
+ if (cmd == SNDRV_PCM_TRIGGER_START) {
/* start dma */
saa7134_dma_start(dev);
- } else if (cmd == SNDRV_PCM_TRIGGER_STOP) {
+ } else if (cmd == SNDRV_PCM_TRIGGER_STOP) {
/* stop dma */
saa7134_dma_stop(dev);
- } else {
- err = -EINVAL;
- }
- spin_unlock_irq(&dev->slock);
-
- return err;
-}
-
-/*
- * DMA buffer config
- *
- * Sets the values that will later be used as the size of the buffer,
- * size of the fragments, and total number of fragments.
- * Must be called during the preparation stage, before memory is
- * allocated
- *
- * - Copied verbatim from saa7134-oss. Can be dropped
- * if we just share dsp_buffer_conf from OSS.
- */
+ } else {
+ err = -EINVAL;
+ }
+ spin_unlock(&dev->slock);
-static int dsp_buffer_conf(struct saa7134_dev *dev, int blksize, int blocks)
-{
- if (blksize < 0x100)
- blksize = 0x100;
- if (blksize > 0x10000)
- blksize = 0x10000;
-
- if (blocks < 2)
- blocks = 2;
- if ((blksize * blocks) > 1024*1024)
- blocks = 1024*1024 / blksize;
-
- dev->dmasound.blocks = blocks;
- dev->dmasound.blksize = blksize;
- dev->dmasound.bufsize = blksize * blocks;
-
- dprintk("buffer config: %d blocks / %d bytes, %d kB total\n",
- blocks,blksize,blksize * blocks / 1024);
- return 0;
+ return err;
}
/*
@@ -307,16 +276,16 @@ static int dsp_buffer_conf(struct saa7134_dev *dev, int blksize, int blocks)
* ALSA, but I was unable to use ALSA's own DMA, and had to force the
* usage of V4L's
*
- * - Copied verbatim from saa7134-oss. Can be dropped
- * if we just share dsp_buffer_init from OSS.
+ * - Copied verbatim from saa7134-oss.
+ *
*/
static int dsp_buffer_init(struct saa7134_dev *dev)
{
int err;
- if (!dev->dmasound.bufsize)
- BUG();
+ BUG_ON(!dev->dmasound.bufsize);
+
videobuf_dma_init(&dev->dmasound.dma);
err = videobuf_dma_init_kernel(&dev->dmasound.dma, PCI_DMA_FROMDEVICE,
(dev->dmasound.bufsize + PAGE_SIZE) >> PAGE_SHIFT);
@@ -326,6 +295,28 @@ static int dsp_buffer_init(struct saa7134_dev *dev)
}
/*
+ * DMA buffer release
+ *
+ * Called after closing the device, during snd_card_saa7134_capture_close
+ *
+ */
+
+static int dsp_buffer_free(struct saa7134_dev *dev)
+{
+ if (!dev->dmasound.blksize)
+ BUG();
+
+ videobuf_dma_free(&dev->dmasound.dma);
+
+ dev->dmasound.blocks = 0;
+ dev->dmasound.blksize = 0;
+ dev->dmasound.bufsize = 0;
+
+ return 0;
+}
+
+
+/*
* ALSA PCM preparation
*
* - One of the ALSA capture callbacks.
@@ -340,84 +331,30 @@ static int dsp_buffer_init(struct saa7134_dev *dev)
static int snd_card_saa7134_capture_prepare(snd_pcm_substream_t * substream)
{
snd_pcm_runtime_t *runtime = substream->runtime;
- int err, bswap, sign;
+ int bswap, sign;
u32 fmt, control;
snd_card_saa7134_t *saa7134 = snd_pcm_substream_chip(substream);
struct saa7134_dev *dev;
- snd_card_saa7134_pcm_t *saapcm = runtime->private_data;
- unsigned int bps;
- unsigned long size;
- unsigned count;
-
- size = snd_pcm_lib_buffer_bytes(substream);
- count = snd_pcm_lib_period_bytes(substream);
-
- saapcm->saadev->dmasound.substream = substream;
- bps = runtime->rate * runtime->channels;
- bps *= snd_pcm_format_width(runtime->format);
- bps /= 8;
- if (bps <= 0)
- return -EINVAL;
- saapcm->pcm_bps = bps;
- saapcm->pcm_size = snd_pcm_lib_buffer_bytes(substream);
- saapcm->pcm_count = snd_pcm_lib_period_bytes(substream);
-
+ snd_card_saa7134_pcm_t *pcm = runtime->private_data;
- dev=saa7134->saadev;
+ pcm->dev->dmasound.substream = substream;
- dsp_buffer_conf(dev,saapcm->pcm_count,(saapcm->pcm_size/saapcm->pcm_count));
+ dev = saa7134->dev;
- err = dsp_buffer_init(dev);
- if (0 != err)
- goto fail2;
-
- /* prepare buffer */
- if (0 != (err = videobuf_dma_pci_map(dev->pci,&dev->dmasound.dma)))
- return err;
- if (0 != (err = saa7134_pgtable_alloc(dev->pci,&dev->dmasound.pt)))
- goto fail1;
- if (0 != (err = saa7134_pgtable_build(dev->pci,&dev->dmasound.pt,
- dev->dmasound.dma.sglist,
- dev->dmasound.dma.sglen,
- 0)))
- goto fail2;
-
-
-
- switch (runtime->format) {
- case SNDRV_PCM_FORMAT_U8:
- case SNDRV_PCM_FORMAT_S8:
+ if (snd_pcm_format_width(runtime->format) == 8)
fmt = 0x00;
- break;
- case SNDRV_PCM_FORMAT_U16_LE:
- case SNDRV_PCM_FORMAT_U16_BE:
- case SNDRV_PCM_FORMAT_S16_LE:
- case SNDRV_PCM_FORMAT_S16_BE:
+ else
fmt = 0x01;
- break;
- default:
- err = -EINVAL;
- return 1;
- }
- switch (runtime->format) {
- case SNDRV_PCM_FORMAT_S8:
- case SNDRV_PCM_FORMAT_S16_LE:
- case SNDRV_PCM_FORMAT_S16_BE:
+ if (snd_pcm_format_signed(runtime->format))
sign = 1;
- break;
- default:
+ else
sign = 0;
- break;
- }
- switch (runtime->format) {
- case SNDRV_PCM_FORMAT_U16_BE:
- case SNDRV_PCM_FORMAT_S16_BE:
- bswap = 1; break;
- default:
- bswap = 0; break;
- }
+ if (snd_pcm_format_big_endian(runtime->format))
+ bswap = 1;
+ else
+ bswap = 0;
switch (dev->pci->device) {
case PCI_DEVICE_ID_PHILIPS_SAA7134:
@@ -445,7 +382,6 @@ static int snd_card_saa7134_capture_prepare(snd_pcm_substream_t * substream)
fmt |= 0x04;
saa_writel(SAA7133_NUM_SAMPLES, dev->dmasound.blksize -1);
saa_writel(SAA7133_AUDIO_CHANNEL, 0x543210 | (fmt << 24));
- //saa_writel(SAA7133_AUDIO_CHANNEL, 0x543210);
break;
}
@@ -459,12 +395,6 @@ static int snd_card_saa7134_capture_prepare(snd_pcm_substream_t * substream)
if (bswap)
control |= SAA7134_RS_CONTROL_BSWAP;
- /* I should be able to use runtime->dma_addr in the control
- byte, but it doesn't work. So I allocate the DMA using the
- V4L functions, and force ALSA to use that as the DMA area */
-
- runtime->dma_area = dev->dmasound.dma.vmalloc;
-
saa_writel(SAA7134_RS_BA1(6),0);
saa_writel(SAA7134_RS_BA2(6),dev->dmasound.blksize);
saa_writel(SAA7134_RS_PITCH(6),0);
@@ -473,12 +403,6 @@ static int snd_card_saa7134_capture_prepare(snd_pcm_substream_t * substream)
dev->dmasound.rate = runtime->rate;
return 0;
- fail2:
- saa7134_pgtable_free(dev->pci,&dev->dmasound.pt);
- fail1:
- videobuf_dma_pci_unmap(dev->pci,&dev->dmasound.dma);
- return err;
-
}
@@ -496,10 +420,8 @@ static int snd_card_saa7134_capture_prepare(snd_pcm_substream_t * substream)
static snd_pcm_uframes_t snd_card_saa7134_capture_pointer(snd_pcm_substream_t * substream)
{
snd_pcm_runtime_t *runtime = substream->runtime;
- snd_card_saa7134_pcm_t *saapcm = runtime->private_data;
- struct saa7134_dev *dev=saapcm->saadev;
-
-
+ snd_card_saa7134_pcm_t *pcm = runtime->private_data;
+ struct saa7134_dev *dev=pcm->dev;
if (dev->dmasound.read_count) {
dev->dmasound.read_count -= snd_pcm_lib_period_bytes(substream);
@@ -540,9 +462,9 @@ static snd_pcm_hardware_t snd_card_saa7134_capture =
static void snd_card_saa7134_runtime_free(snd_pcm_runtime_t *runtime)
{
- snd_card_saa7134_pcm_t *saapcm = runtime->private_data;
+ snd_card_saa7134_pcm_t *pcm = runtime->private_data;
- kfree(saapcm);
+ kfree(pcm);
}
@@ -552,17 +474,76 @@ static void snd_card_saa7134_runtime_free(snd_pcm_runtime_t *runtime)
* - One of the ALSA capture callbacks.
*
* Called on initialization, right before the PCM preparation
- * Usually used in ALSA to allocate the DMA, but since we don't use the
- * ALSA DMA it does nothing
*
*/
static int snd_card_saa7134_hw_params(snd_pcm_substream_t * substream,
snd_pcm_hw_params_t * hw_params)
{
+ snd_card_saa7134_t *saa7134 = snd_pcm_substream_chip(substream);
+ struct saa7134_dev *dev;
+ unsigned int period_size, periods;
+ int err;
- return 0;
+ period_size = params_period_bytes(hw_params);
+ periods = params_periods(hw_params);
+
+ snd_assert(period_size >= 0x100 && period_size <= 0x10000,
+ return -EINVAL);
+ snd_assert(periods >= 2, return -EINVAL);
+ snd_assert(period_size * periods <= 1024 * 1024, return -EINVAL);
+ dev = saa7134->dev;
+
+ if (dev->dmasound.blocks == periods &&
+ dev->dmasound.blksize == period_size)
+ return 0;
+
+ /* release the old buffer */
+ if (substream->runtime->dma_area) {
+ saa7134_pgtable_free(dev->pci, &dev->dmasound.pt);
+ videobuf_dma_pci_unmap(dev->pci, &dev->dmasound.dma);
+ dsp_buffer_free(dev);
+ substream->runtime->dma_area = NULL;
+ }
+ dev->dmasound.blocks = periods;
+ dev->dmasound.blksize = period_size;
+ dev->dmasound.bufsize = period_size * periods;
+
+ err = dsp_buffer_init(dev);
+ if (0 != err) {
+ dev->dmasound.blocks = 0;
+ dev->dmasound.blksize = 0;
+ dev->dmasound.bufsize = 0;
+ return err;
+ }
+
+ if (0 != (err = videobuf_dma_pci_map(dev->pci, &dev->dmasound.dma))) {
+ dsp_buffer_free(dev);
+ return err;
+ }
+ if (0 != (err = saa7134_pgtable_alloc(dev->pci,&dev->dmasound.pt))) {
+ videobuf_dma_pci_unmap(dev->pci, &dev->dmasound.dma);
+ dsp_buffer_free(dev);
+ return err;
+ }
+ if (0 != (err = saa7134_pgtable_build(dev->pci,&dev->dmasound.pt,
+ dev->dmasound.dma.sglist,
+ dev->dmasound.dma.sglen,
+ 0))) {
+ saa7134_pgtable_free(dev->pci, &dev->dmasound.pt);
+ videobuf_dma_pci_unmap(dev->pci, &dev->dmasound.dma);
+ dsp_buffer_free(dev);
+ return err;
+ }
+
+ /* I should be able to use runtime->dma_addr in the control
+ byte, but it doesn't work. So I allocate the DMA using the
+ V4L functions, and force ALSA to use that as the DMA area */
+
+ substream->runtime->dma_area = dev->dmasound.dma.vmalloc;
+
+ return 1;
}
@@ -572,33 +553,23 @@ static int snd_card_saa7134_hw_params(snd_pcm_substream_t * substream,
* - One of the ALSA capture callbacks.
*
* Called after closing the device, but before snd_card_saa7134_capture_close
- * Usually used in ALSA to free the DMA, but since we don't use the
- * ALSA DMA I'm almost sure this isn't necessary.
+ * It stops the DMA audio and releases the buffers.
*
*/
static int snd_card_saa7134_hw_free(snd_pcm_substream_t * substream)
{
- return 0;
-}
-
-/*
- * DMA buffer release
- *
- * Called after closing the device, during snd_card_saa7134_capture_close
- *
- */
-
-static int dsp_buffer_free(struct saa7134_dev *dev)
-{
- if (!dev->dmasound.blksize)
- BUG();
+ snd_card_saa7134_t *saa7134 = snd_pcm_substream_chip(substream);
+ struct saa7134_dev *dev;
- videobuf_dma_free(&dev->dmasound.dma);
+ dev = saa7134->dev;
- dev->dmasound.blocks = 0;
- dev->dmasound.blksize = 0;
- dev->dmasound.bufsize = 0;
+ if (substream->runtime->dma_area) {
+ saa7134_pgtable_free(dev->pci, &dev->dmasound.pt);
+ videobuf_dma_pci_unmap(dev->pci, &dev->dmasound.dma);
+ dsp_buffer_free(dev);
+ substream->runtime->dma_area = NULL;
+ }
return 0;
}
@@ -608,21 +579,12 @@ static int dsp_buffer_free(struct saa7134_dev *dev)
*
* - One of the ALSA capture callbacks.
*
- * Called after closing the device. It stops the DMA audio and releases
- * the buffers
+ * Called after closing the device.
*
*/
static int snd_card_saa7134_capture_close(snd_pcm_substream_t * substream)
{
- snd_card_saa7134_t *chip = snd_pcm_substream_chip(substream);
- struct saa7134_dev *dev = chip->saadev;
-
- /* unlock buffer */
- saa7134_pgtable_free(dev->pci,&dev->dmasound.pt);
- videobuf_dma_pci_unmap(dev->pci,&dev->dmasound.dma);
-
- dsp_buffer_free(dev);
return 0;
}
@@ -639,29 +601,28 @@ static int snd_card_saa7134_capture_close(snd_pcm_substream_t * substream)
static int snd_card_saa7134_capture_open(snd_pcm_substream_t * substream)
{
snd_pcm_runtime_t *runtime = substream->runtime;
- snd_card_saa7134_pcm_t *saapcm;
+ snd_card_saa7134_pcm_t *pcm;
snd_card_saa7134_t *saa7134 = snd_pcm_substream_chip(substream);
- struct saa7134_dev *dev = saa7134->saadev;
+ struct saa7134_dev *dev = saa7134->dev;
int err;
down(&dev->dmasound.lock);
- dev->dmasound.afmt = SNDRV_PCM_FORMAT_U8;
- dev->dmasound.channels = 2;
dev->dmasound.read_count = 0;
dev->dmasound.read_offset = 0;
up(&dev->dmasound.lock);
- saapcm = kzalloc(sizeof(*saapcm), GFP_KERNEL);
- if (saapcm == NULL)
+ pcm = kzalloc(sizeof(*pcm), GFP_KERNEL);
+ if (pcm == NULL)
return -ENOMEM;
- saapcm->saadev=saa7134->saadev;
- spin_lock_init(&saapcm->lock);
+ pcm->dev=saa7134->dev;
- saapcm->substream = substream;
- runtime->private_data = saapcm;
+ spin_lock_init(&pcm->lock);
+
+ pcm->substream = substream;
+ runtime->private_data = pcm;
runtime->private_free = snd_card_saa7134_runtime_free;
runtime->hw = snd_card_saa7134_capture;
@@ -736,7 +697,6 @@ static int snd_saa7134_volume_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_
static int snd_saa7134_volume_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
{
snd_card_saa7134_t *chip = snd_kcontrol_chip(kcontrol);
- unsigned long flags;
int change, addr = kcontrol->private_value;
int left, right;
@@ -750,12 +710,12 @@ static int snd_saa7134_volume_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_
right = 0;
if (right > 20)
right = 20;
- spin_lock_irqsave(&chip->mixer_lock, flags);
+ spin_lock_irq(&chip->mixer_lock);
change = chip->mixer_volume[addr][0] != left ||
chip->mixer_volume[addr][1] != right;
chip->mixer_volume[addr][0] = left;
chip->mixer_volume[addr][1] = right;
- spin_unlock_irqrestore(&chip->mixer_lock, flags);
+ spin_unlock_irq(&chip->mixer_lock);
return change;
}
@@ -777,38 +737,37 @@ static int snd_saa7134_capsrc_info(snd_kcontrol_t * kcontrol, snd_ctl_elem_info_
static int snd_saa7134_capsrc_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
{
snd_card_saa7134_t *chip = snd_kcontrol_chip(kcontrol);
- unsigned long flags;
int addr = kcontrol->private_value;
- spin_lock_irqsave(&chip->mixer_lock, flags);
+ spin_lock_irq(&chip->mixer_lock);
ucontrol->value.integer.value[0] = chip->capture_source[addr][0];
ucontrol->value.integer.value[1] = chip->capture_source[addr][1];
- spin_unlock_irqrestore(&chip->mixer_lock, flags);
+ spin_unlock_irq(&chip->mixer_lock);
+
return 0;
}
static int snd_saa7134_capsrc_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
{
snd_card_saa7134_t *chip = snd_kcontrol_chip(kcontrol);
- unsigned long flags;
int change, addr = kcontrol->private_value;
int left, right;
u32 anabar, xbarin;
int analog_io, rate;
struct saa7134_dev *dev;
- dev = chip->saadev;
+ dev = chip->dev;
left = ucontrol->value.integer.value[0] & 1;
right = ucontrol->value.integer.value[1] & 1;
- spin_lock_irqsave(&chip->mixer_lock, flags);
+ spin_lock_irq(&chip->mixer_lock);
change = chip->capture_source[addr][0] != left ||
chip->capture_source[addr][1] != right;
chip->capture_source[addr][0] = left;
chip->capture_source[addr][1] = right;
dev->dmasound.input=addr;
- spin_unlock_irqrestore(&chip->mixer_lock, flags);
+ spin_unlock_irq(&chip->mixer_lock);
if (change) {
@@ -898,43 +857,44 @@ static int snd_card_saa7134_new_mixer(snd_card_saa7134_t * chip)
return 0;
}
-static int snd_saa7134_free(snd_card_saa7134_t *chip)
+static void snd_saa7134_free(snd_card_t * card)
{
- return 0;
-}
+ snd_card_saa7134_t *chip = card->private_data;
+
+ if (chip->dev->dmasound.priv_data == NULL)
+ return;
+
+ if (chip->irq >= 0) {
+ synchronize_irq(chip->irq);
+ free_irq(chip->irq, &chip->dev->dmasound);
+ }
+
+ chip->dev->dmasound.priv_data = NULL;
-static int snd_saa7134_dev_free(snd_device_t *device)
-{
- snd_card_saa7134_t *chip = device->device_data;
- return snd_saa7134_free(chip);
}
/*
* ALSA initialization
*
- * Called by saa7134-core, it creates the basic structures and registers
- * the ALSA devices
+ * Called by the init routine, once for each saa7134 device present,
+ * it creates the basic structures and registers the ALSA devices
*
*/
-int alsa_card_saa7134_create (struct saa7134_dev *saadev)
+int alsa_card_saa7134_create(struct saa7134_dev *dev, int devnum)
{
- static int dev;
snd_card_t *card;
snd_card_saa7134_t *chip;
int err;
- static snd_device_ops_t ops = {
- .dev_free = snd_saa7134_dev_free,
- };
- if (dev >= SNDRV_CARDS)
+ if (devnum >= SNDRV_CARDS)
return -ENODEV;
- if (!enable[dev])
+ if (!enable[devnum])
return -ENODEV;
- card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0);
+ card = snd_card_new(index[devnum], id[devnum], THIS_MODULE, sizeof(snd_card_saa7134_t));
if (card == NULL)
return -ENOMEM;
@@ -943,34 +903,33 @@ int alsa_card_saa7134_create (struct saa7134_dev *saadev)
/* Card "creation" */
- chip = kcalloc(1, sizeof(*chip), GFP_KERNEL);
- if (chip == NULL) {
- return -ENOMEM;
- }
+ card->private_free = snd_saa7134_free;
+ chip = (snd_card_saa7134_t *) card->private_data;
spin_lock_init(&chip->lock);
spin_lock_init(&chip->mixer_lock);
- chip->saadev = saadev;
+ chip->dev = dev;
chip->card = card;
- chip->pci = saadev->pci;
- chip->irq = saadev->pci->irq;
- chip->iobase = pci_resource_start(saadev->pci, 0);
+ chip->pci = dev->pci;
+ chip->iobase = pci_resource_start(dev->pci, 0);
- err = request_irq(saadev->pci->irq, saa7134_alsa_irq,
- SA_SHIRQ | SA_INTERRUPT, saadev->name, saadev);
+
+ err = request_irq(dev->pci->irq, saa7134_alsa_irq,
+ SA_SHIRQ | SA_INTERRUPT, dev->name,
+ (void*) &dev->dmasound);
if (err < 0) {
printk(KERN_ERR "%s: can't get IRQ %d for ALSA\n",
- saadev->name, saadev->pci->irq);
+ dev->name, dev->pci->irq);
goto __nodev;
}
- if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) < 0) {
- goto __nodev;
- }
+ chip->irq = dev->pci->irq;
+
+ init_MUTEX(&dev->dmasound.lock);
if ((err = snd_card_saa7134_new_mixer(chip)) < 0)
goto __nodev;
@@ -984,16 +943,15 @@ int alsa_card_saa7134_create (struct saa7134_dev *saadev)
strcpy(card->shortname, "SAA7134");
sprintf(card->longname, "%s at 0x%lx irq %d",
- chip->saadev->name, chip->iobase, chip->irq);
+ chip->dev->name, chip->iobase, chip->irq);
if ((err = snd_card_register(card)) == 0) {
- snd_saa7134_cards[dev] = card;
+ snd_saa7134_cards[devnum] = card;
return 0;
}
__nodev:
snd_card_free(card);
- kfree(chip);
return err;
}
@@ -1007,21 +965,29 @@ __nodev:
static int saa7134_alsa_init(void)
{
- struct saa7134_dev *saadev = NULL;
- struct list_head *list;
+ struct saa7134_dev *dev = NULL;
+ struct list_head *list;
- printk(KERN_INFO "saa7134 ALSA driver for DMA sound loaded\n");
+ position = 0;
- list_for_each(list,&saa7134_devlist) {
- saadev = list_entry(list, struct saa7134_dev, devlist);
- alsa_card_saa7134_create(saadev);
- }
+ printk(KERN_INFO "saa7134 ALSA driver for DMA sound loaded\n");
- if (saadev == NULL)
+ list_for_each(list,&saa7134_devlist) {
+ dev = list_entry(list, struct saa7134_dev, devlist);
+ if (dev->dmasound.priv_data == NULL) {
+ dev->dmasound.priv_data = dev;
+ alsa_card_saa7134_create(dev,position);
+ position++;
+ } else {
+ printk(KERN_ERR "saa7134 ALSA: DMA sound is being handled by OSS. ignoring %s\n",dev->name);
+ return -EBUSY;
+ }
+ }
+
+ if (dev == NULL)
printk(KERN_INFO "saa7134 ALSA: no saa7134 cards found\n");
return 0;
-
}
/*
diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c
index 663d03e5bc6..75abc20b0cc 100644
--- a/drivers/media/video/saa7134/saa7134-cards.c
+++ b/drivers/media/video/saa7134/saa7134-cards.c
@@ -2529,6 +2529,32 @@ struct saa7134_board saa7134_boards[] = {
.amux = LINE1,
}},
},
+ [SAA7134_BOARD_MSI_TVATANYWHERE_PLUS] = {
+ .name = "MSI TV@Anywhere plus",
+ .audio_clock = 0x00187de7,
+ .tuner_type = TUNER_PHILIPS_TDA8290,
+ .radio_type = UNSET,
+ .tuner_addr = ADDR_UNSET,
+ .radio_addr = ADDR_UNSET,
+ .inputs = {{
+ .name = name_tv,
+ .vmux = 1,
+ .amux = TV,
+ .tv = 1,
+ },{
+ .name = name_comp1,
+ .vmux = 3,
+ .amux = LINE1,
+ },{
+ .name = name_svideo,
+ .vmux = 0,
+ .amux = LINE1,
+ }},
+ .radio = {
+ .name = name_radio,
+ .amux = LINE1,
+ },
+ },
};
const unsigned int saa7134_bcount = ARRAY_SIZE(saa7134_boards);
@@ -2970,6 +2996,12 @@ struct pci_device_id saa7134_pci_tbl[] = {
.subdevice = 0x2018,
.driver_data = SAA7134_BOARD_PHILIPS_TIGER,
},{
+ .vendor = PCI_VENDOR_ID_PHILIPS,
+ .device = PCI_DEVICE_ID_PHILIPS_SAA7133,
+ .subvendor = 0x1462,
+ .subdevice = 0x6231,
+ .driver_data = SAA7134_BOARD_MSI_TVATANYWHERE_PLUS,
+ },{
/* --- boards without eeprom + subsystem ID --- */
.vendor = PCI_VENDOR_ID_PHILIPS,
.device = PCI_DEVICE_ID_PHILIPS_SAA7134,
diff --git a/drivers/media/video/saa7134/saa7134-core.c b/drivers/media/video/saa7134/saa7134-core.c
index 19b88744fb3..4275d2ddb86 100644
--- a/drivers/media/video/saa7134/saa7134-core.c
+++ b/drivers/media/video/saa7134/saa7134-core.c
@@ -53,13 +53,13 @@ static unsigned int gpio_tracking = 0;
module_param(gpio_tracking, int, 0644);
MODULE_PARM_DESC(gpio_tracking,"enable debug messages [gpio]");
-static unsigned int oss = 0;
-module_param(oss, int, 0444);
-MODULE_PARM_DESC(oss,"register oss devices (default: no)");
-
static unsigned int alsa = 0;
-module_param(alsa, int, 0444);
-MODULE_PARM_DESC(alsa,"register alsa devices (default: no)");
+module_param(alsa, int, 0644);
+MODULE_PARM_DESC(alsa,"enable ALSA DMA sound [dmasound]");
+
+static unsigned int oss = 0;
+module_param(oss, int, 0644);
+MODULE_PARM_DESC(oss,"enable OSS DMA sound [dmasound]");
static unsigned int latency = UNSET;
module_param(latency, int, 0444);
@@ -68,24 +68,18 @@ MODULE_PARM_DESC(latency,"pci latency timer");
static unsigned int video_nr[] = {[0 ... (SAA7134_MAXBOARDS - 1)] = UNSET };
static unsigned int vbi_nr[] = {[0 ... (SAA7134_MAXBOARDS - 1)] = UNSET };
static unsigned int radio_nr[] = {[0 ... (SAA7134_MAXBOARDS - 1)] = UNSET };
-static unsigned int dsp_nr[] = {[0 ... (SAA7134_MAXBOARDS - 1)] = UNSET };
-static unsigned int mixer_nr[] = {[0 ... (SAA7134_MAXBOARDS - 1)] = UNSET };
static unsigned int tuner[] = {[0 ... (SAA7134_MAXBOARDS - 1)] = UNSET };
static unsigned int card[] = {[0 ... (SAA7134_MAXBOARDS - 1)] = UNSET };
module_param_array(video_nr, int, NULL, 0444);
module_param_array(vbi_nr, int, NULL, 0444);
module_param_array(radio_nr, int, NULL, 0444);
-module_param_array(dsp_nr, int, NULL, 0444);
-module_param_array(mixer_nr, int, NULL, 0444);
module_param_array(tuner, int, NULL, 0444);
module_param_array(card, int, NULL, 0444);
MODULE_PARM_DESC(video_nr, "video device number");
MODULE_PARM_DESC(vbi_nr, "vbi device number");
MODULE_PARM_DESC(radio_nr, "radio device number");
-MODULE_PARM_DESC(dsp_nr, "oss dsp device number");
-MODULE_PARM_DESC(mixer_nr, "oss mixer device number");
MODULE_PARM_DESC(tuner, "tuner type");
MODULE_PARM_DESC(card, "card type");
@@ -195,6 +189,7 @@ void saa7134_track_gpio(struct saa7134_dev *dev, char *msg)
static int need_empress;
static int need_dvb;
static int need_alsa;
+static int need_oss;
static int pending_call(struct notifier_block *self, unsigned long state,
void *module)
@@ -208,6 +203,8 @@ static int pending_call(struct notifier_block *self, unsigned long state,
request_module("saa7134-dvb");
if (need_alsa)
request_module("saa7134-alsa");
+ if (need_oss)
+ request_module("saa7134-oss");
return NOTIFY_DONE;
}
@@ -218,10 +215,11 @@ static struct notifier_block pending_notifier = {
static void request_module_depend(char *name, int *flag)
{
+ int err;
switch (THIS_MODULE->state) {
case MODULE_STATE_COMING:
if (!pending_registered) {
- register_module_notifier(&pending_notifier);
+ err = register_module_notifier(&pending_notifier);
pending_registered = 1;
}
*flag = 1;
@@ -578,12 +576,14 @@ static irqreturn_t saa7134_irq(int irq, void *dev_id, struct pt_regs *regs)
goto out;
}
- /* If alsa support is active and we get a sound report, exit
- and let the saa7134-alsa module deal with it */
+ /* If dmasound support is active and we get a sound report, exit
+ and let the saa7134-alsa/oss module deal with it */
- if ((report & SAA7134_IRQ_REPORT_DONE_RA3) && alsa) {
+ if ((report & SAA7134_IRQ_REPORT_DONE_RA3) &&
+ (dev->dmasound.priv_data != NULL) )
+ {
if (irq_debug > 1)
- printk(KERN_DEBUG "%s/irq: ignoring interrupt for ALSA\n",
+ printk(KERN_DEBUG "%s/irq: ignoring interrupt for DMA sound\n",
dev->name);
goto out;
}
@@ -609,12 +609,6 @@ static irqreturn_t saa7134_irq(int irq, void *dev_id, struct pt_regs *regs)
card_has_mpeg(dev))
saa7134_irq_ts_done(dev,status);
- if ((report & SAA7134_IRQ_REPORT_DONE_RA3)) {
- if (oss) {
- saa7134_irq_oss_done(dev,status);
- }
- }
-
if ((report & (SAA7134_IRQ_REPORT_GPIO16 |
SAA7134_IRQ_REPORT_GPIO18)) &&
dev->remote)
@@ -689,14 +683,6 @@ static int saa7134_hwinit1(struct saa7134_dev *dev)
* audio will not work.
*/
- switch (dev->pci->device) {
- case PCI_DEVICE_ID_PHILIPS_SAA7134:
- case PCI_DEVICE_ID_PHILIPS_SAA7133:
- case PCI_DEVICE_ID_PHILIPS_SAA7135:
- saa7134_oss_init1(dev);
- break;
- }
-
/* enable peripheral devices */
saa_writeb(SAA7134_SPECIAL_MODE, 0x01);
@@ -728,8 +714,6 @@ static int saa7134_hwinit2(struct saa7134_dev *dev)
irq2_mask |= (SAA7134_IRQ2_INTE_GPIO18 |
SAA7134_IRQ2_INTE_GPIO18A |
SAA7134_IRQ2_INTE_GPIO16 );
- else if (dev->has_remote == SAA7134_REMOTE_I2C)
- request_module("ir-kbd-i2c");
saa_writel(SAA7134_IRQ1, 0);
saa_writel(SAA7134_IRQ2, irq2_mask);
@@ -742,13 +726,6 @@ static int saa7134_hwfini(struct saa7134_dev *dev)
{
dprintk("hwfini\n");
- switch (dev->pci->device) {
- case PCI_DEVICE_ID_PHILIPS_SAA7134:
- case PCI_DEVICE_ID_PHILIPS_SAA7133:
- case PCI_DEVICE_ID_PHILIPS_SAA7135:
- saa7134_oss_fini(dev);
- break;
- }
if (card_has_mpeg(dev))
saa7134_ts_fini(dev);
saa7134_input_fini(dev);
@@ -986,11 +963,12 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev,
if (card_is_dvb(dev))
request_module_depend("saa7134-dvb",&need_dvb);
- if (!oss && alsa) {
- dprintk("Requesting ALSA module\n");
+
+ if (alsa)
request_module_depend("saa7134-alsa",&need_alsa);
- }
+ if (oss)
+ request_module_depend("saa7134-oss",&need_oss);
v4l2_prio_init(&dev->prio);
@@ -1024,32 +1002,6 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev,
dev->name,dev->radio_dev->minor & 0x1f);
}
- /* register oss devices */
- switch (dev->pci->device) {
- case PCI_DEVICE_ID_PHILIPS_SAA7134:
- case PCI_DEVICE_ID_PHILIPS_SAA7133:
- case PCI_DEVICE_ID_PHILIPS_SAA7135:
- if (oss) {
- err = dev->dmasound.minor_dsp =
- register_sound_dsp(&saa7134_dsp_fops,
- dsp_nr[dev->nr]);
- if (err < 0) {
- goto fail4;
- }
- printk(KERN_INFO "%s: registered device dsp%d\n",
- dev->name,dev->dmasound.minor_dsp >> 4);
-
- err = dev->dmasound.minor_mixer =
- register_sound_mixer(&saa7134_mixer_fops,
- mixer_nr[dev->nr]);
- if (err < 0)
- goto fail5;
- printk(KERN_INFO "%s: registered device mixer%d\n",
- dev->name,dev->dmasound.minor_mixer >> 4);
- }
- break;
- }
-
/* everything worked */
pci_set_drvdata(pci_dev,dev);
saa7134_devcount++;
@@ -1064,17 +1016,9 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev,
/* check for signal */
saa7134_irq_video_intl(dev);
+
return 0;
- fail5:
- switch (dev->pci->device) {
- case PCI_DEVICE_ID_PHILIPS_SAA7134:
- case PCI_DEVICE_ID_PHILIPS_SAA7133:
- case PCI_DEVICE_ID_PHILIPS_SAA7135:
- if (oss)
- unregister_sound_dsp(dev->dmasound.minor_dsp);
- break;
- }
fail4:
saa7134_unregister_video(dev);
saa7134_i2c_unregister(dev);
@@ -1125,19 +1069,16 @@ static void __devexit saa7134_finidev(struct pci_dev *pci_dev)
saa7134_devcount--;
saa7134_i2c_unregister(dev);
- switch (dev->pci->device) {
- case PCI_DEVICE_ID_PHILIPS_SAA7134:
- case PCI_DEVICE_ID_PHILIPS_SAA7133:
- case PCI_DEVICE_ID_PHILIPS_SAA7135:
- if (oss) {
- unregister_sound_mixer(dev->dmasound.minor_mixer);
- unregister_sound_dsp(dev->dmasound.minor_dsp);
- }
- break;
- }
saa7134_unregister_video(dev);
- /* release ressources */
+ /* the DMA sound modules should be unloaded before reaching
+ this, but just in case they are still present... */
+ if (dev->dmasound.priv_data != NULL) {
+ free_irq(pci_dev->irq, &dev->dmasound);
+ dev->dmasound.priv_data = NULL;
+ }
+
+ /* release resources */
free_irq(pci_dev->irq, dev);
iounmap(dev->lmmio);
release_mem_region(pci_resource_start(pci_dev,0),
@@ -1225,7 +1166,7 @@ EXPORT_SYMBOL(saa7134_i2c_call_clients);
EXPORT_SYMBOL(saa7134_devlist);
EXPORT_SYMBOL(saa7134_boards);
-/* ----------------- For ALSA -------------------------------- */
+/* ----------------- for the DMA sound modules --------------- */
EXPORT_SYMBOL(saa7134_pgtable_free);
EXPORT_SYMBOL(saa7134_pgtable_build);
diff --git a/drivers/media/video/saa7134/saa7134-input.c b/drivers/media/video/saa7134/saa7134-input.c
index 329accda6d4..e648cc3bc96 100644
--- a/drivers/media/video/saa7134/saa7134-input.c
+++ b/drivers/media/video/saa7134/saa7134-input.c
@@ -485,64 +485,6 @@ static IR_KEYTAB_TYPE ir_codes_purpletv[IR_KEYTAB_SIZE] = {
};
-static IR_KEYTAB_TYPE ir_codes_pinnacle[IR_KEYTAB_SIZE] = {
- [ 0x59 ] = KEY_MUTE,
- [ 0x4a ] = KEY_POWER,
-
- [ 0x18 ] = KEY_TEXT,
- [ 0x26 ] = KEY_TV,
- [ 0x3d ] = KEY_PRINT,
-
- [ 0x48 ] = KEY_RED,
- [ 0x04 ] = KEY_GREEN,
- [ 0x11 ] = KEY_YELLOW,
- [ 0x00 ] = KEY_BLUE,
-
- [ 0x2d ] = KEY_VOLUMEUP,
- [ 0x1e ] = KEY_VOLUMEDOWN,
-
- [ 0x49 ] = KEY_MENU,
-
- [ 0x16 ] = KEY_CHANNELUP,
- [ 0x17 ] = KEY_CHANNELDOWN,
-
- [ 0x20 ] = KEY_UP,
- [ 0x21 ] = KEY_DOWN,
- [ 0x22 ] = KEY_LEFT,
- [ 0x23 ] = KEY_RIGHT,
- [ 0x0d ] = KEY_SELECT,
-
-
-
- [ 0x08 ] = KEY_BACK,
- [ 0x07 ] = KEY_REFRESH,
-
- [ 0x2f ] = KEY_ZOOM,
- [ 0x29 ] = KEY_RECORD,
-
- [ 0x4b ] = KEY_PAUSE,
- [ 0x4d ] = KEY_REWIND,
- [ 0x2e ] = KEY_PLAY,
- [ 0x4e ] = KEY_FORWARD,
- [ 0x53 ] = KEY_PREVIOUS,
- [ 0x4c ] = KEY_STOP,
- [ 0x54 ] = KEY_NEXT,
-
- [ 0x69 ] = KEY_KP0,
- [ 0x6a ] = KEY_KP1,
- [ 0x6b ] = KEY_KP2,
- [ 0x6c ] = KEY_KP3,
- [ 0x6d ] = KEY_KP4,
- [ 0x6e ] = KEY_KP5,
- [ 0x6f ] = KEY_KP6,
- [ 0x70 ] = KEY_KP7,
- [ 0x71 ] = KEY_KP8,
- [ 0x72 ] = KEY_KP9,
-
- [ 0x74 ] = KEY_CHANNEL,
- [ 0x0a ] = KEY_BACKSPACE,
-};
-
/* Mapping for the 28 key remote control as seen at
http://www.sednacomputer.com/photo/cardbus-tv.jpg
Pavel Mihaylov <bin@bash.info> */
@@ -635,57 +577,6 @@ static int get_key_purpletv(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
return 1;
}
-/* The new pinnacle PCTV remote (with the colored buttons)
- *
- * Ricardo Cerqueira <v4l@cerqueira.org>
- */
-
-static int get_key_pinnacle(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw)
-{
- unsigned char b[4];
- unsigned int start = 0,parity = 0,code = 0;
-
- /* poll IR chip */
- if (4 != i2c_master_recv(&ir->c,b,4)) {
- i2cdprintk("read error\n");
- return -EIO;
- }
-
- for (start = 0; start<4; start++) {
- if (b[start] == 0x80) {
- code=b[(start+3)%4];
- parity=b[(start+2)%4];
- }
- }
-
- /* Empty Request */
- if (parity==0)
- return 0;
-
- /* Repeating... */
- if (ir->old == parity)
- return 0;
-
-
- ir->old = parity;
-
- /* Reduce code value to fit inside IR_KEYTAB_SIZE
- *
- * this is the only value that results in 42 unique
- * codes < 128
- */
-
- code %= 0x88;
-
- *ir_raw = code;
- *ir_key = code;
-
- i2cdprintk("Pinnacle PCTV key %02x\n", code);
-
- return 1;
-}
-
-
void saa7134_input_irq(struct saa7134_dev *dev)
{
struct saa7134_ir *ir = dev->remote;
diff --git a/drivers/media/video/saa7134/saa7134-oss.c b/drivers/media/video/saa7134/saa7134-oss.c
index fd53dfcc164..fd9ed11ab1e 100644
--- a/drivers/media/video/saa7134/saa7134-oss.c
+++ b/drivers/media/video/saa7134/saa7134-oss.c
@@ -4,6 +4,8 @@
* oss dsp interface
*
* (c) 2001,02 Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]
+ * 2005 conversion to standalone module:
+ * Ricardo Cerqueira <v4l@cerqueira.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -25,7 +27,9 @@
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/kernel.h>
+#include <linux/interrupt.h>
#include <linux/slab.h>
+#include <linux/sound.h>
#include <linux/soundcard.h>
#include "saa7134-reg.h"
@@ -33,15 +37,23 @@
/* ------------------------------------------------------------------ */
-static unsigned int oss_debug = 0;
-module_param(oss_debug, int, 0644);
-MODULE_PARM_DESC(oss_debug,"enable debug messages [oss]");
+static unsigned int debug = 0;
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug,"enable debug messages [oss]");
-static unsigned int oss_rate = 0;
-module_param(oss_rate, int, 0444);
-MODULE_PARM_DESC(oss_rate,"sample rate (valid are: 32000,48000)");
+static unsigned int rate = 0;
+module_param(rate, int, 0444);
+MODULE_PARM_DESC(rate,"sample rate (valid are: 32000,48000)");
-#define dprintk(fmt, arg...) if (oss_debug) \
+static unsigned int dsp_nr[] = {[0 ... (SAA7134_MAXBOARDS - 1)] = UNSET };
+MODULE_PARM_DESC(dsp_nr, "device numbers for SAA7134 capture interface(s).");
+module_param_array(dsp_nr, int, NULL, 0444);
+
+static unsigned int mixer_nr[] = {[0 ... (SAA7134_MAXBOARDS - 1)] = UNSET };
+MODULE_PARM_DESC(mixer_nr, "mixer numbers for SAA7134 capture interface(s).");
+module_param_array(mixer_nr, int, NULL, 0444);
+
+#define dprintk(fmt, arg...) if (debug) \
printk(KERN_DEBUG "%s/oss: " fmt, dev->name , ## arg)
@@ -369,7 +381,7 @@ static int dsp_ioctl(struct inode *inode, struct file *file,
int __user *p = argp;
int val = 0;
- if (oss_debug > 1)
+ if (debug > 1)
saa7134_print_ioctl(dev->name,cmd);
switch (cmd) {
case OSS_GETVERSION:
@@ -665,7 +677,7 @@ static int mixer_ioctl(struct inode *inode, struct file *file,
void __user *argp = (void __user *) arg;
int __user *p = argp;
- if (oss_debug > 1)
+ if (debug > 1)
saa7134_print_ioctl(dev->name,cmd);
switch (cmd) {
case OSS_GETVERSION:
@@ -768,8 +780,41 @@ struct file_operations saa7134_mixer_fops = {
/* ------------------------------------------------------------------ */
+static irqreturn_t saa7134_oss_irq(int irq, void *dev_id, struct pt_regs *regs)
+{
+ struct saa7134_dmasound *dmasound = dev_id;
+ struct saa7134_dev *dev = dmasound->priv_data;
+ unsigned long report, status;
+ int loop, handled = 0;
+
+ for (loop = 0; loop < 10; loop++) {
+ report = saa_readl(SAA7134_IRQ_REPORT);
+ status = saa_readl(SAA7134_IRQ_STATUS);
+
+ if (report & SAA7134_IRQ_REPORT_DONE_RA3) {
+ handled = 1;
+ saa_writel(SAA7134_IRQ_REPORT,report);
+ saa7134_irq_oss_done(dev, status);
+ } else {
+ goto out;
+ }
+ }
+
+ if (loop == 10) {
+ dprintk("error! looping IRQ!");
+ }
+out:
+ return IRQ_RETVAL(handled);
+}
+
int saa7134_oss_init1(struct saa7134_dev *dev)
{
+
+ if ((request_irq(dev->pci->irq, saa7134_oss_irq,
+ SA_SHIRQ | SA_INTERRUPT, dev->name,
+ (void*) &dev->dmasound)) < 0)
+ return -1;
+
/* general */
init_MUTEX(&dev->dmasound.lock);
init_waitqueue_head(&dev->dmasound.wq);
@@ -785,8 +830,8 @@ int saa7134_oss_init1(struct saa7134_dev *dev)
/* dsp */
dev->dmasound.rate = 32000;
- if (oss_rate)
- dev->dmasound.rate = oss_rate;
+ if (rate)
+ dev->dmasound.rate = rate;
dev->dmasound.rate = (dev->dmasound.rate > 40000) ? 48000 : 32000;
/* mixer */
@@ -840,7 +885,7 @@ void saa7134_irq_oss_done(struct saa7134_dev *dev, unsigned long status)
/* next block addr */
next_blk = (dev->dmasound.dma_blk + 2) % dev->dmasound.blocks;
saa_writel(reg,next_blk * dev->dmasound.blksize);
- if (oss_debug > 2)
+ if (debug > 2)
dprintk("irq: ok, %s, next_blk=%d, addr=%x\n",
(status & 0x10000000) ? "even" : "odd ", next_blk,
next_blk * dev->dmasound.blksize);
@@ -854,6 +899,98 @@ void saa7134_irq_oss_done(struct saa7134_dev *dev, unsigned long status)
spin_unlock(&dev->slock);
}
+int saa7134_dsp_create(struct saa7134_dev *dev)
+{
+ int err;
+
+ err = dev->dmasound.minor_dsp =
+ register_sound_dsp(&saa7134_dsp_fops,
+ dsp_nr[dev->nr]);
+ if (err < 0) {
+ goto fail;
+ }
+ printk(KERN_INFO "%s: registered device dsp%d\n",
+ dev->name,dev->dmasound.minor_dsp >> 4);
+
+ err = dev->dmasound.minor_mixer =
+ register_sound_mixer(&saa7134_mixer_fops,
+ mixer_nr[dev->nr]);
+ if (err < 0)
+ goto fail;
+ printk(KERN_INFO "%s: registered device mixer%d\n",
+ dev->name,dev->dmasound.minor_mixer >> 4);
+
+ return 0;
+
+fail:
+ unregister_sound_dsp(dev->dmasound.minor_dsp);
+ return 0;
+
+
+}
+
+static int saa7134_oss_init(void)
+{
+ struct saa7134_dev *dev = NULL;
+ struct list_head *list;
+
+ printk(KERN_INFO "saa7134 OSS driver for DMA sound loaded\n");
+
+ list_for_each(list,&saa7134_devlist) {
+ dev = list_entry(list, struct saa7134_dev, devlist);
+ if (dev->dmasound.priv_data == NULL) {
+ dev->dmasound.priv_data = dev;
+ saa7134_oss_init1(dev);
+ saa7134_dsp_create(dev);
+ } else {
+ printk(KERN_ERR "saa7134 OSS: DMA sound is being handled by ALSA, ignoring %s\n",dev->name);
+ return -EBUSY;
+ }
+ }
+
+ if (dev == NULL)
+ printk(KERN_INFO "saa7134 OSS: no saa7134 cards found\n");
+
+ return 0;
+
+}
+
+void saa7134_oss_exit(void)
+{
+ struct saa7134_dev *dev = NULL;
+ struct list_head *list;
+
+ list_for_each(list,&saa7134_devlist) {
+ dev = list_entry(list, struct saa7134_dev, devlist);
+
+ /* Device isn't registered by OSS, probably ALSA's */
+ if (!dev->dmasound.minor_dsp)
+ continue;
+
+ unregister_sound_mixer(dev->dmasound.minor_mixer);
+ unregister_sound_dsp(dev->dmasound.minor_dsp);
+
+ saa7134_oss_fini(dev);
+
+ if (dev->pci->irq > 0) {
+ synchronize_irq(dev->pci->irq);
+ free_irq(dev->pci->irq,&dev->dmasound);
+ }
+
+ dev->dmasound.priv_data = NULL;
+
+ }
+
+ printk(KERN_INFO "saa7134 OSS driver for DMA sound unloaded\n");
+
+ return;
+}
+
+module_init(saa7134_oss_init);
+module_exit(saa7134_oss_exit);
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]");
+
/* ----------------------------------------------------------- */
/*
* Local variables:
diff --git a/drivers/media/video/saa7134/saa7134.h b/drivers/media/video/saa7134/saa7134.h
index fb972747166..244e1973081 100644
--- a/drivers/media/video/saa7134/saa7134.h
+++ b/drivers/media/video/saa7134/saa7134.h
@@ -208,6 +208,7 @@ struct saa7134_format {
#define SAA7134_BOARD_SEDNA_PC_TV_CARDBUS 79
#define SAA7134_BOARD_ASUSTEK_DIGIMATRIX_TV 80
#define SAA7134_BOARD_PHILIPS_TIGER 81
+#define SAA7134_BOARD_MSI_TVATANYWHERE_PLUS 82
#define SAA7134_MAXBOARDS 8
#define SAA7134_INPUT_MAX 8
@@ -383,6 +384,7 @@ struct saa7134_dmasound {
unsigned int dma_blk;
unsigned int read_offset;
unsigned int read_count;
+ void * priv_data;
snd_pcm_substream_t *substream;
};