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

📄 em8xxx_oss.c

📁 Sigma SMP8634 Mrua v. 2.8.2.0
💻 C
📖 第 1 页 / 共 4 页
字号:
/***************************************** Copyright  2004-2005 Sigma Designs, Inc. All Rights Reserved Proprietary and Confidential *****************************************//**  @file   em8xxx_oss.c  @brief    OSS sound driver for em8xxx series.  @author Yoann Walther  @date   2005-07-12*/#include "em8xxxoss.h"static u_long audio_capture_index; static u_long audio_decoder_index=1;static u_long audio_engine_index;static u_long audio_mmID = 0;#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,17)module_param(audio_decoder_index, ulong,0);module_param(audio_mmID, ulong,0);#elseMODULE_PARM(audio_decoder_index, "l");MODULE_PARM(audio_mmID, "l");#endifMODULE_PARM_DESC(audio_decoder_index, "Audio Decoder in use\n");MODULE_PARM_DESC(audio_mmID, "Audio Memory Manager in use\n");MODULE_DESCRIPTION("EM8XXX Sound OSS Driver");MODULE_AUTHOR("Yoann Walther <yoann_walther@sdesigns.eu>");#ifdef MODULE_LICENSEMODULE_LICENSE("Proprietary");#endifextern struct em8xxxprivate Etable[MAXLLAD];RMstatus krua_register_event_callback(void *pE,RMuint32 ModuleID,RMuint32 mask, Event_callback callback);RMstatus krua_unregister_event_callback(void *pE,RMuint32 ModuleID,Event_callback callback);static RMstatus prepare_data(struct sndprivate *pS);static RMuint32 bytes_to_samples(struct sndprivate *pS,RMuint32 count);static RMstatus start_capture(struct em8xxxprivate *pE);static RMstatus start_playback(struct em8xxxprivate *pE);/* mixer file operations */static int rm_open_mixer(struct inode *inode, struct file *file);static int rm_release_mixer(struct inode *inode, struct file *file);static int rm_ioctl_mixer(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg);static int process_ioctl_mixer(struct em8xxxprivate *pE, unsigned int cmd, unsigned long arg);static struct file_operations rm_mixer_fops = {	owner:		THIS_MODULE,	ioctl:		rm_ioctl_mixer,	open:		rm_open_mixer,	release:	rm_release_mixer,};/* dsp file operations */static ssize_t rm_read_dsp(struct file *file, char *buffer, size_t count, loff_t *ppos);static ssize_t rm_write_dsp(struct file *file, const char *buffer, size_t count, loff_t *ppos);static unsigned int rm_poll_dsp(struct file *file, struct poll_table_struct *wait);static int rm_mmap_dsp(struct file *file, struct vm_area_struct *vma);static int rm_ioctl_dsp(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg);static int rm_open_dsp(struct inode *inode, struct file *file);static int rm_release_dsp(struct inode *inode, struct file *file);static int process_ioctl_dsp(struct sndprivate *pS, unsigned int cmd, unsigned long arg);//static RMstatus set_audio_parameters(struct em8xxxprivate *pE, int format, int sampleRate, int channelCount);static RMstatus init_audio(struct sndprivate *pS);static RMstatus cleanup_audio(struct sndprivate *pS);static int rm_free_ptr(struct em8xxxprivate *pE,RMuint32 ptr);static /*const*/ struct file_operations rm_dsp_fops = {	// this replaces MOD_INC_USE_COUNT/MOD_DEC_USE_COUNT pain	owner:		THIS_MODULE,	read:		rm_read_dsp,	write:		rm_write_dsp,	poll:		rm_poll_dsp,	ioctl:		rm_ioctl_dsp,	mmap:		rm_mmap_dsp,	open:		rm_open_dsp,	release:	rm_release_dsp,};static int sndprivate_init(struct em8xxxprivate *pE){	struct sndprivate *pS=Stable+(pE-Etable);		if (pS->sndprivate_active == 0) {		memset(pS,0,sizeof(struct sndprivate));				if ((pS->mixer_dev = register_sound_mixer(&rm_mixer_fops, -1)) < 0) {			printk("Cannot register em8xxx sound mixer device\n");			goto error_mixer;		}		if ((pS->dsp_dev = register_sound_dsp(&rm_dsp_fops, -1)) < 0) {			printk("Cannot register em8xxx sound dsp device\n");			goto error_dsp;		}	}	else {		printk("em8xxx sound driver (/dev/mixer%d, /dev/dsp%d) already registered\n", pS->mixer_dev, pS->dsp_dev);		return -EINVAL;	}		pS->sndprivate_active = 1;	printk("em8xxx sound driver (/dev/mixer%d, /dev/dsp%d) registered.\n", pS->mixer_dev, pS->dsp_dev);	return 0;	 error_dsp:	unregister_sound_mixer(pS->mixer_dev);	 error_mixer:	return -EINVAL;}static int sndprivate_cleanup(struct em8xxxprivate *pE){	struct sndprivate *pS=Stable+(pE-Etable);		// unregister dsp & mixer		if (pS->sndprivate_active == 1) {		if ((pS->mixer_open_count == 0) && 		    (pS->dsp_open_count == 0)) {			unregister_sound_mixer(pS->mixer_dev);			unregister_sound_dsp(pS->dsp_dev);		}		else {			if (pS->mixer_open_count > 0) 				printk("cannot unregistered (/dev/mixer%d). device is opened %d times\n", pS->mixer_dev, pS->mixer_open_count);						if (pS->dsp_open_count > 0)				printk("cannot unregistered (/dev/dsp%d). device is opened %d times\n", pS->dsp_dev, pS->dsp_open_count);			return -EINVAL;		}	}	else {		printk("no em8xxx sound mixer device registered\n");		return -EINVAL;	}			printk("em8xxx sound mixer (/dev/mixer%d, /dev/dsp%d) unregistered\n", pS->mixer_dev, pS->dsp_dev);	pS->sndprivate_active = 0;	return 0;}//////////////////////////////////////////////////////////////////////////////////////////////////////////////////                                   MIXER FILE OPERATIONS                                       ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////static int rm_open_mixer(struct inode *inode, struct file *file){	int i;	int minor = MINOR(inode->i_rdev);	struct em8xxxprivate *pE = (struct em8xxxprivate *) NULL; 	struct sndprivate *pS = (struct sndprivate *) NULL;	 	for (i=0 ; i<MAXLLAD ; i++) {		pE = &Etable[i];		pS = Stable+(pE-Etable);		if (pS->sndprivate_active == 1) {			if (pS->mixer_dev == minor) 				break;		}	}		if (i == MAXLLAD) { // can't find corresponding realmagic device		printk("Cannot open em8xxx sound mixer device\n");		return -EINVAL;	}		printk("Opens em8xxx sound mixer (/dev/mixer%d)\n", minor);	pS->mixer_open_count ++;		file->private_data = pS;	return 0;}static int rm_release_mixer(struct inode *inode, struct file *file){	struct sndprivate *pS=(struct sndprivate *)file->private_data;	struct em8xxxprivate *pE;		pE=Etable+(pS-Stable);		printk("closes em8xxx sound mixer (/dev/mixer%d)\n", pS->mixer_dev);	if(pS->mixer_open_count) pS->mixer_open_count --;	return 0;}static int rm_ioctl_mixer(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg){	struct sndprivate *pS=(struct sndprivate *)file->private_data;	struct em8xxxprivate *pE=Etable+(pS-Stable);	int rc;	rc = process_ioctl_mixer(pE, cmd, arg);	return rc;}static int process_ioctl_mixer(struct em8xxxprivate *pE, unsigned int cmd, unsigned long arg){	int val, i,volume_index;	int r,l;	int rc = -EINVAL;	struct sndprivate *pS=Stable+(pE-Etable);	struct AudioEngine_Volume_type volume;	struct AudioDecoder_MixerWeight_type cmdblock;	RMstatus err;	RMuint32 audio_decoder = EMHWLIB_MODULE(AudioDecoder,audio_decoder_index);	if (_IOC_TYPE(cmd) != 'M' || _SIOC_SIZE(cmd) != sizeof(int)) {		return -EINVAL;	}	        if (_SIOC_DIR(cmd) == _SIOC_READ) {                switch (_IOC_NR(cmd)) {                case SOUND_MIXER_DEVMASK: /* Arg contains a bit for each supported device */			val = SOUND_MASK_VOLUME | SOUND_MASK_PCM;			rc = kc_logging_copy_to_user((int *) arg, &val, sizeof(int));			return rc;		case SOUND_MIXER_STEREODEVS: /* Mixer channels supporting stereo */			val = SOUND_MASK_VOLUME | SOUND_MASK_PCM;			rc = kc_logging_copy_to_user((int *) arg, &val, sizeof(int));			return rc;		case SOUND_MIXER_RECMASK:		case SOUND_MIXER_CAPS:		case SOUND_MIXER_RECSRC:			val = 0;			rc =kc_logging_copy_to_user((int *) arg, &val, sizeof(int));			return rc;					default:			i = _IOC_NR(cmd);			switch(i){			case SOUND_MIXER_PCM:								val = pS->weight;								rc =kc_logging_copy_to_user((int *) arg, &val, sizeof(int));				return rc;							case SOUND_MIXER_VOLUME:												val = pS->volume;								rc =kc_logging_copy_to_user((int *) arg, &val, sizeof(int));				return rc;						default:				return -EINVAL;			}		}	}	        if (_SIOC_DIR(cmd) != (_SIOC_READ|_SIOC_WRITE)) {		return -EINVAL;	}		switch (_IOC_NR(cmd)) {	case SOUND_MIXER_RECSRC: /* Arg contains a bit for each recording source */		return 0;			default: 		i = _IOC_NR(cmd);		switch(i){		case SOUND_MIXER_PCM:			rc =kc_logging_copy_from_user(&val, (int *) arg, sizeof(int));			if (rc != 0)				break;				// Mixer weight initialization					l = val & 0xff;					volume_index=l*74/100;			volume_index=volume_index % 75;			cmdblock.MixerValue_ch0=VolumeTable[volume_index] ;						EM8XXXSNDSP( pE, audio_decoder,RMAudioDecoderPropertyID_MixerWeight,&cmdblock,sizeof(cmdblock));			r = (val >> 8) & 0xff;						volume_index=r*74/100;			volume_index=volume_index % 75;				cmdblock.MixerValue_ch2=VolumeTable[volume_index] ;						EM8XXXSNDSP( pE, audio_decoder,RMAudioDecoderPropertyID_MixerWeight,&cmdblock,sizeof(cmdblock));						pS->weight = val;						rc =kc_logging_copy_to_user((int *) arg, &val, sizeof(int));			return rc;		case SOUND_MIXER_VOLUME:						rc =kc_logging_copy_from_user(&val, (int *) arg, sizeof(int));			if (rc != 0)				break;						/* sets the left volume */						l = val & 0xff;						volume_index=l*74/100;			volume_index=volume_index % 75;			volume.Channel=0;			volume.Volume=VolumeTable[volume_index];						EM8XXXSNDSP(pE,EMHWLIB_MODULE(AudioEngine,audio_engine_index),RMAudioEnginePropertyID_Volume,&volume,sizeof(volume));			if (RMFAILED(err)){				printk("error while setting volume \n");			}						/* sets the right volume */			r = (val >> 8) & 0xff;						volume_index=r*74/100;			volume_index=volume_index % 75;			volume.Channel=2;			volume.Volume=VolumeTable[volume_index];						EM8XXXSNDSP(pE,EMHWLIB_MODULE(AudioEngine,audio_engine_index),RMAudioEnginePropertyID_Volume,&volume,sizeof(volume));			if (RMFAILED(err)){				printk("error while setting volume \n");			}						pS->volume = val;			rc =kc_logging_copy_to_user((int *) arg, &val, sizeof(int));			return rc;		default:			return -EINVAL;		}	}	return rc;}/////////////////////////////////////////////////////////////////////////////////////////////////////////////////                              /DEV/DSP FILE OPERATIONS                                 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////static RMuint32 bytes_to_samples(struct sndprivate *pS,RMuint32 count){	RMuint32 samples;	RMuint32 nb_bits_per_sample = pS->nb_bits_per_sample;	RMuint32 channel_count = pS->channel_count;	samples = (count*8) / (nb_bits_per_sample*channel_count);	return samples;}static RMstatus prepare_data(struct sndprivate *pS){	struct em8xxx_data param;	struct em8xxxprivate *pE = Etable + (pS-Stable);	RMuint8 *buffer=NULL;	RMuint32 timeout = 0;	RMstatus err=RM_OK;	RMuint32 audio_capture = EMHWLIB_MODULE(AudioCapture,audio_capture_index);	struct ReadBufferInfo prop;	RMuint32 nb_buf = 0;		while (1) {				timeout=0;				buffer=kdmapool_getbuffer(pE->pllad,pS->capture_dmapool_id,&timeout);						if (buffer==NULL){			break;		}			nb_buf ++;			param.moduleId = audio_capture;		param.poolId = pS->capture_dmapool_id;		param.bus_addr = kdmapool_get_bus_address(pE->pllad,pS->capture_dmapool_id,buffer, 0);		param.dataSize = (1<<SERIALIN_DMA_BUFFER_SIZE_LOG2);				prop.address = param.bus_addr;		prop.size = param.dataSize;		prop.context = (void *) ((pE-Etable) + param.poolId + 1);		EM8XXXSNDSP(pE, param.moduleId, RMGenericPropertyID_AddReadBuffer, &prop, sizeof(prop));				buffer=NULL;	}		printk("prepared %ld buffers \n",nb_buf);	return err;	}void em8xxx_snd_clear_event_mask(unsigned long private_data){	struct sndprivate *pS = (struct sndprivate *) private_data;	struct em8xxxprivate *pE = Etable + (pS-Stable);	RMuint32 status=0;	RMuint32 mask;	kc_spin_lock(pE->lock);	mask = pS->event_mask;	kc_spin_unlock(pE->lock);	if (mask & SOFT_IRQ_EVENT_XFER_RECEIVE_READY) {		kc_wake_up_interruptible(pS->sq);		status |= SOFT_IRQ_EVENT_XFER_RECEIVE_READY;	}	kc_spin_lock(pE->lock);	EMhwlibSetProperty(pE->pemhwlib,EMHWLIB_MODULE(AudioCapture,audio_capture_index),RMGenericPropertyID_ClearEventMask,&status,sizeof(status));	pS->event_mask = 0;	kc_spin_unlock(pE->lock);}static RMuint32 event_callback(void *pE,RMuint32 ModuleID,RMuint32 mask){	struct em8xxxprivate *real_pE = (struct em8xxxprivate *) pE;	struct sndprivate *pS = Stable + (real_pE-Etable);	kc_spin_lock(real_pE->lock);	pS->event_mask |= mask;	kc_spin_unlock(real_pE->lock);	tasklet_hi_schedule(&pS->event_tq);	return mask;}static int rm_open_dsp(struct inode *inode, struct file *file){	int i;	int minor = MINOR(inode->i_rdev);	struct em8xxxprivate *pE = (struct em8xxxprivate *) NULL; 	struct sndprivate *pS = (struct sndprivate *) NULL;	 	for (i=0 ; i<MAXLLAD ; i++) {		pE = &Etable[i];		pS=Stable+(pE-Etable);				if (pS->sndprivate_active==1) {			if (pS->dsp_dev==minor) break;		}	}		if (i == MAXLLAD) { // can't find corresponding realmagic device		printk("Cannot open em8xxx sound dsp device\n");		return -EINVAL;	}	printk("Opens em8xxx sound device (/dev/dsp%d)\n", minor);	/*Only one process can used oss device*/	if(pS->dsp_open_count != 0){		RMDBGLOG((ENABLE, "/dev/dsp already opened\n"));		return -EMFILE;	}	pS->dsp_open_count ++;	file->private_data = pS;	init_waitqueue_head(&pS->sound_queue);	kc_init_waitqueue_head(&pS->sq);	if(init_audio(pS) != RM_OK)	{		printk("Audio initialisation error.\n");		cleanup_audio(pS);		pS->dsp_open_count --;		return -EINVAL;	}		printk("Open the pools\n");	//open the pools	 	pS->dmapool_id=kdmapool_open(pE->pllad,NULL,AUDIO_DMA_BUFFER_COUNT,AUDIO_DMA_BUFFER_SIZE_LOG2);	printk("dmapool id = %ld\n", pS->dmapool_id);	{	RMuint32 timeout = 0;	pS->pBuf=kdmapool_getbuffer(pE->pllad,pS->dmapool_id,&timeout);	}	pS->capture_dmapool_id=kdmapool_open(pE->pllad,NULL,SERIALIN_DMA_BUFFER_COUNT,SERIALIN_DMA_BUFFER_SIZE_LOG2); 	printk("capture_dmapool id = %ld\n", pS->capture_dmapool_id);	prepare_data(pS);		tasklet_init(&pS->event_tq,em8xxx_snd_clear_event_mask,(unsigned long) pS);	krua_register_event_callback(pE,EMHWLIB_MODULE(AudioCapture,audio_capture_index),SOFT_IRQ_EVENT_XFER_RECEIVE_READY,event_callback);		return 0;}

⌨️ 快捷键说明

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