⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 opti92x-ad1848.c

📁 LINUX 2.6.17.4的源码
💻 C
📖 第 1 页 / 共 4 页
字号:
	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(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 list_head *pos;		struct snd_pcm_substream *s;		snd_pcm_group_for_each(pos, substream) {			s = snd_pcm_group_substream_entry(pos);			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);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -