linux/sound/pci/cs4281.c

// SPDX-License-Identifier: GPL-2.0-or-later
/*
 *  Driver for Cirrus Logic CS4281 based PCI soundcard
 *  Copyright (c) by Jaroslav Kysela <[email protected]>,
 */

#include <linux/io.h>
#include <linux/delay.h>
#include <linux/interrupt.h>
#include <linux/init.h>
#include <linux/pci.h>
#include <linux/slab.h>
#include <linux/gameport.h>
#include <linux/module.h>
#include <sound/core.h>
#include <sound/control.h>
#include <sound/pcm.h>
#include <sound/rawmidi.h>
#include <sound/ac97_codec.h>
#include <sound/tlv.h>
#include <sound/opl3.h>
#include <sound/initval.h>


MODULE_AUTHOR();
MODULE_DESCRIPTION();
MODULE_LICENSE();

static int index[SNDRV_CARDS] =;	/* Index 0-MAX */
static char *id[SNDRV_CARDS] =;	/* ID for this card */
static bool enable[SNDRV_CARDS] =;	/* Enable switches */
static bool dual_codec[SNDRV_CARDS];	/* dual codec */

module_param_array();
MODULE_PARM_DESC();
module_param_array();
MODULE_PARM_DESC();
module_param_array();
MODULE_PARM_DESC();
module_param_array();
MODULE_PARM_DESC();

/*
 *  Direct registers
 */

#define CS4281_BA0_SIZE
#define CS4281_BA1_SIZE

/*
 *  BA0 registers
 */
#define BA0_HISR
#define BA0_HISR_INTENA
#define BA0_HISR_MIDI
#define BA0_HISR_FIFOI
#define BA0_HISR_DMAI
#define BA0_HISR_FIFO(c)
#define BA0_HISR_DMA(c)
#define BA0_HISR_GPPI
#define BA0_HISR_GPSI
#define BA0_HISR_GP3I
#define BA0_HISR_GP1I
#define BA0_HISR_VUPI
#define BA0_HISR_VDNI

#define BA0_HICR
#define BA0_HICR_CHGM
#define BA0_HICR_IEV
#define BA0_HICR_EOI

#define BA0_HIMR
					/* Use same contants as for BA0_HISR */

#define BA0_IIER

#define BA0_HDSR0
#define BA0_HDSR1
#define BA0_HDSR2
#define BA0_HDSR3

#define BA0_HDSR_CH1P
#define BA0_HDSR_CH2P
#define BA0_HDSR_DHTC
#define BA0_HDSR_DTC
#define BA0_HDSR_DRUN
#define BA0_HDSR_RQ

#define BA0_DCA0
#define BA0_DCC0
#define BA0_DBA0
#define BA0_DBC0
#define BA0_DCA1
#define BA0_DCC1
#define BA0_DBA1
#define BA0_DBC1
#define BA0_DCA2
#define BA0_DCC2
#define BA0_DBA2
#define BA0_DBC2
#define BA0_DCA3
#define BA0_DCC3
#define BA0_DBA3
#define BA0_DBC3
#define BA0_DMR0
#define BA0_DCR0
#define BA0_DMR1
#define BA0_DCR1
#define BA0_DMR2
#define BA0_DCR2
#define BA0_DMR3
#define BA0_DCR3

#define BA0_DMR_DMA
#define BA0_DMR_POLL
#define BA0_DMR_TBC
#define BA0_DMR_CBC
#define BA0_DMR_SWAPC
#define BA0_DMR_SIZE20
#define BA0_DMR_USIGN
#define BA0_DMR_BEND
#define BA0_DMR_MONO
#define BA0_DMR_SIZE8
#define BA0_DMR_TYPE_DEMAND
#define BA0_DMR_TYPE_SINGLE
#define BA0_DMR_TYPE_BLOCK
#define BA0_DMR_TYPE_CASCADE
#define BA0_DMR_DEC
#define BA0_DMR_AUTO
#define BA0_DMR_TR_VERIFY
#define BA0_DMR_TR_WRITE
#define BA0_DMR_TR_READ

#define BA0_DCR_HTCIE
#define BA0_DCR_TCIE
#define BA0_DCR_MSK

#define BA0_FCR0
#define BA0_FCR1
#define BA0_FCR2
#define BA0_FCR3

#define BA0_FCR_FEN
#define BA0_FCR_DACZ
#define BA0_FCR_PSH
#define BA0_FCR_RS(x)
#define BA0_FCR_LS(x)
#define BA0_FCR_SZ(x)
#define BA0_FCR_OF(x)

#define BA0_FPDR0
#define BA0_FPDR1
#define BA0_FPDR2
#define BA0_FPDR3

#define BA0_FCHS
#define BA0_FCHS_RCO(x)
#define BA0_FCHS_LCO(x)
#define BA0_FCHS_MRP(x)
#define BA0_FCHS_FE(x)
#define BA0_FCHS_FF(x)
#define BA0_FCHS_IOR(x)
#define BA0_FCHS_RCI(x)
#define BA0_FCHS_LCI(x)

#define BA0_FSIC0
#define BA0_FSIC1
#define BA0_FSIC2
#define BA0_FSIC3

#define BA0_FSIC_FIC(x)
#define BA0_FSIC_FORIE
#define BA0_FSIC_FURIE
#define BA0_FSIC_FSCIE
#define BA0_FSIC_FSC(x)
#define BA0_FSIC_FOR
#define BA0_FSIC_FUR
#define BA0_FSIC_FSCR

#define BA0_PMCS
#define BA0_CWPR

#define BA0_EPPMC
#define BA0_EPPMC_FPDN

#define BA0_GPIOR

#define BA0_SPMC
#define BA0_SPMC_GIPPEN
#define BA0_SPMC_GISPEN
#define BA0_SPMC_EESPD
#define BA0_SPMC_ASDI2E
#define BA0_SPMC_ASDO
#define BA0_SPMC_WUP2
#define BA0_SPMC_WUP1
#define BA0_SPMC_ASYNC
#define BA0_SPMC_RSTN

#define BA0_CFLR
#define BA0_CFLR_DEFAULT
#define BA0_IISR
#define BA0_TMS
#define BA0_SSVID

#define BA0_CLKCR1
#define BA0_CLKCR1_CLKON
#define BA0_CLKCR1_DLLRDY
#define BA0_CLKCR1_DLLOS
#define BA0_CLKCR1_SWCE
#define BA0_CLKCR1_DLLP
#define BA0_CLKCR1_DLLSS

#define BA0_FRR
#define BA0_SLT12O

#define BA0_SERMC
#define BA0_SERMC_FCRN
#define BA0_SERMC_ODSEN2
#define BA0_SERMC_ODSEN1
#define BA0_SERMC_SXLB
#define BA0_SERMC_SLB
#define BA0_SERMC_LOVF
#define BA0_SERMC_TCID(x)
#define BA0_SERMC_PXLB
#define BA0_SERMC_PLB
#define BA0_SERMC_PTC
#define BA0_SERMC_PTC_AC97
#define BA0_SERMC_MSPE

#define BA0_SERC1
#define BA0_SERC1_SO1F(x)
#define BA0_SERC1_AC97
#define BA0_SERC1_SO1EN

#define BA0_SERC2
#define BA0_SERC2_SI1F(x)
#define BA0_SERC2_AC97
#define BA0_SERC2_SI1EN

#define BA0_SLT12M

#define BA0_ACCTL
#define BA0_ACCTL_TC
#define BA0_ACCTL_CRW
#define BA0_ACCTL_DCV
#define BA0_ACCTL_VFRM
#define BA0_ACCTL_ESYN

#define BA0_ACSTS
#define BA0_ACSTS_VSTS
#define BA0_ACSTS_CRDY

#define BA0_ACOSV
#define BA0_ACOSV_SLV(x)

#define BA0_ACCAD
#define BA0_ACCDA

#define BA0_ACISV
#define BA0_ACISV_SLV(x)

#define BA0_ACSAD
#define BA0_ACSDA
#define BA0_JSPT
#define BA0_JSCTL
#define BA0_JSC1
#define BA0_JSC2
#define BA0_JSIO

#define BA0_MIDCR
#define BA0_MIDCR_MRST
#define BA0_MIDCR_MLB
#define BA0_MIDCR_TIE
#define BA0_MIDCR_RIE
#define BA0_MIDCR_RXE
#define BA0_MIDCR_TXE

#define BA0_MIDCMD

#define BA0_MIDSR
#define BA0_MIDSR_RDA
#define BA0_MIDSR_TBE
#define BA0_MIDSR_RBE
#define BA0_MIDSR_TBF

#define BA0_MIDWP
#define BA0_MIDRP

#define BA0_AODSD1
#define BA0_AODSD1_NDS(x)

#define BA0_AODSD2
#define BA0_AODSD2_NDS(x)

#define BA0_CFGI
#define BA0_SLT12M2
#define BA0_ACSTS2
#define BA0_ACISV2
#define BA0_ACSAD2
#define BA0_ACSDA2
#define BA0_FMSR
#define BA0_B0AP
#define BA0_FMDP
#define BA0_B1AP
#define BA0_B1DP

#define BA0_SSPM
#define BA0_SSPM_MIXEN
#define BA0_SSPM_CSRCEN
#define BA0_SSPM_PSRCEN
#define BA0_SSPM_JSEN
#define BA0_SSPM_ACLEN
#define BA0_SSPM_FMEN

#define BA0_DACSR
#define BA0_ADCSR

#define BA0_SSCR
#define BA0_SSCR_HVS1
#define BA0_SSCR_MVCS
#define BA0_SSCR_MVLD
#define BA0_SSCR_MVAD
#define BA0_SSCR_MVMD
#define BA0_SSCR_XLPSRC
#define BA0_SSCR_LPSRC
#define BA0_SSCR_CDTX
#define BA0_SSCR_HVC

#define BA0_FMLVC
#define BA0_FMRVC
#define BA0_SRCSA
#define BA0_PPLVC
#define BA0_PPRVC
#define BA0_PASR
#define BA0_CASR

/* Source Slot Numbers - Playback */
#define SRCSLOT_LEFT_PCM_PLAYBACK
#define SRCSLOT_RIGHT_PCM_PLAYBACK
#define SRCSLOT_PHONE_LINE_1_DAC
#define SRCSLOT_CENTER_PCM_PLAYBACK
#define SRCSLOT_LEFT_SURROUND_PCM_PLAYBACK
#define SRCSLOT_RIGHT_SURROUND_PCM_PLAYBACK
#define SRCSLOT_LFE_PCM_PLAYBACK
#define SRCSLOT_PHONE_LINE_2_DAC
#define SRCSLOT_HEADSET_DAC
#define SRCSLOT_LEFT_WT
#define SRCSLOT_RIGHT_WT

/* Source Slot Numbers - Capture */
#define SRCSLOT_LEFT_PCM_RECORD
#define SRCSLOT_RIGHT_PCM_RECORD
#define SRCSLOT_PHONE_LINE_1_ADC
#define SRCSLOT_MIC_ADC
#define SRCSLOT_PHONE_LINE_2_ADC
#define SRCSLOT_HEADSET_ADC
#define SRCSLOT_SECONDARY_LEFT_PCM_RECORD
#define SRCSLOT_SECONDARY_RIGHT_PCM_RECORD
#define SRCSLOT_SECONDARY_PHONE_LINE_1_ADC
#define SRCSLOT_SECONDARY_MIC_ADC
#define SRCSLOT_SECONDARY_PHONE_LINE_2_ADC
#define SRCSLOT_SECONDARY_HEADSET_ADC

/* Source Slot Numbers - Others */
#define SRCSLOT_POWER_DOWN

/* MIDI modes */
#define CS4281_MODE_OUTPUT
#define CS4281_MODE_INPUT

/* joystick bits */
/* Bits for JSPT */
#define JSPT_CAX
#define JSPT_CAY
#define JSPT_CBX
#define JSPT_CBY
#define JSPT_BA1
#define JSPT_BA2
#define JSPT_BB1
#define JSPT_BB2

/* Bits for JSCTL */
#define JSCTL_SP_MASK
#define JSCTL_SP_SLOW
#define JSCTL_SP_MEDIUM_SLOW
#define JSCTL_SP_MEDIUM_FAST
#define JSCTL_SP_FAST
#define JSCTL_ARE

/* Data register pairs masks */
#define JSC1_Y1V_MASK
#define JSC1_X1V_MASK
#define JSC1_Y1V_SHIFT
#define JSC1_X1V_SHIFT
#define JSC2_Y2V_MASK
#define JSC2_X2V_MASK
#define JSC2_Y2V_SHIFT
#define JSC2_X2V_SHIFT

/* JS GPIO */
#define JSIO_DAX
#define JSIO_DAY
#define JSIO_DBX
#define JSIO_DBY
#define JSIO_AXOE
#define JSIO_AYOE
#define JSIO_BXOE
#define JSIO_BYOE

/*
 *
 */

struct cs4281_dma {};

#define SUSPEND_REGISTERS

struct cs4281 {};

static irqreturn_t snd_cs4281_interrupt(int irq, void *dev_id);

static const struct pci_device_id snd_cs4281_ids[] =;

MODULE_DEVICE_TABLE(pci, snd_cs4281_ids);

/*
 *  constants
 */

#define CS4281_FIFO_SIZE

/*
 *  common I/O routines
 */

static inline void snd_cs4281_pokeBA0(struct cs4281 *chip, unsigned long offset,
				      unsigned int val)
{}

static inline unsigned int snd_cs4281_peekBA0(struct cs4281 *chip, unsigned long offset)
{}

static void snd_cs4281_ac97_write(struct snd_ac97 *ac97,
				  unsigned short reg, unsigned short val)
{}

static unsigned short snd_cs4281_ac97_read(struct snd_ac97 *ac97,
					   unsigned short reg)
{}

/*
 *  PCM part
 */

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

static unsigned int snd_cs4281_rate(unsigned int rate, unsigned int *real_rate)
{}

static void snd_cs4281_mode(struct cs4281 *chip, struct cs4281_dma *dma,
			    struct snd_pcm_runtime *runtime,
			    int capture, int src)
{}

static int snd_cs4281_playback_prepare(struct snd_pcm_substream *substream)
{}

static int snd_cs4281_capture_prepare(struct snd_pcm_substream *substream)
{}

static snd_pcm_uframes_t snd_cs4281_pointer(struct snd_pcm_substream *substream)
{}

static const struct snd_pcm_hardware snd_cs4281_playback =;

static const struct snd_pcm_hardware snd_cs4281_capture =;

static int snd_cs4281_playback_open(struct snd_pcm_substream *substream)
{}

static int snd_cs4281_capture_open(struct snd_pcm_substream *substream)
{}

static int snd_cs4281_playback_close(struct snd_pcm_substream *substream)
{}

static int snd_cs4281_capture_close(struct snd_pcm_substream *substream)
{}

static const struct snd_pcm_ops snd_cs4281_playback_ops =;

static const struct snd_pcm_ops snd_cs4281_capture_ops =;

static int snd_cs4281_pcm(struct cs4281 *chip, int device)
{}

/*
 *  Mixer section
 */

#define CS_VOL_MASK

static int snd_cs4281_info_volume(struct snd_kcontrol *kcontrol,
				  struct snd_ctl_elem_info *uinfo)
{}
 
static int snd_cs4281_get_volume(struct snd_kcontrol *kcontrol,
				 struct snd_ctl_elem_value *ucontrol)
{}

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

static const DECLARE_TLV_DB_SCALE(db_scale_dsp, -4650, 150, 0);

static const struct snd_kcontrol_new snd_cs4281_fm_vol =;

static const struct snd_kcontrol_new snd_cs4281_pcm_vol =;

static void snd_cs4281_mixer_free_ac97_bus(struct snd_ac97_bus *bus)
{}

static void snd_cs4281_mixer_free_ac97(struct snd_ac97 *ac97)
{}

static int snd_cs4281_mixer(struct cs4281 *chip)
{}


/*
 * proc interface
 */

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

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)
{}

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)
{}

static const struct snd_info_entry_ops snd_cs4281_proc_ops_BA0 =;

static const struct snd_info_entry_ops snd_cs4281_proc_ops_BA1 =;

static void snd_cs4281_proc_init(struct cs4281 *chip)
{}

/*
 * joystick support
 */

#if IS_REACHABLE(CONFIG_GAMEPORT)

static void snd_cs4281_gameport_trigger(struct gameport *gameport)
{}

static unsigned char snd_cs4281_gameport_read(struct gameport *gameport)
{}

#ifdef COOKED_MODE
static int snd_cs4281_gameport_cooked_read(struct gameport *gameport,
					   int *axes, int *buttons)
{
	struct cs4281 *chip = gameport_get_port_data(gameport);
	unsigned js1, js2, jst;
	
	if (snd_BUG_ON(!chip))
		return 0;

	js1 = snd_cs4281_peekBA0(chip, BA0_JSC1);
	js2 = snd_cs4281_peekBA0(chip, BA0_JSC2);
	jst = snd_cs4281_peekBA0(chip, BA0_JSPT);
	
	*buttons = (~jst >> 4) & 0x0F; 
	
	axes[0] = ((js1 & JSC1_Y1V_MASK) >> JSC1_Y1V_SHIFT) & 0xFFFF;
	axes[1] = ((js1 & JSC1_X1V_MASK) >> JSC1_X1V_SHIFT) & 0xFFFF;
	axes[2] = ((js2 & JSC2_Y2V_MASK) >> JSC2_Y2V_SHIFT) & 0xFFFF;
	axes[3] = ((js2 & JSC2_X2V_MASK) >> JSC2_X2V_SHIFT) & 0xFFFF;

	for (jst = 0; jst < 4; ++jst)
		if (axes[jst] == 0xFFFF) axes[jst] = -1;
	return 0;
}
#else
#define snd_cs4281_gameport_cooked_read
#endif

static int snd_cs4281_gameport_open(struct gameport *gameport, int mode)
{}

static int snd_cs4281_create_gameport(struct cs4281 *chip)
{}

static void snd_cs4281_free_gameport(struct cs4281 *chip)
{}
#else
static inline int snd_cs4281_create_gameport(struct cs4281 *chip) { return -ENOSYS; }
static inline void snd_cs4281_free_gameport(struct cs4281 *chip) { }
#endif /* IS_REACHABLE(CONFIG_GAMEPORT) */

static void snd_cs4281_free(struct snd_card *card)
{}

static int snd_cs4281_chip_init(struct cs4281 *chip); /* defined below */

static int snd_cs4281_create(struct snd_card *card,
			     struct pci_dev *pci,
			     int dual_codec)
{}

static int snd_cs4281_chip_init(struct cs4281 *chip)
{}

/*
 *  MIDI section
 */

static void snd_cs4281_midi_reset(struct cs4281 *chip)
{}

static int snd_cs4281_midi_input_open(struct snd_rawmidi_substream *substream)
{}

static int snd_cs4281_midi_input_close(struct snd_rawmidi_substream *substream)
{}

static int snd_cs4281_midi_output_open(struct snd_rawmidi_substream *substream)
{}

static int snd_cs4281_midi_output_close(struct snd_rawmidi_substream *substream)
{}

static void snd_cs4281_midi_input_trigger(struct snd_rawmidi_substream *substream, int up)
{}

static void snd_cs4281_midi_output_trigger(struct snd_rawmidi_substream *substream, int up)
{}

static const struct snd_rawmidi_ops snd_cs4281_midi_output =;

static const struct snd_rawmidi_ops snd_cs4281_midi_input =;

static int snd_cs4281_midi(struct cs4281 *chip, int device)
{}

/*
 *  Interrupt handler
 */

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


/*
 * OPL3 command
 */
static void snd_cs4281_opl3_command(struct snd_opl3 *opl3, unsigned short cmd,
				    unsigned char val)
{}

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

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

/*
 * Power Management
 */
static const int saved_regs[SUSPEND_REGISTERS] =;

#define CLKCR1_CKRA

static int cs4281_suspend(struct device *dev)
{}

static int cs4281_resume(struct device *dev)
{}

static DEFINE_SIMPLE_DEV_PM_OPS(cs4281_pm, cs4281_suspend, cs4281_resume);

static struct pci_driver cs4281_driver =;
	
module_pci_driver();