linux/sound/pci/ens1370.c

// SPDX-License-Identifier: GPL-2.0-or-later
/*
 *  Driver for Ensoniq ES1370/ES1371 AudioPCI soundcard
 *  Copyright (c) by Jaroslav Kysela <[email protected]>,
 *		     Thomas Sailer <[email protected]>
 */

/* Power-Management-Code ( CONFIG_PM )
 * for ens1371 only ( FIXME )
 * derived from cs4281.c, atiixp.c and via82xx.c
 * using https://www.kernel.org/doc/html/latest/sound/kernel-api/writing-an-alsa-driver.html
 * by Kurt J. Bosch
 */

#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 <linux/mutex.h>

#include <sound/core.h>
#include <sound/control.h>
#include <sound/pcm.h>
#include <sound/rawmidi.h>
#ifdef CHIP1371
#include <sound/ac97_codec.h>
#else
#include <sound/ak4531_codec.h>
#endif
#include <sound/initval.h>
#include <sound/asoundef.h>

#ifndef CHIP1371
#undef CHIP1370
#define CHIP1370
#endif

#ifdef CHIP1370
#define DRIVER_NAME
#define CHIP_NAME
#else
#define DRIVER_NAME
#define CHIP_NAME
#endif


MODULE_AUTHOR();
MODULE_LICENSE();
#ifdef CHIP1370
MODULE_DESCRIPTION();
#endif
#ifdef CHIP1371
MODULE_DESCRIPTION("Ensoniq/Creative AudioPCI ES1371+");
#endif

#if IS_REACHABLE(CONFIG_GAMEPORT)
#define SUPPORT_JOYSTICK
#endif

static int index[SNDRV_CARDS] =;	/* Index 0-MAX */
static char *id[SNDRV_CARDS] =;	/* ID for this card */
static bool enable[SNDRV_CARDS] =;	/* Enable switches */
#ifdef SUPPORT_JOYSTICK
#ifdef CHIP1371
static int joystick_port[SNDRV_CARDS];
#else
static bool joystick[SNDRV_CARDS];
#endif
#endif
#ifdef CHIP1371
static int spdif[SNDRV_CARDS];
static int lineio[SNDRV_CARDS];
#endif

module_param_array();
MODULE_PARM_DESC();
module_param_array();
MODULE_PARM_DESC();
module_param_array();
MODULE_PARM_DESC();
#ifdef SUPPORT_JOYSTICK
#ifdef CHIP1371
module_param_hw_array(joystick_port, int, ioport, NULL, 0444);
MODULE_PARM_DESC(joystick_port, "Joystick port address.");
#else
module_param_array();
MODULE_PARM_DESC();
#endif
#endif /* SUPPORT_JOYSTICK */
#ifdef CHIP1371
module_param_array(spdif, int, NULL, 0444);
MODULE_PARM_DESC(spdif, "S/PDIF output (-1 = none, 0 = auto, 1 = force).");
module_param_array(lineio, int, NULL, 0444);
MODULE_PARM_DESC(lineio, "Line In to Rear Out (0 = auto, 1 = force).");
#endif

/* ES1371 chip ID */
/* This is a little confusing because all ES1371 compatible chips have the
   same DEVICE_ID, the only thing differentiating them is the REV_ID field.
   This is only significant if you want to enable features on the later parts.
   Yes, I know it's stupid and why didn't we use the sub IDs?
*/
#define ES1371REV_ES1373_A
#define ES1371REV_ES1373_B
#define ES1371REV_CT5880_A
#define CT5880REV_CT5880_C
#define CT5880REV_CT5880_D
#define CT5880REV_CT5880_E
#define ES1371REV_ES1371_B
#define EV1938REV_EV1938_A
#define ES1371REV_ES1373_8

/*
 * Direct registers
 */

#define ES_REG(ensoniq, x)

#define ES_REG_CONTROL
#define ES_1370_ADC_STOP
#define ES_1370_XCTL1
#define ES_1373_BYPASS_P1
#define ES_1373_BYPASS_P2
#define ES_1373_BYPASS_R
#define ES_1373_TEST_BIT
#define ES_1373_RECEN_B
#define ES_1373_SPDIF_THRU
#define ES_1371_JOY_ASEL(o)
#define ES_1371_JOY_ASELM
#define ES_1371_JOY_ASELI(i)
#define ES_1371_GPIO_IN(i)
#define ES_1370_PCLKDIVO(o)
#define ES_1370_PCLKDIVM
#define ES_1370_PCLKDIVI(i)
#define ES_1371_GPIO_OUT(o)
#define ES_1371_GPIO_OUTM
#define ES_MSFMTSEL
#define ES_1370_M_SBB
#define ES_1371_SYNC_RES
#define ES_1370_WTSRSEL(o)
#define ES_1370_WTSRSELM
#define ES_1371_ADC_STOP
#define ES_1371_PWR_INTRM
#define ES_1370_DAC_SYNC
#define ES_1371_M_CB
#define ES_CCB_INTRM
#define ES_1370_M_CB
#define ES_1370_XCTL0
#define ES_1371_PDLEV(o)
#define ES_1371_PDLEVM
#define ES_BREQ
#define ES_DAC1_EN
#define ES_DAC2_EN
#define ES_ADC_EN
#define ES_UART_EN
#define ES_JYSTK_EN
#define ES_1370_CDC_EN
#define ES_1371_XTALCKDIS
#define ES_1370_SERR_DISABLE
#define ES_1371_PCICLKDIS
#define ES_REG_STATUS
#define ES_INTR
#define ES_1371_ST_AC97_RST
#define ES_1373_REAR_BIT27
#define ES_1373_REAR_BIT26
#define ES_1373_REAR_BIT24
#define ES_1373_GPIO_INT_EN(o)
#define ES_1373_SPDIF_EN
#define ES_1373_SPDIF_TEST
#define ES_1371_TEST
#define ES_1373_GPIO_INT(i)
#define ES_1370_CSTAT
#define ES_1370_CBUSY
#define ES_1370_CWRIP
#define ES_1371_SYNC_ERR
#define ES_1371_VC(i)
#define ES_1370_VC(i)
#define ES_1371_MPWR
#define ES_MCCB
#define ES_UART
#define ES_DAC1
#define ES_DAC2
#define ES_ADC
#define ES_REG_UART_DATA
#define ES_REG_UART_STATUS
#define ES_RXINT
#define ES_TXINT
#define ES_TXRDY
#define ES_RXRDY
#define ES_REG_UART_CONTROL
#define ES_RXINTEN
#define ES_TXINTENO(o)
#define ES_TXINTENM
#define ES_TXINTENI(i)
#define ES_CNTRL(o)
#define ES_CNTRLM
#define ES_REG_UART_RES
#define ES_TEST_MODE
#define ES_REG_MEM_PAGE
#define ES_MEM_PAGEO(o)
#define ES_MEM_PAGEM
#define ES_MEM_PAGEI(i)
#define ES_REG_1370_CODEC
#define ES_1370_CODEC_WRITE(a,d)
#define ES_REG_1371_CODEC
#define ES_1371_CODEC_RDY
#define ES_1371_CODEC_WIP
#define EV_1938_CODEC_MAGIC
#define ES_1371_CODEC_PIRD
#define ES_1371_CODEC_WRITE(a,d)
#define ES_1371_CODEC_READS(a)
#define ES_1371_CODEC_READ(i)

#define ES_REG_1371_SMPRATE
#define ES_1371_SRC_RAM_ADDRO(o)
#define ES_1371_SRC_RAM_ADDRM
#define ES_1371_SRC_RAM_ADDRI(i)
#define ES_1371_SRC_RAM_WE
#define ES_1371_SRC_RAM_BUSY
#define ES_1371_SRC_DISABLE
#define ES_1371_DIS_P1
#define ES_1371_DIS_P2
#define ES_1371_DIS_R1
#define ES_1371_SRC_RAM_DATAO(o)
#define ES_1371_SRC_RAM_DATAM
#define ES_1371_SRC_RAM_DATAI(i)

#define ES_REG_1371_LEGACY
#define ES_1371_JFAST
#define ES_1371_HIB
#define ES_1371_VSB
#define ES_1371_VMPUO(o)
#define ES_1371_VMPUM
#define ES_1371_VMPUI(i)
#define ES_1371_VCDCO(o)
#define ES_1371_VCDCM
#define ES_1371_VCDCI(i)
#define ES_1371_FIRQ
#define ES_1371_SDMACAP
#define ES_1371_SPICAP
#define ES_1371_MDMACAP
#define ES_1371_MPICAP
#define ES_1371_ADCAP
#define ES_1371_SVCAP
#define ES_1371_CDCCAP
#define ES_1371_BACAP
#define ES_1371_EXI(i)
#define ES_1371_AI(i)
#define ES_1371_WR
#define ES_1371_LEGINT

#define ES_REG_CHANNEL_STATUS

#define ES_REG_SERIAL
#define ES_1371_DAC_TEST
#define ES_P2_END_INCO(o)
#define ES_P2_END_INCM
#define ES_P2_END_INCI(i)
#define ES_P2_ST_INCO(o)
#define ES_P2_ST_INCM
#define ES_P2_ST_INCI(i)
#define ES_R1_LOOP_SEL
#define ES_P2_LOOP_SEL
#define ES_P1_LOOP_SEL
#define ES_P2_PAUSE
#define ES_P1_PAUSE
#define ES_R1_INT_EN
#define ES_P2_INT_EN
#define ES_P1_INT_EN
#define ES_P1_SCT_RLD
#define ES_P2_DAC_SEN
#define ES_R1_MODEO(o)
#define ES_R1_MODEM
#define ES_R1_MODEI(i)
#define ES_P2_MODEO(o)
#define ES_P2_MODEM
#define ES_P2_MODEI(i)
#define ES_P1_MODEO(o)
#define ES_P1_MODEM
#define ES_P1_MODEI(i)

#define ES_REG_DAC1_COUNT
#define ES_REG_DAC2_COUNT
#define ES_REG_ADC_COUNT
#define ES_REG_CURR_COUNT(i)
#define ES_REG_COUNTO(o)
#define ES_REG_COUNTM
#define ES_REG_COUNTI(i)

#define ES_REG_DAC1_FRAME
#define ES_REG_DAC1_SIZE
#define ES_REG_DAC2_FRAME
#define ES_REG_DAC2_SIZE
#define ES_REG_ADC_FRAME
#define ES_REG_ADC_SIZE
#define ES_REG_FCURR_COUNTO(o)
#define ES_REG_FCURR_COUNTM
#define ES_REG_FCURR_COUNTI(i)
#define ES_REG_FSIZEO(o)
#define ES_REG_FSIZEM
#define ES_REG_FSIZEI(i)
#define ES_REG_PHANTOM_FRAME
#define ES_REG_PHANTOM_COUNT

#define ES_REG_UART_FIFO
#define ES_REG_UF_VALID
#define ES_REG_UF_BYTEO(o)
#define ES_REG_UF_BYTEM
#define ES_REG_UF_BYTEI(i)


/*
 *  Pages
 */

#define ES_PAGE_DAC
#define ES_PAGE_ADC
#define ES_PAGE_UART
#define ES_PAGE_UART1

/*
 *  Sample rate converter addresses
 */

#define ES_SMPREG_DAC1
#define ES_SMPREG_DAC2
#define ES_SMPREG_ADC
#define ES_SMPREG_VOL_ADC
#define ES_SMPREG_VOL_DAC1
#define ES_SMPREG_VOL_DAC2
#define ES_SMPREG_TRUNC_N
#define ES_SMPREG_INT_REGS
#define ES_SMPREG_ACCUM_FRAC
#define ES_SMPREG_VFREQ_FRAC

/*
 *  Some contants
 */

#define ES_1370_SRCLOCK
#define ES_1370_SRTODIV(x)

/*
 *  Open modes
 */

#define ES_MODE_PLAY1
#define ES_MODE_PLAY2
#define ES_MODE_CAPTURE

#define ES_MODE_OUTPUT
#define ES_MODE_INPUT

/*

 */

struct ensoniq {};

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

static const struct pci_device_id snd_audiopci_ids[] =;

MODULE_DEVICE_TABLE(pci, snd_audiopci_ids);

/*
 *  constants
 */

#define POLL_COUNT

#ifdef CHIP1370
static const unsigned int snd_es1370_fixed_rates[] =;
static const struct snd_pcm_hw_constraint_list snd_es1370_hw_constraints_rates =;
static const struct snd_ratnum es1370_clock =;
static const struct snd_pcm_hw_constraint_ratnums snd_es1370_hw_constraints_clock =;
#else
static const struct snd_ratden es1371_dac_clock = {
	.num_min = 3000 * (1 << 15),
	.num_max = 48000 * (1 << 15),
	.num_step = 3000,
	.den = 1 << 15,
};
static const struct snd_pcm_hw_constraint_ratdens snd_es1371_hw_constraints_dac_clock = {
	.nrats = 1,
	.rats = &es1371_dac_clock,
};
static const struct snd_ratnum es1371_adc_clock = {
	.num = 48000 << 15,
	.den_min = 32768, 
	.den_max = 393216,
	.den_step = 1,
};
static const struct snd_pcm_hw_constraint_ratnums snd_es1371_hw_constraints_adc_clock = {
	.nrats = 1,
	.rats = &es1371_adc_clock,
};
#endif
static const unsigned int snd_ensoniq_sample_shift[] =;

/*
 *  common I/O routines
 */

#ifdef CHIP1371

static unsigned int snd_es1371_wait_src_ready(struct ensoniq * ensoniq)
{
	unsigned int t, r = 0;

	for (t = 0; t < POLL_COUNT; t++) {
		r = inl(ES_REG(ensoniq, 1371_SMPRATE));
		if ((r & ES_1371_SRC_RAM_BUSY) == 0)
			return r;
		cond_resched();
	}
	dev_err(ensoniq->card->dev, "wait src ready timeout 0x%lx [0x%x]\n",
		   ES_REG(ensoniq, 1371_SMPRATE), r);
	return 0;
}

static unsigned int snd_es1371_src_read(struct ensoniq * ensoniq, unsigned short reg)
{
	unsigned int temp, i, orig, r;

	/* wait for ready */
	temp = orig = snd_es1371_wait_src_ready(ensoniq);

	/* expose the SRC state bits */
	r = temp & (ES_1371_SRC_DISABLE | ES_1371_DIS_P1 |
		    ES_1371_DIS_P2 | ES_1371_DIS_R1);
	r |= ES_1371_SRC_RAM_ADDRO(reg) | 0x10000;
	outl(r, ES_REG(ensoniq, 1371_SMPRATE));

	/* now, wait for busy and the correct time to read */
	temp = snd_es1371_wait_src_ready(ensoniq);
	
	if ((temp & 0x00870000) != 0x00010000) {
		/* wait for the right state */
		for (i = 0; i < POLL_COUNT; i++) {
			temp = inl(ES_REG(ensoniq, 1371_SMPRATE));
			if ((temp & 0x00870000) == 0x00010000)
				break;
		}
	}

	/* hide the state bits */	
	r = orig & (ES_1371_SRC_DISABLE | ES_1371_DIS_P1 |
		   ES_1371_DIS_P2 | ES_1371_DIS_R1);
	r |= ES_1371_SRC_RAM_ADDRO(reg);
	outl(r, ES_REG(ensoniq, 1371_SMPRATE));
	
	return temp;
}

static void snd_es1371_src_write(struct ensoniq * ensoniq,
				 unsigned short reg, unsigned short data)
{
	unsigned int r;

	r = snd_es1371_wait_src_ready(ensoniq) &
	    (ES_1371_SRC_DISABLE | ES_1371_DIS_P1 |
	     ES_1371_DIS_P2 | ES_1371_DIS_R1);
	r |= ES_1371_SRC_RAM_ADDRO(reg) | ES_1371_SRC_RAM_DATAO(data);
	outl(r | ES_1371_SRC_RAM_WE, ES_REG(ensoniq, 1371_SMPRATE));
}

#endif /* CHIP1371 */

#ifdef CHIP1370

static void snd_es1370_codec_write(struct snd_ak4531 *ak4531,
				   unsigned short reg, unsigned short val)
{}

#endif /* CHIP1370 */

#ifdef CHIP1371

static inline bool is_ev1938(struct ensoniq *ensoniq)
{
	return ensoniq->pci->device == 0x8938;
}

static void snd_es1371_codec_write(struct snd_ac97 *ac97,
				   unsigned short reg, unsigned short val)
{
	struct ensoniq *ensoniq = ac97->private_data;
	unsigned int t, x, flag;

	flag = is_ev1938(ensoniq) ? EV_1938_CODEC_MAGIC : 0;
	mutex_lock(&ensoniq->src_mutex);
	for (t = 0; t < POLL_COUNT; t++) {
		if (!(inl(ES_REG(ensoniq, 1371_CODEC)) & ES_1371_CODEC_WIP)) {
			/* save the current state for latter */
			x = snd_es1371_wait_src_ready(ensoniq);
			outl((x & (ES_1371_SRC_DISABLE | ES_1371_DIS_P1 |
			           ES_1371_DIS_P2 | ES_1371_DIS_R1)) | 0x00010000,
			     ES_REG(ensoniq, 1371_SMPRATE));
			/* wait for not busy (state 0) first to avoid
			   transition states */
			for (t = 0; t < POLL_COUNT; t++) {
				if ((inl(ES_REG(ensoniq, 1371_SMPRATE)) & 0x00870000) ==
				    0x00000000)
					break;
			}
			/* wait for a SAFE time to write addr/data and then do it, dammit */
			for (t = 0; t < POLL_COUNT; t++) {
				if ((inl(ES_REG(ensoniq, 1371_SMPRATE)) & 0x00870000) ==
				    0x00010000)
					break;
			}
			outl(ES_1371_CODEC_WRITE(reg, val) | flag,
			     ES_REG(ensoniq, 1371_CODEC));
			/* restore SRC reg */
			snd_es1371_wait_src_ready(ensoniq);
			outl(x, ES_REG(ensoniq, 1371_SMPRATE));
			mutex_unlock(&ensoniq->src_mutex);
			return;
		}
	}
	mutex_unlock(&ensoniq->src_mutex);
	dev_err(ensoniq->card->dev, "codec write timeout at 0x%lx [0x%x]\n",
		   ES_REG(ensoniq, 1371_CODEC), inl(ES_REG(ensoniq, 1371_CODEC)));
}

static unsigned short snd_es1371_codec_read(struct snd_ac97 *ac97,
					    unsigned short reg)
{
	struct ensoniq *ensoniq = ac97->private_data;
	unsigned int t, x, flag, fail = 0;

	flag = is_ev1938(ensoniq) ? EV_1938_CODEC_MAGIC : 0;
      __again:
	mutex_lock(&ensoniq->src_mutex);
	for (t = 0; t < POLL_COUNT; t++) {
		if (!(inl(ES_REG(ensoniq, 1371_CODEC)) & ES_1371_CODEC_WIP)) {
			/* save the current state for latter */
			x = snd_es1371_wait_src_ready(ensoniq);
			outl((x & (ES_1371_SRC_DISABLE | ES_1371_DIS_P1 |
			           ES_1371_DIS_P2 | ES_1371_DIS_R1)) | 0x00010000,
			     ES_REG(ensoniq, 1371_SMPRATE));
			/* wait for not busy (state 0) first to avoid
			   transition states */
			for (t = 0; t < POLL_COUNT; t++) {
				if ((inl(ES_REG(ensoniq, 1371_SMPRATE)) & 0x00870000) ==
				    0x00000000)
					break;
			}
			/* wait for a SAFE time to write addr/data and then do it, dammit */
			for (t = 0; t < POLL_COUNT; t++) {
				if ((inl(ES_REG(ensoniq, 1371_SMPRATE)) & 0x00870000) ==
				    0x00010000)
					break;
			}
			outl(ES_1371_CODEC_READS(reg) | flag,
			     ES_REG(ensoniq, 1371_CODEC));
			/* restore SRC reg */
			snd_es1371_wait_src_ready(ensoniq);
			outl(x, ES_REG(ensoniq, 1371_SMPRATE));
			/* wait for WIP again */
			for (t = 0; t < POLL_COUNT; t++) {
				if (!(inl(ES_REG(ensoniq, 1371_CODEC)) & ES_1371_CODEC_WIP))
					break;		
			}
			/* now wait for the stinkin' data (RDY) */
			for (t = 0; t < POLL_COUNT; t++) {
				x = inl(ES_REG(ensoniq, 1371_CODEC));
				if (x & ES_1371_CODEC_RDY) {
					if (is_ev1938(ensoniq)) {
						for (t = 0; t < 100; t++)
							inl(ES_REG(ensoniq, CONTROL));
						x = inl(ES_REG(ensoniq, 1371_CODEC));
					}
					mutex_unlock(&ensoniq->src_mutex);
					return ES_1371_CODEC_READ(x);
				}
			}
			mutex_unlock(&ensoniq->src_mutex);
			if (++fail > 10) {
				dev_err(ensoniq->card->dev,
					"codec read timeout (final) at 0x%lx, reg = 0x%x [0x%x]\n",
					   ES_REG(ensoniq, 1371_CODEC), reg,
					   inl(ES_REG(ensoniq, 1371_CODEC)));
				return 0;
			}
			goto __again;
		}
	}
	mutex_unlock(&ensoniq->src_mutex);
	dev_err(ensoniq->card->dev, "codec read timeout at 0x%lx [0x%x]\n",
		   ES_REG(ensoniq, 1371_CODEC), inl(ES_REG(ensoniq, 1371_CODEC)));
	return 0;
}

static void snd_es1371_codec_wait(struct snd_ac97 *ac97)
{
	msleep(750);
	snd_es1371_codec_read(ac97, AC97_RESET);
	snd_es1371_codec_read(ac97, AC97_VENDOR_ID1);
	snd_es1371_codec_read(ac97, AC97_VENDOR_ID2);
	msleep(50);
}

static void snd_es1371_adc_rate(struct ensoniq * ensoniq, unsigned int rate)
{
	unsigned int n, truncm, freq;

	mutex_lock(&ensoniq->src_mutex);
	n = rate / 3000;
	if ((1 << n) & ((1 << 15) | (1 << 13) | (1 << 11) | (1 << 9)))
		n--;
	truncm = (21 * n - 1) | 1;
	freq = ((48000UL << 15) / rate) * n;
	if (rate >= 24000) {
		if (truncm > 239)
			truncm = 239;
		snd_es1371_src_write(ensoniq, ES_SMPREG_ADC + ES_SMPREG_TRUNC_N,
				(((239 - truncm) >> 1) << 9) | (n << 4));
	} else {
		if (truncm > 119)
			truncm = 119;
		snd_es1371_src_write(ensoniq, ES_SMPREG_ADC + ES_SMPREG_TRUNC_N,
				0x8000 | (((119 - truncm) >> 1) << 9) | (n << 4));
	}
	snd_es1371_src_write(ensoniq, ES_SMPREG_ADC + ES_SMPREG_INT_REGS,
			     (snd_es1371_src_read(ensoniq, ES_SMPREG_ADC +
						  ES_SMPREG_INT_REGS) & 0x00ff) |
			     ((freq >> 5) & 0xfc00));
	snd_es1371_src_write(ensoniq, ES_SMPREG_ADC + ES_SMPREG_VFREQ_FRAC, freq & 0x7fff);
	snd_es1371_src_write(ensoniq, ES_SMPREG_VOL_ADC, n << 8);
	snd_es1371_src_write(ensoniq, ES_SMPREG_VOL_ADC + 1, n << 8);
	mutex_unlock(&ensoniq->src_mutex);
}

static void snd_es1371_dac1_rate(struct ensoniq * ensoniq, unsigned int rate)
{
	unsigned int freq, r;

	mutex_lock(&ensoniq->src_mutex);
	freq = DIV_ROUND_CLOSEST(rate << 15, 3000);
	r = (snd_es1371_wait_src_ready(ensoniq) & (ES_1371_SRC_DISABLE |
						   ES_1371_DIS_P2 | ES_1371_DIS_R1)) |
		ES_1371_DIS_P1;
	outl(r, ES_REG(ensoniq, 1371_SMPRATE));
	snd_es1371_src_write(ensoniq, ES_SMPREG_DAC1 + ES_SMPREG_INT_REGS,
			     (snd_es1371_src_read(ensoniq, ES_SMPREG_DAC1 +
						  ES_SMPREG_INT_REGS) & 0x00ff) |
			     ((freq >> 5) & 0xfc00));
	snd_es1371_src_write(ensoniq, ES_SMPREG_DAC1 + ES_SMPREG_VFREQ_FRAC, freq & 0x7fff);
	r = (snd_es1371_wait_src_ready(ensoniq) & (ES_1371_SRC_DISABLE |
						   ES_1371_DIS_P2 | ES_1371_DIS_R1));
	outl(r, ES_REG(ensoniq, 1371_SMPRATE));
	mutex_unlock(&ensoniq->src_mutex);
}

static void snd_es1371_dac2_rate(struct ensoniq * ensoniq, unsigned int rate)
{
	unsigned int freq, r;

	mutex_lock(&ensoniq->src_mutex);
	freq = DIV_ROUND_CLOSEST(rate << 15, 3000);
	r = (snd_es1371_wait_src_ready(ensoniq) & (ES_1371_SRC_DISABLE |
						   ES_1371_DIS_P1 | ES_1371_DIS_R1)) |
		ES_1371_DIS_P2;
	outl(r, ES_REG(ensoniq, 1371_SMPRATE));
	snd_es1371_src_write(ensoniq, ES_SMPREG_DAC2 + ES_SMPREG_INT_REGS,
			     (snd_es1371_src_read(ensoniq, ES_SMPREG_DAC2 +
						  ES_SMPREG_INT_REGS) & 0x00ff) |
			     ((freq >> 5) & 0xfc00));
	snd_es1371_src_write(ensoniq, ES_SMPREG_DAC2 + ES_SMPREG_VFREQ_FRAC,
			     freq & 0x7fff);
	r = (snd_es1371_wait_src_ready(ensoniq) & (ES_1371_SRC_DISABLE |
						   ES_1371_DIS_P1 | ES_1371_DIS_R1));
	outl(r, ES_REG(ensoniq, 1371_SMPRATE));
	mutex_unlock(&ensoniq->src_mutex);
}

#endif /* CHIP1371 */

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

/*
 *  PCM part
 */

static int snd_ensoniq_playback1_prepare(struct snd_pcm_substream *substream)
{}

static int snd_ensoniq_playback2_prepare(struct snd_pcm_substream *substream)
{}

static int snd_ensoniq_capture_prepare(struct snd_pcm_substream *substream)
{}

static snd_pcm_uframes_t snd_ensoniq_playback1_pointer(struct snd_pcm_substream *substream)
{}

static snd_pcm_uframes_t snd_ensoniq_playback2_pointer(struct snd_pcm_substream *substream)
{}

static snd_pcm_uframes_t snd_ensoniq_capture_pointer(struct snd_pcm_substream *substream)
{}

static const struct snd_pcm_hardware snd_ensoniq_playback1 =;

static const struct snd_pcm_hardware snd_ensoniq_playback2 =;

static const struct snd_pcm_hardware snd_ensoniq_capture =;

static int snd_ensoniq_playback1_open(struct snd_pcm_substream *substream)
{}

static int snd_ensoniq_playback2_open(struct snd_pcm_substream *substream)
{}

static int snd_ensoniq_capture_open(struct snd_pcm_substream *substream)
{}

static int snd_ensoniq_playback1_close(struct snd_pcm_substream *substream)
{}

static int snd_ensoniq_playback2_close(struct snd_pcm_substream *substream)
{}

static int snd_ensoniq_capture_close(struct snd_pcm_substream *substream)
{}

static const struct snd_pcm_ops snd_ensoniq_playback1_ops =;

static const struct snd_pcm_ops snd_ensoniq_playback2_ops =;

static const struct snd_pcm_ops snd_ensoniq_capture_ops =;

static const struct snd_pcm_chmap_elem surround_map[] =;

static int snd_ensoniq_pcm(struct ensoniq *ensoniq, int device)
{}

static int snd_ensoniq_pcm2(struct ensoniq *ensoniq, int device)
{}

/*
 *  Mixer section
 */

/*
 * ENS1371 mixer (including SPDIF interface)
 */
#ifdef CHIP1371
static int snd_ens1373_spdif_info(struct snd_kcontrol *kcontrol,
				  struct snd_ctl_elem_info *uinfo)
{
	uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
	uinfo->count = 1;
	return 0;
}

static int snd_ens1373_spdif_default_get(struct snd_kcontrol *kcontrol,
                                         struct snd_ctl_elem_value *ucontrol)
{
	struct ensoniq *ensoniq = snd_kcontrol_chip(kcontrol);
	spin_lock_irq(&ensoniq->reg_lock);
	ucontrol->value.iec958.status[0] = (ensoniq->spdif_default >> 0) & 0xff;
	ucontrol->value.iec958.status[1] = (ensoniq->spdif_default >> 8) & 0xff;
	ucontrol->value.iec958.status[2] = (ensoniq->spdif_default >> 16) & 0xff;
	ucontrol->value.iec958.status[3] = (ensoniq->spdif_default >> 24) & 0xff;
	spin_unlock_irq(&ensoniq->reg_lock);
	return 0;
}

static int snd_ens1373_spdif_default_put(struct snd_kcontrol *kcontrol,
                                         struct snd_ctl_elem_value *ucontrol)
{
	struct ensoniq *ensoniq = snd_kcontrol_chip(kcontrol);
	unsigned int val;
	int change;

	val = ((u32)ucontrol->value.iec958.status[0] << 0) |
	      ((u32)ucontrol->value.iec958.status[1] << 8) |
	      ((u32)ucontrol->value.iec958.status[2] << 16) |
	      ((u32)ucontrol->value.iec958.status[3] << 24);
	spin_lock_irq(&ensoniq->reg_lock);
	change = ensoniq->spdif_default != val;
	ensoniq->spdif_default = val;
	if (change && ensoniq->playback1_substream == NULL &&
	    ensoniq->playback2_substream == NULL)
		outl(val, ES_REG(ensoniq, CHANNEL_STATUS));
	spin_unlock_irq(&ensoniq->reg_lock);
	return change;
}

static int snd_ens1373_spdif_mask_get(struct snd_kcontrol *kcontrol,
				      struct snd_ctl_elem_value *ucontrol)
{
	ucontrol->value.iec958.status[0] = 0xff;
	ucontrol->value.iec958.status[1] = 0xff;
	ucontrol->value.iec958.status[2] = 0xff;
	ucontrol->value.iec958.status[3] = 0xff;
	return 0;
}

static int snd_ens1373_spdif_stream_get(struct snd_kcontrol *kcontrol,
					struct snd_ctl_elem_value *ucontrol)
{
	struct ensoniq *ensoniq = snd_kcontrol_chip(kcontrol);
	spin_lock_irq(&ensoniq->reg_lock);
	ucontrol->value.iec958.status[0] = (ensoniq->spdif_stream >> 0) & 0xff;
	ucontrol->value.iec958.status[1] = (ensoniq->spdif_stream >> 8) & 0xff;
	ucontrol->value.iec958.status[2] = (ensoniq->spdif_stream >> 16) & 0xff;
	ucontrol->value.iec958.status[3] = (ensoniq->spdif_stream >> 24) & 0xff;
	spin_unlock_irq(&ensoniq->reg_lock);
	return 0;
}

static int snd_ens1373_spdif_stream_put(struct snd_kcontrol *kcontrol,
                                        struct snd_ctl_elem_value *ucontrol)
{
	struct ensoniq *ensoniq = snd_kcontrol_chip(kcontrol);
	unsigned int val;
	int change;

	val = ((u32)ucontrol->value.iec958.status[0] << 0) |
	      ((u32)ucontrol->value.iec958.status[1] << 8) |
	      ((u32)ucontrol->value.iec958.status[2] << 16) |
	      ((u32)ucontrol->value.iec958.status[3] << 24);
	spin_lock_irq(&ensoniq->reg_lock);
	change = ensoniq->spdif_stream != val;
	ensoniq->spdif_stream = val;
	if (change && (ensoniq->playback1_substream != NULL ||
		       ensoniq->playback2_substream != NULL))
		outl(val, ES_REG(ensoniq, CHANNEL_STATUS));
	spin_unlock_irq(&ensoniq->reg_lock);
	return change;
}

#define ES1371_SPDIF

#define snd_es1371_spdif_info

static int snd_es1371_spdif_get(struct snd_kcontrol *kcontrol,
				struct snd_ctl_elem_value *ucontrol)
{
	struct ensoniq *ensoniq = snd_kcontrol_chip(kcontrol);
	
	spin_lock_irq(&ensoniq->reg_lock);
	ucontrol->value.integer.value[0] = ensoniq->ctrl & ES_1373_SPDIF_THRU ? 1 : 0;
	spin_unlock_irq(&ensoniq->reg_lock);
	return 0;
}

static int snd_es1371_spdif_put(struct snd_kcontrol *kcontrol,
				struct snd_ctl_elem_value *ucontrol)
{
	struct ensoniq *ensoniq = snd_kcontrol_chip(kcontrol);
	unsigned int nval1, nval2;
	int change;
	
	nval1 = ucontrol->value.integer.value[0] ? ES_1373_SPDIF_THRU : 0;
	nval2 = ucontrol->value.integer.value[0] ? ES_1373_SPDIF_EN : 0;
	spin_lock_irq(&ensoniq->reg_lock);
	change = (ensoniq->ctrl & ES_1373_SPDIF_THRU) != nval1;
	ensoniq->ctrl &= ~ES_1373_SPDIF_THRU;
	ensoniq->ctrl |= nval1;
	ensoniq->cssr &= ~ES_1373_SPDIF_EN;
	ensoniq->cssr |= nval2;
	outl(ensoniq->ctrl, ES_REG(ensoniq, CONTROL));
	outl(ensoniq->cssr, ES_REG(ensoniq, STATUS));
	spin_unlock_irq(&ensoniq->reg_lock);
	return change;
}


/* spdif controls */
static const struct snd_kcontrol_new snd_es1371_mixer_spdif[] = {
	ES1371_SPDIF(SNDRV_CTL_NAME_IEC958("",PLAYBACK,SWITCH)),
	{
		.iface =	SNDRV_CTL_ELEM_IFACE_PCM,
		.name =		SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT),
		.info =		snd_ens1373_spdif_info,
		.get =		snd_ens1373_spdif_default_get,
		.put =		snd_ens1373_spdif_default_put,
	},
	{
		.access =	SNDRV_CTL_ELEM_ACCESS_READ,
		.iface =	SNDRV_CTL_ELEM_IFACE_PCM,
		.name =		SNDRV_CTL_NAME_IEC958("",PLAYBACK,MASK),
		.info =		snd_ens1373_spdif_info,
		.get =		snd_ens1373_spdif_mask_get
	},
	{
		.iface =	SNDRV_CTL_ELEM_IFACE_PCM,
		.name =		SNDRV_CTL_NAME_IEC958("",PLAYBACK,PCM_STREAM),
		.info =		snd_ens1373_spdif_info,
		.get =		snd_ens1373_spdif_stream_get,
		.put =		snd_ens1373_spdif_stream_put
	},
};


#define snd_es1373_rear_info

static int snd_es1373_rear_get(struct snd_kcontrol *kcontrol,
			       struct snd_ctl_elem_value *ucontrol)
{
	struct ensoniq *ensoniq = snd_kcontrol_chip(kcontrol);
	int val = 0;
	
	spin_lock_irq(&ensoniq->reg_lock);
	if ((ensoniq->cssr & (ES_1373_REAR_BIT27|ES_1373_REAR_BIT26|
			      ES_1373_REAR_BIT24)) == ES_1373_REAR_BIT26)
	    	val = 1;
	ucontrol->value.integer.value[0] = val;
	spin_unlock_irq(&ensoniq->reg_lock);
	return 0;
}

static int snd_es1373_rear_put(struct snd_kcontrol *kcontrol,
			       struct snd_ctl_elem_value *ucontrol)
{
	struct ensoniq *ensoniq = snd_kcontrol_chip(kcontrol);
	unsigned int nval1;
	int change;
	
	nval1 = ucontrol->value.integer.value[0] ?
		ES_1373_REAR_BIT26 : (ES_1373_REAR_BIT27|ES_1373_REAR_BIT24);
	spin_lock_irq(&ensoniq->reg_lock);
	change = (ensoniq->cssr & (ES_1373_REAR_BIT27|
				   ES_1373_REAR_BIT26|ES_1373_REAR_BIT24)) != nval1;
	ensoniq->cssr &= ~(ES_1373_REAR_BIT27|ES_1373_REAR_BIT26|ES_1373_REAR_BIT24);
	ensoniq->cssr |= nval1;
	outl(ensoniq->cssr, ES_REG(ensoniq, STATUS));
	spin_unlock_irq(&ensoniq->reg_lock);
	return change;
}

static const struct snd_kcontrol_new snd_ens1373_rear =
{
	.iface =	SNDRV_CTL_ELEM_IFACE_MIXER,
	.name =		"AC97 2ch->4ch Copy Switch",
	.info =		snd_es1373_rear_info,
	.get =		snd_es1373_rear_get,
	.put =		snd_es1373_rear_put,
};

#define snd_es1373_line_info

static int snd_es1373_line_get(struct snd_kcontrol *kcontrol,
			       struct snd_ctl_elem_value *ucontrol)
{
	struct ensoniq *ensoniq = snd_kcontrol_chip(kcontrol);
	int val = 0;
	
	spin_lock_irq(&ensoniq->reg_lock);
	if (ensoniq->ctrl & ES_1371_GPIO_OUT(4))
	    	val = 1;
	ucontrol->value.integer.value[0] = val;
	spin_unlock_irq(&ensoniq->reg_lock);
	return 0;
}

static int snd_es1373_line_put(struct snd_kcontrol *kcontrol,
			       struct snd_ctl_elem_value *ucontrol)
{
	struct ensoniq *ensoniq = snd_kcontrol_chip(kcontrol);
	int changed;
	unsigned int ctrl;
	
	spin_lock_irq(&ensoniq->reg_lock);
	ctrl = ensoniq->ctrl;
	if (ucontrol->value.integer.value[0])
		ensoniq->ctrl |= ES_1371_GPIO_OUT(4);	/* switch line-in -> rear out */
	else
		ensoniq->ctrl &= ~ES_1371_GPIO_OUT(4);
	changed = (ctrl != ensoniq->ctrl);
	if (changed)
		outl(ensoniq->ctrl, ES_REG(ensoniq, CONTROL));
	spin_unlock_irq(&ensoniq->reg_lock);
	return changed;
}

static const struct snd_kcontrol_new snd_ens1373_line =
{
	.iface =	SNDRV_CTL_ELEM_IFACE_MIXER,
	.name =		"Line In->Rear Out Switch",
	.info =		snd_es1373_line_info,
	.get =		snd_es1373_line_get,
	.put =		snd_es1373_line_put,
};

static void snd_ensoniq_mixer_free_ac97(struct snd_ac97 *ac97)
{
	struct ensoniq *ensoniq = ac97->private_data;
	ensoniq->u.es1371.ac97 = NULL;
}

struct es1371_quirk {
	unsigned short vid;		/* vendor ID */
	unsigned short did;		/* device ID */
	unsigned char rev;		/* revision */
};

static int es1371_quirk_lookup(struct ensoniq *ensoniq,
			       const struct es1371_quirk *list)
{
	while (list->vid != (unsigned short)PCI_ANY_ID) {
		if (ensoniq->pci->vendor == list->vid &&
		    ensoniq->pci->device == list->did &&
		    ensoniq->rev == list->rev)
			return 1;
		list++;
	}
	return 0;
}

static const struct es1371_quirk es1371_spdif_present[] = {
	{ .vid = PCI_VENDOR_ID_ENSONIQ, .did = PCI_DEVICE_ID_ENSONIQ_CT5880, .rev = CT5880REV_CT5880_C },
	{ .vid = PCI_VENDOR_ID_ENSONIQ, .did = PCI_DEVICE_ID_ENSONIQ_CT5880, .rev = CT5880REV_CT5880_D },
	{ .vid = PCI_VENDOR_ID_ENSONIQ, .did = PCI_DEVICE_ID_ENSONIQ_CT5880, .rev = CT5880REV_CT5880_E },
	{ .vid = PCI_VENDOR_ID_ENSONIQ, .did = PCI_DEVICE_ID_ENSONIQ_ES1371, .rev = ES1371REV_CT5880_A },
	{ .vid = PCI_VENDOR_ID_ENSONIQ, .did = PCI_DEVICE_ID_ENSONIQ_ES1371, .rev = ES1371REV_ES1373_8 },
	{ .vid = PCI_ANY_ID, .did = PCI_ANY_ID }
};

static const struct snd_pci_quirk ens1373_line_quirk[] = {
	SND_PCI_QUIRK_ID(0x1274, 0x2000), /* GA-7DXR */
	SND_PCI_QUIRK_ID(0x1458, 0xa000), /* GA-8IEXP */
	{ } /* end */
};

static int snd_ensoniq_1371_mixer(struct ensoniq *ensoniq,
				  int has_spdif, int has_line)
{
	struct snd_card *card = ensoniq->card;
	struct snd_ac97_bus *pbus;
	struct snd_ac97_template ac97;
	int err;
	static const struct snd_ac97_bus_ops ops = {
		.write = snd_es1371_codec_write,
		.read = snd_es1371_codec_read,
		.wait = snd_es1371_codec_wait,
	};

	err = snd_ac97_bus(card, 0, &ops, NULL, &pbus);
	if (err < 0)
		return err;

	memset(&ac97, 0, sizeof(ac97));
	ac97.private_data = ensoniq;
	ac97.private_free = snd_ensoniq_mixer_free_ac97;
	ac97.pci = ensoniq->pci;
	ac97.scaps = AC97_SCAP_AUDIO;
	err = snd_ac97_mixer(pbus, &ac97, &ensoniq->u.es1371.ac97);
	if (err < 0)
		return err;
	if (has_spdif > 0 ||
	    (!has_spdif && es1371_quirk_lookup(ensoniq, es1371_spdif_present))) {
		struct snd_kcontrol *kctl;
		int i, is_spdif = 0;

		ensoniq->spdif_default = ensoniq->spdif_stream =
			SNDRV_PCM_DEFAULT_CON_SPDIF;
		outl(ensoniq->spdif_default, ES_REG(ensoniq, CHANNEL_STATUS));

		if (ensoniq->u.es1371.ac97->ext_id & AC97_EI_SPDIF)
			is_spdif++;

		for (i = 0; i < ARRAY_SIZE(snd_es1371_mixer_spdif); i++) {
			kctl = snd_ctl_new1(&snd_es1371_mixer_spdif[i], ensoniq);
			if (!kctl)
				return -ENOMEM;
			kctl->id.index = is_spdif;
			err = snd_ctl_add(card, kctl);
			if (err < 0)
				return err;
		}
	}
	if (ensoniq->u.es1371.ac97->ext_id & AC97_EI_SDAC) {
		/* mirror rear to front speakers */
		ensoniq->cssr &= ~(ES_1373_REAR_BIT27|ES_1373_REAR_BIT24);
		ensoniq->cssr |= ES_1373_REAR_BIT26;
		err = snd_ctl_add(card, snd_ctl_new1(&snd_ens1373_rear, ensoniq));
		if (err < 0)
			return err;
	}
	if (has_line > 0 ||
	    snd_pci_quirk_lookup(ensoniq->pci, ens1373_line_quirk)) {
		 err = snd_ctl_add(card, snd_ctl_new1(&snd_ens1373_line,
						      ensoniq));
		 if (err < 0)
			 return err;
	}

	return 0;
}

#endif /* CHIP1371 */

/* generic control callbacks for ens1370 */
#ifdef CHIP1370
#define ENSONIQ_CONTROL(xname, mask)

#define snd_ensoniq_control_info

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

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

/*
 * ENS1370 mixer
 */

static const struct snd_kcontrol_new snd_es1370_controls[2] =;

#define ES1370_CONTROLS

static void snd_ensoniq_mixer_free_ak4531(struct snd_ak4531 *ak4531)
{}

static int snd_ensoniq_1370_mixer(struct ensoniq *ensoniq)
{}

#endif /* CHIP1370 */

#ifdef SUPPORT_JOYSTICK

#ifdef CHIP1371
static int snd_ensoniq_get_joystick_port(struct ensoniq *ensoniq, int dev)
{
	switch (joystick_port[dev]) {
	case 0: /* disabled */
	case 1: /* auto-detect */
	case 0x200:
	case 0x208:
	case 0x210:
	case 0x218:
		return joystick_port[dev];

	default:
		dev_err(ensoniq->card->dev,
			"invalid joystick port %#x", joystick_port[dev]);
		return 0;
	}
}
#else
static int snd_ensoniq_get_joystick_port(struct ensoniq *ensoniq, int dev)
{}
#endif

static int snd_ensoniq_create_gameport(struct ensoniq *ensoniq, int dev)
{}

static void snd_ensoniq_free_gameport(struct ensoniq *ensoniq)
{}
#else
static inline int snd_ensoniq_create_gameport(struct ensoniq *ensoniq, long port) { return -ENOSYS; }
static inline void snd_ensoniq_free_gameport(struct ensoniq *ensoniq) { }
#endif /* SUPPORT_JOYSTICK */

/*

 */

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

static void snd_ensoniq_proc_init(struct ensoniq *ensoniq)
{}

/*

 */

static void snd_ensoniq_free(struct snd_card *card)
{}

#ifdef CHIP1371
static const struct snd_pci_quirk es1371_amplifier_hack[] = {
	SND_PCI_QUIRK_ID(0x107b, 0x2150),	/* Gateway Solo 2150 */
	SND_PCI_QUIRK_ID(0x13bd, 0x100c),	/* EV1938 on Mebius PC-MJ100V */
	SND_PCI_QUIRK_ID(0x1102, 0x5938),	/* Targa Xtender300 */
	SND_PCI_QUIRK_ID(0x1102, 0x8938),	/* IPC Topnote G notebook */
	{ } /* end */
};

static const struct es1371_quirk es1371_ac97_reset_hack[] = {
	{ .vid = PCI_VENDOR_ID_ENSONIQ, .did = PCI_DEVICE_ID_ENSONIQ_CT5880, .rev = CT5880REV_CT5880_C },
	{ .vid = PCI_VENDOR_ID_ENSONIQ, .did = PCI_DEVICE_ID_ENSONIQ_CT5880, .rev = CT5880REV_CT5880_D },
	{ .vid = PCI_VENDOR_ID_ENSONIQ, .did = PCI_DEVICE_ID_ENSONIQ_CT5880, .rev = CT5880REV_CT5880_E },
	{ .vid = PCI_VENDOR_ID_ENSONIQ, .did = PCI_DEVICE_ID_ENSONIQ_ES1371, .rev = ES1371REV_CT5880_A },
	{ .vid = PCI_VENDOR_ID_ENSONIQ, .did = PCI_DEVICE_ID_ENSONIQ_ES1371, .rev = ES1371REV_ES1373_8 },
	{ .vid = PCI_ANY_ID, .did = PCI_ANY_ID }
};
#endif

static void snd_ensoniq_chip_init(struct ensoniq *ensoniq)
{}

static int snd_ensoniq_suspend(struct device *dev)
{}

static int snd_ensoniq_resume(struct device *dev)
{}

static DEFINE_SIMPLE_DEV_PM_OPS(snd_ensoniq_pm, snd_ensoniq_suspend, snd_ensoniq_resume);

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

/*
 *  MIDI section
 */

static void snd_ensoniq_midi_interrupt(struct ensoniq * ensoniq)
{}

static int snd_ensoniq_midi_input_open(struct snd_rawmidi_substream *substream)
{}

static int snd_ensoniq_midi_input_close(struct snd_rawmidi_substream *substream)
{}

static int snd_ensoniq_midi_output_open(struct snd_rawmidi_substream *substream)
{}

static int snd_ensoniq_midi_output_close(struct snd_rawmidi_substream *substream)
{}

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

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

static const struct snd_rawmidi_ops snd_ensoniq_midi_output =;

static const struct snd_rawmidi_ops snd_ensoniq_midi_input =;

static int snd_ensoniq_midi(struct ensoniq *ensoniq, int device)
{}

/*
 *  Interrupt handler
 */

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

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

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

static struct pci_driver ens137x_driver =;
	
module_pci_driver();