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");
+