At Mon, 9 Jun 2008 23:07:32 +0200, Krzysztof Helt wrote: > > From: Krzysztof Helt <krzysztof.h1@xxxxx> > > This patch converts the Opti93x driver to use > the cs4231 library instead of duplicating the code. > > Signed-off-by: Krzysztof Helt <krzysztof.h1@xxxxx> Could you make diff against the latest alsa.git tree or to linux-next tree? A change in Kconfig file makes this patch not applicable. thanks, Takashi > --- > 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 > > _______________________________________________ > Alsa-devel mailing list > Alsa-devel@xxxxxxxxxxxxxxxx > http://mailman.alsa-project.org/mailman/listinfo/alsa-devel > _______________________________________________ Alsa-devel mailing list Alsa-devel@xxxxxxxxxxxxxxxx http://mailman.alsa-project.org/mailman/listinfo/alsa-devel