[alsa-devel] [PATCH 2/2] opti93x: use cs4231 lib

Krzysztof Helt krzysztof.h1 at poczta.fm
Mon Jun 9 23:07:32 CEST 2008


From: Krzysztof Helt <krzysztof.h1 at wp.pl>

This patch converts the Opti93x driver to use
the cs4231 library instead of duplicating the code.

Signed-off-by: Krzysztof Helt <krzysztof.h1 at wp.pl>

---
This patch requires the patch which adds opti93x
support to the cs4231 library. It saves few hundreds LOCs.

This patch was sent some time ago. It should work
now on Opti93x.

The patch was prepared against the 2.6.26-rc5 kernel.

Tested on Opti 930, 931 and 933.

The previous repost:
http://mailman.alsa-project.org/pipermail/alsa-devel/2008-January/005680.html

diff -urp linux-rc2/sound/isa/Kconfig linux-rc5/sound/isa/Kconfig
--- linux-rc2/sound/isa/Kconfig	2008-04-17 04:49:44.000000000 +0200
+++ linux-rc5/sound/isa/Kconfig	2008-06-08 00:43:27.704186772 +0200
@@ -321,7 +321,7 @@ config SND_OPTI93X
 	depends on SND
 	select SND_OPL3_LIB
 	select SND_MPU401_UART
-	select SND_PCM
+	select SND_CS4231_LIB
 	help
 	  Say Y here to include support for soundcards based on Opti
 	  82C93x chips.
diff -urp linux-rc2/sound/isa/opti9xx/opti92x-ad1848.c linux-rc5/sound/isa/opti9xx/opti92x-ad1848.c
--- linux-rc2/sound/isa/opti9xx/opti92x-ad1848.c	2008-06-08 01:08:48.186548901 +0200
+++ linux-rc5/sound/isa/opti9xx/opti92x-ad1848.c	2008-06-08 10:42:36.915336562 +0200
@@ -33,15 +33,10 @@
 #include <asm/io.h>
 #include <asm/dma.h>
 #include <sound/core.h>
-#ifdef CS4231
+#if defined(CS4231) || defined(OPTi93X)
 #include <sound/cs4231.h>
 #else
-#ifndef OPTi93X
 #include <sound/ad1848.h>
-#else
-#include <sound/control.h>
-#include <sound/pcm.h>
-#endif	/* OPTi93X */
 #endif	/* CS4231 */
 #include <sound/mpu401.h>
 #include <sound/opl3.h>
@@ -109,7 +104,6 @@ module_param(dma2, int, 0444);
 MODULE_PARM_DESC(dma2, "2nd dma # for opti9xx driver.");
 #endif	/* CS4231 || OPTi93X */
 
-#define OPTi9XX_HW_DETECT	0
 #define OPTi9XX_HW_82C928	1
 #define OPTi9XX_HW_82C929	2
 #define OPTi9XX_HW_82C924	3
@@ -123,105 +117,12 @@ MODULE_PARM_DESC(dma2, "2nd dma # for op
 
 #ifdef OPTi93X
 
-#define OPTi93X_INDEX			0x00
-#define OPTi93X_DATA			0x01
 #define OPTi93X_STATUS			0x02
-#define OPTi93X_DDATA			0x03
 #define OPTi93X_PORT(chip, r)		((chip)->port + OPTi93X_##r)
 
-#define OPTi93X_MIXOUT_LEFT		0x00
-#define OPTi93X_MIXOUT_RIGHT		0x01
-#define OPTi93X_CD_LEFT_INPUT		0x02
-#define OPTi93X_CD_RIGHT_INPUT		0x03
-#define OPTi930_AUX_LEFT_INPUT		0x04
-#define OPTi930_AUX_RIGHT_INPUT		0x05
-#define OPTi931_FM_LEFT_INPUT		0x04
-#define OPTi931_FM_RIGHT_INPUT		0x05
-#define OPTi93X_DAC_LEFT		0x06
-#define OPTi93X_DAC_RIGHT		0x07
-#define OPTi93X_PLAY_FORMAT		0x08
-#define OPTi93X_IFACE_CONF		0x09
-#define OPTi93X_PIN_CTRL		0x0a
-#define OPTi93X_ERR_INIT		0x0b
-#define OPTi93X_ID			0x0c
-#define OPTi93X_PLAY_UPR_CNT		0x0e
-#define OPTi93X_PLAY_LWR_CNT		0x0f
-#define OPTi931_AUX_LEFT_INPUT		0x10
-#define OPTi931_AUX_RIGHT_INPUT		0x11
-#define OPTi93X_LINE_LEFT_INPUT		0x12
-#define OPTi93X_LINE_RIGHT_INPUT	0x13
-#define OPTi93X_MIC_LEFT_INPUT		0x14
-#define OPTi93X_MIC_RIGHT_INPUT		0x15
-#define OPTi93X_OUT_LEFT		0x16
-#define OPTi93X_OUT_RIGHT		0x17
-#define OPTi93X_CAPT_FORMAT		0x1c
-#define OPTi93X_CAPT_UPR_CNT		0x1e
-#define OPTi93X_CAPT_LWR_CNT		0x1f
-
-#define OPTi93X_TRD			0x20
-#define OPTi93X_MCE			0x40
-#define OPTi93X_INIT			0x80
-
-#define OPTi93X_MIXOUT_MIC_GAIN		0x20
-#define OPTi93X_MIXOUT_LINE		0x00
-#define OPTi93X_MIXOUT_CD		0x40
-#define OPTi93X_MIXOUT_MIC		0x80
-#define OPTi93X_MIXOUT_MIXER		0xc0
-
-#define OPTi93X_STEREO			0x10
-#define OPTi93X_LINEAR_8		0x00
-#define OPTi93X_ULAW_8			0x20
-#define OPTi93X_LINEAR_16_LIT		0x40
-#define OPTi93X_ALAW_8			0x60
-#define OPTi93X_ADPCM_16		0xa0
-#define OPTi93X_LINEAR_16_BIG		0xc0
-
-#define OPTi93X_CAPTURE_PIO		0x80
-#define OPTi93X_PLAYBACK_PIO		0x40
-#define OPTi93X_AUTOCALIB		0x08
-#define OPTi93X_SINGLE_DMA		0x04
-#define OPTi93X_CAPTURE_ENABLE		0x02
-#define OPTi93X_PLAYBACK_ENABLE		0x01
-
-#define OPTi93X_IRQ_ENABLE		0x02
-
-#define OPTi93X_DMA_REQUEST		0x10
-#define OPTi93X_CALIB_IN_PROGRESS	0x20
-
 #define OPTi93X_IRQ_PLAYBACK		0x04
 #define OPTi93X_IRQ_CAPTURE		0x08
 
-
-struct snd_opti93x {
-	unsigned long port;
-	struct resource *res_port;
-	int irq;
-	int dma1;
-	int dma2;
-
-	struct snd_opti9xx *chip;
-	unsigned short hardware;
-	unsigned char image[32];
-
-	unsigned char mce_bit;
-	unsigned short mode;
-	int mute;
-
-	spinlock_t lock;
-
-	struct snd_card *card;
-	struct snd_pcm *pcm;
-	struct snd_pcm_substream *playback_substream;
-	struct snd_pcm_substream *capture_substream;
-	unsigned int p_dma_size;
-	unsigned int c_dma_size;
-};
-
-#define OPTi93X_MODE_NONE	0x00
-#define OPTi93X_MODE_PLAY	0x01
-#define OPTi93X_MODE_CAPTURE	0x02
-#define OPTi93X_MODE_OPEN	(OPTi93X_MODE_PLAY | OPTi93X_MODE_CAPTURE)
-
 #endif /* OPTi93X */
 
 struct snd_opti9xx {
@@ -234,6 +135,7 @@ struct snd_opti9xx {
 	unsigned long mc_base_size;
 #ifdef OPTi93X
 	unsigned long mc_indir_index;
+	struct snd_cs4231 *codec;
 #endif	/* OPTi93X */
 	unsigned long pwd_reg;
 
@@ -654,979 +556,23 @@ __skip_mpu:
 
 #ifdef OPTi93X
 
-static unsigned char snd_opti93x_default_image[32] =
-{
-	0x00,		/* 00/00 - l_mixout_outctrl */
-	0x00,		/* 01/01 - r_mixout_outctrl */
-	0x88,		/* 02/02 - l_cd_inctrl */
-	0x88,		/* 03/03 - r_cd_inctrl */
-	0x88,		/* 04/04 - l_a1/fm_inctrl */
-	0x88,		/* 05/05 - r_a1/fm_inctrl */
-	0x80,		/* 06/06 - l_dac_inctrl */
-	0x80,		/* 07/07 - r_dac_inctrl */
-	0x00,		/* 08/08 - ply_dataform_reg */
-	0x00,		/* 09/09 - if_conf */
-	0x00,		/* 0a/10 - pin_ctrl */
-	0x00,		/* 0b/11 - err_init_reg */
-	0x0a,		/* 0c/12 - id_reg */
-	0x00,		/* 0d/13 - reserved */
-	0x00,		/* 0e/14 - ply_upcount_reg */
-	0x00,		/* 0f/15 - ply_lowcount_reg */
-	0x88,		/* 10/16 - reserved/l_a1_inctrl */
-	0x88,		/* 11/17 - reserved/r_a1_inctrl */
-	0x88,		/* 12/18 - l_line_inctrl */
-	0x88,		/* 13/19 - r_line_inctrl */
-	0x88,		/* 14/20 - l_mic_inctrl */
-	0x88,		/* 15/21 - r_mic_inctrl */
-	0x80,		/* 16/22 - l_out_outctrl */
-	0x80,		/* 17/23 - r_out_outctrl */
-	0x00,		/* 18/24 - reserved */
-	0x00,		/* 19/25 - reserved */
-	0x00,		/* 1a/26 - reserved */
-	0x00,		/* 1b/27 - reserved */
-	0x00,		/* 1c/28 - cap_dataform_reg */
-	0x00,		/* 1d/29 - reserved */
-	0x00,		/* 1e/30 - cap_upcount_reg */
-	0x00		/* 1f/31 - cap_lowcount_reg */
-};
-
-
-static int snd_opti93x_busy_wait(struct snd_opti93x *chip)
-{
-	int timeout;
-
-	for (timeout = 250; timeout-- > 0; udelay(10))
-		if (!(inb(OPTi93X_PORT(chip, INDEX)) & OPTi93X_INIT))
-			return 0;
-
-	snd_printk("chip still busy.\n");
-	return -EBUSY;
-}
-
-static unsigned char snd_opti93x_in(struct snd_opti93x *chip, unsigned char reg)
-{
-	snd_opti93x_busy_wait(chip);
-	outb(chip->mce_bit | (reg & 0x1f), OPTi93X_PORT(chip, INDEX));
-	return inb(OPTi93X_PORT(chip, DATA));
-}
-
-static void snd_opti93x_out(struct snd_opti93x *chip, unsigned char reg,
-			    unsigned char value)
-{
-	snd_opti93x_busy_wait(chip);
-	outb(chip->mce_bit | (reg & 0x1f), OPTi93X_PORT(chip, INDEX));
-	outb(value, OPTi93X_PORT(chip, DATA));
-}
-
-static void snd_opti93x_out_image(struct snd_opti93x *chip, unsigned char reg,
-				  unsigned char value)
-{
-	snd_opti93x_out(chip, reg, chip->image[reg] = value);
-}
-
-static void snd_opti93x_out_mask(struct snd_opti93x *chip, unsigned char reg,
-				 unsigned char mask, unsigned char value)
-{
-	snd_opti93x_out_image(chip, reg,
-		(chip->image[reg] & ~mask) | (value & mask));
-}
-
-
-static void snd_opti93x_mce_up(struct snd_opti93x *chip)
-{
-	snd_opti93x_busy_wait(chip);
-
-	chip->mce_bit = OPTi93X_MCE;
-	if (!(inb(OPTi93X_PORT(chip, INDEX)) & OPTi93X_MCE))
-		outb(chip->mce_bit, OPTi93X_PORT(chip, INDEX));
-}
-
-static void snd_opti93x_mce_down(struct snd_opti93x *chip)
-{
-	snd_opti93x_busy_wait(chip);
-
-	chip->mce_bit = 0;
-	if (inb(OPTi93X_PORT(chip, INDEX)) & OPTi93X_MCE)
-		outb(chip->mce_bit, OPTi93X_PORT(chip, INDEX));
-}
-
-#define snd_opti93x_mute_reg(chip, reg, mute)	\
-	snd_opti93x_out(chip, reg, mute ? 0x80 : chip->image[reg]);
-
-static void snd_opti93x_mute(struct snd_opti93x *chip, int mute)
-{
-	mute = mute ? 1 : 0;
-	if (chip->mute == mute)
-		return;
-
-	chip->mute = mute;
-
-	snd_opti93x_mute_reg(chip, OPTi93X_CD_LEFT_INPUT, mute);
-	snd_opti93x_mute_reg(chip, OPTi93X_CD_RIGHT_INPUT, mute);
-	switch (chip->hardware) {
-	case OPTi9XX_HW_82C930:
-		snd_opti93x_mute_reg(chip, OPTi930_AUX_LEFT_INPUT, mute);
-		snd_opti93x_mute_reg(chip, OPTi930_AUX_RIGHT_INPUT, mute);
-		break;
-	case OPTi9XX_HW_82C931:
-	case OPTi9XX_HW_82C933:
-		snd_opti93x_mute_reg(chip, OPTi931_FM_LEFT_INPUT, mute);
-		snd_opti93x_mute_reg(chip, OPTi931_FM_RIGHT_INPUT, mute);
-		snd_opti93x_mute_reg(chip, OPTi931_AUX_LEFT_INPUT, mute);
-		snd_opti93x_mute_reg(chip, OPTi931_AUX_RIGHT_INPUT, mute);
-	}
-	snd_opti93x_mute_reg(chip, OPTi93X_DAC_LEFT, mute);
-	snd_opti93x_mute_reg(chip, OPTi93X_DAC_RIGHT, mute);
-	snd_opti93x_mute_reg(chip, OPTi93X_LINE_LEFT_INPUT, mute);
-	snd_opti93x_mute_reg(chip, OPTi93X_LINE_RIGHT_INPUT, mute);
-	snd_opti93x_mute_reg(chip, OPTi93X_MIC_LEFT_INPUT, mute);
-	snd_opti93x_mute_reg(chip, OPTi93X_MIC_RIGHT_INPUT, mute);
-	snd_opti93x_mute_reg(chip, OPTi93X_OUT_LEFT, mute);
-	snd_opti93x_mute_reg(chip, OPTi93X_OUT_RIGHT, mute);
-}
-
-
-static unsigned int snd_opti93x_get_count(unsigned char format,
-					  unsigned int size)
-{
-	switch (format & 0xe0) {
-	case OPTi93X_LINEAR_16_LIT:
-	case OPTi93X_LINEAR_16_BIG:
-		size >>= 1;
-		break;
-	case OPTi93X_ADPCM_16:
-		return size >> 2;
-	}
-	return (format & OPTi93X_STEREO) ? (size >> 1) : size;
-}
-
-static unsigned int rates[] = {  5512,  6615,  8000,  9600, 11025, 16000, 
-				18900, 22050, 27428, 32000, 33075, 37800,
-				44100, 48000 };
-#define RATES ARRAY_SIZE(rates)
-
-static struct snd_pcm_hw_constraint_list hw_constraints_rates = {
-	.count = RATES,
-	.list = rates,
-	.mask = 0,
-};
-
-static unsigned char bits[] = {  0x01,  0x0f,  0x00,  0x0e,  0x03,  0x02,
-				 0x05,  0x07,  0x04,  0x06,  0x0d,  0x09,
-				 0x0b,  0x0c};
-
-static unsigned char snd_opti93x_get_freq(unsigned int rate)
-{
-	unsigned int i;
-
-	for (i = 0; i < RATES; i++) {
-		if (rate == rates[i])
-			return bits[i];
-	}
-	snd_BUG();
-	return bits[RATES-1];
-}
-
-static unsigned char snd_opti93x_get_format(struct snd_opti93x *chip,
-					    unsigned int format, int channels)
-{
-	unsigned char retval = OPTi93X_LINEAR_8;
-
-	switch (format) {
-	case SNDRV_PCM_FORMAT_MU_LAW:
-		retval = OPTi93X_ULAW_8;
-		break;
-	case SNDRV_PCM_FORMAT_A_LAW:
-		retval = OPTi93X_ALAW_8;
-		break;
-	case SNDRV_PCM_FORMAT_S16_LE:
-		retval = OPTi93X_LINEAR_16_LIT;
-		break;
-	case SNDRV_PCM_FORMAT_S16_BE:
-		retval = OPTi93X_LINEAR_16_BIG;
-		break;
-	case SNDRV_PCM_FORMAT_IMA_ADPCM:
-		retval = OPTi93X_ADPCM_16;
-	}
-	return (channels > 1) ? (retval | OPTi93X_STEREO) : retval;
-}
-
-
-static void snd_opti93x_playback_format(struct snd_opti93x *chip, unsigned char fmt)
-{
-	unsigned char mask;
-
-	snd_opti93x_mute(chip, 1);
-
-	snd_opti93x_mce_up(chip);
-	mask = (chip->mode & OPTi93X_MODE_CAPTURE) ? 0xf0 : 0xff;
-	snd_opti93x_out_mask(chip, OPTi93X_PLAY_FORMAT, mask, fmt);
-	snd_opti93x_mce_down(chip);
-
-	snd_opti93x_mute(chip, 0);
-}
-
-static void snd_opti93x_capture_format(struct snd_opti93x *chip, unsigned char fmt)
-{
-	snd_opti93x_mute(chip, 1);
-
-	snd_opti93x_mce_up(chip);
-	if (!(chip->mode & OPTi93X_MODE_PLAY))
-		snd_opti93x_out_mask(chip, OPTi93X_PLAY_FORMAT, 0x0f, fmt);
-	else
-		fmt = chip->image[OPTi93X_PLAY_FORMAT] & 0xf0;
-	snd_opti93x_out_image(chip, OPTi93X_CAPT_FORMAT, fmt);
-	snd_opti93x_mce_down(chip);
-
-	snd_opti93x_mute(chip, 0);
-}
-
-
-static int snd_opti93x_open(struct snd_opti93x *chip, unsigned int mode)
-{
-	unsigned long flags;
-
-	spin_lock_irqsave(&chip->lock, flags);
-
-	if (chip->mode & mode) {
-		spin_unlock_irqrestore(&chip->lock, flags);
-		return -EAGAIN;
-	}
-
-	if (!(chip->mode & OPTi93X_MODE_OPEN)) {
-		outb(0x00, OPTi93X_PORT(chip, STATUS));
-		snd_opti93x_out_mask(chip, OPTi93X_PIN_CTRL,
-			OPTi93X_IRQ_ENABLE, OPTi93X_IRQ_ENABLE);
-		chip->mode = mode;
-	}
-	else
-		chip->mode |= mode;
-
-	spin_unlock_irqrestore(&chip->lock, flags);
-	return 0;
-}
-
-static void snd_opti93x_close(struct snd_opti93x *chip, unsigned int mode)
-{
-	unsigned long flags;
-
-	spin_lock_irqsave(&chip->lock, flags);
-
-	chip->mode &= ~mode;
-	if (chip->mode & OPTi93X_MODE_OPEN) {
-		spin_unlock_irqrestore(&chip->lock, flags);
-		return;
-	}
-
-	snd_opti93x_mute(chip, 1);
-
-	outb(0, OPTi93X_PORT(chip, STATUS));
-	snd_opti93x_out_mask(chip, OPTi93X_PIN_CTRL, OPTi93X_IRQ_ENABLE,
-		~OPTi93X_IRQ_ENABLE);
-
-	snd_opti93x_mce_up(chip);
-	snd_opti93x_out_image(chip, OPTi93X_IFACE_CONF, 0x00);
-	snd_opti93x_mce_down(chip);
-	chip->mode = 0;
-
-	snd_opti93x_mute(chip, 0);
-	spin_unlock_irqrestore(&chip->lock, flags);
-}
-
-static int snd_opti93x_trigger(struct snd_pcm_substream *substream, 
-			       unsigned char what, int cmd)
-{
-	struct snd_opti93x *chip = snd_pcm_substream_chip(substream);
-
-	switch (cmd) {
-	case SNDRV_PCM_TRIGGER_START:
-	case SNDRV_PCM_TRIGGER_STOP:
-	{
-		unsigned int what = 0;
-		struct snd_pcm_substream *s;
-		snd_pcm_group_for_each_entry(s, substream) {
-			if (s == chip->playback_substream) {
-				what |= OPTi93X_PLAYBACK_ENABLE;
-				snd_pcm_trigger_done(s, substream);
-			} else if (s == chip->capture_substream) {
-				what |= OPTi93X_CAPTURE_ENABLE;
-				snd_pcm_trigger_done(s, substream);
-			}
-		}
-		spin_lock(&chip->lock);
-		if (cmd == SNDRV_PCM_TRIGGER_START) {
-			snd_opti93x_out_mask(chip, OPTi93X_IFACE_CONF, what, what);
-			if (what & OPTi93X_CAPTURE_ENABLE)
-				udelay(50);
-		} else
-			snd_opti93x_out_mask(chip, OPTi93X_IFACE_CONF, what, 0x00);
-		spin_unlock(&chip->lock);
-		break;
-	}
-	default:
-		return -EINVAL;
-	}
-	return 0;
-}
-
-static int snd_opti93x_playback_trigger(struct snd_pcm_substream *substream, int cmd)
-{
-	return snd_opti93x_trigger(substream,
-				   OPTi93X_PLAYBACK_ENABLE, cmd);
-}
-
-static int snd_opti93x_capture_trigger(struct snd_pcm_substream *substream, int cmd)
-{
-	return snd_opti93x_trigger(substream,
-				   OPTi93X_CAPTURE_ENABLE, cmd);
-}
-
-static int snd_opti93x_hw_params(struct snd_pcm_substream *substream,
-				 struct snd_pcm_hw_params *hw_params)
-{
-	return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params));
-}
-
-
-static int snd_opti93x_hw_free(struct snd_pcm_substream *substream)
-{
-	snd_pcm_lib_free_pages(substream);
-	return 0;
-}
-
-
-static int snd_opti93x_playback_prepare(struct snd_pcm_substream *substream)
-{
-	struct snd_opti93x *chip = snd_pcm_substream_chip(substream);
-	struct snd_pcm_runtime *runtime = substream->runtime;
-	unsigned long flags;
-	unsigned char format;
-	unsigned int count = snd_pcm_lib_period_bytes(substream);
-	unsigned int size = snd_pcm_lib_buffer_bytes(substream);
-
-	spin_lock_irqsave(&chip->lock, flags);
-
-	chip->p_dma_size = size;
-	snd_opti93x_out_mask(chip, OPTi93X_IFACE_CONF,
-		OPTi93X_PLAYBACK_ENABLE | OPTi93X_PLAYBACK_PIO,
-		~(OPTi93X_PLAYBACK_ENABLE | OPTi93X_PLAYBACK_PIO));
-
-	snd_dma_program(chip->dma1, runtime->dma_addr, size,
-		DMA_MODE_WRITE | DMA_AUTOINIT);
-
-	format = snd_opti93x_get_freq(runtime->rate);
-	format |= snd_opti93x_get_format(chip, runtime->format,
-		runtime->channels);
-	snd_opti93x_playback_format(chip, format);
-	format = chip->image[OPTi93X_PLAY_FORMAT];
-
-	count = snd_opti93x_get_count(format, count) - 1;
-	snd_opti93x_out_image(chip, OPTi93X_PLAY_LWR_CNT, count);
-	snd_opti93x_out_image(chip, OPTi93X_PLAY_UPR_CNT, count >> 8);
-
-	spin_unlock_irqrestore(&chip->lock, flags);
-	return 0;
-}
-
-static int snd_opti93x_capture_prepare(struct snd_pcm_substream *substream)
-{
-	struct snd_opti93x *chip = snd_pcm_substream_chip(substream);
-	struct snd_pcm_runtime *runtime = substream->runtime;
-	unsigned long flags;
-	unsigned char format;
-	unsigned int count = snd_pcm_lib_period_bytes(substream);
-	unsigned int size = snd_pcm_lib_buffer_bytes(substream);
-
-	spin_lock_irqsave(&chip->lock, flags);
-
-	chip->c_dma_size = size;
-	snd_opti93x_out_mask(chip, OPTi93X_IFACE_CONF,
-		OPTi93X_CAPTURE_ENABLE | OPTi93X_CAPTURE_PIO, 0);
-
-	snd_dma_program(chip->dma2, runtime->dma_addr, size,
-		DMA_MODE_READ | DMA_AUTOINIT);
-
-	format = snd_opti93x_get_freq(runtime->rate);
-	format |= snd_opti93x_get_format(chip, runtime->format,
-		runtime->channels);
-	snd_opti93x_capture_format(chip, format);
-	format = chip->image[OPTi93X_CAPT_FORMAT];
-
-	count = snd_opti93x_get_count(format, count) - 1;
-	snd_opti93x_out_image(chip, OPTi93X_CAPT_LWR_CNT, count);
-	snd_opti93x_out_image(chip, OPTi93X_CAPT_UPR_CNT, count >> 8);
-
-	spin_unlock_irqrestore(&chip->lock, flags);
-	return 0;
-}
-
-static snd_pcm_uframes_t snd_opti93x_playback_pointer(struct snd_pcm_substream *substream)
-{
-	struct snd_opti93x *chip = snd_pcm_substream_chip(substream);
-	size_t ptr;
-
-	if (!(chip->image[OPTi93X_IFACE_CONF] & OPTi93X_PLAYBACK_ENABLE))
-		return 0;
-
-	ptr = snd_dma_pointer(chip->dma1, chip->p_dma_size);
-	return bytes_to_frames(substream->runtime, ptr);
-}
-
-static snd_pcm_uframes_t snd_opti93x_capture_pointer(struct snd_pcm_substream *substream)
-{
-	struct snd_opti93x *chip = snd_pcm_substream_chip(substream);
-	size_t ptr;
-	
-	if (!(chip->image[OPTi93X_IFACE_CONF] & OPTi93X_CAPTURE_ENABLE))
-		return 0;
-
-	ptr = snd_dma_pointer(chip->dma2, chip->c_dma_size);
-	return bytes_to_frames(substream->runtime, ptr);
-}
-
-
-static void snd_opti93x_overrange(struct snd_opti93x *chip)
-{
-	unsigned long flags;
-
-	spin_lock_irqsave(&chip->lock, flags);
-
-	if (snd_opti93x_in(chip, OPTi93X_ERR_INIT) & (0x08 | 0x02))
-		chip->capture_substream->runtime->overrange++;
-
-	spin_unlock_irqrestore(&chip->lock, flags);
-}
-
 static irqreturn_t snd_opti93x_interrupt(int irq, void *dev_id)
 {
-	struct snd_opti93x *codec = dev_id;
+	struct snd_cs4231 *codec = dev_id;
+	struct snd_opti9xx *chip = codec->card->private_data;
 	unsigned char status;
 
-	status = snd_opti9xx_read(codec->chip, OPTi9XX_MC_REG(11));
+	status = snd_opti9xx_read(chip, OPTi9XX_MC_REG(11));
 	if ((status & OPTi93X_IRQ_PLAYBACK) && codec->playback_substream)
 		snd_pcm_period_elapsed(codec->playback_substream);
 	if ((status & OPTi93X_IRQ_CAPTURE) && codec->capture_substream) {
-		snd_opti93x_overrange(codec);
+		snd_cs4231_overrange(codec);
 		snd_pcm_period_elapsed(codec->capture_substream);
 	}
 	outb(0x00, OPTi93X_PORT(codec, STATUS));
 	return IRQ_HANDLED;
 }
 
-
-static struct snd_pcm_hardware snd_opti93x_playback = {
-	.info =			(SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
-				 SNDRV_PCM_INFO_MMAP_VALID | SNDRV_PCM_INFO_SYNC_START),
-	.formats =		(SNDRV_PCM_FMTBIT_MU_LAW | SNDRV_PCM_FMTBIT_A_LAW | SNDRV_PCM_FMTBIT_IMA_ADPCM |
-				 SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S16_BE),
-	.rates =		SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_8000_48000,
-	.rate_min =		5512,
-	.rate_max =		48000,
-	.channels_min =		1,
-	.channels_max =		2,
-	.buffer_bytes_max =	(128*1024),
-	.period_bytes_min =	64,
-	.period_bytes_max =	(128*1024),
-	.periods_min =		1,
-	.periods_max =		1024,
-	.fifo_size =		0,
-};
-
-static struct snd_pcm_hardware snd_opti93x_capture = {
-	.info =			(SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
-				 SNDRV_PCM_INFO_MMAP_VALID | SNDRV_PCM_INFO_SYNC_START),
-	.formats =		(SNDRV_PCM_FMTBIT_MU_LAW | SNDRV_PCM_FMTBIT_A_LAW | SNDRV_PCM_FMTBIT_IMA_ADPCM |
-				 SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S16_BE),
-	.rates =		SNDRV_PCM_RATE_8000_48000,
-	.rate_min =		5512,
-	.rate_max =		48000,
-	.channels_min =		1,
-	.channels_max =		2,
-	.buffer_bytes_max =	(128*1024),
-	.period_bytes_min =	64,
-	.period_bytes_max =	(128*1024),
-	.periods_min =		1,
-	.periods_max =		1024,
-	.fifo_size =		0,
-};
-
-static int snd_opti93x_playback_open(struct snd_pcm_substream *substream)
-{
-	int error;
-	struct snd_opti93x *chip = snd_pcm_substream_chip(substream);
-	struct snd_pcm_runtime *runtime = substream->runtime;
-
-	if ((error = snd_opti93x_open(chip, OPTi93X_MODE_PLAY)) < 0)
-		return error;
-	snd_pcm_set_sync(substream);
-	chip->playback_substream = substream;
-	runtime->hw = snd_opti93x_playback;
-	snd_pcm_limit_isa_dma_size(chip->dma1, &runtime->hw.buffer_bytes_max);
-	snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, &hw_constraints_rates);
-	return error;
-}
-
-static int snd_opti93x_capture_open(struct snd_pcm_substream *substream)
-{
-	int error;
-	struct snd_opti93x *chip = snd_pcm_substream_chip(substream);
-	struct snd_pcm_runtime *runtime = substream->runtime;
-
-	if ((error = snd_opti93x_open(chip, OPTi93X_MODE_CAPTURE)) < 0)
-		return error;
-	runtime->hw = snd_opti93x_capture;
-	snd_pcm_set_sync(substream);
-	chip->capture_substream = substream;
-	snd_pcm_limit_isa_dma_size(chip->dma2, &runtime->hw.buffer_bytes_max);
-	snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, &hw_constraints_rates);
-	return error;
-}
-
-static int snd_opti93x_playback_close(struct snd_pcm_substream *substream)
-{
-	struct snd_opti93x *chip = snd_pcm_substream_chip(substream);
-
-	chip->playback_substream = NULL;
-	snd_opti93x_close(chip, OPTi93X_MODE_PLAY);
-	return 0;
-}
-
-static int snd_opti93x_capture_close(struct snd_pcm_substream *substream)
-{
-	struct snd_opti93x *chip = snd_pcm_substream_chip(substream);
-
-	chip->capture_substream = NULL;
-	snd_opti93x_close(chip, OPTi93X_MODE_CAPTURE);
-	return 0;
-}
-
-
-static void snd_opti93x_init(struct snd_opti93x *chip)
-{
-	unsigned long flags;
-	int i;
-
-	spin_lock_irqsave(&chip->lock, flags);
-	snd_opti93x_mce_up(chip);
-
-	for (i = 0; i < 32; i++)
-		snd_opti93x_out_image(chip, i, snd_opti93x_default_image[i]);
-
-	snd_opti93x_mce_down(chip);
-	spin_unlock_irqrestore(&chip->lock, flags);
-}
-
-static int snd_opti93x_probe(struct snd_opti93x *chip)
-{
-	unsigned long flags;
-	unsigned char val;
-
-	spin_lock_irqsave(&chip->lock, flags);
-	val = snd_opti93x_in(chip, OPTi93X_ID) & 0x0f;
-	spin_unlock_irqrestore(&chip->lock, flags);
-
-	return (val == 0x0a) ? 0 : -ENODEV;
-}
-
-static int snd_opti93x_free(struct snd_opti93x *chip)
-{
-	release_and_free_resource(chip->res_port);
-	if (chip->dma1 >= 0) {
-		disable_dma(chip->dma1);
-		free_dma(chip->dma1);
-	}
-	if (chip->dma2 >= 0) {
-		disable_dma(chip->dma2);
-		free_dma(chip->dma2);
-	}
-	if (chip->irq >= 0) {
-	  free_irq(chip->irq, chip);
-	}
-	kfree(chip);
-	return 0;
-}
-
-static int snd_opti93x_dev_free(struct snd_device *device)
-{
-	struct snd_opti93x *chip = device->device_data;
-	return snd_opti93x_free(chip);
-}
-
-static const char *snd_opti93x_chip_id(struct snd_opti93x *codec)
-{
-	switch (codec->hardware) {
-	case OPTi9XX_HW_82C930: return "82C930";
-	case OPTi9XX_HW_82C931: return "82C931";
-	case OPTi9XX_HW_82C933: return "82C933";
-	default:		return "???";
-	}
-}
-
-static int snd_opti93x_create(struct snd_card *card, struct snd_opti9xx *chip,
-			      int dma1, int dma2,
-			      struct snd_opti93x **rcodec)
-{
-	static struct snd_device_ops ops = {
-		.dev_free =	snd_opti93x_dev_free,
-	};
-	int error;
-	struct snd_opti93x *codec;
-
-	*rcodec = NULL;
-	codec = kzalloc(sizeof(*codec), GFP_KERNEL);
-	if (codec == NULL)
-		return -ENOMEM;
-	codec->irq = -1;
-	codec->dma1 = -1;
-	codec->dma2 = -1;
-
-	if ((codec->res_port = request_region(chip->wss_base + 4, 4, "OPTI93x CODEC")) == NULL) {
-		snd_printk(KERN_ERR "opti9xx: can't grab port 0x%lx\n", chip->wss_base + 4);
-		snd_opti93x_free(codec);
-		return -EBUSY;
-	}
-	if (request_dma(dma1, "OPTI93x - 1")) {
-		snd_printk(KERN_ERR "opti9xx: can't grab DMA1 %d\n", dma1);
-		snd_opti93x_free(codec);
-		return -EBUSY;
-	}
-	codec->dma1 = chip->dma1;
-	if (request_dma(dma2, "OPTI93x - 2")) {
-		snd_printk(KERN_ERR "opti9xx: can't grab DMA2 %d\n", dma2);
-		snd_opti93x_free(codec);
-		return -EBUSY;
-	}
-	codec->dma2 = chip->dma2;
-
-	if (request_irq(chip->irq, snd_opti93x_interrupt, IRQF_DISABLED, DEV_NAME" - WSS", codec)) {
-		snd_printk(KERN_ERR "opti9xx: can't grab IRQ %d\n", chip->irq);
-		snd_opti93x_free(codec);
-		return -EBUSY;
-	}
-
-	codec->card = card;
-	codec->port = chip->wss_base + 4;
-	codec->irq = chip->irq;
-
-	spin_lock_init(&codec->lock);
-	codec->hardware = chip->hardware;
-	codec->chip = chip;
-
-	if ((error = snd_opti93x_probe(codec))) {
-		snd_opti93x_free(codec);
-		return error;
-	}
-
-	snd_opti93x_init(codec);
-
-	/* Register device */
-	if ((error = snd_device_new(card, SNDRV_DEV_LOWLEVEL, codec, &ops)) < 0) {
-		snd_opti93x_free(codec);
-		return error;
-	}
-
-	*rcodec = codec;
-	return 0;
-}
-
-static struct snd_pcm_ops snd_opti93x_playback_ops = {
-	.open =		snd_opti93x_playback_open,
-	.close =	snd_opti93x_playback_close,
-	.ioctl =	snd_pcm_lib_ioctl,
-	.hw_params =	snd_opti93x_hw_params,
-	.hw_free =	snd_opti93x_hw_free,
-	.prepare =	snd_opti93x_playback_prepare,
-	.trigger =	snd_opti93x_playback_trigger,
-	.pointer =	snd_opti93x_playback_pointer,
-};
-
-static struct snd_pcm_ops snd_opti93x_capture_ops = {
-	.open =		snd_opti93x_capture_open,
-	.close =	snd_opti93x_capture_close,
-	.ioctl =	snd_pcm_lib_ioctl,
-	.hw_params =	snd_opti93x_hw_params,
-	.hw_free =	snd_opti93x_hw_free,
-	.prepare =	snd_opti93x_capture_prepare,
-	.trigger =	snd_opti93x_capture_trigger,
-	.pointer =	snd_opti93x_capture_pointer,
-};
-
-static int snd_opti93x_pcm(struct snd_opti93x *codec, int device, struct snd_pcm **rpcm)
-{
-	int error;
-	struct snd_pcm *pcm;
-
-	if ((error = snd_pcm_new(codec->card, "OPTi 82C93X", device, 1, 1, &pcm)) < 0)
-		return error;
-
-	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_opti93x_playback_ops);
-	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_opti93x_capture_ops);
-
-	pcm->private_data = codec;
-	pcm->info_flags = SNDRV_PCM_INFO_JOINT_DUPLEX;
-
-	strcpy(pcm->name, snd_opti93x_chip_id(codec));
-
-	snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
-					      snd_dma_isa_data(),
-					      64*1024, codec->dma1 > 3 || codec->dma2 > 3 ? 128*1024 : 64*1024);
-
-	codec->pcm = pcm;
-	if (rpcm)
-		*rpcm = pcm;
-	return 0;
-}
-
-/*
- *  MIXER part
- */
-
-static int snd_opti93x_info_mux(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
-{
-	static char *texts[4] = {
-		"Line1", "Aux", "Mic", "Mix"
-	};
-
-	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
-	uinfo->count = 2;
-	uinfo->value.enumerated.items = 4;
-	if (uinfo->value.enumerated.item > 3)
-		uinfo->value.enumerated.item = 3;
-	strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
-	return 0;
-}
-
-static int snd_opti93x_get_mux(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
-{
-	struct snd_opti93x *chip = snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
-	
-	spin_lock_irqsave(&chip->lock, flags);
-	ucontrol->value.enumerated.item[0] = (chip->image[OPTi93X_MIXOUT_LEFT] & OPTi93X_MIXOUT_MIXER) >> 6;
-	ucontrol->value.enumerated.item[1] = (chip->image[OPTi93X_MIXOUT_RIGHT] & OPTi93X_MIXOUT_MIXER) >> 6;
-	spin_unlock_irqrestore(&chip->lock, flags);
-	return 0;
-}
-
-static int snd_opti93x_put_mux(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
-{
-	struct snd_opti93x *chip = snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
-	unsigned short left, right;
-	int change;
-	
-	if (ucontrol->value.enumerated.item[0] > 3 ||
-	    ucontrol->value.enumerated.item[1] > 3)
-		return -EINVAL;
-	left = ucontrol->value.enumerated.item[0] << 6;
-	right = ucontrol->value.enumerated.item[1] << 6;
-	spin_lock_irqsave(&chip->lock, flags);
-	left = (chip->image[OPTi93X_MIXOUT_LEFT] & ~OPTi93X_MIXOUT_MIXER) | left;
-	right = (chip->image[OPTi93X_MIXOUT_RIGHT] & ~OPTi93X_MIXOUT_MIXER) | right;
-	change = left != chip->image[OPTi93X_MIXOUT_LEFT] ||
-	         right != chip->image[OPTi93X_MIXOUT_RIGHT];
-	snd_opti93x_out_image(chip, OPTi93X_MIXOUT_LEFT, left);
-	snd_opti93x_out_image(chip, OPTi93X_MIXOUT_RIGHT, right);
-	spin_unlock_irqrestore(&chip->lock, flags);
-	return change;
-}
-
-#if 0
-
-#define OPTi93X_SINGLE(xname, xindex, reg, shift, mask, invert) \
-{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \
-  .info = snd_opti93x_info_single, \
-  .get = snd_opti93x_get_single, .put = snd_opti93x_put_single, \
-  .private_value = reg | (shift << 8) | (mask << 16) | (invert << 24) }
-
-static int snd_opti93x_info_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
-{
-	int mask = (kcontrol->private_value >> 16) & 0xff;
-
-	uinfo->type = mask == 1 ? SNDRV_CTL_ELEM_TYPE_BOOLEAN : SNDRV_CTL_ELEM_TYPE_INTEGER;
-	uinfo->count = 1;
-	uinfo->value.integer.min = 0;
-	uinfo->value.integer.max = mask;
-	return 0;
-}
-
-static int snd_opti93x_get_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
-{
-	struct snd_opti93x *chip = snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
-	int reg = kcontrol->private_value & 0xff;
-	int shift = (kcontrol->private_value >> 8) & 0xff;
-	int mask = (kcontrol->private_value >> 16) & 0xff;
-	int invert = (kcontrol->private_value >> 24) & 0xff;
-	
-	spin_lock_irqsave(&chip->lock, flags);
-	ucontrol->value.integer.value[0] = (chip->image[reg] >> shift) & mask;
-	spin_unlock_irqrestore(&chip->lock, flags);
-	if (invert)
-		ucontrol->value.integer.value[0] = mask - ucontrol->value.integer.value[0];
-	return 0;
-}
-
-static int snd_opti93x_put_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
-{
-	struct snd_opti93x *chip = snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
-	int reg = kcontrol->private_value & 0xff;
-	int shift = (kcontrol->private_value >> 8) & 0xff;
-	int mask = (kcontrol->private_value >> 16) & 0xff;
-	int invert = (kcontrol->private_value >> 24) & 0xff;
-	int change;
-	unsigned short val;
-	
-	val = (ucontrol->value.integer.value[0] & mask);
-	if (invert)
-		val = mask - val;
-	val <<= shift;
-	spin_lock_irqsave(&chip->lock, flags);
-	val = (chip->image[reg] & ~(mask << shift)) | val;
-	change = val != chip->image[reg];
-	snd_opti93x_out(chip, reg, val);
-	spin_unlock_irqrestore(&chip->lock, flags);
-	return change;
-}
-
-#endif /* single */
-
-#define OPTi93X_DOUBLE(xname, xindex, left_reg, right_reg, shift_left, shift_right, mask, invert) \
-{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \
-  .info = snd_opti93x_info_double, \
-  .get = snd_opti93x_get_double, .put = snd_opti93x_put_double, \
-  .private_value = left_reg | (right_reg << 8) | (shift_left << 16) | (shift_right << 19) | (mask << 24) | (invert << 22) }
-
-#define OPTi93X_DOUBLE_INVERT_INVERT(xctl) \
-	do { xctl.private_value ^= 22; } while (0)
-#define OPTi93X_DOUBLE_CHANGE_REGS(xctl, left_reg, right_reg) \
-	do { xctl.private_value &= ~0x0000ffff; \
-	     xctl.private_value |= left_reg | (right_reg << 8); } while (0)
-
-static int snd_opti93x_info_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
-{
-	int mask = (kcontrol->private_value >> 24) & 0xff;
-
-	uinfo->type = mask == 1 ? SNDRV_CTL_ELEM_TYPE_BOOLEAN : SNDRV_CTL_ELEM_TYPE_INTEGER;
-	uinfo->count = 2;
-	uinfo->value.integer.min = 0;
-	uinfo->value.integer.max = mask;
-	return 0;
-}
-
-static int snd_opti93x_get_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
-{
-	struct snd_opti93x *chip = snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
-	int left_reg = kcontrol->private_value & 0xff;
-	int right_reg = (kcontrol->private_value >> 8) & 0xff;
-	int shift_left = (kcontrol->private_value >> 16) & 0x07;
-	int shift_right = (kcontrol->private_value >> 19) & 0x07;
-	int mask = (kcontrol->private_value >> 24) & 0xff;
-	int invert = (kcontrol->private_value >> 22) & 1;
-	
-	spin_lock_irqsave(&chip->lock, flags);
-	ucontrol->value.integer.value[0] = (chip->image[left_reg] >> shift_left) & mask;
-	ucontrol->value.integer.value[1] = (chip->image[right_reg] >> shift_right) & mask;
-	spin_unlock_irqrestore(&chip->lock, flags);
-	if (invert) {
-		ucontrol->value.integer.value[0] = mask - ucontrol->value.integer.value[0];
-		ucontrol->value.integer.value[1] = mask - ucontrol->value.integer.value[1];
-	}
-	return 0;
-}
-
-static int snd_opti93x_put_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
-{
-	struct snd_opti93x *chip = snd_kcontrol_chip(kcontrol);
-	unsigned long flags;
-	int left_reg = kcontrol->private_value & 0xff;
-	int right_reg = (kcontrol->private_value >> 8) & 0xff;
-	int shift_left = (kcontrol->private_value >> 16) & 0x07;
-	int shift_right = (kcontrol->private_value >> 19) & 0x07;
-	int mask = (kcontrol->private_value >> 24) & 0xff;
-	int invert = (kcontrol->private_value >> 22) & 1;
-	int change;
-	unsigned short val1, val2;
-	
-	val1 = ucontrol->value.integer.value[0] & mask;
-	val2 = ucontrol->value.integer.value[1] & mask;
-	if (invert) {
-		val1 = mask - val1;
-		val2 = mask - val2;
-	}
-	val1 <<= shift_left;
-	val2 <<= shift_right;
-	spin_lock_irqsave(&chip->lock, flags);
-	val1 = (chip->image[left_reg] & ~(mask << shift_left)) | val1;
-	val2 = (chip->image[right_reg] & ~(mask << shift_right)) | val2;
-	change = val1 != chip->image[left_reg] || val2 != chip->image[right_reg];
-	snd_opti93x_out_image(chip, left_reg, val1);
-	snd_opti93x_out_image(chip, right_reg, val2);
-	spin_unlock_irqrestore(&chip->lock, flags);
-	return change;
-}
-
-static struct snd_kcontrol_new snd_opti93x_controls[] __devinitdata = {
-OPTi93X_DOUBLE("Master Playback Switch", 0, OPTi93X_OUT_LEFT, OPTi93X_OUT_RIGHT, 7, 7, 1, 1),
-OPTi93X_DOUBLE("Master Playback Volume", 0, OPTi93X_OUT_LEFT, OPTi93X_OUT_RIGHT, 1, 1, 31, 1), 
-OPTi93X_DOUBLE("PCM Playback Switch", 0, OPTi93X_DAC_LEFT, OPTi93X_DAC_RIGHT, 7, 7, 1, 1),
-OPTi93X_DOUBLE("PCM Playback Volume", 0, OPTi93X_DAC_LEFT, OPTi93X_DAC_RIGHT, 0, 0, 31, 1),
-OPTi93X_DOUBLE("FM Playback Switch", 0, OPTi931_FM_LEFT_INPUT, OPTi931_FM_RIGHT_INPUT, 7, 7, 1, 1),
-OPTi93X_DOUBLE("FM Playback Volume", 0, OPTi931_FM_LEFT_INPUT, OPTi931_FM_RIGHT_INPUT, 1, 1, 15, 1),
-OPTi93X_DOUBLE("Line Playback Switch", 0, OPTi93X_LINE_LEFT_INPUT, OPTi93X_LINE_RIGHT_INPUT, 7, 7, 1, 1),
-OPTi93X_DOUBLE("Line Playback Volume", 0, OPTi93X_LINE_LEFT_INPUT, OPTi93X_LINE_RIGHT_INPUT, 1, 1, 15, 1), 
-OPTi93X_DOUBLE("Mic Playback Switch", 0, OPTi93X_MIC_LEFT_INPUT, OPTi93X_MIC_RIGHT_INPUT, 7, 7, 1, 1),
-OPTi93X_DOUBLE("Mic Playback Volume", 0, OPTi93X_MIC_LEFT_INPUT, OPTi93X_MIC_RIGHT_INPUT, 1, 1, 15, 1), 
-OPTi93X_DOUBLE("Mic Boost", 0, OPTi93X_MIXOUT_LEFT, OPTi93X_MIXOUT_RIGHT, 5, 5, 1, 1),
-OPTi93X_DOUBLE("CD Playback Switch", 0, OPTi93X_CD_LEFT_INPUT, OPTi93X_CD_RIGHT_INPUT, 7, 7, 1, 1),
-OPTi93X_DOUBLE("CD Playback Volume", 0, OPTi93X_CD_LEFT_INPUT, OPTi93X_CD_RIGHT_INPUT, 1, 1, 15, 1),
-OPTi93X_DOUBLE("Aux Playback Switch", 0, OPTi931_AUX_LEFT_INPUT, OPTi931_AUX_RIGHT_INPUT, 7, 7, 1, 1),
-OPTi93X_DOUBLE("Aux Playback Volume", 0, OPTi931_AUX_LEFT_INPUT, OPTi931_AUX_RIGHT_INPUT, 1, 1, 15, 1), 
-OPTi93X_DOUBLE("Capture Volume", 0, OPTi93X_MIXOUT_LEFT, OPTi93X_MIXOUT_RIGHT, 0, 0, 15, 0),
-{
-	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-	.name = "Capture Source",
-	.info = snd_opti93x_info_mux,
-	.get = snd_opti93x_get_mux,
-	.put = snd_opti93x_put_mux,
-}
-};
-                                        
-static int __devinit snd_opti93x_mixer(struct snd_opti93x *chip)
-{
-	struct snd_card *card;
-	struct snd_kcontrol_new knew;
-	int err;
-	unsigned int idx;
-
-	snd_assert(chip != NULL && chip->card != NULL, return -EINVAL);
-
-	card = chip->card;
-
-	strcpy(card->mixername, snd_opti93x_chip_id(chip));
-
-	for (idx = 0; idx < ARRAY_SIZE(snd_opti93x_controls); idx++) {
-		knew = snd_opti93x_controls[idx];
-		if (chip->hardware == OPTi9XX_HW_82C930) {
-			if (strstr(knew.name, "FM"))	/* skip FM controls */
-				continue;
-			else if (strcmp(knew.name, "Mic Playback Volume"))
-				OPTi93X_DOUBLE_INVERT_INVERT(knew);
-			else if (strstr(knew.name, "Aux"))
-				OPTi93X_DOUBLE_CHANGE_REGS(knew, OPTi930_AUX_LEFT_INPUT, OPTi930_AUX_RIGHT_INPUT);
-			else if (strcmp(knew.name, "PCM Playback Volume"))
-				OPTi93X_DOUBLE_INVERT_INVERT(knew);
-			else if (strcmp(knew.name, "Master Playback Volume"))
-				OPTi93X_DOUBLE_INVERT_INVERT(knew);
-		}
-		if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_opti93x_controls[idx], chip))) < 0)
-			return err;
-	}
-	return 0;
-}
-
 #endif /* OPTi93X */
 
 static int __devinit snd_card_opti9xx_detect(struct snd_card *card,
@@ -1739,8 +685,16 @@ static void snd_card_opti9xx_free(struct
 {
 	struct snd_opti9xx *chip = card->private_data;
         
-	if (chip)
+	if (chip) {
+#ifdef OPTi93X
+		struct snd_cs4231 *codec = chip->codec;
+		if (codec->irq > 0) {
+			disable_irq(codec->irq);
+			free_irq(codec->irq, codec);
+		}
+#endif
 		release_and_free_resource(chip->res_mc_base);
+	}
 }
 
 static int __devinit snd_opti9xx_probe(struct snd_card *card)
@@ -1748,11 +702,11 @@ static int __devinit snd_opti9xx_probe(s
 	static long possible_ports[] = {0x530, 0xe80, 0xf40, 0x604, -1};
 	int error;
 	struct snd_opti9xx *chip = card->private_data;
-#if defined(OPTi93X)
-	struct snd_opti93x *codec;
-#elif defined(CS4231)
+#if defined(CS4231) || defined(OPTi93X)
 	struct snd_cs4231 *codec;
+#ifdef CS4231
 	struct snd_timer *timer;
+#endif
 #else
 	struct snd_ad1848 *codec;
 #endif
@@ -1784,26 +738,34 @@ static int __devinit snd_opti9xx_probe(s
 	if ((error = snd_opti9xx_configure(chip)))
 		return error;
 
-#if defined(OPTi93X)
-	if ((error = snd_opti93x_create(card, chip, chip->dma1, chip->dma2, &codec)))
-		return error;
-	if ((error = snd_opti93x_pcm(codec, 0, &pcm)) < 0)
-		return error;
-	if ((error = snd_opti93x_mixer(codec)) < 0)
-		return error;
-#elif defined(CS4231)
+#if defined(CS4231) || defined(OPTi93X)
 	if ((error = snd_cs4231_create(card, chip->wss_base + 4, -1,
 				       chip->irq, chip->dma1, chip->dma2,
-				       CS4231_HW_DETECT,
-				       0,
+#ifdef CS4231
+				       CS4231_HW_DETECT, 0,
+#else /* OPTi93x */
+				       CS4231_HW_OPTI93X, CS4231_HWSHARE_IRQ,
+#endif
 				       &codec)) < 0)
 		return error;
+#ifdef OPTi93X
+	chip->codec = codec;
+#endif
 	if ((error = snd_cs4231_pcm(codec, 0, &pcm)) < 0)
 		return error;
 	if ((error = snd_cs4231_mixer(codec)) < 0)
 		return error;
+#ifdef CS4231
 	if ((error = snd_cs4231_timer(codec, 0, &timer)) < 0)
 		return error;
+#else /* OPTI93X */
+	error = request_irq(chip->irq, snd_opti93x_interrupt,
+			    IRQF_DISABLED, DEV_NAME" - WSS", codec);
+	if (error < 0) {
+		snd_printk(KERN_ERR "opti9xx: can't grab IRQ %d\n", chip->irq);
+		return error;
+	}
+#endif
 #else
 	if ((error = snd_ad1848_create(card, chip->wss_base + 4,
 				       chip->irq, chip->dma1,

---------------------------------------------------------------
Sprawdz jak zdobyc zdrowy usmiech!
Kliknij >> http://link.interia.pl/f1e26



More information about the Alsa-devel mailing list