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

📄 ad1848_lib.c

📁 鼎力推荐!本程序是基于嵌入式LUNUX系统开发的源程序代码
💻 C
📖 第 1 页 / 共 3 页
字号:
	/* ok. now enable and ack CODEC IRQ */	spin_lock_irqsave(&chip->reg_lock, flags);	outb(0, AD1848P(chip, STATUS));	/* clear IRQ */	outb(0, AD1848P(chip, STATUS));	/* clear IRQ */	chip->image[AD1848_PIN_CTRL] |= AD1848_IRQ_ENABLE;	snd_ad1848_out(chip, AD1848_PIN_CTRL, chip->image[AD1848_PIN_CTRL]);	spin_unlock_irqrestore(&chip->reg_lock, flags);	chip->mode = mode;	up(&chip->open_mutex);	return 0;}static void snd_ad1848_close(ad1848_t *chip){	unsigned long flags;	down(&chip->open_mutex);	if (!chip->mode) {		up(&chip->open_mutex);		return;	}	/* disable IRQ */	spin_lock_irqsave(&chip->reg_lock, flags);	outb(0, AD1848P(chip, STATUS));	/* clear IRQ */	outb(0, AD1848P(chip, STATUS));	/* clear IRQ */	chip->image[AD1848_PIN_CTRL] &= ~AD1848_IRQ_ENABLE;	snd_ad1848_out(chip, AD1848_PIN_CTRL, chip->image[AD1848_PIN_CTRL]);	spin_unlock_irqrestore(&chip->reg_lock, flags);	/* now disable capture & playback */	snd_ad1848_mce_up(chip);	spin_lock_irqsave(&chip->reg_lock, flags);	chip->image[AD1848_IFACE_CTRL] &= ~(AD1848_PLAYBACK_ENABLE | AD1848_PLAYBACK_PIO |			     AD1848_CAPTURE_ENABLE | AD1848_CAPTURE_PIO);	snd_ad1848_out(chip, AD1848_IFACE_CTRL, chip->image[AD1848_IFACE_CTRL]);	spin_unlock_irqrestore(&chip->reg_lock, flags);	snd_ad1848_mce_down(chip);	/* clear IRQ again */	spin_lock_irqsave(&chip->reg_lock, flags);	outb(0, AD1848P(chip, STATUS));	/* clear IRQ */	outb(0, AD1848P(chip, STATUS));	/* clear IRQ */	spin_unlock_irqrestore(&chip->reg_lock, flags);	chip->mode = 0;	up(&chip->open_mutex);}/* *  ok.. exported functions.. */static int snd_ad1848_playback_trigger(snd_pcm_substream_t * substream,				       int cmd){	ad1848_t *chip = snd_pcm_substream_chip(substream);	return snd_ad1848_trigger(chip, AD1848_PLAYBACK_ENABLE, SNDRV_PCM_STREAM_PLAYBACK, cmd);}static int snd_ad1848_capture_trigger(snd_pcm_substream_t * substream,				      int cmd){	ad1848_t *chip = snd_pcm_substream_chip(substream);	return snd_ad1848_trigger(chip, AD1848_CAPTURE_ENABLE, SNDRV_PCM_STREAM_CAPTURE, cmd);}static int snd_ad1848_playback_hw_params(snd_pcm_substream_t * substream,					 snd_pcm_hw_params_t * hw_params){	ad1848_t *chip = snd_pcm_substream_chip(substream);	unsigned long flags;	int err;	if ((err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params))) < 0)		return err;	snd_ad1848_calibrate_mute(chip, 1);	snd_ad1848_set_data_format(chip, hw_params);	snd_ad1848_mce_up(chip);	spin_lock_irqsave(&chip->reg_lock, flags);	snd_ad1848_out(chip, AD1848_DATA_FORMAT, chip->image[AD1848_DATA_FORMAT]);	spin_unlock_irqrestore(&chip->reg_lock, flags);	snd_ad1848_mce_down(chip);	snd_ad1848_calibrate_mute(chip, 0);	return 0;}static int snd_ad1848_playback_hw_free(snd_pcm_substream_t * substream){	return snd_pcm_lib_free_pages(substream);}static int snd_ad1848_playback_prepare(snd_pcm_substream_t * substream){	ad1848_t *chip = snd_pcm_substream_chip(substream);	snd_pcm_runtime_t *runtime = substream->runtime;	unsigned long flags;	unsigned int size = snd_pcm_lib_buffer_bytes(substream);	unsigned int count = snd_pcm_lib_period_bytes(substream);	chip->dma_size = size;	chip->image[AD1848_IFACE_CTRL] &= ~(AD1848_PLAYBACK_ENABLE | AD1848_PLAYBACK_PIO);	snd_dma_program(chip->dma, runtime->dma_addr, size, DMA_MODE_WRITE | DMA_AUTOINIT);	count = snd_ad1848_get_count(chip->image[AD1848_DATA_FORMAT], count) - 1;	spin_lock_irqsave(&chip->reg_lock, flags);	snd_ad1848_out(chip, AD1848_DATA_LWR_CNT, (unsigned char) count);	snd_ad1848_out(chip, AD1848_DATA_UPR_CNT, (unsigned char) (count >> 8));	spin_unlock_irqrestore(&chip->reg_lock, flags);	return 0;}static int snd_ad1848_capture_hw_params(snd_pcm_substream_t * substream,					snd_pcm_hw_params_t * hw_params){	ad1848_t *chip = snd_pcm_substream_chip(substream);	unsigned long flags;	int err;	if ((err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params))) < 0)		return err;	snd_ad1848_calibrate_mute(chip, 1);	snd_ad1848_set_data_format(chip, hw_params);	snd_ad1848_mce_up(chip);	spin_lock_irqsave(&chip->reg_lock, flags);	snd_ad1848_out(chip, AD1848_DATA_FORMAT, chip->image[AD1848_DATA_FORMAT]);	spin_unlock_irqrestore(&chip->reg_lock, flags);	snd_ad1848_mce_down(chip);	snd_ad1848_calibrate_mute(chip, 0);	return 0;}static int snd_ad1848_capture_hw_free(snd_pcm_substream_t * substream){	return snd_pcm_lib_free_pages(substream);}static int snd_ad1848_capture_prepare(snd_pcm_substream_t * substream){	ad1848_t *chip = snd_pcm_substream_chip(substream);	snd_pcm_runtime_t *runtime = substream->runtime;	unsigned long flags;	unsigned int size = snd_pcm_lib_buffer_bytes(substream);	unsigned int count = snd_pcm_lib_period_bytes(substream);	chip->dma_size = size;	chip->image[AD1848_IFACE_CTRL] &= ~(AD1848_CAPTURE_ENABLE | AD1848_CAPTURE_PIO);	snd_dma_program(chip->dma, runtime->dma_addr, size, DMA_MODE_READ | DMA_AUTOINIT);	count = snd_ad1848_get_count(chip->image[AD1848_DATA_FORMAT], count) - 1;	spin_lock_irqsave(&chip->reg_lock, flags);	snd_ad1848_out(chip, AD1848_DATA_LWR_CNT, (unsigned char) count);	snd_ad1848_out(chip, AD1848_DATA_UPR_CNT, (unsigned char) (count >> 8));	spin_unlock_irqrestore(&chip->reg_lock, flags);	return 0;}static irqreturn_t snd_ad1848_interrupt(int irq, void *dev_id, struct pt_regs *regs){	ad1848_t *chip = dev_id;	if ((chip->mode & AD1848_MODE_PLAY) && chip->playback_substream &&	    (chip->mode & AD1848_MODE_RUNNING))		snd_pcm_period_elapsed(chip->playback_substream);	if ((chip->mode & AD1848_MODE_CAPTURE) && chip->capture_substream &&	    (chip->mode & AD1848_MODE_RUNNING))		snd_pcm_period_elapsed(chip->capture_substream);	outb(0, AD1848P(chip, STATUS));	/* clear global interrupt bit */	return IRQ_HANDLED;}static snd_pcm_uframes_t snd_ad1848_playback_pointer(snd_pcm_substream_t * substream){	ad1848_t *chip = snd_pcm_substream_chip(substream);	size_t ptr;		if (!(chip->image[AD1848_IFACE_CTRL] & AD1848_PLAYBACK_ENABLE))		return 0;	ptr = snd_dma_pointer(chip->dma, chip->dma_size);	return bytes_to_frames(substream->runtime, ptr);}static snd_pcm_uframes_t snd_ad1848_capture_pointer(snd_pcm_substream_t * substream){	ad1848_t *chip = snd_pcm_substream_chip(substream);	size_t ptr;	if (!(chip->image[AD1848_IFACE_CTRL] & AD1848_CAPTURE_ENABLE))		return 0;	ptr = snd_dma_pointer(chip->dma, chip->dma_size);	return bytes_to_frames(substream->runtime, ptr);}/* */static void snd_ad1848_thinkpad_twiddle(ad1848_t *chip, int on) {	int tmp;	if (!chip->thinkpad_flag) return;	outb(0x1c, AD1848_THINKPAD_CTL_PORT1);	tmp = inb(AD1848_THINKPAD_CTL_PORT2);	if (on)		/* turn it on */		tmp |= AD1848_THINKPAD_CS4248_ENABLE_BIT;	else		/* turn it off */		tmp &= ~AD1848_THINKPAD_CS4248_ENABLE_BIT;		outb(tmp, AD1848_THINKPAD_CTL_PORT2);}#ifdef CONFIG_PMstatic int snd_ad1848_suspend(snd_card_t *card, unsigned int state){	ad1848_t *chip = card->pm_private_data;	snd_pcm_suspend_all(chip->pcm);	/* FIXME: save registers? */	if (chip->thinkpad_flag)		snd_ad1848_thinkpad_twiddle(chip, 0);	return 0;}static int snd_ad1848_resume(snd_card_t *card, unsigned int state){	ad1848_t *chip = card->pm_private_data;	if (chip->thinkpad_flag)		snd_ad1848_thinkpad_twiddle(chip, 1);	/* FIXME: restore registers? */	return 0;}#endif /* CONFIG_PM */static int snd_ad1848_probe(ad1848_t * chip){	unsigned long flags;	int i, id, rev, ad1847;	unsigned char *ptr;#if 0	snd_ad1848_debug(chip);#endif	id = ad1847 = 0;	for (i = 0; i < 1000; i++) {		mb();		if (inb(AD1848P(chip, REGSEL)) & AD1848_INIT)			udelay(500);		else {			spin_lock_irqsave(&chip->reg_lock, flags);			snd_ad1848_out(chip, AD1848_MISC_INFO, 0x00);			snd_ad1848_out(chip, AD1848_LEFT_INPUT, 0xaa);			snd_ad1848_out(chip, AD1848_RIGHT_INPUT, 0x45);			rev = snd_ad1848_in(chip, AD1848_RIGHT_INPUT);			if (rev == 0x65) {				spin_unlock_irqrestore(&chip->reg_lock, flags);				id = 1;				ad1847 = 1;				break;			}			if (snd_ad1848_in(chip, AD1848_LEFT_INPUT) == 0xaa && rev == 0x45) {				spin_unlock_irqrestore(&chip->reg_lock, flags);				id = 1;				break;			}			spin_unlock_irqrestore(&chip->reg_lock, flags);		}	}	if (id != 1)		return -ENODEV;	/* no valid device found */	if (chip->hardware == AD1848_HW_DETECT) {		if (ad1847) {			chip->hardware = AD1848_HW_AD1847;		} else {			chip->hardware = AD1848_HW_AD1848;			rev = snd_ad1848_in(chip, AD1848_MISC_INFO);			if (rev & 0x80) {				chip->hardware = AD1848_HW_CS4248;			} else if ((rev & 0x0f) == 0x0a) {				snd_ad1848_out(chip, AD1848_MISC_INFO, 0x40);				for (i = 0; i < 16; ++i) {					if (snd_ad1848_in(chip, i) != snd_ad1848_in(chip, i + 16)) {						chip->hardware = AD1848_HW_CMI8330;						break;					}				}				snd_ad1848_out(chip, AD1848_MISC_INFO, 0x00);			}		}	}	spin_lock_irqsave(&chip->reg_lock, flags);	inb(AD1848P(chip, STATUS));	/* clear any pendings IRQ */	outb(0, AD1848P(chip, STATUS));	mb();	spin_unlock_irqrestore(&chip->reg_lock, flags);	chip->image[AD1848_MISC_INFO] = 0x00;	chip->image[AD1848_IFACE_CTRL] =	    (chip->image[AD1848_IFACE_CTRL] & ~AD1848_SINGLE_DMA) | AD1848_SINGLE_DMA;	ptr = (unsigned char *) &chip->image;	snd_ad1848_mce_down(chip);	spin_lock_irqsave(&chip->reg_lock, flags);	for (i = 0; i < 16; i++)	/* ok.. fill all AD1848 registers */		snd_ad1848_out(chip, i, *ptr++);	spin_unlock_irqrestore(&chip->reg_lock, flags);	snd_ad1848_mce_up(chip);	snd_ad1848_mce_down(chip);	return 0;		/* all things are ok.. */}/* */static snd_pcm_hardware_t snd_ad1848_playback ={	.info =			(SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |				 SNDRV_PCM_INFO_MMAP_VALID),	.formats =		(SNDRV_PCM_FMTBIT_MU_LAW | SNDRV_PCM_FMTBIT_A_LAW |				 SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE),	.rates =		SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_8000_48000,	.rate_min =		5510,	.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 snd_pcm_hardware_t snd_ad1848_capture ={	.info =			(SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |				 SNDRV_PCM_INFO_MMAP_VALID),	.formats =		(SNDRV_PCM_FMTBIT_MU_LAW | SNDRV_PCM_FMTBIT_A_LAW |				 SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE),	.rates =		SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_8000_48000,	.rate_min =		5510,	.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_ad1848_playback_open(snd_pcm_substream_t * substream){	ad1848_t *chip = snd_pcm_substream_chip(substream);	snd_pcm_runtime_t *runtime = substream->runtime;	int err;	if ((err = snd_ad1848_open(chip, AD1848_MODE_PLAY)) < 0)		return err;	chip->playback_substream = substream;	runtime->hw = snd_ad1848_playback;	snd_pcm_limit_isa_dma_size(chip->dma, &runtime->hw.buffer_bytes_max);	snd_pcm_limit_isa_dma_size(chip->dma, &runtime->hw.period_bytes_max);	snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, &hw_constraints_rates);	return 0;}static int snd_ad1848_capture_open(snd_pcm_substream_t * substream){	ad1848_t *chip = snd_pcm_substream_chip(substream);	snd_pcm_runtime_t *runtime = substream->runtime;	int err;	if ((err = snd_ad1848_open(chip, AD1848_MODE_CAPTURE)) < 0)		return err;	chip->capture_substream = substream;	runtime->hw = snd_ad1848_capture;	snd_pcm_limit_isa_dma_size(chip->dma, &runtime->hw.buffer_bytes_max);	snd_pcm_limit_isa_dma_size(chip->dma, &runtime->hw.period_bytes_max);	snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, &hw_constraints_rates);	return 0;}static int snd_ad1848_playback_close(snd_pcm_substream_t * substream){	ad1848_t *chip = snd_pcm_substream_chip(substream);	chip->mode &= ~AD1848_MODE_PLAY;	chip->playback_substream = NULL;	snd_ad1848_close(chip);	return 0;}static int snd_ad1848_capture_close(snd_pcm_substream_t * substream){	ad1848_t *chip = snd_pcm_substream_chip(substream);	chip->mode &= ~AD1848_MODE_CAPTURE;	chip->capture_substream = NULL;	snd_ad1848_close(chip);	return 0;}static int snd_ad1848_free(ad1848_t *chip){	if (chip->res_port) {		release_resource(chip->res_port);		kfree_nocheck(chip->res_port);	}	if (chip->irq >= 0)		free_irq(chip->irq, (void *) chip);

⌨️ 快捷键说明

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