| /******************************************************************************* |
| * 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"); |
| |