[alsa-devel] [PATCH 2/2] opti93x: use cs4231 lib
From: Krzysztof Helt krzysztof.h1@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@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.htm...
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
On 09-06-08 23:07, Krzysztof Helt wrote:
From: Krzysztof Helt krzysztof.h1@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@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.
Tested-by: Rene Herman rene.herman@gmail.com
again also on 930, 931 and 933. As said, good to see this. Only quickly scanned the code and didn't immedately see the mixer level issue. Is the level difference reproducible at your end or should I investigate further?
Rene.
At Mon, 9 Jun 2008 23:07:32 +0200, Krzysztof Helt wrote:
From: Krzysztof Helt krzysztof.h1@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@wp.pl
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.htm...
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_pcm_period_elapsed(codec->capture_substream); } outb(0x00, OPTi93X_PORT(codec, STATUS)); return IRQ_HANDLED;snd_cs4231_overrange(codec);
}
-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@alsa-project.org http://mailman.alsa-project.org/mailman/listinfo/alsa-devel
On Tue, 10 Jun 2008 07:40:51 +0200 Takashi Iwai tiwai@suse.de wrote:
A change in Kconfig file makes this patch not applicable.
This is a diff against the latest alsa-drivers snapshot. However, the original patch applied against the snapshot but the Kconfig change was shifted bu -17 lines.
Regards, Krzysztof
--- From: Krzysztof Helt krzysztof.h1@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@wp.pl ---
diff -urp linux-mm/sound/isa/Kconfig linux-alsa/sound/isa/Kconfig --- linux-mm/sound/isa/Kconfig 2008-06-10 15:55:47.000000000 +0200 +++ linux-alsa/sound/isa/Kconfig 2008-06-10 23:04:05.621118551 +0200 @@ -304,7 +304,7 @@ config SND_OPTI93X tristate "OPTi 82C93x" 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-mm/sound/isa/opti9xx/opti92x-ad1848.c linux-alsa/sound/isa/opti9xx/opti92x-ad1848.c --- linux-mm/sound/isa/opti9xx/opti92x-ad1848.c 2008-06-10 23:02:16.733113027 +0200 +++ linux-alsa/sound/isa/opti9xx/opti92x-ad1848.c 2008-06-10 23:04:05.629118315 +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;
@@ -491,16 +393,9 @@ static int __devinit snd_opti9xx_configu break;
#else /* OPTi93X */ - case OPTi9XX_HW_82C930: case OPTi9XX_HW_82C931: case OPTi9XX_HW_82C933: - snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(6), 0x02, 0x03); - snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(3), 0x00, 0xff); - snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(4), 0x10 | - (chip->hardware == OPTi9XX_HW_82C930 ? 0x00 : 0x04), - 0x34); - snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(5), 0x20, 0xbf); - /* + /* * The BTC 1817DW has QS1000 wavetable which is connected * to the serial digital input of the OPTI931. */ @@ -510,6 +405,13 @@ static int __devinit snd_opti9xx_configu * or digital input signal. */ snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(26), 0x01, 0x01); + case OPTi9XX_HW_82C930: /* FALL THROUGH */ + snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(6), 0x02, 0x03); + snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(3), 0x00, 0xff); + snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(4), 0x10 | + (chip->hardware == OPTi9XX_HW_82C930 ? 0x00 : 0x04), + 0x34); + snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(5), 0x20, 0xbf); break; #endif /* OPTi93X */
@@ -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,
---------------------------------------------------------------------- Tania telefonia internetowa! Sprawdz >>> http://link.interia.pl/f1e2e
At Tue, 10 Jun 2008 23:09:02 +0200, Krzysztof Helt wrote:
On Tue, 10 Jun 2008 07:40:51 +0200 Takashi Iwai tiwai@suse.de wrote:
A change in Kconfig file makes this patch not applicable.
This is a diff against the latest alsa-drivers snapshot. However, the original patch applied against the snapshot but the Kconfig change was shifted bu -17 lines.
Heh yes, it worked surprisingly, too. The patch program is cleverer than I thought :)
I applied both patches on my tree now. Thanks!
Takashi
participants (3)
-
Krzysztof Helt
-
Rene Herman
-
Takashi Iwai