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

📄 ice1712.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 5 页
字号:
		}		if (status & ICE1712_IRQ_FM)			outb(ICE1712_IRQ_FM, ICEREG(ice, IRQSTAT));		if (status & ICE1712_IRQ_PBKDS) {			u32 idx;			u16 pbkstatus;			snd_pcm_substream_t *substream;			pbkstatus = inw(ICEDS(ice, INTSTAT));			//printk("pbkstatus = 0x%x\n", pbkstatus);			for (idx = 0; idx < 6; idx++) {				if ((pbkstatus & (3 << (idx * 2))) == 0)					continue;				if ((substream = ice->playback_con_substream_ds[idx]) != NULL)					snd_pcm_period_elapsed(substream);				outw(3 << (idx * 2), ICEDS(ice, INTSTAT));			}			outb(ICE1712_IRQ_PBKDS, ICEREG(ice, IRQSTAT));		}		if (status & ICE1712_IRQ_CONCAP) {			if (ice->capture_con_substream)				snd_pcm_period_elapsed(ice->capture_con_substream);			outb(ICE1712_IRQ_CONCAP, ICEREG(ice, IRQSTAT));		}		if (status & ICE1712_IRQ_CONPBK) {			if (ice->playback_con_substream)				snd_pcm_period_elapsed(ice->playback_con_substream);			outb(ICE1712_IRQ_CONPBK, ICEREG(ice, IRQSTAT));		}	}	return IRQ_RETVAL(handled);}/* *  PCM part - misc */static int snd_ice1712_hw_params(snd_pcm_substream_t * substream,				 snd_pcm_hw_params_t * hw_params){	return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params));}static int snd_ice1712_hw_free(snd_pcm_substream_t * substream){	return snd_pcm_lib_free_pages(substream);}/* *  PCM part - consumer I/O */static int snd_ice1712_playback_trigger(snd_pcm_substream_t * substream,					int cmd){	ice1712_t *ice = snd_pcm_substream_chip(substream);	int result = 0;	u32 tmp;		spin_lock(&ice->reg_lock);	tmp = snd_ice1712_read(ice, ICE1712_IREG_PBK_CTRL);	if (cmd == SNDRV_PCM_TRIGGER_START) {		tmp |= 1;	} else if (cmd == SNDRV_PCM_TRIGGER_STOP) {		tmp &= ~1;	} else if (cmd == SNDRV_PCM_TRIGGER_PAUSE_PUSH) {		tmp |= 2;	} else if (cmd == SNDRV_PCM_TRIGGER_PAUSE_RELEASE) {		tmp &= ~2;	} else {		result = -EINVAL;	}	snd_ice1712_write(ice, ICE1712_IREG_PBK_CTRL, tmp);	spin_unlock(&ice->reg_lock);	return result;}static int snd_ice1712_playback_ds_trigger(snd_pcm_substream_t * substream,					   int cmd){	ice1712_t *ice = snd_pcm_substream_chip(substream);	int result = 0;	u32 tmp;		spin_lock(&ice->reg_lock);	tmp = snd_ice1712_ds_read(ice, substream->number * 2, ICE1712_DSC_CONTROL);	if (cmd == SNDRV_PCM_TRIGGER_START) {		tmp |= 1;	} else if (cmd == SNDRV_PCM_TRIGGER_STOP) {		tmp &= ~1;	} else if (cmd == SNDRV_PCM_TRIGGER_PAUSE_PUSH) {		tmp |= 2;	} else if (cmd == SNDRV_PCM_TRIGGER_PAUSE_RELEASE) {		tmp &= ~2;	} else {		result = -EINVAL;	}	snd_ice1712_ds_write(ice, substream->number * 2, ICE1712_DSC_CONTROL, tmp);	spin_unlock(&ice->reg_lock);	return result;}static int snd_ice1712_capture_trigger(snd_pcm_substream_t * substream,				       int cmd){	ice1712_t *ice = snd_pcm_substream_chip(substream);	int result = 0;	u8 tmp;		spin_lock(&ice->reg_lock);	tmp = snd_ice1712_read(ice, ICE1712_IREG_CAP_CTRL);	if (cmd == SNDRV_PCM_TRIGGER_START) {		tmp |= 1;	} else if (cmd == SNDRV_PCM_TRIGGER_STOP) {		tmp &= ~1;	} else {		result = -EINVAL;	}	snd_ice1712_write(ice, ICE1712_IREG_CAP_CTRL, tmp);	spin_unlock(&ice->reg_lock);	return result;}static int snd_ice1712_playback_prepare(snd_pcm_substream_t * substream){	ice1712_t *ice = snd_pcm_substream_chip(substream);	snd_pcm_runtime_t *runtime = substream->runtime;	u32 period_size, buf_size, rate, tmp;	period_size = (snd_pcm_lib_period_bytes(substream) >> 2) - 1;	buf_size = snd_pcm_lib_buffer_bytes(substream) - 1;	tmp = 0x0000;	if (snd_pcm_format_width(runtime->format) == 16)		tmp |= 0x10;	if (runtime->channels == 2)		tmp |= 0x08;	rate = (runtime->rate * 8192) / 375;	if (rate > 0x000fffff)		rate = 0x000fffff;	spin_lock_irq(&ice->reg_lock);	outb(0, ice->ddma_port + 15);	outb(ICE1712_DMA_MODE_WRITE | ICE1712_DMA_AUTOINIT, ice->ddma_port + 0x0b);	outl(runtime->dma_addr, ice->ddma_port + 0);	outw(buf_size, ice->ddma_port + 4);	snd_ice1712_write(ice, ICE1712_IREG_PBK_RATE_LO, rate & 0xff);	snd_ice1712_write(ice, ICE1712_IREG_PBK_RATE_MID, (rate >> 8) & 0xff);	snd_ice1712_write(ice, ICE1712_IREG_PBK_RATE_HI, (rate >> 16) & 0xff);	snd_ice1712_write(ice, ICE1712_IREG_PBK_CTRL, tmp);	snd_ice1712_write(ice, ICE1712_IREG_PBK_COUNT_LO, period_size & 0xff);	snd_ice1712_write(ice, ICE1712_IREG_PBK_COUNT_HI, period_size >> 8);	snd_ice1712_write(ice, ICE1712_IREG_PBK_LEFT, 0);	snd_ice1712_write(ice, ICE1712_IREG_PBK_RIGHT, 0);	spin_unlock_irq(&ice->reg_lock);	return 0;}static int snd_ice1712_playback_ds_prepare(snd_pcm_substream_t * substream){	ice1712_t *ice = snd_pcm_substream_chip(substream);	snd_pcm_runtime_t *runtime = substream->runtime;	u32 period_size, buf_size, rate, tmp, chn;	period_size = snd_pcm_lib_period_bytes(substream) - 1;	buf_size = snd_pcm_lib_buffer_bytes(substream) - 1;	tmp = 0x0064;	if (snd_pcm_format_width(runtime->format) == 16)		tmp &= ~0x04;	if (runtime->channels == 2)		tmp |= 0x08;	rate = (runtime->rate * 8192) / 375;	if (rate > 0x000fffff)		rate = 0x000fffff;	ice->playback_con_active_buf[substream->number] = 0;	ice->playback_con_virt_addr[substream->number] = runtime->dma_addr;	chn = substream->number * 2;	spin_lock_irq(&ice->reg_lock);	snd_ice1712_ds_write(ice, chn, ICE1712_DSC_ADDR0, runtime->dma_addr);	snd_ice1712_ds_write(ice, chn, ICE1712_DSC_COUNT0, period_size);	snd_ice1712_ds_write(ice, chn, ICE1712_DSC_ADDR1, runtime->dma_addr + (runtime->periods > 1 ? period_size + 1 : 0));	snd_ice1712_ds_write(ice, chn, ICE1712_DSC_COUNT1, period_size);	snd_ice1712_ds_write(ice, chn, ICE1712_DSC_RATE, rate);	snd_ice1712_ds_write(ice, chn, ICE1712_DSC_VOLUME, 0);	snd_ice1712_ds_write(ice, chn, ICE1712_DSC_CONTROL, tmp);	if (runtime->channels == 2) {		snd_ice1712_ds_write(ice, chn + 1, ICE1712_DSC_RATE, rate);		snd_ice1712_ds_write(ice, chn + 1, ICE1712_DSC_VOLUME, 0);	}	spin_unlock_irq(&ice->reg_lock);	return 0;}static int snd_ice1712_capture_prepare(snd_pcm_substream_t * substream){	ice1712_t *ice = snd_pcm_substream_chip(substream);	snd_pcm_runtime_t *runtime = substream->runtime;	u32 period_size, buf_size;	u8 tmp;	period_size = (snd_pcm_lib_period_bytes(substream) >> 2) - 1;	buf_size = snd_pcm_lib_buffer_bytes(substream) - 1;	tmp = 0x06;	if (snd_pcm_format_width(runtime->format) == 16)		tmp &= ~0x04;	if (runtime->channels == 2)		tmp &= ~0x02;	spin_lock_irq(&ice->reg_lock);	outl(ice->capture_con_virt_addr = runtime->dma_addr, ICEREG(ice, CONCAP_ADDR));	outw(buf_size, ICEREG(ice, CONCAP_COUNT));	snd_ice1712_write(ice, ICE1712_IREG_CAP_COUNT_HI, period_size >> 8);	snd_ice1712_write(ice, ICE1712_IREG_CAP_COUNT_LO, period_size & 0xff);	snd_ice1712_write(ice, ICE1712_IREG_CAP_CTRL, tmp);	spin_unlock_irq(&ice->reg_lock);	snd_ac97_set_rate(ice->ac97, AC97_PCM_LR_ADC_RATE, runtime->rate);	return 0;}static snd_pcm_uframes_t snd_ice1712_playback_pointer(snd_pcm_substream_t * substream){	ice1712_t *ice = snd_pcm_substream_chip(substream);	snd_pcm_runtime_t *runtime = substream->runtime;	size_t ptr;	if (!(snd_ice1712_read(ice, ICE1712_IREG_PBK_CTRL) & 1))		return 0;	ptr = runtime->buffer_size - inw(ice->ddma_port + 4);	if (ptr == runtime->buffer_size)		ptr = 0;	return bytes_to_frames(substream->runtime, ptr);}static snd_pcm_uframes_t snd_ice1712_playback_ds_pointer(snd_pcm_substream_t * substream){	ice1712_t *ice = snd_pcm_substream_chip(substream);	u8 addr;	size_t ptr;	if (!(snd_ice1712_ds_read(ice, substream->number * 2, ICE1712_DSC_CONTROL) & 1))		return 0;	if (ice->playback_con_active_buf[substream->number])		addr = ICE1712_DSC_ADDR1;	else		addr = ICE1712_DSC_ADDR0;	ptr = snd_ice1712_ds_read(ice, substream->number * 2, addr) -		ice->playback_con_virt_addr[substream->number];	if (ptr == substream->runtime->buffer_size)		ptr = 0;	return bytes_to_frames(substream->runtime, ptr);}static snd_pcm_uframes_t snd_ice1712_capture_pointer(snd_pcm_substream_t * substream){	ice1712_t *ice = snd_pcm_substream_chip(substream);	size_t ptr;	if (!(snd_ice1712_read(ice, ICE1712_IREG_CAP_CTRL) & 1))		return 0;	ptr = inl(ICEREG(ice, CONCAP_ADDR)) - ice->capture_con_virt_addr;	if (ptr == substream->runtime->buffer_size)		ptr = 0;	return bytes_to_frames(substream->runtime, ptr);}static snd_pcm_hardware_t snd_ice1712_playback ={	.info =			(SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |				 SNDRV_PCM_INFO_BLOCK_TRANSFER |				 SNDRV_PCM_INFO_MMAP_VALID |				 SNDRV_PCM_INFO_PAUSE),	.formats =		SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE,	.rates =		SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000,	.rate_min =		4000,	.rate_max =		48000,	.channels_min =		1,	.channels_max =		2,	.buffer_bytes_max =	(64*1024),	.period_bytes_min =	64,	.period_bytes_max =	(64*1024),	.periods_min =		1,	.periods_max =		1024,	.fifo_size =		0,};static snd_pcm_hardware_t snd_ice1712_playback_ds ={	.info =			(SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |				 SNDRV_PCM_INFO_BLOCK_TRANSFER |				 SNDRV_PCM_INFO_MMAP_VALID |				 SNDRV_PCM_INFO_PAUSE),	.formats =		SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE,	.rates =		SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000,	.rate_min =		4000,	.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 =		2,	.periods_max =		2,	.fifo_size =		0,};static snd_pcm_hardware_t snd_ice1712_capture ={	.info =			(SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |				 SNDRV_PCM_INFO_BLOCK_TRANSFER |				 SNDRV_PCM_INFO_MMAP_VALID),	.formats =		SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE,	.rates =		SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000,	.rate_min =		4000,	.rate_max =		48000,	.channels_min =		1,	.channels_max =		2,	.buffer_bytes_max =	(64*1024),	.period_bytes_min =	64,	.period_bytes_max =	(64*1024),	.periods_min =		1,	.periods_max =		1024,	.fifo_size =		0,};static int snd_ice1712_playback_open(snd_pcm_substream_t * substream){	snd_pcm_runtime_t *runtime = substream->runtime;	ice1712_t *ice = snd_pcm_substream_chip(substream);	ice->playback_con_substream = substream;	runtime->hw = snd_ice1712_playback;	return 0;}static int snd_ice1712_playback_ds_open(snd_pcm_substream_t * substream){	snd_pcm_runtime_t *runtime = substream->runtime;	ice1712_t *ice = snd_pcm_substream_chip(substream);	u32 tmp;	ice->playback_con_substream_ds[substream->number] = substream;	runtime->hw = snd_ice1712_playback_ds;	spin_lock_irq(&ice->reg_lock); 	tmp = inw(ICEDS(ice, INTMASK)) & ~(1 << (substream->number * 2));	outw(tmp, ICEDS(ice, INTMASK));	spin_unlock_irq(&ice->reg_lock);	return 0;}static int snd_ice1712_capture_open(snd_pcm_substream_t * substream){	snd_pcm_runtime_t *runtime = substream->runtime;	ice1712_t *ice = snd_pcm_substream_chip(substream);	ice->capture_con_substream = substream;	runtime->hw = snd_ice1712_capture;	runtime->hw.rates = ice->ac97->rates[AC97_RATES_ADC];	if (!(runtime->hw.rates & SNDRV_PCM_RATE_8000))		runtime->hw.rate_min = 48000;	return 0;}static int snd_ice1712_playback_close(snd_pcm_substream_t * substream){	ice1712_t *ice = snd_pcm_substream_chip(substream);	ice->playback_con_substream = NULL;	return 0;}static int snd_ice1712_playback_ds_close(snd_pcm_substream_t * substream){	ice1712_t *ice = snd_pcm_substream_chip(substream);	u32 tmp;	spin_lock_irq(&ice->reg_lock); 	tmp = inw(ICEDS(ice, INTMASK)) | (3 << (substream->number * 2));	outw(tmp, ICEDS(ice, INTMASK));	spin_unlock_irq(&ice->reg_lock);	ice->playback_con_substream_ds[substream->number] = NULL;	return 0;}static int snd_ice1712_capture_close(snd_pcm_substream_t * substream){	ice1712_t *ice = snd_pcm_substream_chip(substream);	ice->capture_con_substream = NULL;	return 0;}static snd_pcm_ops_t snd_ice1712_playback_ops = {	.open =		snd_ice1712_playback_open,	.close =	snd_ice1712_playback_close,	.ioctl =	snd_pcm_lib_ioctl,	.hw_params =	snd_ice1712_hw_params,	.hw_free =	snd_ice1712_hw_free,	.prepare =	snd_ice1712_playback_prepare,	.trigger =	snd_ice1712_playback_trigger,	.pointer =	snd_ice1712_playback_pointer,};static snd_pcm_ops_t snd_ice1712_playback_ds_ops = {	.open =		snd_ice1712_playback_ds_open,	.close =	snd_ice1712_playback_ds_close,	.ioctl =	snd_pcm_lib_ioctl,	.hw_params =	snd_ice1712_hw_params,	.hw_free =	snd_ice1712_hw_free,	.prepare =	snd_ice1712_playback_ds_prepare,	.trigger =	snd_ice1712_playback_ds_trigger,	.pointer =	snd_ice1712_playback_ds_pointer,};static snd_pcm_ops_t snd_ice1712_capture_ops = {	.open =		snd_ice1712_capture_open,	.close =	snd_ice1712_capture_close,	.ioctl =	snd_pcm_lib_ioctl,	.hw_params =	snd_ice1712_hw_params,	.hw_free =	snd_ice1712_hw_free,	.prepare =	snd_ice1712_capture_prepare,	.trigger =	snd_ice1712_capture_trigger,	.pointer =	snd_ice1712_capture_pointer,};static void snd_ice1712_pcm_free(snd_pcm_t *pcm){	ice1712_t *ice = pcm->private_data;	ice->pcm = NULL;	snd_pcm_lib_preallocate_free_for_all(pcm);}static int __devinit snd_ice1712_pcm(ice1712_t * ice, int device, snd_pcm_t ** rpcm){	snd_pcm_t *pcm;	int err;	if (rpcm)		*rpcm = NULL;	err = snd_pcm_new(ice->card, "ICE1712 consumer", device, 1, 1, &pcm);	if (err < 0)		return err;	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_ice1712_playback_ops);

⌨️ 快捷键说明

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