zte's code,first commit

Change-Id: I9a04da59e459a9bc0d67f101f700d9d7dc8d681b
diff --git a/ap/os/linux/linux-3.4.x/drivers/slic/usr_line.c b/ap/os/linux/linux-3.4.x/drivers/slic/usr_line.c
new file mode 100755
index 0000000..b45eb5c
--- /dev/null
+++ b/ap/os/linux/linux-3.4.x/drivers/slic/usr_line.c
@@ -0,0 +1,2189 @@
+/*******************************************************************************
+*  SUBSYSTEM£º  User Line Driver
+*  MOUDLE:      USL
+*  FILE NAME:   usr_line.c
+*  PURPOSE:     To scan and control the user line(slic/daa).
+*  Author:      jiang.yuelong
+*  Version£º    1.0
+*  Date£º       24/12/2004
+*------------------------------------------------------------------------------
+*  DEVELOPMENT HISTORY
+*  Date          Version        Modifier    Description of Mpdify
+*  mm/dd/yyyy      x.x               X XX         xxxxxxxxxxxxx
+*******************************************************************************/
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/wait.h>
+#include <linux/init.h>
+#include <linux/list.h>
+#include <linux/slab.h>
+#include <linux/signal.h>
+//#include <linux/smp_lock.h>
+#include <linux/fs.h>      
+#include <asm/uaccess.h>
+#include <linux/delay.h>
+#include <linux/version.h>
+#include <linux/interrupt.h>
+#include <linux/gpio.h>
+#include <mach/gpio.h>
+#include <linux/irqreturn.h>
+#include <mach/pcu.h>
+#include <linux/irq.h>
+#include <linux/platform_device.h>
+#include <linux/device.h>
+#include <linux/wakelock.h>
+#include <linux/soc/zte/pm/drv_idle.h>
+
+#include "usr_line.h"
+#include "si3217x_constants.h"
+//#include <linux/soc/zte/rpm/rpmsg.h>
+#include <mach/gpio_cfg.h>
+
+#include "i2s.h"
+
+/* ---- Public Variables ------------------------------------------------- */
+USL_PORT *pstUslPort = NULL;                            /* global USL_PORT pointer */
+u8 si_usl_debuglvl = 3;                                 /* control whether to print message to serial port, init to enable printk */
+int dtmf_mute = 0;
+int slic_pcm_open = 0;
+struct spi_device *pslicSpi;
+static struct class *slic_dev_class;
+static	struct device *slic_device;
+static int fskbuf_avail_flag = 0;
+/* ---- Private Variables ------------------------------------------------ */
+static u8 *pIoctlData = NULL;                           /* global pointer for ioctl parameters */
+
+static USL_MSG                   *msg_queue; 
+static DECLARE_WAIT_QUEUE_HEAD(msg_wait_queue);         /* for message report */
+
+static u8           timer_run = 1;
+static u8           scan_over = 0;
+static u8           self_test = 0;
+u8  slic_offhook = 0;
+
+u8   init_flg = 0;
+slic_state current_state = NONE;
+int irq_num = 0;
+
+#define MAX_INT_STRINGS 38
+#define FSK_DEPTH_TRIG  4
+#define SLIC_INT_GPIO ZX29_GPIO_53
+#define FNC_SLIC_INT_GPIO GPIO53_EXT_INT6
+#define SLIC_RST_GPIO ZX29_GPIO_122
+#define FNC_SLIC_RST_GPIO GPIO122_GPIO122
+static struct wake_lock slic_wakelock;
+
+static char *intMapStrings[] =
+{
+  "IRQ_OSC1_T1",
+  "IRQ_OSC1_T2",
+  "IRQ_OSC2_T1",
+  "IRQ_OSC2_T2",
+  "IRQ_RING_T1",
+  "IRQ_RING_T2",
+  "IRQ_PM_T1",
+  "IRQ_PM_T2",
+  "IRQ_FSKBUF_AVAIL", /**< FSK FIFO depth reached */
+  "IRQ_VBAT",
+  "IRQ_RING_TRIP", /**< Ring Trip detected */
+  "IRQ_LOOP_STATUS",  /**< Loop Current changed */
+  "IRQ_LONG_STAT",
+  "IRQ_VOC_TRACK",
+  "IRQ_DTMF",         /**< DTMF Detected - call @ref ProSLIC_DTMFReadDigit to decode the value */
+  "IRQ_INDIRECT",     /**< Indirect/RAM access completed */
+  "IRQ_TXMDM",
+  "IRQ_RXMDM",
+  "IRQ_PQ1",          /**< Power alarm 1 */
+  "IRQ_PQ2",          /**< Power alarm 2 */
+  "IRQ_PQ3",          /**< Power alarm 3 */
+  "IRQ_PQ4",          /**< Power alarm 4 */
+  "IRQ_PQ5",          /**< Power alarm 5 */
+  "IRQ_PQ6",          /**< Power alarm 6 */
+  "IRQ_RING_FAIL",
+  "IRQ_CM_BAL",
+  "IRQ_USER_0",
+  "IRQ_USER_1",
+  "IRQ_USER_2",
+  "IRQ_USER_3",
+  "IRQ_USER_4",
+  "IRQ_USER_5",
+  "IRQ_USER_6",
+  "IRQ_USER_7",
+  "IRQ_DSP",
+  "IRQ_MADC_FS",
+  "IRQ_P_HVIC",
+  "IRQ_P_THERM", /**< Thermal alarm */
+  "IRQ_P_OFFLD"
+};
+
+
+/*--------extern variables---------------------------------------------*/
+
+
+/* ---- Public functions ------------------------------------------------- */
+
+
+/* ---- Private functions ------------------------------------------------ */
+static s8 SlicMallocMemory(void);    /*  */
+static void SlicFreeMemory(void);    /*  */
+static void zx29_i2s_tdm_pin_cfg(void);
+
+//volatile static T_ZDrvRpMsg_Msg icp_pMsg;
+volatile static int rpMsgBuf[8] = {1,2};
+
+
+/*--------extern functions---------------------------------------------*/
+
+
+
+
+
+/*---------------------func define--------------------------------*/
+
+/*
+*****************************************************************************
+** FUNCTION:   SlicMallocMemory
+**
+** PURPOSE:    request memory for global variables pstUslPort and pIoctlData,
+**             used in si_usrline_init only
+**
+** PARAMETERS: none
+**
+** RETURNS:    0 on success, else -1
+**
+*****************************************************************************
+*/
+static s8 SlicMallocMemory(void)
+{
+    /* USL_PORT used */
+    pstUslPort = (USL_PORT *)kmalloc(sizeof(USL_PORT)*MAX_PORT_NUM, GFP_KERNEL);
+    
+    if (NULL != pstUslPort)
+    {
+        memset(pstUslPort, 0, sizeof(USL_PORT)*MAX_PORT_NUM);
+    }
+    else
+    {
+        return -1;
+    }
+    
+    /* ioctl used */
+    pIoctlData = (u8 *)kmalloc(512, GFP_KERNEL);
+    
+    if (NULL != pIoctlData)
+    {
+        memset(pIoctlData, 0, 512);
+    }
+    else
+    {
+        kfree(pstUslPort);
+        return -1;
+    }
+
+    return 0;
+}
+
+/*
+*****************************************************************************
+** FUNCTION:   SlicFreeMemory
+**
+** PURPOSE:    free memory requested by SlicMallocMemory
+**
+** PARAMETERS: none
+**
+** RETURNS:    none
+**
+*****************************************************************************
+*/
+static void SlicFreeMemory(void)
+{
+    if (NULL != pstUslPort)
+    {
+        kfree(pstUslPort);
+    }
+    pstUslPort = NULL;
+    
+    if (NULL != pIoctlData)
+    {
+        kfree(pIoctlData);
+    }
+    pIoctlData = NULL;
+    
+    if (NULL != msg_queue )
+    {
+        kfree(msg_queue);  
+    }
+    msg_queue = NULL ;
+
+    return;
+}
+
+void CreatMsgQueue(void)
+{
+    msg_queue = kzalloc(sizeof(USL_MSG),GFP_KERNEL);
+}
+
+bool QueueEmpty(void)
+{
+    return msg_queue->tail == msg_queue->head;
+}
+
+bool QueueFull(void)
+{
+    return (msg_queue->tail + 1)%MSGMAX == msg_queue->head;
+}
+
+s8 usrline_report(const u16 port, const u8 event, const u32 payload,u16 mask)
+{
+    USLPUT1("->%s: port %d, ev %d, pay %d, mask %x.\n", __FUNCTION__, port, event, payload, mask );
+    if( GET_EV_MASK(event) & mask ) {
+        USLPUT1("ev %x, ~mask%x\n", GET_EV_MASK(event), mask );
+        return 0;
+    }
+    if (QueueFull())
+    {
+		USLPUT0(" usrline_report msgqueue full!!( event=%d,port=%d,payload=%d). \n", event, port, payload);
+		return -1;
+    }
+    /* add to queue tail */
+    //msg_queue->data[msg_queue->tail].port = port;
+    msg_queue->data[msg_queue->tail].msgid = event;
+    msg_queue->data[msg_queue->tail].payload = payload;
+    msg_queue->tail = (msg_queue->tail + 1)%MSGMAX;
+     /* wake up messages wait queue*/
+    wake_up_interruptible(&msg_wait_queue);
+    USLPUT1("\nevent:%d port:%d payload:0x%x\n", event, port, payload);
+
+    return 0;
+}
+
+static s8 usrline_ioctl_msg_rev(USL_PORT *data, SLIC_IOCTL_DATA *pstCmd)
+{
+	printk("howard usrline_ioctl_msg_rev\n");
+    if (NULL == pstCmd)
+    {
+        USLPUT0("%s pstCmd NULL\n",__FUNCTION__);
+        return SLC_FAIL;
+    }
+    
+    if (QueueEmpty())        /* no message. sleep */
+    {
+      interruptible_sleep_on(&msg_wait_queue);      
+    }
+    
+    while (self_test)
+    {
+        sleep_on_timeout(&msg_wait_queue, 10);
+    }
+    
+    if (copy_to_user(pstCmd->data, &msg_queue->data[msg_queue->head], sizeof(MSG_DATA)) != 0)
+    {
+        USLPUT0("%s copy data to user fail!\n",__FUNCTION__);
+    }
+    msg_queue->head = (msg_queue->head + 1)%MSGMAX;
+    
+    return SLC_SUCCESS;
+}
+
+
+static s8 usrline_ioctl_msg_clear(USL_PORT *data, SLIC_IOCTL_DATA *pstCmd)
+{
+    if (NULL != msg_queue)
+    {
+        memset(msg_queue,0,sizeof(USL_MSG));
+    }
+    
+    return SLC_SUCCESS;
+}
+
+s8 usrline_port_register( const u16 port, const u8 type, 
+	         CODEC_OPS *ops, Port_t *pchip)
+{
+
+    USL_PORT *ptr;
+    
+    if (NULL == pstUslPort)
+    {
+        USLPUT0("usrline_port_register pstUslPort NULL!\n");
+        return -1;
+    }
+    
+    if (port >= MAX_PORT_NUM)
+    {
+        USLPUT0("usrline_port_register port %d illegal\n", port);
+        return -1;
+    }
+    
+    if ((NULL == ops) || (NULL == pchip))
+    {
+        USLPUT0("usrline_port_register input pointer NULL!\n");
+        return -1;
+    }
+    
+    ptr = (USL_PORT *)&pstUslPort[port];
+
+    if (NULL == ptr)
+    {
+        USLPUT0("usrline_port_register get port Para NULL!\n");
+        return -1;
+    }
+
+    ptr->port = port;
+    ptr->port_type = type;
+    ptr->codec_ops = ops;
+    
+    ptr->pLine = pchip;
+    ptr->event_mask = 0;
+    ptr->signal_flag = SIGNAL_PLAY_STOP;
+    ptr->signal_on = RING_SIGNAL_OFF;
+    
+    /*added for ring queue*/   
+    ptr->stRingQuenePara.dwRingStop        = 0;
+    ptr->stRingQuenePara.dwNeedSort        = 0;
+    ptr->stRingQuenePara.dwOffCountStart   = 0;
+    ptr->stRingQuenePara.dwOffCount        = 0;
+    ptr->stRingQuenePara.dwOffMaxCount     = 0;
+    ptr->stRingQuenePara.RingQueneDelay    = 10;
+    
+    ptr->dwIsRevPol = 0;
+    
+    ptr->dwInitOK = LINE_INITOK;
+    ptr->flag = LINE_ENABLE;
+    
+    return 0;
+}
+
+static void uslput_sig(const SIGNAL_DATA *sig)
+{
+	USLPUT3("signal_type:%d cid:%s tone_type:%d\n",
+		     sig->signal_type,sig->cid,sig->tone_type);    
+}
+
+/* ================================================================== */
+static s8 usrline_ioctl_Inf_precfg(USL_PORT *data, SLIC_IOCTL_DATA *pstCmd)
+{
+    if (NULL == pstCmd)
+    {
+        USLPUT0("%s pstCmd NULL\n",__FUNCTION__);
+        return -1;
+    }
+    
+    if (copy_from_user(pIoctlData, pstCmd->data, pstCmd->data_size) != 0)
+    {
+        USLPUT0("%s copy data from user fail!\n",__FUNCTION__);
+        return -1;
+    }
+    
+    slic_inf_precfg((SLCINF_CFG *)pIoctlData);
+
+    return 0;
+}
+
+static unsigned char checkBufSum(char *str, int nLen)
+{
+    int i=0;
+    uInt8 sum = 0;
+	for(i=0; i<nLen; i++)
+    {
+        sum += str[i];
+		LOGPRINT ("\nsum=%02X", sum);
+    }
+
+    return -sum;
+}
+
+static int WaitOnFSKBuffer (proslicChanType *pProslic){ 
+	uInt8 avail;
+	uInt32 i=0;
+	uInt8 hook_status = 0;
+	ProSLIC_ReadHookStatus(pProslic,&hook_status);
+	if(hook_status == PROSLIC_OFFHOOK)
+    {
+      ProSLIC_DisableCID(pProslic);
+      return -1;
+	}
+	do {
+		if (fskbuf_avail_flag == 1)
+			break;
+		ProSLIC_CheckCIDBuffer(pProslic,&avail);
+		i++;
+	}
+	while ((avail == 0)&& (i<20000));
+	fskbuf_avail_flag = 0; 
+	if(i>=20000)
+	{
+		printk("\nWaitOnFSKBuffer Time = %d", i);
+	}
+	//return 0;
+}
+
+static int DoOnHookCallerIDEx (proslicChanType *pProslic, int8 *BufTel, int8 *BufTxt)
+{ //SI324X/26 example code--------
+	char sTime[] = "01020304";
+	unsigned char preamble[] ={'U','U','U','U','U','U','U','U'};
+	int i;uInt8 data;
+	int j;
+    unsigned char TxBuf[256];
+    unsigned char *pTxBuf=TxBuf;
+	int nTxLen;
+	int nNumLen = strlen(BufTel);
+	int nTxtLen = strlen(BufTxt);
+	uInt8 hook_status = 0;
+	// Êý¾Ý×é°ü
+	*pTxBuf++ = 0x80;		   //msg type: ¸´ºÏÊý¾Ý¸ñʽ
+	 if(1)
+	 {
+		if(nNumLen==0)
+       	{
+			*pTxBuf++ = (2+8)+(2+nTxtLen); //msg length  
+		}
+		else if(nTxtLen==0)
+       	{
+			*pTxBuf++ = (2+8)+(2+nNumLen); //msg length  
+		}
+		else
+       	{
+			*pTxBuf++ = (2+8)+(2+nNumLen)+(2+nTxtLen); //msg length  
+		}
+       	*pTxBuf++  = 0x01;//²ÎÊýÀàÐÍ £ºÈÕÆÚʱ¼ä
+    	*pTxBuf++  = 0x08;//ʱ¼ä³¤¶È
+       	for(i=0; i<8; i++)
+       	{
+          	*pTxBuf++  = sTime[i];
+       	}
+    }
+    else
+    {
+       //MSG_FATAL("-zja--Don't SENDING current_time",0,0,0);
+       *pTxBuf++ = (2+nNumLen)+(2+nTxtLen); //msg length  
+    }
+	if(nNumLen!=0)
+	{
+		*pTxBuf++ =0x02;		  //²ÎÊýÀàÐÍ £ºµç»°ºÅÂë
+		*pTxBuf++ =nNumLen;   //²ÎÊý³¤¶È
+		memcpy(pTxBuf, BufTel, nNumLen);	 
+		pTxBuf += nNumLen;
+	}
+	if(nTxtLen!=0)
+	{
+		*pTxBuf++=0x07; 		 //²ÎÊýÀàÐÍ £ºÖ÷½ÐÐÅÏ¢
+		*pTxBuf++=nTxtLen;			//²ÎÊýÀàÐÍ £ºµç»°ºÅÂë
+		memcpy(pTxBuf, BufTxt, nTxtLen);	
+		pTxBuf += nTxtLen;
+	}
+	*pTxBuf++=(checkBufSum(TxBuf, pTxBuf-TxBuf));
+	nTxLen = pTxBuf-TxBuf;
+	printk("\n Len=%d", nTxLen);
+	for(i=0; i<nTxLen; i++)
+	{
+		if((i&0x0F)==0)
+			printk("\n");
+		printk("0x%02X ", TxBuf[i]);
+	}
+	printk("\n");
+	/* The setting for FSKDEPTH will depend on your system contraints*/ 
+	//fire interrupt when FSK_DEPTH_TRIG bytes of space, set FSKDEPTH to 8-FSK_DEPTH_TRIG
+
+	ProSLIC_ReadHookStatus(pProslic,&hook_status);
+	if(hook_status == PROSLIC_OFFHOOK)
+    {
+      return -1;
+	}
+
+	ProSLIC_FSKSetup (pProslic, 1);
+
+	if (pProslic->debugMode)
+		LOGPRINT ("\nSending CID to channel %d\n",pProslic->channel);
+	(pProslic->deviceId->ctrlInterface)->Delay_fptr((pProslic->deviceId->ctrlInterface)->hTimer,50);
+//	(pProslic->deviceId->ctrlInterface)->Delay_fptr((pProslic->deviceId->ctrlInterface)->hTimer,130); //130ms of mark bits
+	
+	ProSLIC_EnableCID(pProslic);
+
+		
+	for (i=0;i<30;i+=FSK_DEPTH_TRIG)
+	{
+		/*if (WaitOnFSKBuffer (pProslic))
+		{
+			//printk("howard offhook during ONHOOK FSK CID\n");
+			return -1;
+		}*/
+		if(i>=4)
+		{
+			WaitOnFSKBuffer (pProslic);
+		}
+		ProSLIC_SendCID(pProslic,preamble,FSK_DEPTH_TRIG);
+	}
+
+	if (30%FSK_DEPTH_TRIG)
+	{
+		/*if (WaitOnFSKBuffer (pProslic))
+		{
+			//printk("howard offhook during ONHOOK FSK CID\n");
+			return -1;
+		}*/
+		WaitOnFSKBuffer (pProslic);
+	}
+	
+	ProSLIC_SendCID(pProslic,preamble,30%FSK_DEPTH_TRIG);
+	WaitOnFSKBuffer (pProslic);
+	/*if (WaitOnFSKBuffer (pProslic))
+	{
+		//printk("howard offhook during ONHOOK FSK CID\n");
+		return -1;
+	}*/
+	(pProslic->deviceId->ctrlInterface)->Delay_fptr((pProslic->deviceId->ctrlInterface)->hTimer,140); //wait for 1 byte then 130ms +/- 25ms mark bits
+
+	for (i=0;i<nTxLen; i+=FSK_DEPTH_TRIG){
+		/*if (WaitOnFSKBuffer (pProslic))
+		{
+			//printk("howard offhook during ONHOOK FSK CID\n");
+			return -1;
+		}*/
+		ProSLIC_SendCID (pProslic,&(TxBuf[i]),FSK_DEPTH_TRIG);
+		WaitOnFSKBuffer (pProslic);
+
+	}
+	if (nTxLen%FSK_DEPTH_TRIG)
+	{
+		/*if (WaitOnFSKBuffer (pProslic))
+		{
+			//printk("howard offhook during ONHOOK FSK CID\n");
+			return -1;
+		}*/		
+		ProSLIC_SendCID (pProslic,&(TxBuf[(nTxLen/FSK_DEPTH_TRIG)*FSK_DEPTH_TRIG]),nTxLen%FSK_DEPTH_TRIG);
+		WaitOnFSKBuffer (pProslic);
+	}
+
+	
+	(pProslic->deviceId->ctrlInterface)->Delay_fptr((pProslic->deviceId->ctrlInterface)->hTimer,10*(FSK_DEPTH_TRIG));
+	(pProslic->deviceId->ctrlInterface)->Delay_fptr((pProslic->deviceId->ctrlInterface)->hTimer,50); //130ms of mark bits
+	
+	ProSLIC_DisableCID(pProslic);
+}
+
+void ring_sendcid(proslicChanType_ptr hProslic, int8 *cid)
+{
+    /* Ensure OFFHOOK Active */
+    ProSLIC_SetLinefeedStatus(hProslic,LF_FWD_ACTIVE);
+    msleep(500);
+    /* 1st Ring Burst */
+    ProSLIC_SetLinefeedStatus(hProslic,LF_RINGING); 
+    msleep(2500);/* Delay 250 to 3600ms */    
+
+	printk("ring_sendcid %s\n", cid);
+    DoOnHookCallerIDEx(hProslic, cid, "");
+	//DoOnHookCallerIDEx(hProslic, "15029909468", "");
+}
+
+static s8 usrline_ioctl_signal_start(USL_PORT *data, SLIC_IOCTL_DATA *pstCmd)
+{
+    s8 i = 0;
+    USL_PORT *pPort = NULL;
+    SIGNAL_DATA *sig = NULL;
+	int use_cid=1;
+	int cid_len = 0;
+    //CANDENCE_ATTR *cadc = NULL;
+    printk("howard usrline_ioctl_signal_start\n");
+    if ((NULL == data) || (NULL == pstCmd))
+    {
+        USLPUT0("%s data or pstCmd NULL\n",__FUNCTION__);
+        return -1;
+    }
+    
+    USLPUT2("%s: port %d \n",__FUNCTION__, data->port );
+    pPort = (USL_PORT *)&pstUslPort[(data->port+1)%2];
+    sig = (SIGNAL_DATA *) &(data->sig_data);
+    //cadc = sig->cadence;
+    if (copy_from_user(sig, pstCmd->data, pstCmd->data_size) != 0)
+    {
+        USLPUT0("%s copy data from user fail!\n",__FUNCTION__);
+        return -1;
+    }
+    uslput_sig(sig);
+    /* init signal data */     
+    /*added for ring queue*/
+    //data->stRingQuenePara.dwOffMaxCount = cadc->cadence_off - cadc->cadence_on - data->stRingQuenePara.RingQueneDelay;
+       
+    if (USL_RING_SIGNAL == sig->signal_type)
+    {
+    	printk("ring singnal\n");
+        data->stRingQuenePara.dwRingStop = 0;
+        if((NULL == pPort)  /* no other port */
+             || (USL_TONE_SIGNAL == pPort->sig_data.signal_type)  /* other port is playing tone */
+             || ((USL_RING_SIGNAL == pPort->sig_data.signal_type) && (SIGNAL_PLAY_STOP == pPort->signal_flag)))  /* other port is ringing in off state */
+             //|| (cadc->cadence_off < cadc->cadence_on + data->stRingQuenePara.RingQueneDelay*2))  /* not match quene rule */
+        {
+            data->codec_ops->codec_signal_ctrl(data->pLine, sig, RING_SIGNAL_INIT);
+            data->signal_flag = SIGNAL_PLAY_START;
+
+        }
+        else  /* need quene to ring */
+        {
+            //USLPUT2("stRingQuenePara.dwOffMaxCount = %d\n", data->stRingQuenePara.dwOffMaxCount);
+            data->stRingQuenePara.dwNeedSort = 1;
+        }
+		printk("howard ring and send cid in ioctl\n");
+        //sendCIDStream(data->pLine->ProObj);
+        
+		cid_len = strlen(sig->cid);
+		printk("cid_len %d\n", cid_len);
+        for (i=0; i < cid_len; i++)
+        {
+            if((sig->cid[i]<0x30) || (sig->cid[i]>0x39)) 
+            {
+                use_cid = 0;
+                break;
+            }
+        }
+        if((use_cid == 1) && (cid_len > 0))
+            ring_sendcid(data->pLine->ProObj, sig->cid);
+        else
+            ProSLIC_RingStart(data->pLine->ProObj);
+
+        current_state = RINGING;
+    } else {
+        printk("tone singnal\n");
+        data->codec_ops->codec_signal_ctrl(data->pLine, sig, TONE_SIGNAL_INIT);
+        data->signal_flag = SIGNAL_PLAY_START;
+        data->stRingQuenePara.dwRingStop = 0;
+    }
+    /*ring queue add*/        
+    
+    
+    return 0;
+    }
+             
+/*added for ring queue*/
+static s8 usrline_signal_start(USL_PORT *data)
+{
+    SIGNAL_DATA *sig = NULL;
+     
+    if (NULL == data)
+    {
+        USLPUT0("%s data NULL\n",__FUNCTION__);
+        return -1;
+    }
+             
+    sig = (SIGNAL_DATA *) &(data->sig_data);
+    USLPUT2("%s: port %d \n",__FUNCTION__, data->port );
+    data->codec_ops->codec_signal_ctrl(data->pLine, sig, RING_SIGNAL_INIT);
+    data->signal_flag = SIGNAL_PLAY_START;
+    data->stRingQuenePara.dwNeedSort       = 0;
+    data->stRingQuenePara.dwOffCount       = 0;
+    data->stRingQuenePara.dwOffCountStart  = 0;
+    
+    return 0;
+}
+/*ring queue add*/
+
+/*added for ring queue*/
+static s8 usrline_ioctl_signal_stop(USL_PORT *data, SLIC_IOCTL_DATA *pstCmd)
+{
+	printk("howard usrline_ioctl_signal_stop\n");
+
+    if (NULL == data)
+    {
+        USLPUT0("%s data NULL\n",__FUNCTION__);
+        return -1;
+    }
+    USLPUT2("%s: port %d, signal type %d\n",__FUNCTION__, data->port, data->sig_data.signal_type);
+    
+    if ((data->signal_flag == SIGNAL_PLAY_START)||(1==data->stRingQuenePara.dwNeedSort)) /* stop signal */
+    {
+        data->stRingQuenePara.dwNeedSort = 0;
+        data->stRingQuenePara.dwRingStop = 1;
+    }
+    
+    return 0;
+}
+
+/*added for ring queue*/
+static s8 usrline_signal_stop(USL_PORT *data)
+{
+    u8 cmd = 0;    
+    SIGNAL_DATA *sig = NULL;
+    
+    if (NULL == data)
+    {
+        USLPUT0("%s data NULL\n",__FUNCTION__);
+        return -1;
+    }
+
+    sig = (SIGNAL_DATA *) &(data->sig_data);
+
+    data->signal_flag = SIGNAL_PLAY_STOP;
+
+    if (sig->signal_type == USL_RING_SIGNAL)
+    {
+        USLPUT0("ring singal stop\n");
+        data->signal_on = RING_SIGNAL_OFF;
+        cmd = RING_SIGNAL_CLEAN_OFF;
+    } else {
+        USLPUT0("tone singal stop\n");
+        cmd = TONE_SIGNAL_CLEAN;
+    }
+    
+    data->codec_ops->codec_signal_ctrl(data->pLine, sig, cmd);
+    data->stRingQuenePara.dwRingStop       = 0;
+    data->stRingQuenePara.dwNeedSort       = 0;
+    data->stRingQuenePara.dwOffCountStart  = 0;
+    data->stRingQuenePara.dwOffCount       = 0;
+    
+    return 0;
+}
+
+static s8 usrline_signal_play(USL_PORT *pdata)
+{
+    SIGNAL_DATA *data = (SIGNAL_DATA *) &(pdata->sig_data);
+    u16 port   = pdata->port;
+    u16 signal_type = data->signal_type;
+    u32 delay;
+    u8 signal_clean, signal_on, signal_off;
+
+    //data->tick_count++;
+    if (signal_type == USL_RING_SIGNAL)
+    {
+        if (RINGING != current_state)
+        {
+            signal_on    = RING_SIGNAL_ON;
+            signal_off   = RING_SIGNAL_OFF;
+            signal_clean = RING_SIGNAL_CLEAN_ON;
+            pdata->codec_ops->codec_signal_ctrl(pdata->pLine, data, signal_on);
+            pdata->signal_on = signal_on;
+        }
+    } else {
+        if (PLAYING_TONE != current_state)
+        {
+            signal_on    = TONE_SIGNAL_ON;
+            signal_off   = TONE_SIGNAL_OFF;
+            signal_clean = TONE_SIGNAL_CLEAN;
+            pdata->codec_ops->codec_signal_ctrl(pdata->pLine, data, signal_on);
+            pdata->signal_on = signal_on;
+        }
+    }
+    return 0;
+}
+static s8 usrline_ioctl_pcm_open(USL_PORT *data, SLIC_IOCTL_DATA *pstCmd)
+{
+    proslicChanType_ptr hProslic;
+    hProslic = data->pLine->ProObj;
+    printk("howard usrline_ioctl_pcm_open\n");
+    ProSLIC_PCMStart(hProslic);
+    slic_pcm_open = 1;
+    return 0;
+}
+static s8 usrline_ioctl_pcm_close(USL_PORT *data, SLIC_IOCTL_DATA *pstCmd)
+{
+    proslicChanType_ptr hProslic;
+    hProslic = data->pLine->ProObj;
+    printk("howard usrline_ioctl_pcm_close\n");
+    ProSLIC_PCMStop(hProslic);
+    slic_pcm_open = 0;
+    return 0;
+}
+
+static s8 usrline_ioctl_pcm_set_nb(USL_PORT *data, SLIC_IOCTL_DATA *pstCmd)
+{
+    proslicChanType_ptr hProslic;
+    hProslic = data->pLine->ProObj;
+    printk("howard usrline_ioctl_pcm_set nb\n");
+	ProSLIC_PCMSetup(hProslic, PCM_16LIN);
+    return 0;
+}
+
+
+static s8 usrline_ioctl_pcm_set_wb(USL_PORT *data, SLIC_IOCTL_DATA *pstCmd)
+{
+    proslicChanType_ptr hProslic;
+    hProslic = data->pLine->ProObj;
+    printk("howard usrline_ioctl_pcm_set wb\n");
+	ProSLIC_PCMSetup(hProslic, PCM_16LIN_WB);
+    return 0;
+}
+
+
+
+
+static s8 usrline_ioctl_timeslot_set(USL_PORT *data, SLIC_IOCTL_DATA *pstCmd)
+{
+    if ((NULL == data) || (NULL == pstCmd))
+    {
+        USLPUT0("%s data or pstCmd NULL\n",__FUNCTION__);
+        return -1;
+    }
+    
+    //data->codec_ops->codec_timeslot_set(data->pLine, pstCmd->unPara.stTimeSlot.bTx, pstCmd->unPara.stTimeSlot.bRx);
+    return 0;
+}
+
+static s8 usrline_ioctl_timeslot_release(USL_PORT *data, SLIC_IOCTL_DATA *pstCmd)
+{
+    if (NULL == data)
+    {
+        USLPUT0("%s data NULL\n",__FUNCTION__);
+        return -1;
+    }
+    
+    USLPUT2("%s: port %d \n",__FUNCTION__, data->port );
+    data->codec_ops->codec_timeslot_release( data->pLine );
+    
+    return 0;
+}
+
+static s8 usrline_ioctl_codec_config(USL_PORT *data, SLIC_IOCTL_DATA *pstCmd)
+{
+    if ((NULL == data) || (NULL == pstCmd))
+    {
+        USLPUT0("%s data or pstCmd NULL\n",__FUNCTION__);
+        return -1;
+    }
+    
+    if (copy_from_user(pIoctlData, pstCmd->data, pstCmd->data_size) != 0)
+    {
+        USLPUT0("%s copy data from user fail!\n",__FUNCTION__);
+        return -1;
+    }
+    
+    data->codec_ops->codec_parm_cfg(data->pLine , pIoctlData, pstCmd->data_size);
+    
+    return 0;
+}
+
+static s8 usrline_ioctl_codec_read(USL_PORT *data, SLIC_IOCTL_DATA *pstCmd)
+{
+    if ((NULL == data) || (NULL == pstCmd))
+    {
+        USLPUT0("%s data or pstCmd NULL\n",__FUNCTION__);
+        return -1;
+    }
+    
+    if (copy_from_user(pIoctlData, pstCmd->data, pstCmd->data_size) != 0)
+    {
+        USLPUT0("%s copy data from user fail!\n",__FUNCTION__);
+        return -1;
+    }
+    
+    data->codec_ops->codec_parm_get(data->pLine, pIoctlData, pstCmd->data_size);
+    return 0;
+}
+
+static s8 usrline_ioctl_ram_config(USL_PORT *data, SLIC_IOCTL_DATA *pstCmd)
+{
+    if ((NULL == data) || (NULL == pstCmd))
+    {
+        USLPUT0("%s data or pstCmd NULL\n",__FUNCTION__);
+        return -1;
+    }
+    
+    if (copy_from_user(pIoctlData, pstCmd->data, pstCmd->data_size) != 0)
+    {
+        USLPUT0("%s copy data from user fail!\n",__FUNCTION__);
+        return -1;
+    }
+    
+    data->codec_ops->codec_ram_cfg(data->pLine, pIoctlData, pstCmd->data_size);
+    
+    return 0;
+}
+
+static s8 usrline_ioctl_mute(USL_PORT *data, SLIC_IOCTL_DATA *pstCmd)
+{
+	proslicChanType_ptr hProslic;
+	hProslic = data->pLine->ProObj;
+	if ((NULL == data) || (NULL == pstCmd))
+    {
+        USLPUT0("%s data or pstCmd NULL\n",__FUNCTION__);
+        return -1;
+    }
+    
+    if (copy_from_user(pIoctlData, pstCmd->data, pstCmd->data_size) != 0)
+    {
+        USLPUT0("%s copy data from user fail!\n",__FUNCTION__);
+        return -1;
+    }
+	printk("howard slic usrline_ioctl_mute %s\n", pIoctlData);
+	if(*pIoctlData == 't')
+	{
+		ProSLIC_SetMuteStatus(hProslic,PROSLIC_MUTE_TX);
+		printk("howard slic mute tx\n");
+	}
+	else if(*pIoctlData == 'r')
+	{
+		ProSLIC_SetMuteStatus(hProslic,PROSLIC_MUTE_RX);
+		printk("howard slic mute rx\n");
+	}
+	else if(*pIoctlData == 'n') 
+	{
+		ProSLIC_SetMuteStatus(hProslic,PROSLIC_MUTE_NONE);
+		printk("howard slic mute none\n");
+	}
+  
+    return 0;
+}
+
+static s8 usrline_ioctl_ram_read(USL_PORT *data, SLIC_IOCTL_DATA *pstCmd)
+{
+    u16 addr = 0;
+
+    if ((NULL == data) || (NULL == pstCmd))
+    {
+        USLPUT0("%s data or pstCmd NULL\n",__FUNCTION__);
+        return -1;
+    }
+    
+    if (copy_from_user(pIoctlData, pstCmd->data, pstCmd->data_size) != 0)
+    {
+        USLPUT0("%s copy data from user fail!\n",__FUNCTION__);
+        return -1;
+    }
+    addr = *(u16 *)pIoctlData;
+    printk("SLIC usrline_ioctl_ram_read addr %d,size %d\n", addr, pstCmd->data_size);
+    data->codec_ops->codec_ram_get(data->pLine, pIoctlData, pstCmd->data_size);
+    
+    return 0;
+}
+extern void ctrl_ReadRegister(uInt8 cs, uInt8 channel, uInt8 regAddr, uInt8 *prdata);
+extern void ctrl_WriteRegister(uInt8 cs, uInt8 channel,  uInt8 regAddr, uInt8 wdata);
+
+static s8 usrline_ioctl_dev_init(USL_PORT *data, SLIC_IOCTL_DATA *pstCmd)    
+{
+    int ret = 0;
+	printk("howard usrline_ioctl_dev_init\n");
+
+    if (0 == init_flg)
+    {
+        ret = InitSlicChip();
+		if (0 == ret)
+		{
+            init_flg = 1;
+			printk("SLIC init complete\n");
+		}
+		else
+		{
+            init_flg = 0;
+			printk("SLIC init NOT complete\n");
+		}
+        /* disable printk after init */
+        si_usl_debuglvl = 0;
+    }
+
+    return SLC_SUCCESS;
+}
+
+static s8 usrline_ioctl_port_reset(USL_PORT *data, SLIC_IOCTL_DATA *pstCmd)
+{
+    if (NULL == data)
+    {
+        USLPUT0("%s data NULL\n",__FUNCTION__);
+        return -1;
+    }
+    
+    USLPUT2("%s: port %d \n",__FUNCTION__, data->port );
+       
+    usrline_ioctl_timeslot_release(data, pstCmd);
+     
+    if ((data->signal_flag == SIGNAL_PLAY_START)||(1==data->stRingQuenePara.dwNeedSort)) /* stop signal */
+    {
+        //usrline_signal_stop(data);
+        data->stRingQuenePara.dwNeedSort = 0;
+        data->stRingQuenePara.dwRingStop = 1;
+    }
+    data->dwIsRevPol = 0;
+    data->flag = LINE_DISABLE;
+    data->codec_ops->codec_reset(data->pLine, data->port);
+    data->flag = LINE_ENABLE;
+    return SLC_SUCCESS;
+}
+
+/*added for slc time cfg*/ 
+static s8 usrline_ioctl_time_cfg(USL_PORT *data, SLIC_IOCTL_DATA *pstCmd)
+{
+    if ((NULL == data) || (NULL == pstCmd))
+    {
+        USLPUT0("%s data or pstCmd NULL\n",__FUNCTION__);
+        return -1;
+    }
+    
+    if (copy_from_user(pIoctlData, pstCmd->data, pstCmd->data_size) != 0)
+    {
+        USLPUT0("%s copy data from user fail!\n",__FUNCTION__);
+        return -1;
+    }
+    
+    /* first save the ring quene time */
+    data->stRingQuenePara.RingQueneDelay = ((USL_CONFIG *)pIoctlData)->RingQueneDelay;
+    
+    /* then save the chip related time parameters */
+    data->codec_ops->codec_time_cfg(data->pLine, (USL_CONFIG *)pIoctlData);
+                
+    return SLC_SUCCESS;
+}
+static s8 usrline_ioctl_slctool_hooklowlen_cfg(USL_PORT *data, SLIC_IOCTL_DATA *pstCmd)
+{
+    if ((NULL == data) || (NULL == pstCmd))
+    {
+        USLPUT0("%s data or pstCmd NULL\n",__FUNCTION__);
+        return -1;
+    }
+    
+    //data->codec_ops->codec_slctool_time_cfg(data->pLine, SLIC_CFG_HOOK_LOWLEN, pstCmd->unPara.wTime);
+    
+    return 0;
+}
+
+static s8 usrline_ioctl_slctool_hookhiglen_cfg(USL_PORT *data, SLIC_IOCTL_DATA *pstCmd)
+{
+    if ((NULL == data) || (NULL == pstCmd))
+    {
+        USLPUT0("%s data or pstCmd NULL\n",__FUNCTION__);
+        return -1;
+    }
+    
+    //data->codec_ops->codec_slctool_time_cfg(data->pLine, SLIC_CFG_HOOK_HIGLEN, pstCmd->unPara.wTime);
+    
+    return 0;
+}
+static s8 usrline_ioctl_slctool_prehookhiglen_cfg(USL_PORT *data, SLIC_IOCTL_DATA *pstCmd)
+{
+    if ((NULL == data) || (NULL == pstCmd))
+    {
+        USLPUT0("%s data or pstCmd NULL\n",__FUNCTION__);
+        return -1;
+    }
+    
+    //data->codec_ops->codec_slctool_time_cfg(data->pLine, SLIC_CFG_PREHOOK_HIGLEN, pstCmd->unPara.wTime);
+    
+    return 0;
+}
+static s8 usrline_ioctl_slctool_flashlowmin_cfg(USL_PORT *data, SLIC_IOCTL_DATA *pstCmd)
+{
+    if ((NULL == data) || (NULL == pstCmd))
+    {
+        USLPUT0("%s data or pstCmd NULL\n",__FUNCTION__);
+        return -1;
+    }
+    
+    //data->codec_ops->codec_slctool_time_cfg(data->pLine, SLIC_CFG_FLASH_LMIN, pstCmd->unPara.wTime);
+    
+    return 0;
+}
+static s8 usrline_ioctl_slctool_flashlowmax_cfg(USL_PORT *data, SLIC_IOCTL_DATA *pstCmd)
+{
+    if ((NULL == data) || (NULL == pstCmd))
+    {
+        USLPUT0("%s data or pstCmd NULL\n",__FUNCTION__);
+        return -1;
+    }
+    
+    //data->codec_ops->codec_slctool_time_cfg(data->pLine, SLIC_CFG_FLASH_LMAX, pstCmd->unPara.wTime);
+    
+    return 0;
+}
+
+static s8 usrline_ioctl_slctool_flashhfix_cfg(USL_PORT *data, SLIC_IOCTL_DATA *pstCmd)
+{
+    if ((NULL == data) || (NULL == pstCmd))
+    {
+        USLPUT0("%s data or pstCmd NULL\n",__FUNCTION__);
+        return -1;
+    }
+    
+    //data->codec_ops->codec_slctool_time_cfg(data->pLine, SLIC_CFG_FLASH_HFIX, pstCmd->unPara.wTime);
+    
+    return 0;
+}
+
+static s8 usrline_ioctl_slctool_dialhmin_cfg(USL_PORT *data, SLIC_IOCTL_DATA *pstCmd)
+{
+    if ((NULL == data) || (NULL == pstCmd))
+    {
+        USLPUT0("%s data or pstCmd NULL\n",__FUNCTION__);
+        return -1;
+    }
+    
+    //data->codec_ops->codec_slctool_time_cfg(data->pLine, SLIC_CFG_DIAL_HMIN, pstCmd->unPara.wTime);
+    
+    return 0;
+}
+
+static s8 usrline_ioctl_slctool_dialhmax_cfg(USL_PORT *data, SLIC_IOCTL_DATA *pstCmd)
+{
+    if ((NULL == data) || (NULL == pstCmd))
+    {
+        USLPUT0("%s data or pstCmd NULL\n",__FUNCTION__);
+        return -1;
+    }
+    
+    //data->codec_ops->codec_slctool_time_cfg(data->pLine, SLIC_CFG_DIAL_HMAX, pstCmd->unPara.wTime);
+    
+    return 0;
+}
+
+static s8 usrline_ioctl_slctool_diallmin_cfg(USL_PORT *data, SLIC_IOCTL_DATA *pstCmd)
+{
+    if ((NULL == data) || (NULL == pstCmd))
+    {
+        USLPUT0("%s data or pstCmd NULL\n",__FUNCTION__);
+        return -1;
+    }
+    
+    //data->codec_ops->codec_slctool_time_cfg(data->pLine, SLIC_CFG_DIAL_LMIN, pstCmd->unPara.wTime);
+    
+    return 0;
+}
+
+static s8 usrline_ioctl_slctool_diallmax_cfg(USL_PORT *data, SLIC_IOCTL_DATA *pstCmd)
+{
+    if ((NULL == data) || (NULL == pstCmd))
+    {
+        USLPUT0("%s data or pstCmd NULL\n",__FUNCTION__);
+        return -1;
+    }
+    
+    //data->codec_ops->codec_slctool_time_cfg(data->pLine, SLIC_CFG_DIAL_LMAX, pstCmd->unPara.wTime);
+    
+    return 0;
+}
+
+
+static s8 usrline_ioctl_dial_start(USL_PORT *data, SLIC_IOCTL_DATA *pstCmd)
+{
+    if (NULL == data)
+    {
+        USLPUT0("%s data NULL\n",__FUNCTION__);
+        return -1;
+    }
+
+    USLPUT3("%s port %d \n",__FUNCTION__,data->port);  
+    data->codec_ops->codec_dial_set(data->pLine, EV_DIAL_START);
+    
+    return SLC_SUCCESS;    
+}
+
+static s8 usrline_ioctl_dial_stop(USL_PORT *data, SLIC_IOCTL_DATA *pstCmd)
+{
+    if (NULL == data)
+    {
+        USLPUT0("%s data NULL\n",__FUNCTION__);
+        return -1;
+    }
+
+    USLPUT3("%s port %d \n",__FUNCTION__,data->port);  
+    data->codec_ops->codec_dial_set(data->pLine, EV_DIAL_STOP);
+    
+    return SLC_SUCCESS;    
+}
+
+#ifdef POWER_SUPPLY_05A
+/*used for dinggasp deal*/
+extern u8 (*slic_function)(void); 
+/*
+function: return ring state
+return  : zero: not ring; 
+          none zero: is ring
+*/
+u8 slic_is_ring_state(void)
+{
+    USL_PORT *data     = NULL;
+    u8 done_line         = 0;
+    int i                = 0;
+    for ( i = 0; i < MAX_PORT_NUM; i++ )
+    {
+        data = (USL_PORT *)&pstUslPort[i];
+            
+        if((NULL == data) || (LINE_DISABLE == data->flag))
+        { 
+            continue;
+        }
+
+        if (RING_SIGNAL_ON == data->signal_on)
+        {
+            data->stRingQuenePara.dwRingStop = 1;
+            done_line++;
+        }
+    }
+    
+    USLPUT3("done_line = %d.\n",done_line);
+    
+    return done_line;
+}
+#endif
+
+static s8 usrline_ioctl_port_lock(USL_PORT *data, SLIC_IOCTL_DATA *pstCmd)
+{
+    if (NULL == data)
+    {
+        USLPUT0("%s data NULL\n",__FUNCTION__);
+        return -1;
+    }
+
+    USLPUT2("%s: port %d \n",__FUNCTION__, data->port);
+    data->flag = LINE_DISABLE;
+    
+    return 0;
+}
+
+static s8 usrline_ioctl_port_unlock(USL_PORT *data, SLIC_IOCTL_DATA *pstCmd)
+{
+    if (NULL == data)
+    {
+        USLPUT0("%s data NULL\n",__FUNCTION__);
+        return -1;
+    }
+    
+    USLPUT2("%s: port %d \n",__FUNCTION__, data->port);
+    data->flag = LINE_ENABLE;
+    
+    return 0;
+}
+
+static s8 usrline_ioctl_polarity_reverse(USL_PORT *data, SLIC_IOCTL_DATA *pstCmd)
+{
+    if (NULL == data)
+    {
+        USLPUT0("%s data NULL\n",__FUNCTION__);
+        return -1;
+    }
+    
+    USLPUT2("%s: port %d \n",__FUNCTION__, data->port);
+    data->codec_ops->codec_polarity_reverse(data->pLine,data->port);
+    
+    data->dwIsRevPol ^= 1;
+
+    return 0;
+}
+
+static s8 usrline_ioctl_dtmf_start(USL_PORT *data, SLIC_IOCTL_DATA *pstCmd)
+{
+    if (NULL == data)
+    {
+        USLPUT0("%s data NULL\n",__FUNCTION__);
+        return -1;
+    }
+
+    data->codec_ops->codec_signal_ctrl(data->pLine, NULL, RING_SIGNAL_OFF_REVERSED); 
+
+    USLPUT2("%s : port %d  \n",__FUNCTION__, data->port);
+    
+    return 0;    
+}
+
+static s8 usrline_ioctl_fsk_start(USL_PORT *data, SLIC_IOCTL_DATA *pstCmd)
+{
+    if (NULL == data)
+    {
+        USLPUT0("%s data NULL\n",__FUNCTION__);
+        return -1;
+    }
+    
+    USLPUT2("%s : port %d ",__FUNCTION__, data->port);
+    if (0 == data->dwIsRevPol)
+    {
+        USLPUT2("set fsk OHT\n");
+        data->codec_ops->codec_signal_ctrl(data->pLine, NULL, RING_SIGNAL_OFF);
+    }
+    else
+    {
+        USLPUT2("set dtmf OHTREV\n");
+        data->codec_ops->codec_signal_ctrl(data->pLine, NULL, RING_SIGNAL_OFF_REVERSED); 
+    }
+
+    return 0;     
+}
+
+static s8 usrline_ioctl_fsk_stop(USL_PORT *data, SLIC_IOCTL_DATA *pstCmd)
+{
+    if (NULL == data)
+    {
+        USLPUT0("%s data NULL\n",__FUNCTION__);
+        return -1;
+    }
+    
+    USLPUT2("%s : port %d  \n",__FUNCTION__, data->port);
+    data->codec_ops->codec_signal_ctrl(data->pLine, NULL, RING_SIGNAL_CLEAN_ON);
+    
+    return 0; 
+}
+
+static s8 usrline_ioctl_set_debuglvl(USL_PORT *data, SLIC_IOCTL_DATA *pstCmd)
+{
+    USL_PORT *pUslPort = NULL;
+    int i          = 0;
+    
+    if (NULL == pstCmd)
+    {
+        USLPUT0("%s pstCmd NULL\n",__FUNCTION__);
+        return -1;
+    }
+    
+    //si_usl_debuglvl = pstCmd->unPara.wLevel;
+    
+    if(si_usl_debuglvl > 2)
+    {
+        
+        for ( i = 0; i < MAX_PORT_NUM; i++ )
+        {
+            pUslPort = (USL_PORT *)&pstUslPort[i];
+                
+            if((NULL == pUslPort) || (LINE_DISABLE == pUslPort->flag))
+            {
+                continue;
+            }
+            
+            USLPUT0("port: %d\n",pUslPort->port);
+            /* print the chip relative time parameters */
+            pUslPort->codec_ops->codec_time_print(pUslPort->pLine); 
+            
+            USLPUT0("ring_quene:    %d\n",pUslPort->stRingQuenePara.RingQueneDelay);
+        }
+        
+    }
+     
+    return 0;
+}
+
+static s8 usrline_ioctl_start_test(USL_PORT *data, SLIC_IOCTL_DATA *pstCmd)
+{
+    if ((NULL == data) || (NULL == pstCmd))
+    {
+        USLPUT0("%s data or pstCmd NULL\n",__FUNCTION__);
+        return -1;
+    }
+    
+    if (copy_from_user(pIoctlData, pstCmd->data, pstCmd->data_size) != 0)
+    {
+        USLPUT0("%s copy data from user fail!\n",__FUNCTION__);
+        return -1;
+    }
+    
+    data->event_mask = ~(GET_EV_MASK(EV_FXS_TEST_DONE) | GET_EV_MASK(EV_FXS_TEST_ERROR));
+    
+    if (-1 == data->codec_ops->codec_start_test(data->pLine, (WriteCmd_t *)pIoctlData))
+    {
+        data->event_mask = 0;
+        USLPUT0("%s test start error\n",__FUNCTION__);
+    }
+
+    return 0;
+}
+
+static s8 usrline_ioctl_stop_test(USL_PORT *data, SLIC_IOCTL_DATA *pstCmd)
+{
+    if (NULL == data)
+    {
+        USLPUT0("%s data NULL\n",__FUNCTION__);
+        return -1;
+    }
+    
+    data->codec_ops->codec_stop_test(data->pLine);
+    data->event_mask = 0;
+    
+    USLPUT2("%s:port %d.\n", __FUNCTION__, data->port);
+
+    return 0;
+}
+
+static s8 usrline_ioctl_read_test_result(USL_PORT *data, SLIC_IOCTL_DATA *pstCmd)
+{
+    TestResult_t *stResult = (TestResult_t *)pIoctlData;
+    
+    if ((NULL == data) || (NULL == pstCmd))
+    {
+        USLPUT0("%s data or pstResult NULL\n",__FUNCTION__);
+        return -1;
+    }
+    
+    data->codec_ops->codec_read_reslult(data->pLine, stResult);
+    data->event_mask = 0;
+    
+    USLPUT3("%s:port %d.\n", __FUNCTION__, data->port);
+              
+    USLPUT3("112 test result:");    
+    USLPUT3("port        %d\n", stResult->port);
+    USLPUT3("port_type   %d\n", stResult->port_type);
+    USLPUT3("item        %d\n", stResult->item);
+    USLPUT3("obligate    %d\n", stResult->obligate);
+    USLPUT3("num         %ld\n", stResult->num);
+    USLPUT3("omci_item   %d\n", stResult->omci_item);
+    USLPUT3("flg         %d\n", stResult->flg);
+    USLPUT3("user_flg    %d\n", stResult->user_flg);
+    USLPUT3("err_num     %d\n", stResult->err_num);
+    USLPUT3("Vac_tr      %ld\n", stResult->vac_tr);
+    USLPUT3("vac_tg      %ld\n", stResult->vac_tg);
+    USLPUT3("vac_rg      %ld\n", stResult->vac_rg);
+    USLPUT3("Vdc_tr      %ld\n", stResult->vdc_tr);
+    USLPUT3("vdc_tg      %ld\n", stResult->vdc_tg);
+    USLPUT3("vdc_rg      %ld\n", stResult->vdc_rg);
+    USLPUT3("res_tr      %ld\n", stResult->res_tr);
+    USLPUT3("res_tg      %ld\n", stResult->res_tg);
+    USLPUT3("res_rg      %ld\n", stResult->res_rg);
+    USLPUT3("cap_tr      %ld\n", stResult->cap_tr);
+    USLPUT3("cap_tg      %ld\n", stResult->cap_tg);
+    USLPUT3("cap_rg      %ld\n", stResult->cap_rg);
+    USLPUT3("ring_vol    %ld\n", stResult->ring_vol);
+    USLPUT3("Hz          %ld\n", stResult->Hz);
+    USLPUT3("ren         %ld\n", stResult->ren);
+    USLPUT3("loop_curent %ld\n",stResult->loop_curent);
+    USLPUT3("loop_res    %ld\n", stResult->loop_res);
+    USLPUT3("battary     %ld\n", stResult->battary);
+
+    if (copy_to_user(pstCmd->data, stResult, pstCmd->data_size) != 0)
+    {
+        USLPUT0("%s copy data to user fail!\n",__FUNCTION__);
+    }
+    
+    return 0;
+}
+
+static s8 usrline_ioctl_electric_cfg(USL_PORT *data, SLIC_IOCTL_DATA *pstCmd)
+{
+    if ((NULL == data) || (NULL == pstCmd))
+    {
+        USLPUT0("%s data or pstCmd NULL\n",__FUNCTION__);
+        return -1;
+    }
+    
+    if (copy_from_user(pIoctlData, pstCmd->data, pstCmd->data_size) != 0)
+    {
+        USLPUT0("%s copy data from user fail!\n",__FUNCTION__);
+        return -1;
+    }
+    
+    data->codec_ops->codec_electric_cfg(data->pLine, data->port, (ELECTRIC_CFG_CUSTOMIZED *)pIoctlData);
+
+    return 0;
+}
+
+/*ring queue add by chenjian*/  
+void usrline_ring_ctrl(USL_PORT *usl_port)
+{
+    USL_PORT *data = NULL;
+    data = (USL_PORT *)&pstUslPort[(usl_port->port+1)%2];
+
+    if(1 == usl_port->stRingQuenePara.dwNeedSort)
+    {
+        if ((NULL == data) || (SIGNAL_PLAY_STOP == data->signal_flag))
+        {
+            usrline_signal_start(usl_port);
+        }
+         else if ((data->stRingQuenePara.RingQueneDelay <= data->stRingQuenePara.dwOffCount) && (data->stRingQuenePara.dwOffCount <= data->stRingQuenePara.dwOffMaxCount))
+        {
+            usrline_signal_start(usl_port);
+        }
+    }
+
+    if (1==usl_port->stRingQuenePara.dwRingStop)
+    {
+        usrline_signal_stop(usl_port);
+    }
+
+    return;
+}
+/*ring queue add by chenjian*/  
+
+
+static int usrline_scan(void* info)
+{
+    USL_PORT *usl_port = NULL;
+    sigset_t blocked;
+    u16 port = 0;
+    
+    //lock_kernel();
+    sprintf(current->comm, "usl_scan"); /* comm is 16 bytes */
+    daemonize("usl_scan");
+#if 1
+    /* Block and flush all signals */
+    sigfillset(&blocked);
+    sigprocmask(SIG_BLOCK, &blocked, NULL);
+    flush_signals(current);
+#endif
+    /* real time task FIFO */
+    current->policy = SCHED_FIFO;
+    //unlock_kernel();
+    printk("howard usrline_scan, HZ is %d\n", HZ);
+    while (timer_run)
+    {
+        set_current_state(TASK_INTERRUPTIBLE);
+    	schedule_timeout(10);
+    	//if(slic_offhook){
+
+        //schedule_timeout(10);
+		//printk("howard usrline_scan while\n");
+
+        for (port = 0; port < MAX_PORT_NUM; port++)
+        {
+            usl_port = (USL_PORT *)&pstUslPort[port];
+            
+            if((NULL == usl_port) || (LINE_DISABLE == usl_port->flag))
+            { 
+                continue;
+            }
+           
+            usrline_ring_ctrl(usl_port);
+            
+            if (SIGNAL_PLAY_START == usl_port->signal_flag)
+            {
+                usrline_signal_play(usl_port);
+            }
+            
+            usl_port->codec_ops->codec_scan(usl_port);
+        //}
+    	}
+
+    } /* while () */
+
+    USLPUT0("User Line scan thread exit\n\r");
+    scan_over = 1;
+    
+    return 0;
+}
+
+/* ==================================================================== */
+static int usrline_open(struct inode *inode, struct file *filp)
+{
+    //MOD_INC_USE_COUNT;
+    return 0;
+}
+
+static int usrline_release(struct inode *inode, struct file *filp)
+{
+   // MOD_DEC_USE_COUNT;
+    return 0;
+}
+
+static void irq_handle_interrupt(USL_PORT *data,
+                                      ProslicInt interrupt, int *hook_det)
+{
+	proslicChanType_ptr hProslic;
+	hProslic = data->pLine->ProObj;
+
+  switch(interrupt)
+  {
+    case IRQ_LOOP_STATUS:
+      ProSLIC_ReadHookStatus(hProslic,hook_det);
+      if(*hook_det == PROSLIC_OFFHOOK)
+      {
+        slic_offhook = 1;
+        printk("OFFHOOK\n");
+      }
+      else
+      {
+		slic_offhook = 0;
+        printk("ONHOOK\n");
+      }
+      break;
+
+    case IRQ_P_HVIC:
+    case IRQ_P_THERM:
+      printk("IRQ_P_HVIC or IRQ_P_THERM detect, set linefeed FWD_ACTIVE\n");
+      ProSLIC_SetLinefeedStatus(hProslic,LF_FWD_ACTIVE);
+      break;
+
+    case IRQ_DTMF:
+      {
+        unsigned char digit;
+        char digit_char;
+        int ret = 0;
+		//ProSLIC_SetMuteStatus(hProslic,PROSLIC_MUTE_TX);
+		if(slic_pcm_open == 1)
+        {      
+            //ret = zDrvRpMsg_Write(&icp_pMsg);
+            CPPS_FUNC(cpps_callbacks, zDrvVp_SetDtmfMute_Wrap)();
+	    // printk("DTMF zDrvRpMsg_Write ret %d\n",ret);
+        }
+		dtmf_mute = 1;
+        ProSLIC_DTMFReadDigit(hProslic, &digit);
+        if( (digit >=1) && (digit <= 9 ) )
+        {
+          digit_char = digit + '0';
+        }
+        else
+        {
+          if(digit == 0)
+          {
+            digit_char = 'D';
+          }
+          else
+          {
+            char digit_decode[] = "0*#ABC";
+            digit_char = digit_decode[digit - 10];
+          }
+        }
+        printk("detected dtmf-%c\n", digit_char);
+		usrline_report(data->port,EV_FXS_COLLECT_DIG,digit_char, data->event_mask);
+      }
+      break;
+
+    default:
+      break;
+  }
+}
+
+static int irq_check_interrupts(USL_PORT *data, int *hook_det)
+{
+  proslicIntType irqs;
+  ProslicInt arrayIrqs[MAX_PROSLIC_IRQS];
+  proslicChanType_ptr hProslic;
+  hProslic = data->pLine->ProObj;
+
+
+  irqs.irqs = arrayIrqs;
+
+  if (ProSLIC_GetInterrupts(hProslic, &irqs) != 0)
+  {
+    unsigned int i;
+    /* Iterate through the interrupts and handle */
+    for(i=0 ; i<irqs.number;  i++)
+    {
+		if (irqs.irqs[i] == 8)
+			fskbuf_avail_flag = 1;
+		/*
+			if (irqs.irqs[i] < MAX_INT_STRINGS)
+			{
+				printk("detected: %s\n", intMapStrings[irqs.irqs[i]]);
+			}
+		*/
+      irq_handle_interrupt(data,irqs.irqs[i], hook_det);
+    }
+  }
+	/*
+	if (irqs.number)
+	{
+		printk("\n");
+	}
+	*/
+
+  return irqs.number;
+}
+
+static int slic_get_gpio_state(int gpioNum,
+	unsigned int gpio_sel_gpio,unsigned int gpio_sel_int)
+{
+    unsigned int gpio_state = GPIO_HIGH;
+
+    zx29_gpio_config(gpioNum, gpio_sel_gpio);
+    //pcu_clr_irq_pending(irq);
+    zx29_gpio_set_direction(gpioNum,GPIO_IN);
+    msleep(30);
+    gpio_state = gpio_get_value(gpioNum);
+    msleep(30);
+    zx29_gpio_config(gpioNum, gpio_sel_int);/******qhf***int****/
+    //pcu_clr_irq_pending(irq);
+
+    //printk(KERN_INFO "gpio state=%d.\n",gpio_state);
+
+    return gpio_state;  /* 0: µÍµçƽ(press), 1:¸ßµçƽ(release) */
+
+}
+
+static irqreturn_t slic_int_irq(int irq, void *data)
+{
+    int ret = IRQ_HANDLED;
+	int hook_changed = 0;
+	//int gpio_state = 0;
+	proslicChanType_ptr hProslic;
+    hProslic = ((USL_PORT *)data)->pLine->ProObj;
+
+	//gpio_state = slic_get_gpio_state(SLIC_INT_GPIO, GPIO74_GPIO74, GPIO74_EXT_INT12);
+    //printk("howard slic irq %d, clear pending\n", irq);
+	pcu_clr_irq_pending(irq);
+	if (1 == init_flg)
+		irq_check_interrupts((USL_PORT *)data, &hook_changed);
+	
+    /* To be done */
+    return ret;
+}
+/*******************************************************************************
+* Function: slic_int_irq_handler
+* Description: clear irq , wake thread irq
+* Parameters:
+*          Input:
+*       Output:
+********************************************************************************/
+static irqreturn_t slic_int_irq_handler(int irq, void *dev_id)
+{
+    //disable_irq_nosync(irq);
+    //pcu_int_clear(irq);
+    //printk("howard slic int handler irq=%d.\n", irq);
+    pcu_clr_irq_pending(irq);
+
+    return IRQ_WAKE_THREAD;
+}
+#if 0
+static int slic_create_rpmsg()
+{
+    int ret = 0;
+    icp_pMsg.actorID = PS_ID;
+    icp_pMsg.buf = rpMsgBuf;
+    icp_pMsg.len = 8;
+    icp_pMsg.chID = ICP_CHANNEL_DTMF;
+    icp_pMsg.flag |= RPMSG_WRITE_INT;
+    ret = zDrvRpMsg_CreateChannel(PS_ID, ICP_CHANNEL_DTMF, 0x10);
+    printk("create_rpmsg ret %d\n", ret);
+    return ret;
+}
+#endif
+/*********************************************************************************
+*{usrline_ioctl_xxxx},func deals ioctl cmd, if not realized, please fill {NULL},
+*must corresponding to cmd one by one
+*********************************************************************************/
+static const USRLINE_IOCTL_FUNC_MAP IoctlFuncMap[] = 
+{
+	{usrline_ioctl_dev_init},					  /* SLIC_DEV_INIT */
+	{usrline_ioctl_msg_rev},					  /* SLIC_MSG_REV */
+	{NULL},					                      /* SLIC_TEST */
+	{usrline_ioctl_signal_start},				  /* SLIC_SIGNAL_START */
+	{usrline_ioctl_signal_stop},				  /* SLIC_SIGNAL_STOP */
+	{usrline_ioctl_pcm_open},				      /* SLIC_PCM_OPEN */
+	{usrline_ioctl_pcm_close},				      /* SLIC_PCM_CLOSE */
+	{usrline_ioctl_pcm_set_nb},				      /* SLIC_PCM_SET_NB */
+	{usrline_ioctl_pcm_set_wb},				      /* SLIC_PCM_SET_WB */
+
+	{usrline_ioctl_Inf_precfg},                   /* SLIC_INF_PRECFG */
+
+	{NULL},                                       /* SLIC_NOTUSED */
+	{usrline_ioctl_port_reset},                   /* SLIC_PORT_RESET */
+	
+	{usrline_ioctl_msg_clear},                    /* SLIC_MSG_CLR */
+	{usrline_ioctl_dial_start},                   /* SLIC_DIAL_START */
+	{usrline_ioctl_dial_stop},                    /* SLIC_DIAL_STOP */
+
+
+	{usrline_ioctl_timeslot_set},                 /* SLIC_TIMESLOT_SET */
+	{usrline_ioctl_timeslot_release},             /* SLIC_TIMESLOT_RELEASE */
+	{usrline_ioctl_port_lock},                    /* SLIC_PORT_LOCK */
+	{usrline_ioctl_port_unlock},                  /* SLIC_PORT_UNLOCK */
+	{usrline_ioctl_fsk_start},                    /* SLIC_FSK_START */
+	{usrline_ioctl_fsk_stop},                     /* SLIC_FSK_STOP */
+	{usrline_ioctl_polarity_reverse},             /* SLIC_POLARITY_REVERSE */
+	{usrline_ioctl_dtmf_start},                   /* SLIC_DTMFCID_START */
+	{usrline_ioctl_start_test},                   /* SLIC_LINE_TEST_START */
+	{usrline_ioctl_stop_test},                    /* SLIC_LINE_TEST_ABORT */
+	{usrline_ioctl_read_test_result},             /* SLIC_LINE_TEST_READ */
+	{usrline_ioctl_time_cfg},                     /* SLIC_TIMEPARA_CFG */
+	{usrline_ioctl_electric_cfg},                 /* SLIC_ELECTRIC_CFG */
+	{usrline_ioctl_set_debuglvl},                 /* SLIC_DEBUG_LEVEL */
+	{usrline_ioctl_slctool_hooklowlen_cfg},       /* SLIC_CFG_HOOK_LOWLEN */
+	{usrline_ioctl_slctool_hookhiglen_cfg},       /* SLIC_CFG_HOOK_HIGLEN */
+	{usrline_ioctl_slctool_flashlowmin_cfg},      /* SLIC_CFG_FLASH_LMIN */
+	{usrline_ioctl_slctool_flashlowmax_cfg},      /* SLIC_CFG_FLASH_LMAX */
+	{usrline_ioctl_slctool_flashhfix_cfg},        /* SLIC_CFG_FLASH_HFIX */
+	{usrline_ioctl_slctool_dialhmin_cfg},         /* SLIC_CFG_DIAL_HMIN */
+	{usrline_ioctl_slctool_dialhmax_cfg},         /* SLIC_CFG_DIAL_HMAX */
+	{usrline_ioctl_slctool_diallmin_cfg},         /* SLIC_CFG_DIAL_LMIN */
+	{usrline_ioctl_slctool_diallmax_cfg},         /* SLIC_CFG_DIAL_LMAX */
+	{NULL},                                       /* SLIC_CFG_RINGCEASE */
+	{usrline_ioctl_slctool_prehookhiglen_cfg},    /* SLIC_CFG_PREHOOK_HIGLEN */
+	{NULL},                                       /* SLIC_CFG_QUEUE_DELAY */
+	{usrline_ioctl_codec_read},                   /* SLIC_CODEC_GET */
+	{usrline_ioctl_codec_config},                 /* SLIC_CODEC_SET */
+	{usrline_ioctl_ram_read},                     /* SLIC_RAM_GET */
+	{usrline_ioctl_ram_config},                   /* SLIC_RAM_SET */
+	{usrline_ioctl_mute},                		   /* SLIC_RAM_SET */
+	{NULL},                                       /* SLIC_CODEC_GETALL */
+	{NULL},                                       /* SLIC_RAM_GETALL */
+	{NULL},                                       /* SLIC_GET_CHIP_NAME */
+};
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 36)
+static long usrline_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
+#else
+static int usrline_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg)
+#endif
+{
+    s8 rev          = -1;
+    USL_PORT *usl_port  = NULL;
+    SLIC_IOCTL_DATA stCmd = {0};
+    
+    printk("howard usrline_ioctl cmd=%d\n", cmd);
+
+	if((0 == init_flg) && (SLIC_DEV_INIT != cmd) && (SLIC_MSG_REV != cmd))
+    {
+        printk("SLIC init NOT complete\n");
+        return -1;
+    }
+
+    if (NULL != (void *)arg)
+    {
+        if (copy_from_user(&stCmd, (SLIC_IOCTL_DATA *)arg, sizeof(SLIC_IOCTL_DATA)) != 0)
+        {
+            USLPUT0("usrline_ioctl copy data from user fail!\n");
+            return rev;
+        }
+#if 0
+        if (stCmd.port >= MAX_PORT_NUM)
+        {
+            USLPUT0("usrline_ioctl port:%d illegal, max:%d\n", stCmd.port, MAX_PORT_NUM-1);
+            return rev;
+        }
+#endif
+        usl_port = (USL_PORT *)&pstUslPort[0];
+		//ProSLIC_Init_MultiBOM(&(pstUslPort->pLine->ProObj),1,3);
+
+        if (NULL == usl_port)
+        {
+            USLPUT0("usrline_ioctl usl_port NULL\n");
+            return rev;
+        }
+        
+        if (LINE_DISABLE == usl_port->flag)
+        {
+            USLPUT0("usrline_ioctl port:0 is disable now!\n");
+            switch (cmd)
+            {
+            case SLIC_INF_PRECFG:
+            case SLIC_MSG_REV:
+                rev = IoctlFuncMap[cmd].pIoctlFunc(usl_port, &stCmd);
+                break;
+            case SLIC_PORT_UNLOCK:
+                if (LINE_INITOK == usl_port->dwInitOK)
+                {
+                    rev = IoctlFuncMap[cmd].pIoctlFunc(usl_port, &stCmd);
+                }
+                break;
+            default:
+				rev = IoctlFuncMap[cmd].pIoctlFunc(usl_port, &stCmd);
+                break;
+            }
+            
+            return rev;
+        }
+    }
+    
+    if ((cmd >= 0) && (cmd < SLIC_IOCTL_CMD_MAX))
+    {
+        if (NULL != IoctlFuncMap[cmd].pIoctlFunc)
+        {
+            rev = IoctlFuncMap[cmd].pIoctlFunc(usl_port, &stCmd);
+        }
+        else
+        {
+            USLPUT0("cmd:%d not realized!\n", cmd);
+        }
+    }
+    else
+    {
+        USLPUT0("cmd:%d not supprot!\n", cmd);
+    }
+    
+    return rev;
+}
+
+static struct file_operations usrline_fops = {
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 36)
+    unlocked_ioctl:  usrline_ioctl,
+#else
+    ioctl:      usrline_ioctl,
+#endif
+    open:       usrline_open,
+    release:    usrline_release,
+    owner:      THIS_MODULE
+};
+
+/* =================================================== */
+int  si_usrline_init(void)
+{
+    int rev;
+        
+    init_waitqueue_head(&msg_wait_queue);
+
+    CreatMsgQueue();
+    printk("howard si_usrline_init\n");
+
+    rev = register_chrdev(USL_MAJOR, USL_NAME, &usrline_fops);
+    if (rev < 0) {
+        USLPUT0("%s: can't get major %d\n", USL_NAME, USL_MAJOR);
+        return rev;
+    }
+    
+    if (0 != SlicMallocMemory())
+    {
+        unregister_chrdev(USL_MAJOR, USL_NAME);
+        USLPUT0("Can't get USL_PORT memory!\n");
+        return -1;
+    }
+	slic_dev_class = class_create(THIS_MODULE, USL_NAME);
+	if (IS_ERR(slic_dev_class))
+	{
+		printk("howard failed in creat slic class!\n");
+        unregister_chrdev(USL_MAJOR, USL_NAME);
+		return -1;
+	}
+	slic_device = device_create(slic_dev_class, NULL, MKDEV(USL_MAJOR, 0), NULL, USL_NAME);
+	if (IS_ERR(slic_device))
+	{
+		printk("howard failed in creat slic device!\n");
+		class_destroy(slic_dev_class);
+        unregister_chrdev(USL_MAJOR, USL_NAME);		
+		return -1;
+	}
+    printk("howard kernel_thread\n");
+    kernel_thread(usrline_scan, NULL, 0);  /* fork the main thread */
+    
+    SlicCfgParaBasedBoardType();
+#ifdef POWER_SUPPLY_05A
+    slic_function = slic_is_ring_state;
+#endif
+     SPI_Init();
+
+    //zx29_gpio_config(SLIC_POW_EN_GPIO, GPIO121_GPIO121);   /* set SLIC 3.3V EN GPIO */
+	//zx29_gpio_set_direction(SLIC_POW_EN_GPIO, GPIO_OUT);
+	//gpio_direction_output(SLIC_POW_EN_GPIO, 1);	
+
+/* add by zhanghuan for INT and RST GPIO */
+	//zx29_gpio_config(SLIC_INT_GPIO, GPIO74_GPIO74);   /* set SLIC_INT_GPIO as GPIO */
+	//zx29_gpio_config(SLIC_RST_GPIO, GPIO77_GPIO77);   /* set SLIC_RST_GPIO as GPIO */
+	#if 0
+    rev = gpio_is_valid(SLIC_INT_GPIO);
+    if(rev < 0)
+    {
+        printk("SLIC_INT_GPIO is not valid\n"); 
+        //return -1;
+    };
+	rev = gpio_request(SLIC_INT_GPIO, "slic int");
+    if(rev < 0)
+    {
+        printk("SLIC_INT_GPIO is not valid\n"); 
+        //return -1;
+    };
+	//gpio_direction_input(SLIC_INT_GPIO);
+	
+	zx29_gpio_config(SLIC_INT_GPIO, GPIO74_GPIO74);   /* set SLIC_INT_GPIO as GPIO */
+	gpio_direction_input(SLIC_INT_GPIO);
+	#endif
+	//zx29_gpio_set_direction(SLIC_INT_GPIO, GPIO_IN);
+	#if 1
+	rev = gpio_request(SLIC_INT_GPIO, "slic_int");
+	if (rev) {
+		printk(KERN_INFO "slic_int gpio request error.\n");
+		return rev;
+	}
+	
+	zx29_gpio_pd_pu_set(SLIC_INT_GPIO, IO_CFG_PULL_DISABLE);//IO_CFG_PULL_DISABLE
+	rev = zx29_gpio_config(SLIC_INT_GPIO,FNC_SLIC_INT_GPIO);/********V3 GPIO53:0 /EXT_INT:6*******//********V2 GPIO74:0 /EXT_INT:12*******/
+
+    zx29_gpio_set_inttype(SLIC_INT_GPIO,IRQ_TYPE_EDGE_FALLING/*IRQ_TYPE_EDGE_FALLING/*IRQ_TYPE_EDGE_RISING*/);  //INT_POSEDGE
+    //zx29_gpio_pd_pu_set(SLIC_INT_GPIO, 0);
+	irq_num = gpio_to_irq(SLIC_INT_GPIO);
+    rev = irq_set_irq_wake(irq_num, 1);
+    printk("howard irq_set_irq_wake irq_num %d, ret %d\n", irq_num, rev);
+    pcu_clr_irq_pending(irq_num);
+	
+	request_threaded_irq(irq_num, slic_int_irq_handler, 
+		slic_int_irq, IRQF_ONESHOT, "slic int", pstUslPort);
+	#endif 
+	rev = gpio_is_valid(SLIC_RST_GPIO);
+    if(rev < 0)
+    {
+        printk("SLIC_RST_GPIO is not valid\n"); 
+        //return -1;
+    };
+	rev = gpio_request(SLIC_RST_GPIO, "slic reset");
+    if(rev < 0)
+    {
+        printk("SLIC_RST_GPIO is not valid\n"); 
+        //return -1;
+    };
+	zx29_gpio_config(SLIC_RST_GPIO, FNC_SLIC_RST_GPIO);   /* set SLIC_RST_GPIO as GPIO */
+
+	//zx29_gpio_set_direction(SLIC_RST_GPIO, GPIO_OUT);
+	gpio_direction_output(SLIC_RST_GPIO, 0);
+	gpio_set_value(SLIC_RST_GPIO,1);
+	//gpio_direction_output(SLIC_RST_GPIO, 1);
+	//zx29_gpio_output_data(SLIC_RST_GPIO, 1);
+    /* add by zhanghuan for SLIC wake lock */	
+    wake_lock_init(&slic_wakelock, WAKE_LOCK_SUSPEND, "slic_wakelock");
+    wake_lock(&slic_wakelock);
+    zx_cpuidle_set_busy(IDLE_FLAG_SLIC);
+#if 0
+    rev = slic_create_rpmsg();
+    if(rev < 0)
+    {
+        printk("slic_create_rpmsg failed\n"); 
+    };
+#endif
+    zx29_i2s_tdm_pin_cfg();
+
+    USLPUT0("howard:User SLIC Driver V3.0.0 Init Finish.\n\r");
+    return 0;
+}
+
+void  si_usrline_cleanup(void)
+{
+    timer_run = 0;    /* stop scan */   
+    while(!scan_over) /* wait scan thread exit */
+    {
+        schedule();
+    }
+    printk("howard si_usrline_cleanup\n");
+	free_irq(irq_num, pstUslPort);
+
+    DeinitSlicChip();
+    SlicFreeMemory();
+
+	SPI_Exit();
+	gpio_free(SLIC_INT_GPIO);
+	gpio_free(SLIC_RST_GPIO);
+	printk("howard free irq\n");
+	device_destroy(slic_dev_class, MKDEV(USL_MAJOR, 0));
+	class_destroy(slic_dev_class);
+    unregister_chrdev(USL_MAJOR, USL_NAME);
+    wake_lock_destroy(&slic_wakelock);
+    zx_cpuidle_set_free(IDLE_FLAG_SLIC);
+    USLPUT0("SLC:User SLIC Driver remove OK!\n\r");
+
+    return;
+}
+static void zx29_i2s_tdm_pin_cfg(void)
+{
+	unsigned int regval = 0;
+	
+	int ret = 0;
+	  printk("zx29_i2s_tdm_pin_cfg\n");
+	    //ret = zOss_NvItemRead(OS_FLASH_VOICE_DRV_RW_NONFAC_BASE_ADDR, ((UINT8 *)(&audionvflag)),  sizeof(audionvflag));
+
+	  printk("after zx29_i2s_tdm_pin_cfg\n");
+	  #if 0
+	  ret = gpio_request(PIN_TDM_FS, "i2s0_ws");
+	  if (ret < 0)
+		BUG();
+	  ret = gpio_request(PIN_TDM_CLK, "i2s0_clk");
+         if (ret < 0)
+		BUG();
+	  ret = gpio_request(PIN_TDM_DIN, "i2s0_din");
+	  if (ret < 0)
+		BUG();
+	  ret = gpio_request(PIN_TDM_DOUT, "i2s0_dout");
+	  if (ret < 0)
+		BUG();
+	  zx29_gpio_config(PIN_TDM_FS, FUN_TDM_FS);
+	  zx29_gpio_config(PIN_TDM_CLK, FUN_TDM_CLK);
+	  zx29_gpio_config(PIN_TDM_DIN, FUN_TDM_DIN);
+	  zx29_gpio_config(PIN_TDM_DOUT, FUN_TDM_DOUT);
+	
+
+         //zDrvRamlog_PRINTF(RAMLOG_MOD_AUDIO,"vp_SetTopTdmConfig set top TDM,ARM_TDM_LOOP_SET=0x%x\n",ARM_TDM_LOOP_SET);
+         // sel tdm wclk
+         regval = zx_read_reg(ZX29_TDM_MOD_CLK_SEL);
+         regval &= 0xfcffffff;   //set mod_clk_sel bit 25:24 to select the tdm wclk, 0, main_clk;1,122.88m;2,mpll104m;3,mpll104m;
+         zx_write_reg(ZX29_TDM_MOD_CLK_SEL, regval);
+         //zDrvRamlog_PRINTF(RAMLOG_MOD_AUDIO,"vp_SetTopTdmConfig set top TDM,MOD_CLK_SEL=0x%x\n",TDM_MOD_CLK_SEL);
+         //zDrvRamlog_PRINTF(RAMLOG_MOD_AUDIO,"vp_SetTopTdmConfig set top TDM,DMA_SEL_CFG=0x%x\n",DMA_SEL_CFG);
+
+	  // sel tdm use dma
+	  regval = zx_read_reg(ZX29_I2S_DMA_SEL_CFG);
+	  regval &= 0xffffff87;
+	  regval |= 0x00000018; //  bit3 1 tdmtx,bit4 1 tdmrx bit5 i2s1tx,bit6 i2s1rx
+         zx_write_reg(ZX29_I2S_DMA_SEL_CFG, regval);
+	
+         printk("slic cfg tdm gpio pin end !\n");
+	#else
+	  ret = gpio_request(PIN_I2S0_WS, "i2s0_ws");
+	  if (ret < 0)
+		BUG();
+	  ret = gpio_request(PIN_I2S0_CLK, "i2s0_clk");
+	  if (ret < 0)
+		BUG();
+	  ret = gpio_request(PIN_I2S0_DIN, "i2s0_din");
+	  if (ret < 0)
+		BUG();
+	  ret = gpio_request(PIN_I2S0_DOUT, "i2s0_dout");
+	  if (ret < 0)
+		BUG();
+	  zx29_gpio_config(PIN_I2S0_WS, FUN_I2S0_WS);
+	  zx29_gpio_config(PIN_I2S0_CLK, FUN_I2S0_CLK);
+	  zx29_gpio_config(PIN_I2S0_DIN, FUN_I2S0_DIN);
+	  zx29_gpio_config(PIN_I2S0_DOUT, FUN_I2S0_DOUT);
+
+		// sel i2s0 use dma
+	  regval = zx_read_reg(ZX29_I2S_DMA_SEL_CFG);
+	  regval &= 0xffffff87; //bit3 1 i2s0tx,bit4 1 i2s0rx bit5 i2s1tx,bit6 i2s1rx
+	  zx_write_reg(ZX29_I2S_DMA_SEL_CFG, regval);	
+         printk("slic cfg i2s0 gpio pin end !\n");
+
+	#endif
+	//top i2s1 cfg
+	regval = zx_read_reg(ZX29_I2S_LOOP_CFG);
+	regval &= 0xfffffff8;
+	regval |= 0x00000001; //  inter arm_i2s1--top i2s1
+	zx_write_reg(ZX29_I2S_LOOP_CFG, regval);	   
+	   
+       // inter loop
+       regval = zx_read_reg(ZX29_I2S_LOOP_CFG);
+       regval &= 0xfffffe07;
+       regval |= 0x000000a8; //  inter arm_i2s2--afe i2s
+       zx_write_reg(ZX29_I2S_LOOP_CFG, regval);
+	   
+	printk("slic cfg top gpio  end !\n");
+
+		   
+
+}
+/* =================================================== */
+#ifdef USE_GPIO_SPI_SLIC
+module_init(si_usrline_init);
+module_exit(si_usrline_cleanup);
+#endif
+
+#ifdef USE_STD_SPI_SLIC
+/* É豸̽²âº¯Êý */
+static int slic_probe(struct spi_device *spi)
+{
+	printk("howard slic_probe\n");
+	pslicSpi =spi;
+	si_usrline_init();
+	return 0;
+
+}
+static int slic_remove(struct spi_device *spi)
+{
+    printk("howard slic_remove\n");
+	si_usrline_cleanup();
+    return 0;
+}
+
+static const struct spi_device_id slic_id[] = {
+    {"slic_spi", 0 },
+    { }
+};
+
+MODULE_DEVICE_TABLE(spi, slic_id);
+
+static struct spi_driver slic_spi_driver = {
+    .driver = {
+        .name = "slic_spi",
+        .owner = THIS_MODULE,
+    },
+    .probe = slic_probe,
+    .remove = slic_remove,
+    .id_table = slic_id,
+};
+
+static int __init slic_spi_init(void)
+{
+    int ret;
+	printk("howard slic_spi_init\n");
+
+    ret = spi_register_driver(&slic_spi_driver);
+    if (ret != 0)
+    {
+        printk("howard slic Failed to register slic_spi_driver : %d\n", ret);
+    }
+    
+    return ret;
+}
+
+static void __exit slic_spi_exit(void)
+{
+	printk("howard slic_spi_exit\n");
+	spi_unregister_driver(&slic_spi_driver);
+}
+
+module_init(slic_spi_init);
+module_exit(slic_spi_exit);
+#endif
+MODULE_AUTHOR("zxic");
+MODULE_DESCRIPTION("SLIC Driver");
+MODULE_LICENSE("GPL");
+