📄 opti92x-ad1848.c
字号:
} spin_unlock_irqrestore(&chip->lock, flags);}#define snd_opti9xx_write_mask(chip, reg, value, mask) \ snd_opti9xx_write(chip, reg, \ (snd_opti9xx_read(chip, reg) & ~(mask)) | ((value) & (mask)))static int __devinit snd_opti9xx_configure(opti9xx_t *chip){ unsigned char wss_base_bits; unsigned char irq_bits; unsigned char dma_bits; unsigned char mpu_port_bits = 0; unsigned char mpu_irq_bits; switch (chip->hardware) {#ifndef OPTi93X case OPTi9XX_HW_82C924: snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(4), 0xf0, 0xfc); snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(6), 0x02, 0x02); case OPTi9XX_HW_82C925: snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(1), 0x80, 0x80); snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(2), 0x00, 0x20); snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(3), 0xf0, 0xff);#ifdef CS4231 snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(5), 0x02, 0x02);#else snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(5), 0x00, 0x02);#endif /* CS4231 */ break; case OPTi9XX_HW_82C928: case OPTi9XX_HW_82C929: snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(1), 0x80, 0x80); snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(2), 0x00, 0x20); /* snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(3), 0xa2, 0xae); */ snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(4), 0x00, 0x0c);#ifdef CS4231 snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(5), 0x02, 0x02);#else snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(5), 0x00, 0x02);#endif /* CS4231 */ 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); break;#endif /* OPTi93X */ default: snd_printk("chip %d not supported\n", chip->hardware); return -EINVAL; } switch (chip->wss_base) { case 0x530: wss_base_bits = 0x00; break; case 0x604: wss_base_bits = 0x03; break; case 0xe80: wss_base_bits = 0x01; break; case 0xf40: wss_base_bits = 0x02; break; default: snd_printk("WSS port 0x%lx not valid\n", chip->wss_base); goto __skip_base; } snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(1), wss_base_bits << 4, 0x30);__skip_base: switch (chip->irq) {//#ifdef OPTi93X case 5: irq_bits = 0x05; break;//#endif /* OPTi93X */ case 7: irq_bits = 0x01; break; case 9: irq_bits = 0x02; break; case 10: irq_bits = 0x03; break; case 11: irq_bits = 0x04; break; default: snd_printk("WSS irq # %d not valid\n", chip->irq); goto __skip_resources; } switch (chip->dma1) { case 0: dma_bits = 0x01; break; case 1: dma_bits = 0x02; break; case 3: dma_bits = 0x03; break; default: snd_printk("WSS dma1 # %d not valid\n", chip->dma1); goto __skip_resources; }#if defined(CS4231) || defined(OPTi93X) if (chip->dma1 == chip->dma2) { snd_printk("don't want to share dmas\n"); return -EBUSY; } switch (chip->dma2) { case 0: case 1: break; default: snd_printk("WSS dma2 # %d not valid\n", chip->dma2); goto __skip_resources; } dma_bits |= 0x04;#endif /* CS4231 || OPTi93X */#ifndef OPTi93X outb(irq_bits << 3 | dma_bits, chip->wss_base);#else /* OPTi93X */ snd_opti9xx_write(chip, OPTi9XX_MC_REG(3), (irq_bits << 3 | dma_bits));#endif /* OPTi93X */__skip_resources: if (chip->hardware > OPTi9XX_HW_82C928) { switch (chip->mpu_port) { case 0: case -1: break; case 0x300: mpu_port_bits = 0x03; break; case 0x310: mpu_port_bits = 0x02; break; case 0x320: mpu_port_bits = 0x01; break; case 0x330: mpu_port_bits = 0x00; break; default: snd_printk("MPU-401 port 0x%lx not valid\n", chip->mpu_port); goto __skip_mpu; } switch (chip->mpu_irq) { case 5: mpu_irq_bits = 0x02; break; case 7: mpu_irq_bits = 0x03; break; case 9: mpu_irq_bits = 0x00; break; case 10: mpu_irq_bits = 0x01; break; default: snd_printk("MPU-401 irq # %d not valid\n", chip->mpu_irq); goto __skip_mpu; } snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(6), (chip->mpu_port <= 0) ? 0x00 : 0x80 | mpu_port_bits << 5 | mpu_irq_bits << 3, 0xf8); }__skip_mpu: return 0;}#ifdef OPTi93Xstatic 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(opti93x_t *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(opti93x_t *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(opti93x_t *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(opti93x_t *chip, unsigned char reg, unsigned char value){ snd_opti93x_out(chip, reg, chip->image[reg] = value);}static void snd_opti93x_out_mask(opti93x_t *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(opti93x_t *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(opti93x_t *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(opti93x_t *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 snd_pcm_hw_constraint_list_t 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(opti93x_t *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(opti93x_t *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(opti93x_t *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(opti93x_t *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; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -