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

📄 ac97.c

📁 君正早期ucos系统(只有早期的才不没有打包成库),MPLAYER,文件系统,图片解码,浏览,电子书,录音,想学ucos,识货的人就下吧 russblock fmradio explore set
💻 C
📖 第 1 页 / 共 3 页
字号:
		if (REG32(AC97_ACSR) & AIC_ACSR_CADT) {			REG32(AC97_ACSR) &= ~AIC_ACSR_CADT;			done = 1;		} else			udelay (1);	}	return done;}	static inline int jz_in_status_ready(void){	int t2 = 1000;	int done = 0;	while (! done && t2-- > 0)		if (REG32(AC97_ACSR) & AIC_ACSR_SADR) {			REG32(AC97_ACSR) &= ~AIC_ACSR_SADR;			done = 1;		} else {			if (REG32(AC97_ACSR) & AIC_ACSR_RSTO) {				REG32(AC97_ACSR) &= ~AIC_ACSR_RSTO;				done = 0;				break;			}			udelay (1);		}	return done;}static int jz_readAC97Reg (u8 reg){	u16 value;	if (reg < 128) {		u8  ret_reg;		__ac97_out_rcmd_addr(reg);		if (jz_out_command_ready())			while (jz_in_status_ready()) {				ret_reg = __ac97_in_status_addr();				value = __ac97_in_data();				if (ret_reg == reg)					return value;				else					return -1;			}	}	value = __ac97_in_data();	return -1;}static int jz_writeAC97Reg (u8 reg, u16 value){	unsigned long flags;	int done = 0;	flags = spin_lock_irqsave();	__ac97_out_wcmd_addr(reg);	__ac97_out_data(value);	if (jz_out_command_ready())		done = 1;	spin_unlock_irqrestore(flags);	return done;}u16 ac97_codec_read(u8 reg){	int res = jz_readAC97Reg(reg);	int count = 0;	while (res == -1) {		udelay(1000);		__ac97_warm_reset_codec();		udelay(1000);		res = jz_readAC97Reg(reg);		count ++;		if (count > MAX_RETRY)			break;	}	return (u16)res;}void ac97_codec_write(u8 reg, u16 data){	int done = jz_writeAC97Reg(reg, data);	int count = 0;	while (done == 0) {		count ++;		udelay (2000);		__ac97_warm_reset_codec();		udelay(2000);		done = jz_writeAC97Reg(reg, data);		if ( count > MAX_RETRY )			break;	}}/* AC97 codec initialisation. */static int jz_ac97_codec_init(void){	int num_ac97 = 0;	int ready_2nd = 0;	unsigned short eid, t;	int i = 0;	if (__ac97_codec_is_low_power_mode()) {		printf("AC97 codec is low power mode, warm reset ...\n");		__ac97_warm_reset_codec();		udelay(10);	}	i = 0;	while (!__ac97_codec_is_ready()) {		i++;		if ( i > 100) {			printf("AC97 codec not ready, failed init ..\n");			return -1;		}		udelay(10);	}	i = 0;	/* AC97 probe codec */	ac97_codec_write(AC97_RESET, 0L);	udelay(10);	if (ac97_codec_read(AC97_RESET) & 0x8000) {		printf("AC97 codec not present...\n");		return -1;	}	ac97_codec_write(AC97_EXTENDED_MODEM_ID, 0L);	/*  Probe for Modem Codec */	ac97_codec_read(AC97_EXTENDED_MODEM_ID);	ac97codec_info(ac97_codec_read(AC97_VENDOR_ID1), ac97_codec_read(AC97_VENDOR_ID2));	/*  Codec capacity */	t = ac97_codec_read(AC97_RESET);	printf("Support:");	if (t & 0x04)		printf(" BASS TREBLE");	if (t & 0x10)		printf(" ALTPCM");	printf("\n");	ac97_codec_write(AC97_MASTER_VOL_STEREO, 0x2020);	if (ac97_codec_read(AC97_MASTER_VOL_STEREO) == 0x2020)		bitscale = 6;	else		bitscale = 5;	printf("AC97 Master Volume bit resolution: %dbit\n", bitscale);	eid = ac97_codec_read(AC97_EXTENDED_ID);	if (eid == 0xFFFF) {		printf("AC97: no codec attached?\n");		return -1;	}	if (!(eid & 0x0001))		printf("AC97 codec: only supports fixed 48KHz sample rate\n");	else {		printf("AC97 codec: supports variable sample rate\n");		/* enable head phone */		ac97_codec_write(0x6a, ac97_codec_read(0x6a)|0x40);#if 0		ac97_codec_write(AC97_EXTENDED_STATUS, 9);		ac97_codec_write(AC97_EXTENDED_STATUS,				 ac97_codec_read(AC97_EXTENDED_STATUS)|0xe800);		#endif		ac97_codec_write(AC97_POWER_CONTROL,				 ac97_codec_read(AC97_POWER_CONTROL)&~0x7f00);		for (i=10;i;i--)			if ((ac97_codec_read(AC97_POWER_CONTROL) & 0xf) == 0xf)				break;#if 0		if (!ac97_codec_read(AC97_EXTENDED_STATUS) & 1)			printf("Codec refuse to support VRA, using 48Khz\n");#endif	}	return 0;}static void jz_update_filler(int format, int channels){#define TYPE(fmt,ch) (((fmt)<<3) | ((ch)&7))	/* up to 8 chans supported. */	switch (TYPE(format, channels)) {	default:	case TYPE(AFMT_U8, 1):		__aic_disable_mono2stereo();		__aic_disable_unsignadj();		dma_block_size(AUDIO_READ_DMA, 4);		dma_block_size(AUDIO_WRITE_DMA, 4);		replay_filler = replay_fill_1x8_u;		record_filler = record_fill_1x8_u;		__ac97_set_oass(8);		__ac97_set_iass(8);		dma_src_size(AUDIO_READ_DMA, 8);		dma_dest_size(AUDIO_WRITE_DMA, 8);		break;	case TYPE(AFMT_U8, 2):		__aic_disable_mono2stereo();		__aic_disable_unsignadj();		dma_block_size(AUDIO_READ_DMA, 4);		dma_block_size(AUDIO_WRITE_DMA, 4);		replay_filler = replay_fill_2x8_u;		record_filler = record_fill_2x8_u;		__ac97_set_oass(8);		__ac97_set_iass(8);		dma_src_size(AUDIO_READ_DMA, 8);		dma_dest_size(AUDIO_WRITE_DMA, 8);		break;	case TYPE(AFMT_S16_LE, 1):		__aic_disable_mono2stereo();		dma_block_size(AUDIO_READ_DMA, 4);		dma_block_size(AUDIO_WRITE_DMA, 4);		__aic_disable_unsignadj();		replay_filler = replay_fill_1x16_s;		record_filler = record_fill_1x16_s;		__ac97_set_oass(16);		__ac97_set_iass(16);		dma_src_size(AUDIO_READ_DMA, 16);		dma_dest_size(AUDIO_WRITE_DMA, 16);		break;	case TYPE(AFMT_S16_LE, 2):		dma_block_size(AUDIO_READ_DMA, 4);		dma_block_size(AUDIO_WRITE_DMA, 4);		__aic_disable_mono2stereo();		__aic_disable_unsignadj();		replay_filler = replay_fill_2x16_s;		record_filler = record_fill_2x16_s;		__ac97_set_oass(16);		__ac97_set_iass(16);		dma_src_size(AUDIO_READ_DMA, 16);		dma_dest_size(AUDIO_WRITE_DMA, 16);		break;	}}int pcm_ioctl(unsigned int cmd, unsigned long arg){	switch (cmd) {	case PCM_SET_SAMPLE_RATE:		jz_audio_set_speed(arg);		break;	case PCM_SET_CHANNEL:		jz_audio_set_channels(arg);		break;	case PCM_SET_FORMAT:		jz_audio_set_format(arg);		break;	case PCM_SET_VOL:		if (arg > 100)			arg = 100;		arg = 100 - arg;		arg = arg * ((1 << bitscale) - 1) / 100;		arg = (arg << 8) | arg;		ac97_codec_write(AC97_MASTER_VOL_STEREO, arg);		ac97_codec_write(AC97_PCMOUT_VOL, arg);		break;	case PCM_GET_VOL:		ac97_codec_read(AC97_MASTER_VOL_STEREO);		break;	default:		printf("pcm_ioctl:Unsupported I/O command: %08x\n", cmd);		return -1;	}	return 0;}int pcm_can_write(void){	if (elements_in_queue(&out_empty_queue) > 0)		return 1;	return 0;}int pcm_can_read(void){	if (elements_in_queue(&in_full_queue) > 0)		return 1;	return 0;}int pcm_read(char *buffer, int count){	int id, ret = 0, left_count, copy_count, cnt = 0;	U8 err;	if (count < 0)		return -1;	if (count < 2*PAGE_SIZE / jz_audio_k) {		copy_count = count * 16 / (jz_audio_channels * jz_audio_format);	} else		copy_count = ((2*PAGE_SIZE / jz_audio_k + 3) / 4) * 4;	left_count = count;	if (first_record_call) {		first_record_call = 0;		if ((id = get_buffer_id(&in_empty_queue)) >= 0) {			put_buffer_id(&in_busy_queue, id);			in_dma_buf_data_count[id] = copy_count * (jz_audio_format/8);			__ac97_enable_receive_dma();			__ac97_enable_record();			dma_start(AUDIO_READ_DMA,				  PHYADDR(AIC_DR), in_dma_pbuf[id],				  in_dma_buf_data_count[id]);			OSSemPend(rx_sem, 0, &err);		} 	}	while (left_count > 0) {		while (elements_in_queue(&in_full_queue) <= 0)			OSSemPend(rx_sem, 0, &err);		if ((id = get_buffer_id(&in_full_queue)) >= 0) {			/*			 * FIXME: maybe the buffer is too small.			 */			cnt = record_filler((unsigned long)buffer+ret, copy_count, id);			put_buffer_id(&in_empty_queue, id);		}		if (elements_in_queue(&in_busy_queue) == 0) {			if ((id=get_buffer_id(&in_empty_queue)) >= 0) {				put_buffer_id(&in_busy_queue, id);				in_dma_buf_data_count[id] = copy_count * (jz_audio_format/8);				__ac97_enable_receive_dma();				__ac97_enable_record();				dma_start(AUDIO_READ_DMA,					  PHYADDR(AIC_DR), in_dma_pbuf[id],					  in_dma_buf_data_count[id]);			}		}		if (ret + cnt > count)			cnt = count - ret;		ret += cnt;		left_count -= cnt;	}	return ret;}int pcm_write(char *buffer, int count){	int id, ret = 0, left_count, copy_count;	U8 err;	if (count <= 0)		return -1;	/* The data buffer size of the user space is always a PAGE_SIZE	 * scale, so the process can be simplified. 	 */	if (count < 2*PAGE_SIZE / jz_audio_k)		copy_count = count;	else		copy_count = ((2*PAGE_SIZE / jz_audio_k + 3) / 4) * 4;	left_count = count;  	while (left_count > 0) {		while (elements_in_queue(&out_empty_queue) == 0)			OSSemPend(tx_sem, 0, &err); 		/* the end fragment size in this write */		if (ret + copy_count > count)			copy_count = count - ret;		if ((id = get_buffer_id(&out_empty_queue)) >= 0) {			/*			 * FIXME: maybe the buffer is too small.			 */			replay_filler( (unsigned long)buffer + ret, copy_count, id);			put_buffer_id(&out_full_queue, id);			__dcache_writeback_all();		}  		left_count = left_count - copy_count;		ret += copy_count;		if (elements_in_queue(&out_busy_queue) == 0) {			if ((id=get_buffer_id(&out_full_queue)) >= 0) {				put_buffer_id(&out_busy_queue, id);				__ac97_enable_transmit_dma();				__ac97_enable_replay();				dma_start(AUDIO_WRITE_DMA,					  out_dma_pbuf[id], PHYADDR(AIC_DR),					  out_dma_buf_data_count[id]);							}		}	}	return ret;}static unsigned char dma_pool[PAGE_SIZE * (16 *( QUEUE_MAX + 1)*2)];int pcm_init(void){	int i;	unsigned char *p = dma_pool;	jz_ac97_initHw();	if (jz_ac97_codec_init() < 0)		return -1;	tx_sem = OSSemCreate(0);	rx_sem = OSSemCreate(0);	dma_request(AUDIO_READ_DMA, jz_ac97_record_dma_irq, 0,		    DMAC_DCCSR_DAM|DMAC_DCCSR_RDIL_IGN,		    DMAC_DRSR_RS_AICIN);	dma_request(AUDIO_WRITE_DMA, jz_ac97_replay_dma_irq, 0,		    DMAC_DCCSR_SAM|DMAC_DCCSR_RDIL_IGN,		    DMAC_DRSR_RS_AICOUT);	jz_audio_reset();	jz_audio_set_format(AFMT_U8);	jz_audio_set_speed(8000);	jz_audio_set_channels(1);	last_jz_audio_count = jz_audio_count = 0;	in_empty_queue.count = QUEUE_MAX;	out_empty_queue.count = QUEUE_MAX;	for (i=0;i<QUEUE_MAX;i++) {		in_empty_queue.id[i] = i;		out_empty_queue.id[i] = i;	}	in_full_queue.count = 0;	in_busy_queue.count = 0;	out_busy_queue.count = 0;	out_full_queue.count = 0;	/* Aligned in PAGE_SIZE */	p = (unsigned char *)(((unsigned int)p + PAGE_SIZE) & ~(PAGE_SIZE-1)); 	for (i = 0; i < QUEUE_MAX; i++) {		out_dma_buf[i] = (unsigned long)p;		p += PAGE_SIZE*16;		out_dma_pbuf[i] = PHYADDR((unsigned int)out_dma_buf[i]);		in_dma_buf[i] = (unsigned long)p;		p += PAGE_SIZE*16;		in_dma_pbuf[i] = PHYADDR((unsigned int)in_dma_buf[i]);	}	pcm_ioctl(PCM_SET_SAMPLE_RATE, 16000);	pcm_ioctl(PCM_SET_FORMAT, AFMT_S16_LE);	pcm_ioctl(PCM_SET_CHANNEL, 2);	pcm_ioctl(PCM_SET_VOL, 100);	/* 100% */	return 0;}

⌨️ 快捷键说明

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