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

📄 em8300_audio.c

📁 linux TV 源码
💻 C
📖 第 1 页 / 共 2 页
字号:
		return -EINVAL;		break;	case SNDCTL_DSP_SETFRAGMENT: /* set fragment size */		pr_debug("em8300_audio.o: SNDCTL_DSP_SETFRAGMENT %i\n", val);		pr_info("em8300_audio.o: SNDCTL_DSP_SETFRAGMENT not implemented yet\n");		return -EINVAL;		break;	case SNDCTL_DSP_GETFMTS: /* get possible formats */#ifdef AFMT_AC3		val = AFMT_AC3 | AFMT_S16_BE | AFMT_S16_LE;#else		val = AFMT_S16_BE | AFMT_S16_LE;#endif		pr_debug("em8300_audio.o: SNDCTL_DSP_GETFMTS\n");		break;	case SNDCTL_DSP_SETFMT: /* set sample format */		if (get_user(val, (int *)arg)) {			return -EFAULT;		}		pr_debug("em8300_audio.o: SNDCTL_DSP_SETFMT %i ", val);		val = set_format(em, val);		pr_debug("%i\n", val);		break;	case SOUND_PCM_READ_BITS: /* read sample format */		val = em->audio.format;		pr_debug("em8300_audio.o: SOUND_PCM_READ_BITS\n");		break;	case SNDCTL_DSP_GETOSPACE:	{		audio_buf_info buf_info;		buf_info.fragments = ((*em->mafifo->readptr - *em->mafifo->writeptr)/em->mafifo->slotptrsize+em->mafifo->nslots-1)%em->mafifo->nslots;		buf_info.fragstotal = em->mafifo->nslots;		buf_info.fragsize = em->mafifo->slotsize;		buf_info.bytes = em->mafifo->nslots*em->mafifo->slotsize;		pr_debug("em8300_audio.o: SNDCTL_DSP_GETOSPACE\n");		return copy_to_user((void *)arg, &buf_info, sizeof(audio_buf_info));	}		case SNDCTL_DSP_GETISPACE:		pr_debug("em8300_audio.o: SNDCTL_DSP_GETISPACE\n");		return -EINVAL;		break;	case SNDCTL_DSP_GETCAPS:		val = DSP_CAP_REALTIME | DSP_CAP_BATCH | DSP_CAP_TRIGGER;		pr_debug("em8300_audio.o: SNDCTL_DSP_GETCAPS\n");		break;	case SNDCTL_DSP_GETTRIGGER:		val = em->audio.enable_bits;		pr_debug("em8300_audio.o: SNDCTL_DSP_GETTRIGGER\n");		break;	case SNDCTL_DSP_SETTRIGGER:		if (val & PCM_ENABLE_OUTPUT) {			if (em->audio.enable_bits & PCM_ENABLE_OUTPUT) {				em->audio.enable_bits |= PCM_ENABLE_OUTPUT;				mpegaudio_command(em, MACOMMAND_PLAY);			}		}		pr_debug("em8300_audio.o: SNDCTL_DSP_SETTRIGGER\n");		pr_info("em8300_audio.o: SNDCTL_DSP_SETTRIGGER not implemented properly yet\n");		break;	case SNDCTL_DSP_GETIPTR:		pr_debug("em8300_audio.o: SNDCTL_DSP_GETIPTR\n");		return -EINVAL;		break;	case SNDCTL_DSP_GETOPTR:	{		count_info ci;		ci.bytes = em->mafifo->bytes - (em8300_audio_calcbuffered(em) / em->mafifo->preprocess_ratio);		if (ci.bytes < 0) ci.bytes = 0;		ci.blocks = 0;		ci.ptr = 0;		pr_debug("em8300_audio.o: SNDCTL_DSP_GETOPTR %i\n", ci.bytes);		return copy_to_user((void *)arg, &ci, sizeof(count_info));	}	case SNDCTL_DSP_GETODELAY:		val = em8300_audio_calcbuffered(em) / em->mafifo->preprocess_ratio;		pr_debug("em8300_audio.o: SNDCTL_DSP_GETODELAY %i\n", val);		break;#if 0	case SOUND_DSP_GETERROR:		return -EINVAL;		break;#endif	case EM8300_IOCTL_AUDIO_SETPTS:		if (get_user(em->audio_pts, (int *)arg))			return -EFAULT;		em->audio_pts >>= 1;		em->audio_ptsvalid=1;		em->audio_sync = 1;		break;	default:		pr_info("em8300_audio.o: unknown ioctl called\n");		return -EINVAL;	}	return put_user(val, (int *)arg);}int em8300_audio_flush(struct em8300_s *em){	int audiobuf, audiobufsize;	mpegaudio_command(em, MACOMMAND_STOP);	/* Zero audio buffer */	audiobuf = read_ucregister(MA_BuffStart_Lo) | (read_ucregister(MA_BuffStart_Hi) << 16);	audiobufsize = read_ucregister(MA_BuffSize) | (read_ucregister(MA_BuffSize_Hi) << 16);	mpegaudio_command(em, MACOMMAND_PAUSE);	return em8300_setregblock(em, audiobuf, 0, audiobufsize);}int em8300_audio_open(struct em8300_s *em){	if (!em->ucodeloaded) {		return -ENODEV;	}		em->audio_lastpts = 0;	em->audio_lag = 0;	em->last_calcbuf = 0;	em->mafifo->bytes = 0;	return audio_start(em);}int em8300_audio_release(struct em8300_s *em){	return audio_stop(em);	}static int set_audiomode(struct em8300_s *em, int mode){	unsigned char mutepattern_src[0x300];	unsigned char mutepattern[0x600];		em->audio_mode = mode;		em->clockgen &= ~CLOCKGEN_OUTMASK;	if (em->audio_mode == EM8300_AUDIOMODE_ANALOG) {		em->clockgen |= CLOCKGEN_ANALOGOUT;	} else {		em->clockgen |= CLOCKGEN_DIGITALOUT;	}		em8300_clockgen_write(em, em->clockgen);	memset(mutepattern_src, 0, sizeof(mutepattern_src));	memset(em->byte_D90, 0, sizeof(em->byte_D90));	em->byte_D90[1]=0x98;	switch (em->audio.speed) {	case 32000:		em->byte_D90[3] = 0xc0;		break;	case 44100:		em->byte_D90[3] = 0;		break;	case 48000:		em->byte_D90[3] = 0x40;		break;	}	 	switch (em->audio_mode) {	case EM8300_AUDIOMODE_ANALOG:		em->pcm_mode = EM8300_AUDIOMODE_ANALOG;		write_register(EM8300_AUDIO_RATE, 0x62);		em8300_setregblock(em, 2*ucregister(Mute_Pattern), 0, 0x600);		printk(KERN_NOTICE "em8300_audio.o: Analog audio enabled\n");		break;	case EM8300_AUDIOMODE_DIGITALPCM:		em->pcm_mode = EM8300_AUDIOMODE_DIGITALPCM;		write_register(EM8300_AUDIO_RATE, 0x3a0);		em->byte_D90[0]=0x0;		sub_prepare_SPDIF(em, mutepattern, mutepattern_src, 0x300);			em8300_writeregblock(em, 2*ucregister(Mute_Pattern), (unsigned *)mutepattern, 0x600);		printk(KERN_NOTICE "em8300_audio.o: Digital PCM audio enabled\n");		break;	case EM8300_AUDIOMODE_DIGITALAC3:		write_register(EM8300_AUDIO_RATE, 0x3a0);		em->byte_D90[0]=0x40;		sub_prepare_SPDIF(em, mutepattern, mutepattern_src, 0x300);		em8300_writeregblock(em, 2*ucregister(Mute_Pattern), (unsigned *)mutepattern, 0x600);		printk(KERN_NOTICE "em8300_audio.o: Digital AC3 audio enabled\n");		break;	}	return 0;}int em8300_audio_setup(struct em8300_s *em){	int ret;	em->audio.channels = 2;	em->audio.format = AFMT_S16_NE;	em->audio.slotsize = 0x1000;	em->clockgen = em->clockgen_tvmode;	set_speed(em, 48000);		set_audiomode(em, EM8300_AUDIOMODE_DEFAULT);		ret = em8300_audio_flush(em);	setup_mafifo(em);		if (ret) {		printk(KERN_ERR "em8300_audio.o: Couldn't zero audio buffer\n");		return ret;	}		write_ucregister(MA_Threshold, 6);		mpegaudio_command(em, MACOMMAND_PLAY);	mpegaudio_command(em, MACOMMAND_PAUSE);	em->audio.enable_bits = 0;	return 0;}int em8300_audio_calcbuffered(struct em8300_s *em){	int readptr, writeptr, bufsize, n;	readptr = read_ucregister(MA_Rdptr) | (read_ucregister(MA_Rdptr_Hi) << 16);	writeptr = read_ucregister(MA_Wrptr) | (read_ucregister(MA_Wrptr_Hi) << 16);	bufsize = read_ucregister(MA_BuffSize) | (read_ucregister(MA_BuffSize_Hi) << 16);	n = (bufsize+writeptr-readptr) % bufsize;	return em8300_fifo_calcbuffered(em->mafifo) + n;}int em8300_audio_write(struct em8300_s *em, const char * buf, size_t count, loff_t *ppos){	int32_t diff;	uint32_t vpts, master_vpts;	uint32_t calcbuf;	if (em->audio_sync) {	if (em->audio_ptsvalid) {		em->audio_ptsvalid=0;		if (em->audio_lastpts == 0) {			em->audio_lastpts = em->audio_pts;		}		if (em->rollover) {			em->rollover_lastpts += (em->audio_pts - em->audio_lastpts);			em->audio_lag -= (em->audio_pts - em->audio_lastpts);			em->audio_lastpts = em->audio_pts;		}		/* rollover detected */		if (em->audio_pts < em->audio_lastpts) {			pr_debug("em8300_audio.o: ROLLOVER DETECTED! lastpts: %u pts: %u\n", em->audio_lastpts, em->audio_pts);			em->rollover = 1;			em->rollover_pts = 0;			em->rollover_startpts = em->audio_pts;			em->rollover_lastpts = em->audio_lastpts + em->lastpts_count;			em->audio_lastpts = em->audio_pts;			em->audio_lag -= em->lastpts_count;		} else {			em->audio_lag -= (em->audio_pts - em->audio_lastpts);			em->audio_lastpts = em->audio_pts;		}		em->lastpts_count = 0;	}	if (!em->rollover) {		em->basepts = em->audio_pts;	} else {		em->basepts = em->rollover_lastpts;	}	calcbuf = em8300_audio_calcbuffered(em);#ifdef DEBUG_SYNC	pr_debug("em8300_audio.o: calcbuf: %u since_last_pts: %i\n", calcbuf, em->audio_lag);#endif		vpts = em->basepts + em->audio_lag - (calcbuf * 45000/4 / em->audio.speed);	master_vpts = read_ucregister(MV_SCRlo) | (read_ucregister(MV_SCRhi) << 16);	if (em->rollover && (em->rollover_pts == 0)) {	  /* I'm not sure if there's any significance to this 45000/4 */	  /* I had to add some pts, so I just picked it	   -RH	 */		em->rollover_pts = em->basepts + em->audio_lag + 45000/4;	}	if (em->rollover && (vpts > em->rollover_pts)) {		em->rollover = 0;		vpts -= em->rollover_startpts;	}#ifdef DEBUG_SYNC	pr_debug("em8300_audio.o: pts: %u vpts: %u scr: %u bpts: %u\n", em->audio_pts, vpts, master_vpts, basepts);#endif		diff = vpts - master_vpts;		if (my_abs(diff) > 3600) {	        pr_info("em8300_audio.o: resyncing\n");		pr_debug("em8300_audio.o: master clock adjust time %d -> %d\n", master_vpts, vpts); 		write_ucregister(MV_SCRlo, vpts & 0xffff);		write_ucregister(MV_SCRhi, (vpts >> 16) & 0xffff);		pr_debug("Setting SCR: %d\n", vpts);	}	em->audio_lag += (count * 45000/4 / em->audio.speed);	em->last_calcbuf = calcbuf + count;	em->lastpts_count += (count * 45000/4 / em->audio.speed);	}	return em8300_fifo_writeblocking(em->mafifo, count, buf,0);}/* 18-09-2000 - Ze'ev Maor - added these two ioctls to set and get audio mode. */int em8300_ioctl_setaudiomode(struct em8300_s *em, int mode){	em8300_audio_flush(em);	set_audiomode(em, mode);	setup_mafifo(em);	mpegaudio_command(em, MACOMMAND_PLAY);	em->audio.enable_bits = PCM_ENABLE_OUTPUT;	return 0;}int em8300_ioctl_getaudiomode(struct em8300_s *em, int mode){	int a=em->audio_mode;	copy_to_user((void *)mode, &a, sizeof(int));	return 0;}

⌨️ 快捷键说明

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