// SPDX-License-Identifier: GPL-2.0-only
/*
* SAA713x ALSA support for V4L
*/
#include "saa7134.h"
#include "saa7134-reg.h"
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/time.h>
#include <linux/wait.h>
#include <linux/module.h>
#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 <linux/vmalloc.h>
/*
* Configuration macros
*/
/* defaults */
#define MIXER_ADDR_UNSELECTED -1
#define MIXER_ADDR_TVTUNER 0
#define MIXER_ADDR_LINE1 1
#define MIXER_ADDR_LINE2 2
#define MIXER_ADDR_LAST 2
static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */
static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */
static int enable[SNDRV_CARDS] = {1, [1 ... (SNDRV_CARDS - 1)] = 1};
module_param_array(index, int, NULL, 0444);
module_param_array(enable, int, NULL, 0444);
MODULE_PARM_DESC(index, "Index value for SAA7134 capture interface(s).");
MODULE_PARM_DESC(enable, "Enable (or not) the SAA7134 capture interface(s).");
/*
* Main chip structure
*/
typedef struct snd_card_saa7134 {
struct snd_card *card;
spinlock_t mixer_lock;
int mixer_volume[MIXER_ADDR_LAST+1][2];
int capture_source_addr;
int capture_source[2];
struct snd_kcontrol *capture_ctl[MIXER_ADDR_LAST+1];
struct pci_dev *pci;
struct saa7134_dev *dev;
unsigned long iobase;
s16 irq;
u16 mute_was_on;
spinlock_t lock;
} snd_card_saa7134_t;
/*
* PCM structure
*/
typedef struct snd_card_saa7134_pcm {
struct saa7134_dev *dev;
spinlock_t lock;
struct snd_pcm_substream *substream;
} snd_card_saa7134_pcm_t;
static struct snd_card *snd_saa7134_cards[SNDRV_CARDS];
/*
* saa7134 DMA audio stop
*
* Called when the capture device is released or the buffer overflows
*
* - 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;
saa7134_set_dmabits(dev);
}
/*
* saa7134 DMA audio start
*
* Called when preparing the capture device for use
*
* - Copied verbatim from saa7134-oss's dsp_dma_start.
*
*/
static void saa7134_dma_start(struct saa7134_dev *dev)
{
dev->dmasound.dma_blk = 0;
dev->dmasound.dma_running = 1;
saa7134_set_dmabits(dev);
}
/*
* saa7134 audio DMA IRQ handler
*
* Called whenever we get an SAA7134_IRQ_REPORT_DONE_RA3 interrupt
* Handles shifting between the 2 buffers, manages the read counters,
* and notifies ALSA when periods elapse
*
* - Mostly copied from saa7134-oss's saa7134_irq_oss_done.
*
*/
static void saa7134_irq_alsa_done(struct saa7134_dev *dev,
unsigned long status)
{
int next_blk, reg = 0;
spin_lock(&dev->slock);
if (UNSET == dev->dmasound.dma_blk) {
pr_debug("irq: recording stopped\n");
goto done;
}
if (0 != (status & 0x0f000000))
pr_debug("irq: lost %ld\n", (status >> 24) & 0x0f);
if (0 == (status & 0x10000000)) {
/* odd */
if (