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

📄 em8xxx_voip_new.c

📁 Sigma SMP8634 Mrua v. 2.8.2.0
💻 C
📖 第 1 页 / 共 4 页
字号:
/***************************************** Copyright @ 2005, 2006, 2007 Sigma Designs, Inc. All Rights Reserved Proprietary and Confidential *****************************************//**  @file   em8xxx_voip_new.c  @brief    New linux kernel telephony driver of the em8xxx boards  @author Yoann Walther   @date   2006-11-07*//* to enable or disable the debug messages of this source file, put 1 or 0 below */#if 1#define LOCALDBG ENABLE#else#define LOCALDBG DISABLE#endif#include "em8xxxvoip_new.h"MODULE_DESCRIPTION("EM8XXX New Linux Telephony Driver");MODULE_AUTHOR("Yoann Walther <yoann_walther@sdesigns.eu>");#ifdef MODULE_LICENSEMODULE_LICENSE("Proprietary");#endifextern struct em8xxxprivate Etable[MAXLLAD];static RMuint32 em8xxx_voip_event_callback(void *pE,RMuint32 ModuleID,RMuint32 mask);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 int rm_free_ptr(struct em8xxxprivate *pE,RMuint32 ptr);static int gpio_set_dir(struct em8xxxprivate *pE,int gpio_number,int dir);static int read_gpio(struct em8xxxprivate *pE,int gpio_number);static int write_gpio(struct em8xxxprivate *pE,int gpio_number, int val);static int init_gpio(struct em8xxxprivate *pE);static int SlicSetState(struct voipprivate *pV,enum SLIC_STATES State);static void em8xxx_voip_check_hookstate(struct voipprivate *pV);static void em8xxx_voip_init_timer(struct voipprivate *pV);static void em8xxx_voip_add_timer(struct voipprivate *pV);static void em8xxx_voip_timeout(unsigned long private);static int em8xxx_voip_init(struct em8xxxprivate *pE);static int em8xxx_voip_cleanup(struct em8xxxprivate *pE);static int em8xxx_voip_open(struct phone_device *p, struct file *file_p);static ssize_t em8xxx_voip_read(struct file * file_p, char *buf, size_t length,loff_t * ppos);static ssize_t em8xxx_voip_write(struct file * file_p, const char *buf, size_t count, loff_t * ppos);static unsigned int em8xxx_voip_poll(struct file *file_p, poll_table * wait);static int em8xxx_voip_ioctl(struct inode *inode, struct file *file_p, unsigned int cmd, unsigned long arg);static int em8xxx_voip_release(struct inode *inode, struct file *file_p);static int em8xxx_voip_fasync(int fd, struct file *file_p, int mode);struct file_operations em8xxx_voip_fops ={#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)	NULL,			/* lseek */	em8xxx_voip_read,	em8xxx_voip_write,	NULL,			/* readdir */	em8xxx_voip_poll,	em8xxx_voip_ioctl,	NULL,			/* mmap */	NULL,			/* open */	NULL,			/* flush */	em8xxx_voip_release,	NULL,			/* fsync */	em8xxx_voip_fasync,		/* fasync */	NULL,			/* media change */	NULL,			/* revalidate */	NULL			/* lock */#else#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)	owner:          THIS_MODULE,	read:           em8xxx_voip_read,	write:          em8xxx_voip_write,	poll:           em8xxx_voip_poll,	ioctl:          em8xxx_voip_ioctl,	release:        em8xxx_voip_release,	fasync:         em8xxx_voip_fasync#else	.owner        = THIS_MODULE,	.read         = em8xxx_voip_read,	.write        = em8xxx_voip_write,	.poll         = em8xxx_voip_poll,	.ioctl        = em8xxx_voip_ioctl,	.release      = em8xxx_voip_release,	.fasync       = em8xxx_voip_fasync#endif#endif};static int rm_free_ptr(struct em8xxxprivate *pE,RMuint32 ptr){	RMuint32 dramIndex=0xffffffff;	RMstatus err;		if ((MEM_BASE_dram_controller_0<=ptr)&&(ptr<MEM_BASE_dram_controller_1)) dramIndex=0;	if ((MEM_BASE_dram_controller_1<=ptr)&&(ptr<MEM_BASE_dram_controller_1+(512*1024*1024))) dramIndex=1;	if (dramIndex<=1) {		EM8XXXVOIPSP(pE,			    EMHWLIB_MODULE(MM,dramIndex),			    RMMMPropertyID_Free,			    (void *)(&ptr),sizeof(void *));		if(err!=RM_OK) 			RMDBGLOG((ENABLE,"rm_ptr_free: pointer 0x%08lx cannot be freed\n",ptr));	}	else		RMDBGLOG((ENABLE,"rm_ptr_free: pointer %p not in a dram controller\n",ptr));		return 0;}static void em8xxx_voip_clear_event_mask(unsigned long private_data){	struct voipprivate *pV = (struct voipprivate *) private_data;	struct em8xxxprivate *pE = Etable + (pV-VOIPtable);	RMuint32 status = 0;	RMuint32 mask;	kc_spin_lock(pE->lock);	mask = pV->event_mask;	kc_spin_unlock(pE->lock);	if (mask & SOFT_IRQ_EVENT_COMMANDCOMPLETION) {		kc_wake_up_interruptible(pV->command_q);		status |= SOFT_IRQ_EVENT_COMMANDCOMPLETION;	}	if (mask & SOFT_IRQ_EVENT_VOIP_DTMF_READY) {		pV->exc.bits.dtmf_ready = 1;		kc_wake_up_interruptible(pV->poll_q);		status |= SOFT_IRQ_EVENT_VOIP_DTMF_READY;	}	if (mask & SOFT_IRQ_EVENT_VOIP_FRAME_ENCODED) {		kc_wake_up_interruptible(pV->read_q);		status |= SOFT_IRQ_EVENT_VOIP_FRAME_ENCODED;	}	if (mask & SOFT_IRQ_EVENT_VOIP_FRAME_DECODED) {		kc_wake_up_interruptible(pV->write_q);		status |= SOFT_IRQ_EVENT_VOIP_FRAME_DECODED;	}	kc_spin_lock(pE->lock);	EMhwlibSetProperty(pE->pemhwlib,VoipCodec,RMGenericPropertyID_ClearEventMask,&status,sizeof(status));	pV->event_mask = 0;	kc_spin_unlock(pE->lock);}static RMuint32 em8xxx_voip_event_callback(void *pE,RMuint32 ModuleID,RMuint32 mask){	struct em8xxxprivate *real_pE = (struct em8xxxprivate *) pE;	struct voipprivate *pV = VOIPtable + (real_pE - Etable);	kc_spin_lock(real_pE->lock);	pV->event_mask |= mask;	kc_spin_unlock(real_pE->lock);	tasklet_hi_schedule(&pV->event_tq);	return mask;}static int gpio_set_dir(struct em8xxxprivate *pE,int gpio_number,int dir){	RMuint32 gpio_dir;	RMuint32 gpio_dir_addr;	int nb;	if(gpio_number > 16){		gpio_dir_addr = ETH_GPIO_DIR;		nb = gpio_number - 16;	}	else {		gpio_dir_addr = SYS_GPIO_DATA;		nb = gpio_number;	}	gpio_dir = gbus_read_uint32(pE->pgbus,gpio_dir_addr);	RMsetConsecutiveBitsVar(&gpio_dir,nb+16,nb+16,1);	RMsetConsecutiveBitsVar(&gpio_dir,nb,nb,dir);		gbus_write_uint32(pE->pgbus,gpio_dir_addr,gpio_dir);	gpio_dir = gbus_read_uint32(pE->pgbus,gpio_dir_addr);	if (dir == ((gpio_dir >> nb) & 1))		return 0;	else 		return -1;	}static int read_gpio(struct em8xxxprivate *pE,int gpio_number){	RMuint32 gpio_data;	RMuint32 gpio_data_addr;	int val;	int nb;	if(gpio_number > 16){		gpio_data_addr = ETH_GPIO_DATA;		nb = gpio_number - 16;	}	else {		gpio_data_addr = SYS_GPIO_DATA;		nb = gpio_number;	}		gpio_data = gbus_read_uint32(pE->pgbus,gpio_data_addr);	val = (gpio_data >> nb) & 1;	return val;	}static int write_gpio(struct em8xxxprivate *pE,int gpio_number, int val){	RMuint32 gpio_data;	RMuint32 gpio_data_addr;	int nb;		if(gpio_number > 16){		gpio_data_addr = ETH_GPIO_DATA;		nb = gpio_number - 16;	}	else{		gpio_data_addr = SYS_GPIO_DATA;		nb = gpio_number;	}	gpio_data = gbus_read_uint32(pE->pgbus,gpio_data_addr);	RMsetConsecutiveBitsVar(&gpio_data,nb+16,nb+16,1);	RMsetConsecutiveBitsVar(&gpio_data,nb,nb,val);	gbus_write_uint32(pE->pgbus,gpio_data_addr,gpio_data);	gpio_data = gbus_read_uint32(pE->pgbus,gpio_data_addr);	if (val == ((gpio_data >> nb) & 1))		return 0;	else 		return -1;}static int init_gpio(struct em8xxxprivate *pE){	gpio_set_dir(pE,GPIO_SLIC_COMP,GPIO_DIR_OUTPUT);	gpio_set_dir(pE,GPIO_SLIC_CTL1,GPIO_DIR_OUTPUT);	gpio_set_dir(pE,GPIO_SLIC_CTL2,GPIO_DIR_OUTPUT);	gpio_set_dir(pE,GPIO_SLIC_MUTE,GPIO_DIR_OUTPUT);	gpio_set_dir(pE,GPIO_HDS_MUTE,GPIO_DIR_OUTPUT);	gpio_set_dir(pE,GPIO_LOOP_DETECT,GPIO_DIR_INPUT);	gpio_set_dir(pE,GPIO_FAULT_DETECT,GPIO_DIR_INPUT);	return 0;}static int SlicSetState(struct voipprivate *pV,enum SLIC_STATES State){	struct em8xxxprivate *pE = Etable + (pV - VOIPtable);		switch(State){	case LOW_POWER_STANDBY:		write_gpio(pE,GPIO_SLIC_COMP,0);		write_gpio(pE,GPIO_SLIC_CTL1,0);		write_gpio(pE,GPIO_SLIC_CTL2,0);		break;	case REVERSE_POLARITY:		write_gpio(pE,GPIO_SLIC_COMP,0);		write_gpio(pE,GPIO_SLIC_CTL1,1);		write_gpio(pE,GPIO_SLIC_CTL2,0);		break;	case NORMAL_ACTIVE:		write_gpio(pE,GPIO_SLIC_COMP,0);		write_gpio(pE,GPIO_SLIC_CTL1,0);		write_gpio(pE,GPIO_SLIC_CTL2,1);		break;	case RINGING:		write_gpio(pE,GPIO_SLIC_COMP,0);		write_gpio(pE,GPIO_SLIC_CTL1,1);		write_gpio(pE,GPIO_SLIC_CTL2,1);		break;	case DISCONNECT:		write_gpio(pE,GPIO_SLIC_COMP,1);		write_gpio(pE,GPIO_SLIC_CTL1,0);		write_gpio(pE,GPIO_SLIC_CTL2,0);		break;	}	return 0;}static void em8xxx_voip_check_hookstate(struct voipprivate *pV){	struct em8xxxprivate *pE = Etable + (pV - VOIPtable);		pV->hookstate = !read_gpio(pE,GPIO_LOOP_DETECT);	if(pV->hookstate != pV->last_hookstate){		pV->hook_cnt ++;		if(pV->hook_cnt>=10){			pV->hook_cnt = 0;						RMDBGLOG((LOCALDBG,"detecting hook state change pV->hook_cnt = %d ! \n",pV->hook_cnt));			pV->last_hookstate = pV->hookstate;			pV->exc.bits.hookstate = 1;			kc_wake_up_interruptible(pV->poll_q);			RMDBGLOG((LOCALDBG,"exc.bytes = %d \n",pV->exc.bytes));		}	}}static void em8xxx_voip_timeout(unsigned long private){	struct voipprivate *pV = (struct voipprivate *) private;	struct em8xxxprivate *pE = Etable + (pV - VOIPtable);	struct XferFIFOInfo_type xfer_info;		em8xxx_voip_check_hookstate(pV);	kc_spin_lock(pE->lock);	EMhwlibGetProperty(pE->pemhwlib,EMHWLIB_TARGET_MODULE(VoipCodec,0,0),RMGenericPropertyID_XferFIFOInfo,&xfer_info,sizeof(xfer_info));	kc_spin_unlock(pE->lock);	if (xfer_info.Erasable > 0) {		kc_wake_up_interruptible(pV->poll_q);	}	kc_spin_lock(pE->lock);	EMhwlibGetProperty(pE->pemhwlib,EMHWLIB_TARGET_MODULE(VoipCodec,0,1),RMGenericPropertyID_XferFIFOInfo,&xfer_info,sizeof(xfer_info));	kc_spin_unlock(pE->lock);	if (xfer_info.Writable > 0) {		kc_wake_up_interruptible(pV->poll_q);	}	if(pV->voip_open_count)		em8xxx_voip_add_timer(pV);	return;}static void em8xxx_voip_init_timer(struct voipprivate *pV){	init_timer(&pV->timer);	pV->timer.function = em8xxx_voip_timeout;	pV->timer.data = (unsigned long)pV;}static void em8xxx_voip_add_timer(struct voipprivate *pV){	pV->timer.expires = jiffies + pV->check_interval;	add_timer(&pV->timer);}static RMstatus init_voip(struct voipprivate *pV){	struct em8xxxprivate *pE = Etable + (pV-VOIPtable);	struct MM_Malloc_in_type in;	struct MM_Malloc_out_type out;	enum AudioEngine_SpdifOut_type spdif_out;	struct AudioEngine_I2SConfig_type i2s;	enum AudioEngine_SerialOut_type serialOutStatus;	struct VoipCodec_DRAMSize_in_type dram_in;	struct VoipCodec_DRAMSize_out_type dram_out;	struct VoipCodec_Open_type profile;	enum VoipCodec_Command_type command;	RMuint32 volume;	RMstatus err;	int rc;#ifndef WITH_XLOADED_UCODE	enum ProcessorState run;	struct AudioEngine_MicrocodeDRAMSize_in_type size_in;	struct AudioEngine_MicrocodeDRAMSize_out_type size_out;	struct AudioEngine_Microcode_type ucode;	run = CPU_RESET;	EM8XXXVOIPSP(pE,EMHWLIB_MODULE(AudioEngine,1),RMAudioEnginePropertyID_State,&run,sizeof(run));	if (RMFAILED(err)) {		RMDBGLOG((ENABLE,"Error while resetting Audio RISC\n"));		return err;	}	run = CPU_STOPPED;	EM8XXXVOIPSP(pE,EMHWLIB_MODULE(AudioEngine,1),RMAudioEnginePropertyID_State,&run,sizeof(run));	if (RMFAILED(err)) {		RMDBGLOG((ENABLE,"Error while stopping Audio RISC\n"));		return err;	}	size_in.MicrocodeVersion = 2;	EM8XXXVOIPEXP(pE,EMHWLIB_MODULE(AudioEngine,1),RMAudioEnginePropertyID_MicrocodeDRAMSize, &size_in, sizeof(size_in), &size_out, sizeof(size_out));	if (RMFAILED(err)) {		RMDBGLOG((ENABLE,"Error while getting memory needed for audio microcode!\n"));		return err;	}	if (size_out.Size == 0) {		RMDBGLOG((LOCALDBG,"Voip microcode does not need DRAM\n"));		ucode.Address = 0;	}	else {		in.dramtype=RUA_DRAM_CACHED;		in.Size=size_out.Size;		EM8XXXVOIPEXP(pE,EMHWLIB_MODULE(MM,0),RMMMPropertyID_Malloc,&in,sizeof(in),&out,sizeof(out));		if (err == RM_OK){			ucode.Address = (RMuint32) out.Address;			RMDBGLOG((LOCALDBG,"Voip ucode cached addr : 0x%08lx, size 0x%08lx, end: 0x%08lx\n",ucode.Address,size_out.Size,ucode.Address+size_out.Size));			pV->VoipUCodeAddr = ucode.Address;

⌨️ 快捷键说明

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