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

📄 amd7930.c

📁 一个2.4.21版本的嵌入式linux内核
💻 C
📖 第 1 页 / 共 4 页
字号:
					(info->D.input_callback_arg, der,					 info->D.input_count);		}	}}long amd7930_xmit_idles = 0;static void transceive_Bchannel(struct amd7930_channel *channel,				unsigned long reg){	/* Send the next byte of outgoing data. */	if (channel->output_ptr && channel->output_count > 0) {		u8 byte;		/* Send the next byte and advance buffer pointer. */		switch(channel->output_format) {		case AUDIO_ENCODING_ULAW:		case AUDIO_ENCODING_ALAW:			byte = *(channel->output_ptr);			sbus_writeb(byte, reg);			break;		case AUDIO_ENCODING_LINEAR8:			byte = bilinear2mulaw(*(channel->output_ptr));			sbus_writeb(byte, reg);			break;		case AUDIO_ENCODING_LINEAR:			if (channel->output_count >= 2) {				u16 val = channel->output_ptr[0] << 8;				val |= channel->output_ptr[1];				byte = linear2mulaw(val);				sbus_writeb(byte, reg);				channel->output_ptr++;				channel->output_count--;			};		};		channel->output_ptr++;		channel->output_count--;		/* Done with the buffer? Notify the midlevel driver. */		if (channel->output_count == 0) {			channel->output_ptr = NULL;			channel->output_count = 0;			if (channel->output_callback)				(*channel->output_callback)					(channel->output_callback_arg,1);		}	} else {		sbus_writeb(channel->xmit_idle_char, reg);		amd7930_xmit_idles++;        }	/* Read the next byte of incoming data. */	if (channel->input_ptr && channel->input_count > 0) {		/* Get the next byte and advance buffer pointer. */		switch(channel->input_format) {		case AUDIO_ENCODING_ULAW:		case AUDIO_ENCODING_ALAW:			*(channel->input_ptr) = sbus_readb(reg);			break;		case AUDIO_ENCODING_LINEAR8:			*(channel->input_ptr) = mulaw2bilinear(sbus_readb(reg));			break;		case AUDIO_ENCODING_LINEAR:			if (channel->input_count >= 2) {				u16 val = mulaw2linear(sbus_readb(reg));				channel->input_ptr[0] = val >> 8;				channel->input_ptr[1] = val & 0xff;				channel->input_ptr++;				channel->input_count--;			} else {				*(channel->input_ptr) = 0;			}		};		channel->input_ptr++;		channel->input_count--;		/* Done with the buffer? Notify the midlevel driver. */		if (channel->input_count == 0) {			channel->input_ptr = NULL;			channel->input_count = 0;			if (channel->input_callback)				(*channel->input_callback)					(channel->input_callback_arg, 1, 0);		}	}}/* Interrupt handler (The chip takes only one byte per interrupt. Grrr!) */static void amd7930_interrupt(int irq, void *dev_id, struct pt_regs *intr_regs){	struct sparcaudio_driver *drv = (struct sparcaudio_driver *) dev_id;	struct amd7930_info *info = (struct amd7930_info *) drv->private;	unsigned long regs = info->regs;	__u8 ir;	/* Clear the interrupt. */	ir = sbus_readb(regs + IR);	if (ir & AMR_IR_BBUF) {		if (info->Bb.channel_status == CHANNEL_INUSE)			transceive_Bchannel(&info->Bb, info->regs + BBTB);		if (info->Bc.channel_status == CHANNEL_INUSE)			transceive_Bchannel(&info->Bc, info->regs + BCTB);	}	if (ir & (AMR_IR_DRTHRSH | AMR_IR_DTTHRSH | AMR_IR_DSRI)) {		debug_info(info, 'i');		debug_info(info, '0' + (ir&7));		transceive_Dchannel(info);	}	if (ir & AMR_IR_LSRI) {		__u8 lsr;		sbus_writeb(AMR_LIU_LSR, regs + CR);		lsr = sbus_readb(regs + DR);                info->liu_state = (lsr & 0x7) + 2;                if (info->liu_callback)			(*info->liu_callback)(info->liu_callback_arg);        }}static int amd7930_open(struct inode * inode, struct file * file,			struct sparcaudio_driver *drv){	struct amd7930_info *info = (struct amd7930_info *) drv->private;	switch(MINOR(inode->i_rdev) & 0xf) {	case SPARCAUDIO_AUDIO_MINOR:		info->format_type = AUDIO_ENCODING_ULAW;		break;	case SPARCAUDIO_DSP_MINOR:		info->format_type = AUDIO_ENCODING_LINEAR8;		break;	case SPARCAUDIO_DSP16_MINOR:		info->format_type = AUDIO_ENCODING_LINEAR;		break;	};	MOD_INC_USE_COUNT;	return 0;}static void amd7930_release(struct inode * inode, struct file * file,			    struct sparcaudio_driver *drv){	/* amd7930_disable_ints(drv->private); */	MOD_DEC_USE_COUNT;}static void request_Baudio(struct amd7930_info *info){	if (info->Bb.channel_status == CHANNEL_AVAILABLE) {		info->Bb.channel_status = CHANNEL_INUSE;		info->Baudio = &info->Bb;		/* Multiplexor map - audio (Ba) to Bb */		sbus_writeb(AMR_MUX_MCR1, info->regs + CR);		sbus_writeb(AM_MUX_CHANNEL_Ba | (AM_MUX_CHANNEL_Bb << 4),			    info->regs + DR);		/* Enable B channel interrupts */		sbus_writeb(AMR_MUX_MCR4, info->regs + CR);		sbus_writeb(AM_MUX_MCR4_ENABLE_INTS, info->regs + DR);	} else if (info->Bc.channel_status == CHANNEL_AVAILABLE) {		info->Bc.channel_status = CHANNEL_INUSE;		info->Baudio = &info->Bc;		/* Multiplexor map - audio (Ba) to Bc */		sbus_writeb(AMR_MUX_MCR1, info->regs + CR);		sbus_writeb(AM_MUX_CHANNEL_Ba | (AM_MUX_CHANNEL_Bc << 4),			    info->regs + DR);		/* Enable B channel interrupts */		sbus_writeb(AMR_MUX_MCR4, info->regs + CR);		sbus_writeb(AM_MUX_MCR4_ENABLE_INTS, info->regs + DR);	}}static void release_Baudio(struct amd7930_info *info){	if (info->Baudio) {		info->Baudio->channel_status = CHANNEL_AVAILABLE;		sbus_writeb(AMR_MUX_MCR1, info->regs + CR);		sbus_writeb(0, info->regs + DR);		info->Baudio = NULL;		if (info->Bb.channel_status == CHANNEL_AVAILABLE &&		    info->Bc.channel_status == CHANNEL_AVAILABLE) {			/* Disable B channel interrupts */			sbus_writeb(AMR_MUX_MCR4, info->regs + CR);			sbus_writeb(0, info->regs + DR);		}	}}static void amd7930_start_output(struct sparcaudio_driver *drv,				 __u8 * buffer, unsigned long count){	struct amd7930_info *info = (struct amd7930_info *) drv->private;	if (! info->Baudio)		request_Baudio(info);	if (info->Baudio) {		info->Baudio->output_ptr = buffer;		info->Baudio->output_count = count;		info->Baudio->output_format = info->format_type;		info->Baudio->output_callback = (void *) &sparcaudio_output_done;		info->Baudio->output_callback_arg = (void *) drv;		info->Baudio->xmit_idle_char = 0;	}}static void amd7930_stop_output(struct sparcaudio_driver *drv){	struct amd7930_info *info = (struct amd7930_info *) drv->private;	if (info->Baudio) {		info->Baudio->output_ptr = NULL;		info->Baudio->output_count = 0;		if (! info->Baudio->input_ptr)			release_Baudio(info);	}}static void amd7930_start_input(struct sparcaudio_driver *drv,				__u8 * buffer, unsigned long count){	struct amd7930_info *info = (struct amd7930_info *) drv->private;	if (! info->Baudio)		request_Baudio(info);	if (info->Baudio) {		info->Baudio->input_ptr = buffer;		info->Baudio->input_count = count;		info->Baudio->input_format = info->format_type;		info->Baudio->input_callback = (void *) &sparcaudio_input_done;		info->Baudio->input_callback_arg = (void *) drv;	}}static void amd7930_stop_input(struct sparcaudio_driver *drv){	struct amd7930_info *info = (struct amd7930_info *) drv->private;	if (info->Baudio) {		info->Baudio->input_ptr = NULL;		info->Baudio->input_count = 0;		if (! info->Baudio->output_ptr)			release_Baudio(info);	}}static void amd7930_sunaudio_getdev(struct sparcaudio_driver *drv,				 audio_device_t * audinfo){	strncpy(audinfo->name, "SUNW,am79c30", sizeof(audinfo->name) - 1);	strncpy(audinfo->version, "a", sizeof(audinfo->version) - 1);	strncpy(audinfo->config, "onboard1", sizeof(audinfo->config) - 1);}static int amd7930_sunaudio_getdev_sunos(struct sparcaudio_driver *drv){	return AUDIO_DEV_AMD;}static int amd7930_get_formats(struct sparcaudio_driver *drv){      return (AFMT_MU_LAW | AFMT_A_LAW | AFMT_U8 | AFMT_S16_BE);}static int amd7930_get_output_ports(struct sparcaudio_driver *drv){      return (AUDIO_SPEAKER | AUDIO_HEADPHONE);}static int amd7930_get_input_ports(struct sparcaudio_driver *drv){      return (AUDIO_MICROPHONE);}static int amd7930_set_output_volume(struct sparcaudio_driver *drv, int vol){	struct amd7930_info *info = (struct amd7930_info *) drv->private;	info->pgain = vol;	amd7930_update_map(drv);	return 0;}static int amd7930_get_output_volume(struct sparcaudio_driver *drv){	struct amd7930_info *info = (struct amd7930_info *) drv->private;	return info->pgain;}static int amd7930_set_input_volume(struct sparcaudio_driver *drv, int vol){	struct amd7930_info *info = (struct amd7930_info *) drv->private;	info->rgain = vol;	amd7930_update_map(drv);	return 0;}static int amd7930_get_input_volume(struct sparcaudio_driver *drv){	struct amd7930_info *info = (struct amd7930_info *) drv->private;	return info->rgain;}static int amd7930_set_monitor_volume(struct sparcaudio_driver *drv, int vol){	struct amd7930_info *info = (struct amd7930_info *) drv->private;	info->mgain = vol;	amd7930_update_map(drv);	return 0;}static int amd7930_get_monitor_volume(struct sparcaudio_driver *drv){      struct amd7930_info *info = (struct amd7930_info *) drv->private;      return info->mgain;}/* Cheats. The amd has the minimum capabilities we support */static int amd7930_get_output_balance(struct sparcaudio_driver *drv){	return AUDIO_MID_BALANCE;}static int amd7930_get_input_balance(struct sparcaudio_driver *drv){	return AUDIO_MID_BALANCE;}static int amd7930_get_output_channels(struct sparcaudio_driver *drv){	return AUDIO_MIN_PLAY_CHANNELS;}static int amd7930_set_output_channels(struct sparcaudio_driver *drv, 				       int value){  return (value == AUDIO_MIN_PLAY_CHANNELS) ? 0 : -EINVAL;}static int amd7930_get_input_channels(struct sparcaudio_driver *drv){	return AUDIO_MIN_REC_CHANNELS;}static int amd7930_set_input_channels(struct sparcaudio_driver *drv, int value){	return (value == AUDIO_MIN_REC_CHANNELS) ? 0 : -EINVAL;}static int amd7930_get_output_precision(struct sparcaudio_driver *drv){	return AUDIO_MIN_PLAY_PRECISION;}static int amd7930_set_output_precision(struct sparcaudio_driver *drv, int value){	return (value == AUDIO_MIN_PLAY_PRECISION) ? 0 : -EINVAL;}static int amd7930_get_input_precision(struct sparcaudio_driver *drv){	return AUDIO_MIN_REC_PRECISION;}static int amd7930_set_input_precision(struct sparcaudio_driver *drv, int value){	return (value == AUDIO_MIN_REC_PRECISION) ? 0 : -EINVAL;}static int amd7930_get_output_port(struct sparcaudio_driver *drv){	struct amd7930_info *info = (struct amd7930_info *) drv->private;	if (info->map.mmr2 & AM_MAP_MMR2_LS)		return AUDIO_SPEAKER; 	return AUDIO_HEADPHONE;}static int amd7930_set_output_port(struct sparcaudio_driver *drv, int value){	struct amd7930_info *info = (struct amd7930_info *) drv->private;	switch (value) {	case AUDIO_HEADPHONE:		info->map.mmr2 &= ~AM_MAP_MMR2_LS;		break;	case AUDIO_SPEAKER:		info->map.mmr2 |= AM_MAP_MMR2_LS;		break;	default:		return -EINVAL;	};	amd7930_update_map(drv);	return 0;}/* Only a microphone here, so no troubles */static int amd7930_get_input_port(struct sparcaudio_driver *drv){	return AUDIO_MICROPHONE;}static int amd7930_get_encoding(struct sparcaudio_driver *drv){	struct amd7930_info *info = (struct amd7930_info *) drv->private;	if ((info->map.mmr1 & AM_MAP_MMR1_ALAW) && 	    (info->format_type == AUDIO_ENCODING_ALAW))		return AUDIO_ENCODING_ALAW;	return info->format_type;}static int amd7930_set_encoding(struct sparcaudio_driver *drv, int value){	struct amd7930_info *info = (struct amd7930_info *) drv->private;	switch (value) {	case AUDIO_ENCODING_ALAW:		info->map.mmr1 |= AM_MAP_MMR1_ALAW;		break;	case AUDIO_ENCODING_LINEAR8:	case AUDIO_ENCODING_LINEAR:	case AUDIO_ENCODING_ULAW:		info->map.mmr1 &= ~AM_MAP_MMR1_ALAW;		break;	default:		return -EINVAL;	};	info->format_type = value;	amd7930_update_map(drv);	return 0;}/* This is what you get. Take it or leave it */static int amd7930_get_output_rate(struct sparcaudio_driver *drv){	return AMD7930_RATE;}static int amd7930_set_output_rate(struct sparcaudio_driver *drv, int value){	return (value == AMD7930_RATE) ? 0 : -EINVAL;

⌨️ 快捷键说明

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