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

📄 cardwi.c

📁 鼎力推荐!本程序是基于嵌入式LUNUX系统开发的源程序代码
💻 C
字号:
/* ********************************************************************** *     cardwi.c - PCM input HAL for emu10k1 driver *     Copyright 1999, 2000 Creative Labs, Inc. * ********************************************************************** * *     Date                 Author          Summary of changes *     ----                 ------          ------------------ *     October 20, 1999     Bertrand Lee    base code release * ********************************************************************** * *     This program is free software; you can redistribute it and/or *     modify it under the terms of the GNU General Public License as *     published by the Free Software Foundation; either version 2 of *     the License, or (at your option) any later version. * *     This program is distributed in the hope that it will be useful, *     but WITHOUT ANY WARRANTY; without even the implied warranty of *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the *     GNU General Public License for more details. * *     You should have received a copy of the GNU General Public *     License along with this program; if not, write to the Free *     Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, *     USA. * ********************************************************************** */#include <linux/poll.h>#include "hwaccess.h"#include "timer.h"#include "recmgr.h"#include "audio.h"#include "cardwi.h"/** * query_format - returns a valid sound format * * This function will return a valid sound format as close * to the requested one as possible.  */static void query_format(int recsrc, struct wave_format *wave_fmt){	switch (recsrc) {	case WAVERECORD_AC97:		if ((wave_fmt->channels != 1) && (wave_fmt->channels != 2))			wave_fmt->channels = 2;		if (wave_fmt->samplingrate >= (0xBB80 + 0xAC44) / 2)			wave_fmt->samplingrate = 0xBB80;		else if (wave_fmt->samplingrate >= (0xAC44 + 0x7D00) / 2)			wave_fmt->samplingrate = 0xAC44;		else if (wave_fmt->samplingrate >= (0x7D00 + 0x5DC0) / 2)			wave_fmt->samplingrate = 0x7D00;		else if (wave_fmt->samplingrate >= (0x5DC0 + 0x5622) / 2)			wave_fmt->samplingrate = 0x5DC0;		else if (wave_fmt->samplingrate >= (0x5622 + 0x3E80) / 2)			wave_fmt->samplingrate = 0x5622;		else if (wave_fmt->samplingrate >= (0x3E80 + 0x2B11) / 2)			wave_fmt->samplingrate = 0x3E80;		else if (wave_fmt->samplingrate >= (0x2B11 + 0x1F40) / 2)			wave_fmt->samplingrate = 0x2B11;		else			wave_fmt->samplingrate = 0x1F40;		switch (wave_fmt->id) {		case AFMT_S16_LE:			wave_fmt->bitsperchannel = 16;			break;		case AFMT_U8:			wave_fmt->bitsperchannel = 8;			break;		default:			wave_fmt->id = AFMT_S16_LE;			wave_fmt->bitsperchannel = 16;			break;		}		break;	/* these can't be changed from the original values */	case WAVERECORD_MIC:	case WAVERECORD_FX:		break;	default:		BUG();		break;	}	wave_fmt->bytesperchannel = wave_fmt->bitsperchannel >> 3;	wave_fmt->bytespersample = wave_fmt->channels * wave_fmt->bytesperchannel;	wave_fmt->bytespersec = wave_fmt->bytespersample * wave_fmt->samplingrate;	wave_fmt->bytespervoicesample = wave_fmt->bytespersample;}static int alloc_buffer(struct emu10k1_card *card, struct wavein_buffer *buffer){	buffer->addr = pci_alloc_consistent(card->pci_dev, buffer->size * buffer->cov,					    &buffer->dma_handle);	if (buffer->addr == NULL)		return -1;	return 0;}static void free_buffer(struct emu10k1_card *card, struct wavein_buffer *buffer){	if (buffer->addr != NULL)		pci_free_consistent(card->pci_dev, buffer->size * buffer->cov,				    buffer->addr, buffer->dma_handle);}int emu10k1_wavein_open(struct emu10k1_wavedevice *wave_dev){	struct emu10k1_card *card = wave_dev->card;	struct wiinst *wiinst = wave_dev->wiinst;	struct wiinst **wiinst_tmp = NULL;	u16 delay;	unsigned long flags;	DPF(2, "emu10k1_wavein_open()\n");	switch (wiinst->recsrc) {	case WAVERECORD_AC97:		wiinst_tmp = &card->wavein.ac97;		break;	case WAVERECORD_MIC:		wiinst_tmp = &card->wavein.mic;		break;	case WAVERECORD_FX:		wiinst_tmp = &card->wavein.fx;		break;	default:		BUG();		break;	}	spin_lock_irqsave(&card->lock, flags);	if (*wiinst_tmp != NULL) {		spin_unlock_irqrestore(&card->lock, flags);		return -1;	}	*wiinst_tmp = wiinst;	spin_unlock_irqrestore(&card->lock, flags);	/* handle 8 bit recording */	if (wiinst->format.bytesperchannel == 1) {		if (wiinst->buffer.size > 0x8000) {			wiinst->buffer.size = 0x8000;			wiinst->buffer.sizeregval = 0x1f;		} else			wiinst->buffer.sizeregval += 4;		wiinst->buffer.cov = 2;	} else		wiinst->buffer.cov = 1;	if (alloc_buffer(card, &wiinst->buffer) < 0) {		ERROR();		return -1;	}	emu10k1_set_record_src(card, wiinst);	emu10k1_reset_record(card, &wiinst->buffer);	wiinst->buffer.hw_pos = 0;	wiinst->buffer.pos = 0;	wiinst->buffer.bytestocopy = 0;	delay = (48000 * wiinst->buffer.fragment_size) / wiinst->format.bytespersec;	emu10k1_timer_install(card, &wiinst->timer, delay / 2);	wiinst->state = WAVE_STATE_OPEN;	return 0;}void emu10k1_wavein_close(struct emu10k1_wavedevice *wave_dev){	struct emu10k1_card *card = wave_dev->card;	struct wiinst *wiinst = wave_dev->wiinst;	unsigned long flags;	DPF(2, "emu10k1_wavein_close()\n");	emu10k1_wavein_stop(wave_dev);	emu10k1_timer_uninstall(card, &wiinst->timer);	free_buffer(card, &wiinst->buffer);	spin_lock_irqsave(&card->lock, flags);	switch (wave_dev->wiinst->recsrc) {	case WAVERECORD_AC97:		card->wavein.ac97 = NULL;		break;	case WAVERECORD_MIC:		card->wavein.mic = NULL;		break;	case WAVERECORD_FX:		card->wavein.fx = NULL;		break;	default:		BUG();		break;	}	spin_unlock_irqrestore(&card->lock, flags);	wiinst->state = WAVE_STATE_CLOSED;}void emu10k1_wavein_start(struct emu10k1_wavedevice *wave_dev){	struct emu10k1_card *card = wave_dev->card;	struct wiinst *wiinst = wave_dev->wiinst;	DPF(2, "emu10k1_wavein_start()\n");	emu10k1_start_record(card, &wiinst->buffer);	emu10k1_timer_enable(wave_dev->card, &wiinst->timer);	wiinst->state |= WAVE_STATE_STARTED;}void emu10k1_wavein_stop(struct emu10k1_wavedevice *wave_dev){	struct emu10k1_card *card = wave_dev->card;	struct wiinst *wiinst = wave_dev->wiinst;	DPF(2, "emu10k1_wavein_stop()\n");	if (!(wiinst->state & WAVE_STATE_STARTED))		return;	emu10k1_timer_disable(card, &wiinst->timer);	emu10k1_stop_record(card, &wiinst->buffer);	wiinst->state &= ~WAVE_STATE_STARTED;}int emu10k1_wavein_setformat(struct emu10k1_wavedevice *wave_dev, struct wave_format *format){	struct emu10k1_card *card = wave_dev->card;	struct wiinst *wiinst = wave_dev->wiinst;	u16 delay;	DPF(2, "emu10k1_wavein_setformat()\n");	if (wiinst->state & WAVE_STATE_STARTED)		return -1;	query_format(wiinst->recsrc, format);	if ((wiinst->format.samplingrate != format->samplingrate)	    || (wiinst->format.bitsperchannel != format->bitsperchannel)	    || (wiinst->format.channels != format->channels)) {		wiinst->format = *format;		if (wiinst->state == WAVE_STATE_CLOSED)			return 0;		wiinst->buffer.size *= wiinst->buffer.cov;		if (wiinst->format.bytesperchannel == 1) {			wiinst->buffer.cov = 2;			wiinst->buffer.size /= wiinst->buffer.cov;		} else			wiinst->buffer.cov = 1;		emu10k1_timer_uninstall(card, &wiinst->timer);		delay = (48000 * wiinst->buffer.fragment_size) / wiinst->format.bytespersec;		emu10k1_timer_install(card, &wiinst->timer, delay / 2);	}	return 0;}void emu10k1_wavein_getxfersize(struct wiinst *wiinst, u32 * size){	struct wavein_buffer *buffer = &wiinst->buffer;	*size = buffer->bytestocopy;	if (wiinst->mmapped)		return;	if (*size > buffer->size) {		*size = buffer->size;		buffer->pos = buffer->hw_pos;		buffer->bytestocopy = buffer->size;		DPF(1, "buffer overrun\n");	}}static void copy_block(u8 __user *dst, u8 * src, u32 str, u32 len, u8 cov){	if (cov == 1)		__copy_to_user(dst, src + str, len);	else {		u8 byte;		u32 i;		src += 1 + 2 * str;		for (i = 0; i < len; i++) {			byte = src[2 * i] ^ 0x80;			__copy_to_user(dst + i, &byte, 1);		}	}}void emu10k1_wavein_xferdata(struct wiinst *wiinst, u8 __user *data, u32 * size){	struct wavein_buffer *buffer = &wiinst->buffer;	u32 sizetocopy, sizetocopy_now, start;	unsigned long flags;	sizetocopy = min_t(u32, buffer->size, *size);	*size = sizetocopy;	if (!sizetocopy)		return;	spin_lock_irqsave(&wiinst->lock, flags);	start = buffer->pos;	buffer->pos += sizetocopy;	buffer->pos %= buffer->size;	buffer->bytestocopy -= sizetocopy;	sizetocopy_now = buffer->size - start;	spin_unlock_irqrestore(&wiinst->lock, flags);	if (sizetocopy > sizetocopy_now) {		sizetocopy -= sizetocopy_now;		copy_block(data, buffer->addr, start, sizetocopy_now, buffer->cov);		copy_block(data + sizetocopy_now, buffer->addr, 0, sizetocopy, buffer->cov);	} else {		copy_block(data, buffer->addr, start, sizetocopy, buffer->cov);	}}void emu10k1_wavein_update(struct emu10k1_card *card, struct wiinst *wiinst){	u32 hw_pos;	u32 diff;	/* There is no actual start yet */	if (!(wiinst->state & WAVE_STATE_STARTED)) {		hw_pos = wiinst->buffer.hw_pos;	} else {		/* hw_pos in byte units */		hw_pos = sblive_readptr(card, wiinst->buffer.idxreg, 0) / wiinst->buffer.cov;	}	diff = (wiinst->buffer.size + hw_pos - wiinst->buffer.hw_pos) % wiinst->buffer.size;	wiinst->total_recorded += diff;	wiinst->buffer.bytestocopy += diff;	wiinst->buffer.hw_pos = hw_pos;}

⌨️ 快捷键说明

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