linux/sound/pci/rme32.c

// SPDX-License-Identifier: GPL-2.0-or-later
/*
 *   ALSA driver for RME Digi32, Digi32/8 and Digi32 PRO audio interfaces
 *
 *      Copyright (c) 2002-2004 Martin Langer <[email protected]>,
 *                              Pilo Chambert <[email protected]>
 *
 *      Thanks to :        Anders Torger <[email protected]>,
 *                         Henk Hesselink <[email protected]>
 *                         for writing the digi96-driver 
 *                         and RME for all informations.
 * 
 * ****************************************************************************
 * 
 * Note #1 "Sek'd models" ................................... martin 2002-12-07
 * 
 * Identical soundcards by Sek'd were labeled:
 * RME Digi 32     = Sek'd Prodif 32
 * RME Digi 32 Pro = Sek'd Prodif 96
 * RME Digi 32/8   = Sek'd Prodif Gold
 * 
 * ****************************************************************************
 * 
 * Note #2 "full duplex mode" ............................... martin 2002-12-07
 * 
 * Full duplex doesn't work. All cards (32, 32/8, 32Pro) are working identical
 * in this mode. Rec data and play data are using the same buffer therefore. At
 * first you have got the playing bits in the buffer and then (after playing
 * them) they were overwitten by the captured sound of the CS8412/14. Both 
 * modes (play/record) are running harmonically hand in hand in the same buffer
 * and you have only one start bit plus one interrupt bit to control this 
 * paired action.
 * This is opposite to the latter rme96 where playing and capturing is totally
 * separated and so their full duplex mode is supported by alsa (using two 
 * start bits and two interrupts for two different buffers). 
 * But due to the wrong sequence of playing and capturing ALSA shows no solved
 * full duplex support for the rme32 at the moment. That's bad, but I'm not
 * able to solve it. Are you motivated enough to solve this problem now? Your
 * patch would be welcome!
 * 
 * ****************************************************************************
 *
 * "The story after the long seeking" -- tiwai
 *
 * Ok, the situation regarding the full duplex is now improved a bit.
 * In the fullduplex mode (given by the module parameter), the hardware buffer
 * is split to halves for read and write directions at the DMA pointer.
 * That is, the half above the current DMA pointer is used for write, and
 * the half below is used for read.  To mangle this strange behavior, an
 * software intermediate buffer is introduced.  This is, of course, not good
 * from the viewpoint of the data transfer efficiency.  However, this allows
 * you to use arbitrary buffer sizes, instead of the fixed I/O buffer size.
 *
 * ****************************************************************************
 */


#include <linux/delay.h>
#include <linux/gfp.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/pci.h>
#include <linux/module.h>
#include <linux/io.h>

#include <sound/core.h>
#include <sound/info.h>
#include <sound/control.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
#include <sound/pcm-indirect.h>
#include <sound/asoundef.h>
#include <sound/initval.h>

static int index[SNDRV_CARDS] =;	/* Index 0-MAX */
static char *id[SNDRV_CARDS] =;	/* ID for this card */
static bool enable[SNDRV_CARDS] =;	/* Enable this card */
static bool fullduplex[SNDRV_CARDS]; // = {[0 ... (SNDRV_CARDS - 1)] = 1};

module_param_array();
MODULE_PARM_DESC();
module_param_array();
MODULE_PARM_DESC();
module_param_array();
MODULE_PARM_DESC();
module_param_array();
MODULE_PARM_DESC();
MODULE_AUTHOR();
MODULE_DESCRIPTION();
MODULE_LICENSE();

/* Defines for RME Digi32 series */
#define RME32_SPDIF_NCHANNELS

/* Playback and capture buffer size */
#define RME32_BUFFER_SIZE

/* IO area size */
#define RME32_IO_SIZE

/* IO area offsets */
#define RME32_IO_DATA_BUFFER
#define RME32_IO_CONTROL_REGISTER
#define RME32_IO_GET_POS
#define RME32_IO_CONFIRM_ACTION_IRQ
#define RME32_IO_RESET_POS

/* Write control register bits */
#define RME32_WCR_START
#define RME32_WCR_MONO
#define RME32_WCR_MODE24
#define RME32_WCR_SEL
#define RME32_WCR_FREQ_0
#define RME32_WCR_FREQ_1
#define RME32_WCR_INP_0
#define RME32_WCR_INP_1
#define RME32_WCR_RESET
#define RME32_WCR_MUTE
#define RME32_WCR_PRO
#define RME32_WCR_DS_BM
#define RME32_WCR_ADAT
#define RME32_WCR_AUTOSYNC
#define RME32_WCR_PD
#define RME32_WCR_EMP

#define RME32_WCR_BITPOS_FREQ_0
#define RME32_WCR_BITPOS_FREQ_1
#define RME32_WCR_BITPOS_INP_0
#define RME32_WCR_BITPOS_INP_1

/* Read control register bits */
#define RME32_RCR_AUDIO_ADDR_MASK
#define RME32_RCR_LOCK
#define RME32_RCR_ERF
#define RME32_RCR_FREQ_0
#define RME32_RCR_FREQ_1
#define RME32_RCR_FREQ_2
#define RME32_RCR_KMODE
#define RME32_RCR_IRQ

#define RME32_RCR_BITPOS_F0
#define RME32_RCR_BITPOS_F1
#define RME32_RCR_BITPOS_F2

/* Input types */
#define RME32_INPUT_OPTICAL
#define RME32_INPUT_COAXIAL
#define RME32_INPUT_INTERNAL
#define RME32_INPUT_XLR

/* Clock modes */
#define RME32_CLOCKMODE_SLAVE
#define RME32_CLOCKMODE_MASTER_32
#define RME32_CLOCKMODE_MASTER_44
#define RME32_CLOCKMODE_MASTER_48

/* Block sizes in bytes */
#define RME32_BLOCK_SIZE

/* Software intermediate buffer (max) size */
#define RME32_MID_BUFFER_SIZE

/* Hardware revisions */
#define RME32_32_REVISION
#define RME32_328_REVISION_OLD
#define RME32_328_REVISION_NEW
#define RME32_PRO_REVISION_WITH_8412
#define RME32_PRO_REVISION_WITH_8414


struct rme32 {};

static const struct pci_device_id snd_rme32_ids[] =;

MODULE_DEVICE_TABLE(pci, snd_rme32_ids);

#define RME32_ISWORKING(rme32)
#define RME32_PRO_WITH_8414(rme32)

static int snd_rme32_playback_prepare(struct snd_pcm_substream *substream);

static int snd_rme32_capture_prepare(struct snd_pcm_substream *substream);

static int snd_rme32_pcm_trigger(struct snd_pcm_substream *substream, int cmd);

static void snd_rme32_proc_init(struct rme32 * rme32);

static int snd_rme32_create_switches(struct snd_card *card, struct rme32 * rme32);

static inline unsigned int snd_rme32_pcm_byteptr(struct rme32 * rme32)
{}

/* silence callback for halfduplex mode */
static int snd_rme32_playback_silence(struct snd_pcm_substream *substream,
				      int channel, unsigned long pos,
				      unsigned long count)
{}

/* copy callback for halfduplex mode */
static int snd_rme32_playback_copy(struct snd_pcm_substream *substream,
				   int channel, unsigned long pos,
				   struct iov_iter *src, unsigned long count)
{}

/* copy callback for halfduplex mode */
static int snd_rme32_capture_copy(struct snd_pcm_substream *substream,
				  int channel, unsigned long pos,
				  struct iov_iter *dst, unsigned long count)
{}

/*
 * SPDIF I/O capabilities (half-duplex mode)
 */
static const struct snd_pcm_hardware snd_rme32_spdif_info =;

/*
 * ADAT I/O capabilities (half-duplex mode)
 */
static const struct snd_pcm_hardware snd_rme32_adat_info =;

/*
 * SPDIF I/O capabilities (full-duplex mode)
 */
static const struct snd_pcm_hardware snd_rme32_spdif_fd_info =;

/*
 * ADAT I/O capabilities (full-duplex mode)
 */
static const struct snd_pcm_hardware snd_rme32_adat_fd_info =;

static void snd_rme32_reset_dac(struct rme32 *rme32)
{}

static int snd_rme32_playback_getrate(struct rme32 * rme32)
{}

static int snd_rme32_capture_getrate(struct rme32 * rme32, int *is_adat)
{}

static int snd_rme32_playback_setrate(struct rme32 * rme32, int rate)
{}

static int snd_rme32_setclockmode(struct rme32 * rme32, int mode)
{}

static int snd_rme32_getclockmode(struct rme32 * rme32)
{}

static int snd_rme32_setinputtype(struct rme32 * rme32, int type)
{}

static int snd_rme32_getinputtype(struct rme32 * rme32)
{}

static void
snd_rme32_setframelog(struct rme32 * rme32, int n_channels, int is_playback)
{}

static int snd_rme32_setformat(struct rme32 *rme32, snd_pcm_format_t format)
{}

static int
snd_rme32_playback_hw_params(struct snd_pcm_substream *substream,
			     struct snd_pcm_hw_params *params)
{}

static int
snd_rme32_capture_hw_params(struct snd_pcm_substream *substream,
			    struct snd_pcm_hw_params *params)
{}

static void snd_rme32_pcm_start(struct rme32 * rme32, int from_pause)
{}

static void snd_rme32_pcm_stop(struct rme32 * rme32, int to_pause)
{}

static irqreturn_t snd_rme32_interrupt(int irq, void *dev_id)
{}

static const unsigned int period_bytes[] =;

static const struct snd_pcm_hw_constraint_list hw_constraints_period_bytes =;

static void snd_rme32_set_buffer_constraint(struct rme32 *rme32, struct snd_pcm_runtime *runtime)
{}

static int snd_rme32_playback_spdif_open(struct snd_pcm_substream *substream)
{}

static int snd_rme32_capture_spdif_open(struct snd_pcm_substream *substream)
{}

static int
snd_rme32_playback_adat_open(struct snd_pcm_substream *substream)
{}

static int
snd_rme32_capture_adat_open(struct snd_pcm_substream *substream)
{}

static int snd_rme32_playback_close(struct snd_pcm_substream *substream)
{}

static int snd_rme32_capture_close(struct snd_pcm_substream *substream)
{}

static int snd_rme32_playback_prepare(struct snd_pcm_substream *substream)
{}

static int snd_rme32_capture_prepare(struct snd_pcm_substream *substream)
{}

static int
snd_rme32_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
{}

/* pointer callback for halfduplex mode */
static snd_pcm_uframes_t
snd_rme32_playback_pointer(struct snd_pcm_substream *substream)
{}

static snd_pcm_uframes_t
snd_rme32_capture_pointer(struct snd_pcm_substream *substream)
{}


/* ack and pointer callbacks for fullduplex mode */
static void snd_rme32_pb_trans_copy(struct snd_pcm_substream *substream,
				    struct snd_pcm_indirect *rec, size_t bytes)
{}

static int snd_rme32_playback_fd_ack(struct snd_pcm_substream *substream)
{}

static void snd_rme32_cp_trans_copy(struct snd_pcm_substream *substream,
				    struct snd_pcm_indirect *rec, size_t bytes)
{}

static int snd_rme32_capture_fd_ack(struct snd_pcm_substream *substream)
{}

static snd_pcm_uframes_t
snd_rme32_playback_fd_pointer(struct snd_pcm_substream *substream)
{}

static snd_pcm_uframes_t
snd_rme32_capture_fd_pointer(struct snd_pcm_substream *substream)
{}

/* for halfduplex mode */
static const struct snd_pcm_ops snd_rme32_playback_spdif_ops =;

static const struct snd_pcm_ops snd_rme32_capture_spdif_ops =;

static const struct snd_pcm_ops snd_rme32_playback_adat_ops =;

static const struct snd_pcm_ops snd_rme32_capture_adat_ops =;

/* for fullduplex mode */
static const struct snd_pcm_ops snd_rme32_playback_spdif_fd_ops =;

static const struct snd_pcm_ops snd_rme32_capture_spdif_fd_ops =;

static const struct snd_pcm_ops snd_rme32_playback_adat_fd_ops =;

static const struct snd_pcm_ops snd_rme32_capture_adat_fd_ops =;

static void snd_rme32_free(struct rme32 *rme32)
{}

static void snd_rme32_free_spdif_pcm(struct snd_pcm *pcm)
{}

static void
snd_rme32_free_adat_pcm(struct snd_pcm *pcm)
{}

static int snd_rme32_create(struct rme32 *rme32)
{}

/*
 * proc interface
 */

static void
snd_rme32_proc_read(struct snd_info_entry * entry, struct snd_info_buffer *buffer)
{}

static void snd_rme32_proc_init(struct rme32 *rme32)
{}

/*
 * control interface
 */

#define snd_rme32_info_loopback_control

static int
snd_rme32_get_loopback_control(struct snd_kcontrol *kcontrol,
			       struct snd_ctl_elem_value *ucontrol)
{}
static int
snd_rme32_put_loopback_control(struct snd_kcontrol *kcontrol,
			       struct snd_ctl_elem_value *ucontrol)
{}

static int
snd_rme32_info_inputtype_control(struct snd_kcontrol *kcontrol,
				 struct snd_ctl_elem_info *uinfo)
{}
static int
snd_rme32_get_inputtype_control(struct snd_kcontrol *kcontrol,
				struct snd_ctl_elem_value *ucontrol)
{}
static int
snd_rme32_put_inputtype_control(struct snd_kcontrol *kcontrol,
				struct snd_ctl_elem_value *ucontrol)
{}

static int
snd_rme32_info_clockmode_control(struct snd_kcontrol *kcontrol,
				 struct snd_ctl_elem_info *uinfo)
{}
static int
snd_rme32_get_clockmode_control(struct snd_kcontrol *kcontrol,
				struct snd_ctl_elem_value *ucontrol)
{}
static int
snd_rme32_put_clockmode_control(struct snd_kcontrol *kcontrol,
				struct snd_ctl_elem_value *ucontrol)
{}

static u32 snd_rme32_convert_from_aes(struct snd_aes_iec958 * aes)
{}

static void snd_rme32_convert_to_aes(struct snd_aes_iec958 * aes, u32 val)
{}

static int snd_rme32_control_spdif_info(struct snd_kcontrol *kcontrol,
					struct snd_ctl_elem_info *uinfo)
{}

static int snd_rme32_control_spdif_get(struct snd_kcontrol *kcontrol,
				       struct snd_ctl_elem_value *ucontrol)
{}

static int snd_rme32_control_spdif_put(struct snd_kcontrol *kcontrol,
				       struct snd_ctl_elem_value *ucontrol)
{}

static int snd_rme32_control_spdif_stream_info(struct snd_kcontrol *kcontrol,
					       struct snd_ctl_elem_info *uinfo)
{}

static int snd_rme32_control_spdif_stream_get(struct snd_kcontrol *kcontrol,
					      struct snd_ctl_elem_value *
					      ucontrol)
{}

static int snd_rme32_control_spdif_stream_put(struct snd_kcontrol *kcontrol,
					      struct snd_ctl_elem_value *
					      ucontrol)
{}

static int snd_rme32_control_spdif_mask_info(struct snd_kcontrol *kcontrol,
					     struct snd_ctl_elem_info *uinfo)
{}

static int snd_rme32_control_spdif_mask_get(struct snd_kcontrol *kcontrol,
					    struct snd_ctl_elem_value *
					    ucontrol)
{}

static const struct snd_kcontrol_new snd_rme32_controls[] =;

static int snd_rme32_create_switches(struct snd_card *card, struct rme32 * rme32)
{}

/*
 * Card initialisation
 */

static void snd_rme32_card_free(struct snd_card *card)
{}

static int
__snd_rme32_probe(struct pci_dev *pci, const struct pci_device_id *pci_id)
{}

static int
snd_rme32_probe(struct pci_dev *pci, const struct pci_device_id *pci_id)
{}

static struct pci_driver rme32_driver =;

module_pci_driver();