blob: 9a73c445d74c90b4df18b2450c1e8312a1081e82 [file] [log] [blame]
developere0cea0f2021-12-16 16:08:26 +08001// SPDX-License-Identifier: GPL-2.0
2/*
3 * Vdaa VoiceDAA interface implementation file
4 *
5 * Distributed by:
6 * Silicon Laboratories, Inc
7 *
8 * This file contains proprietary information.
9 * No dissemination allowed without prior written permission from
10 * Silicon Laboratories, Inc.
11 *
12 * File Description:
13 * This is the implementation file for the main VoiceDAA API.
14 *
15 */
16
17#include "../config_inc/si_voice_datatypes.h"
18#include "../inc/si_voice_ctrl.h"
19#include "../inc/si_voice_timer_intf.h"
20#include "../inc/vdaa.h"
21#include "../inc/vdaa_registers.h"
22#include "../config_inc/vdaa_api_config.h"
23
24#define WriteReg pVdaa->deviceId->ctrlInterface->WriteRegister_fptr
25#define ReadReg pVdaa->deviceId->ctrlInterface->ReadRegister_fptr
26#define pVdaaHW pVdaa->deviceId->ctrlInterface->hCtrl
27
28#define WriteRegX deviceId->ctrlInterface->WriteRegister_fptr
29#define ReadRegX deviceId->ctrlInterface->ReadRegister_fptr
30#define pVdaaHWX deviceId->ctrlInterface->hCtrl
31#define LOGPRINT_PREFIX "VDAA: "
32
33/*
34** Static VDAA driver functions
35*/
36
37/*
38** Function: isVerifiedDAA
39**
40** Description:
41** Verifies addressed channel is DAA
42**
43** Input Parameters:
44** pVdaa: pointer to SiVoiceChanType or vdaaChanType
45**
46** Return:
47** Verified DAA
48** Not DAA RC_CHANNEL_TYPE_ERR
49**
50*/
51
52static int isVerifiedDAA(vdaaChanType *pVdaa)
53{
54 uInt8 data = ReadReg(pVdaaHW,pVdaa->channel,LSIDE_REV);
55 if ( (data & 0x40) == 0 ) /*This bit is always 1 for DAA*/
56 {
57 LOGPRINT("%sDAA device not detected\n",LOGPRINT_PREFIX);
58 return RC_CHANNEL_TYPE_ERR;
59 }
60 else
61 {
62 /* For Si3050, the value will be zero initially (calloc), for Si32178/9, this will
63 * be non-zero (Rev B).
64 */
65 if(pVdaa->deviceId->chipRev == 0)
66 {
67 /* Read Device ID and store it */
68 /* NOTE: in earlier releases we also read the line side info here. This is now done
69 Vdaa_duringPowerUpLineside since the information we read was always 0.
70 */
71 data = pVdaa->ReadRegX(pVdaa->pVdaaHWX,pVdaa->channel,SYS_LINE_DEV_REV);
72 pVdaa->deviceId->chipRev= data&0xF;
73#ifdef ENABLE_DEBUG
74 LOGPRINT("%sChipRev = 0x%x\n", LOGPRINT_PREFIX, pVdaa->deviceId->chipRev);
75#endif
76 }
77 }
78
79 return RC_NONE;
80}
81
82#if 0 /* Removed for now since it isn't used, keeping code as reference */
83/*
84** Function: probeDaisyChain
85**
86** Description:
87** Identify how many VDAA devices are in daisychain
88** Only called if channel 0 has be previously qualified
89** as a VDAA.
90**
91** Input Parameters:
92** pVdaa: pointer to SiVoiceChanType or vdaaChanType
93**
94** Return:
95** number of channels in daisy chain
96**
97*/
98
99static int probeDaisyChain (vdaaChanType *pVdaa)
100{
101 int i=0;
102 WriteReg(pVdaaHW,BROADCAST,PCMRX_CNT_LO,0x23); /* Broadcast */
103 while ((ReadReg(pVdaaHW,(uInt8)i++,PCMRX_CNT_LO) == 0x23)
104 &&(i<=16)); /* Count number of channels */
105 return i-1; /* Return number of channels */
106}
107#endif
108
109/*
110**
111** ------ VDAA CONFIGURATION FUNCTIONS -----
112**
113*/
114
115/*
116** Function: Vdaa_RingDetectSetup
117**
118** Description:
119** configure ring detect setup
120**
121** Returns:
122**
123*/
124
125#ifndef DISABLE_VDAA_RING_DETECT_SETUP
126extern vdaa_Ring_Detect_Cfg Vdaa_Ring_Detect_Presets[];
127int Vdaa_RingDetectSetup (vdaaChanType *pVdaa,int32 preset)
128{
129
130 uInt8 regTemp = 0;
131 TRACEPRINT( pVdaa, "preset = %d\n", (unsigned int) preset);
132 if(pVdaa->channelType != DAA)
133 {
134 return RC_IGNORE;
135 }
136
137 regTemp = ReadReg(pVdaaHW,pVdaa->channel,CTRL2) & 0xfB;
138 regTemp |= Vdaa_Ring_Detect_Presets[preset].rdi<<2;
139 WriteReg(pVdaaHW,pVdaa->channel,CTRL2,regTemp);
140
141 regTemp = ReadReg(pVdaaHW,pVdaa->channel,INTL_CTRL1) & 0xfe;
142 regTemp |= Vdaa_Ring_Detect_Presets[preset].rt&1;
143 WriteReg(pVdaaHW,pVdaa->channel,INTL_CTRL1,regTemp);
144
145 regTemp = ReadReg(pVdaaHW,pVdaa->channel,INTL_CTRL2) & 0xef;
146 regTemp |= ((Vdaa_Ring_Detect_Presets[preset].rt>>1)<<4);
147 WriteReg(pVdaaHW,pVdaa->channel,INTL_CTRL2,regTemp);
148
149 WriteReg(pVdaaHW,pVdaa->channel,INTL_CTRL3,
150 Vdaa_Ring_Detect_Presets[preset].rfwe<<1);
151
152 regTemp = (Vdaa_Ring_Detect_Presets[preset].rdly&0x3) << 6;
153 regTemp |= Vdaa_Ring_Detect_Presets[preset].rmx ;
154 WriteReg(pVdaaHW,pVdaa->channel,RNG_VLD_CTRL1,regTemp);
155
156 regTemp = (Vdaa_Ring_Detect_Presets[preset].rdly>>2) << 7;
157 regTemp |= Vdaa_Ring_Detect_Presets[preset].rto << 3 ;
158 regTemp |= Vdaa_Ring_Detect_Presets[preset].rcc ;
159 WriteReg(pVdaaHW,pVdaa->channel,RNG_VLD_CTRL2,regTemp);
160
161 regTemp = Vdaa_Ring_Detect_Presets[preset].rngv << 7;
162 regTemp |= Vdaa_Ring_Detect_Presets[preset].ras ;
163 WriteReg(pVdaaHW,pVdaa->channel,RNG_VLD_CTRL3,regTemp);
164
165 regTemp = Vdaa_Ring_Detect_Presets[preset].rpol<<1;
166 WriteReg(pVdaaHW,pVdaa->channel,DAA_CTRL4,regTemp);
167
168 return RC_NONE;
169}
170#endif
171
172/*
173** Function: Vdaa_TXAudioGainSetup
174**
175** Description:
176** configure tx audio gain
177**
178** Returns:
179**
180**
181*/
182#ifndef DISABLE_VDAA_AUDIO_GAIN_SETUP
183extern vdaa_audioGain_Cfg Vdaa_audioGain_Presets[];
184
185int Vdaa_TXAudioGainSetup (vdaaChanType *pVdaa,int32 preset)
186{
187 uInt8 regTemp = 0;
188 TRACEPRINT( pVdaa, "preset = %d\n", (unsigned int) preset);
189
190 if(pVdaa->channelType != DAA)
191 {
192 return RC_IGNORE;
193 }
194
195 if(Vdaa_audioGain_Presets[preset].xga2 == XGA_ATTEN)
196 {
197 regTemp = 0x10;
198 }
199
200 regTemp |= Vdaa_audioGain_Presets[preset].acgain2 ;
201 WriteReg(pVdaaHW,pVdaa->channel,TX_GN_CTRL2,regTemp);
202
203 regTemp = 0;
204 if(Vdaa_audioGain_Presets[preset].xga3 == XGA_ATTEN)
205 {
206 regTemp = 0x10 ;
207 }
208
209 regTemp |= Vdaa_audioGain_Presets[preset].acgain3 ;
210 WriteReg(pVdaaHW,pVdaa->channel,TX_GN_CTRL3,regTemp);
211
212 if(Vdaa_audioGain_Presets[preset].cpEn)
213 {
214 WriteReg(pVdaaHW,pVdaa->channel,TXCALL_PROG_ATTEN,
215 Vdaa_audioGain_Presets[preset].callProgress);
216 }
217
218 return RC_NONE;
219}
220# endif
221
222
223/*
224** Function: Vdaa_RXAudioGainSetup
225**
226** Description:
227** configure rx audio gain
228**
229** Returns:
230**
231**
232*/
233#ifndef DISABLE_VDAA_AUDIO_GAIN_SETUP
234extern vdaa_audioGain_Cfg Vdaa_audioGain_Presets[];
235
236int Vdaa_RXAudioGainSetup (vdaaChanType *pVdaa,int32 preset)
237{
238 uInt8 regTemp = 0;
239
240 TRACEPRINT( pVdaa, "preset = %d\n", (unsigned int) preset);
241 if(pVdaa->channelType != DAA)
242 {
243 return RC_IGNORE;
244 }
245
246 if(Vdaa_audioGain_Presets[preset].xga2 == XGA_ATTEN)
247 {
248 regTemp = 0x10;
249 }
250 regTemp |= Vdaa_audioGain_Presets[preset].acgain2 ;
251 WriteReg(pVdaaHW,pVdaa->channel,RX_GN_CTRL2,regTemp);
252
253 regTemp = 0;
254 if(Vdaa_audioGain_Presets[preset].xga3 == XGA_ATTEN)
255 {
256 regTemp = 0x10;
257 }
258 regTemp |= Vdaa_audioGain_Presets[preset].acgain3 ;
259 WriteReg(pVdaaHW,pVdaa->channel,RX_GN_CTRL3,regTemp);
260
261 if(Vdaa_audioGain_Presets[preset].cpEn)
262 {
263 WriteReg(pVdaaHW,pVdaa->channel,RXCALL_PROG_ATTEN,
264 Vdaa_audioGain_Presets[preset].callProgress);
265 }
266
267 return RC_NONE;
268}
269#endif
270
271
272/*
273** Function: Vdaa_PCMSetup
274**
275** Description:
276** configure pcm format, clocking and edge placement
277**
278** Returns:
279**
280**
281*/
282#ifndef DISABLE_VDAA_PCM_SETUP
283extern vdaa_PCM_Cfg Vdaa_PCM_Presets [];
284
285int Vdaa_PCMSetup (vdaaChanType *pVdaa,int32 preset)
286{
287 uInt8 regTemp = 0;
288
289 TRACEPRINT( pVdaa, "preset = %d\n", (unsigned int) preset);
290 if(pVdaa->channelType != DAA)
291 {
292 return RC_IGNORE;
293 }
294
295 regTemp = ReadReg(pVdaaHW,pVdaa->channel,PCM_SPI_CTRL)&0xe0;
296 regTemp |= Vdaa_PCM_Presets[preset].pcm_tri;
297 regTemp |= Vdaa_PCM_Presets[preset].pcmHwy << 1;
298 regTemp |= Vdaa_PCM_Presets[preset].pcmFormat << 3;
299 WriteReg(pVdaaHW,pVdaa->channel,PCM_SPI_CTRL,regTemp);
300
301 return RC_NONE;
302}
303#endif
304
305/*
306** Function: Vdaa_PCMTimeSlotSetup
307**
308** Description:
309** configure pcm timeslot
310**
311** Returns:
312**
313*/
314int Vdaa_PCMTimeSlotSetup (vdaaChanType *pVdaa, uInt16 rxcount, uInt16 txcount)
315{
316 uInt8 data = 0;
317 uInt8 pcmStatus;
318
319 TRACEPRINT( pVdaa, "rxcount = %u txcount = %u\n", (unsigned int)rxcount,
320 (unsigned int)txcount);
321 if(pVdaa->channelType != DAA)
322 {
323 return RC_IGNORE;
324 }
325
326 /* Disable PCM if enabled - restore after updating timeslots */
327 pcmStatus = ReadReg(pVdaaHW,pVdaa->channel,PCM_SPI_CTRL);
328 if (pcmStatus&0x20)
329 {
330 WriteReg(pVdaaHW,pVdaa->channel,PCM_SPI_CTRL,pcmStatus&~(0x20));
331 }
332
333 /*Storing 10 bit value of Transmit PCM sample in REG 34 and REG 35[0:1]*/
334 data = (uInt8)(txcount & 0xff);
335 WriteReg(pVdaaHW,pVdaa->channel,PCMTX_CNT_LO,data);
336 data = (uInt8)(txcount >> 8) ;
337 WriteReg(pVdaaHW,pVdaa->channel,PCMTX_CNT_HI,data);
338
339 /*Storing 10 bit value of Receive PCM sample in REG 34 and REG 35[0:1]*/
340 data = (uInt8)(rxcount & 0xff);
341 WriteReg(pVdaaHW,pVdaa->channel,PCMRX_CNT_LO,data);
342 data = (uInt8)(rxcount >> 8);
343 WriteReg(pVdaaHW,pVdaa->channel,PCMRX_CNT_HI,data);
344
345 /* Enable back the PCM after storing the values*/
346 WriteReg(pVdaaHW,pVdaa->channel,PCM_SPI_CTRL,pcmStatus);
347
348 return RC_NONE;
349}
350
351/*
352** Function: Vdaa_CountrySetup
353**
354** Description:
355** configure country specific settings
356**
357** Returns:
358**
359**
360*/
361
362#ifndef DISABLE_VDAA_COUNTRY_SETUP
363extern vdaa_Country_Cfg Vdaa_Country_Presets [];
364
365int Vdaa_CountrySetup (vdaaChanType *pVdaa,int32 preset)
366{
367 uInt8 regTemp = 0;
368
369 TRACEPRINT( pVdaa, "preset = %d\n", (unsigned int) preset);
370 if(pVdaa->channelType != DAA)
371 {
372 return RC_IGNORE;
373 }
374
375 regTemp = ReadReg(pVdaaHW,pVdaa->channel,CTRL2) & 0xFD;
376 WriteReg(pVdaaHW,pVdaa->channel,CTRL2,regTemp); /* disable hybrid */
377
378 regTemp = ReadReg(pVdaaHW,pVdaa->channel,INTL_CTRL1) & 0xFD;
379 regTemp |= Vdaa_Country_Presets[preset].rz << 1 ;
380 WriteReg(pVdaaHW,pVdaa->channel,INTL_CTRL1,regTemp);
381
382 regTemp = Vdaa_Country_Presets[preset].dcr;
383 regTemp |= Vdaa_Country_Presets[preset].ilim<<1;
384 regTemp |= Vdaa_Country_Presets[preset].mini<<4;
385 regTemp |= Vdaa_Country_Presets[preset].dcv<<6;
386 WriteReg(pVdaaHW,pVdaa->channel,DC_TERM_CTRL,regTemp);
387
388 regTemp = ReadReg(pVdaaHW,pVdaa->channel,AC_TERM_CTRL) & 0xF0;
389 regTemp |= Vdaa_Country_Presets[preset].acim;
390 WriteReg(pVdaaHW,pVdaa->channel,AC_TERM_CTRL,regTemp);
391
392 regTemp = ReadReg(pVdaaHW,pVdaa->channel,SPRK_QNCH_CTRL) & 0xAF;
393 regTemp |= ((Vdaa_Country_Presets[preset].ohs_sq >> 2)&1)<<4 ;
394 regTemp |= ((Vdaa_Country_Presets[preset].ohs_sq >> 3)&1)<<6 ;
395 WriteReg(pVdaaHW,pVdaa->channel,SPRK_QNCH_CTRL,regTemp);
396
397 regTemp = ReadReg(pVdaaHW,pVdaa->channel,INTL_CTRL1) & 0xBF;
398 regTemp |= ((Vdaa_Country_Presets[preset].ohs_sq >> 1)&1)<<6 ;
399 WriteReg(pVdaaHW,pVdaa->channel,INTL_CTRL1,regTemp);
400
401 regTemp = ReadReg(pVdaaHW,pVdaa->channel,DAA_CTRL5) & 0xE7;
402 regTemp |= (Vdaa_Country_Presets[preset].ohs_sq&1)<<3 ;
403 WriteReg(pVdaaHW,pVdaa->channel,DAA_CTRL5,regTemp);
404
405 regTemp = ReadReg(pVdaaHW,pVdaa->channel,CTRL2) & 0xFD;
406 regTemp |= (Vdaa_Country_Presets[preset].hbe)<<1 ;
407 WriteReg(pVdaaHW,pVdaa->channel,CTRL2,regTemp);
408
409 return RC_NONE;
410}
411#endif
412
413/*
414** Function: Vdaa_HybridSetup
415**
416** Description:
417** configure hybrid
418**
419*/
420
421#ifndef DISABLE_VDAA_HYBRID_SETUP
422extern vdaa_Hybrid_Cfg Vdaa_Hybrid_Presets [];
423
424int Vdaa_HybridSetup (vdaaChanType *pVdaa,int32 preset)
425{
426 uInt8 regSave = 0;
427
428 TRACEPRINT( pVdaa, "preset = %d\n", (unsigned int) preset);
429 if(pVdaa->channelType != DAA)
430 {
431 return RC_IGNORE;
432 }
433
434 regSave = ReadReg(pVdaaHW,pVdaa->channel,CTRL2);
435 WriteReg(pVdaaHW,pVdaa->channel,CTRL2,regSave&0xFD); /* disable hybrid */
436
437 WriteReg(pVdaaHW,pVdaa->channel,HYB1,Vdaa_Hybrid_Presets[preset].hyb1);
438 WriteReg(pVdaaHW,pVdaa->channel,HYB2,Vdaa_Hybrid_Presets[preset].hyb2);
439 WriteReg(pVdaaHW,pVdaa->channel,HYB3,Vdaa_Hybrid_Presets[preset].hyb3);
440 WriteReg(pVdaaHW,pVdaa->channel,HYB4,Vdaa_Hybrid_Presets[preset].hyb4);
441 WriteReg(pVdaaHW,pVdaa->channel,HYB5,Vdaa_Hybrid_Presets[preset].hyb5);
442 WriteReg(pVdaaHW,pVdaa->channel,HYB6,Vdaa_Hybrid_Presets[preset].hyb6);
443 WriteReg(pVdaaHW,pVdaa->channel,HYB7,Vdaa_Hybrid_Presets[preset].hyb7);
444 WriteReg(pVdaaHW,pVdaa->channel,HYB8,Vdaa_Hybrid_Presets[preset].hyb8);
445
446 WriteReg(pVdaaHW,pVdaa->channel,CTRL2,
447 regSave); /* Restore hybrid enable state at entry */
448
449 return RC_NONE;
450}
451#endif
452
453/*
454** Function: Vdaa_SetAudioMute
455**
456** Description:
457** Control RX and TX mute
458**
459*/
460
461int Vdaa_SetAudioMute(vdaaChanType *pVdaa, tMUTE mute)
462{
463 uInt8 regData;
464
465 TRACEPRINT( pVdaa, "mode = %u\n", (unsigned int) mute);
466 if(pVdaa->channelType != DAA)
467 {
468 return RC_IGNORE;
469 }
470
471 regData = ReadReg(pVdaaHW,pVdaa->channel,TXRX_GN_CTRL);
472
473 switch(mute)
474 {
475 case MUTE_DISABLE_ALL:
476 regData = 0;
477 break;
478
479 case MUTE_DISABLE_RX:
480 regData &= 0x80;
481 break;
482
483 case MUTE_DISABLE_TX:
484 regData &= 0x08;
485 break;
486
487 case MUTE_ENABLE_RX:
488 regData |= 0x08;
489 break;
490
491 case MUTE_ENABLE_TX:
492 regData |= 0x80;
493 break;
494
495 case MUTE_ENABLE_ALL:
496 regData = 0x88;
497 break;
498 }
499
500 WriteReg(pVdaaHW,pVdaa->channel,TXRX_GN_CTRL,regData);
501
502 return RC_NONE;
503}
504
505/*
506** Function: Vdaa_PCMStart
507**
508** Description:
509** Enables PCM bus
510**
511*/
512
513int Vdaa_PCMStart (vdaaChanType *pVdaa)
514{
515 uInt8 data = 0;
516
517 TRACEPRINT( pVdaa, "\n", NULL);
518 if(pVdaa->channelType != DAA)
519 {
520 return RC_IGNORE;
521 }
522
523 /*Enable PCM transfers by setting REG 33[5]=1 */
524 data = ReadReg(pVdaaHW,pVdaa->channel,PCM_SPI_CTRL);
525 data |= 0x20;
526 WriteReg(pVdaaHW,pVdaa->channel,PCM_SPI_CTRL,data);
527 return RC_NONE;
528}
529
530/*
531** Function: Vdaa_PCMStop
532**
533** Description:
534** Disables PCM bus
535**
536*/
537
538int Vdaa_PCMStop (vdaaChanType *pVdaa)
539{
540 uInt8 data = 0;
541
542 TRACEPRINT( pVdaa, "\n", NULL);
543 if(pVdaa->channelType != DAA)
544 {
545 return RC_IGNORE;
546 }
547
548 /*disable PCM transfers by setting REG 33[5]=0 */
549 data = ReadReg(pVdaaHW,pVdaa->channel,PCM_SPI_CTRL);
550 data &= ~(0x20);
551 WriteReg(pVdaaHW,pVdaa->channel,PCM_SPI_CTRL,data);
552 return RC_NONE;
553}
554
555/*
556** Function: Vdaa_SetInterruptMask
557**
558** Description:
559** Enables interrupts based on passed 9-bit bitmask. Bit
560** values defined by vdaaIntMask enum.
561**
562*/
563
564int Vdaa_SetInterruptMask(vdaaChanType *pVdaa, vdaaIntMask bitmask)
565{
566 uInt8 intMaskReg = 0;
567 uInt8 cviReg = 0;
568
569 TRACEPRINT( pVdaa, "mask = 0x%03x\n", (unsigned int)bitmask);
570 /* Channel validation */
571 if(pVdaa->channelType != DAA)
572 {
573 return RC_CHANNEL_TYPE_ERR;
574 }
575
576 intMaskReg = (uInt8)(bitmask & 0x00ff);
577 cviReg = ReadReg(pVdaaHW,pVdaa->channel,LN_VI_THRESH_INTE_CTRL);
578 cviReg |= (uInt8) ((bitmask >> 7) & 0x0002);
579
580 WriteReg (pVdaaHW,pVdaa->channel,INTE_MSK,intMaskReg);
581 WriteReg(pVdaaHW,pVdaa->channel,LN_VI_THRESH_INTE_CTRL,cviReg);
582
583 return RC_NONE;
584}
585
586/*
587** Function: Vdaa_ReadRingDetectStatus
588**
589** Description:
590** Reads ring detect/hook status
591**
592** Returns:
593**
594**
595*/
596
597int Vdaa_ReadRingDetectStatus (vdaaChanType *pVdaa,
598 vdaaRingDetectStatusType *pStatus)
599{
600 uInt8 reg;
601
602 TRACEPRINT( pVdaa, "\n", NULL);
603 if(pVdaa->channelType != DAA)
604 {
605 return RC_IGNORE;
606 }
607
608 reg = ReadReg(pVdaaHW,pVdaa->channel,DAA_CTRL1);
609 pStatus->offhook = reg & 0x01;
610 pStatus->ringDetected = (reg & 0x4)>>2;
611 pStatus->onhookLineMonitor = (reg & 0x8)>>3;
612 pStatus->ringDetectedPos = (reg & 0x20)>>5;
613 pStatus->ringDetectedNeg = (reg & 0x40)>>6;
614 return RC_NONE;
615}
616
617/*
618** Function: Vdaa_Init
619**
620** Description:
621** Initialize VDAA, load general config parameters
622**
623*/
624
625extern vdaa_General_Cfg Vdaa_General_Configuration;
626
627int Vdaa_Init (vdaaChanType_ptr *pVdaa,int size)
628{
629 uInt8 data;
630 int k;
631 int num_devices = 0;
632
633 TRACEPRINT( *pVdaa, "size = %d\n", size);
634
635 for (k=0; k<size; k++)
636 {
637
638 if(pVdaa[k]->channelType == PROSLIC)
639 {
640 continue; /* Skip if we know this is a ProSLIC, else check the device out */
641 }
642
643 if (isVerifiedDAA(pVdaa[k]) == RC_CHANNEL_TYPE_ERR)
644 {
645 pVdaa[k]->channelEnable = FALSE;
646 pVdaa[k]->error = RC_CHANNEL_TYPE_ERR;
647 pVdaa[k]->channelType = UNKNOWN;
648 DEBUG_PRINT(pVdaa[k], "%sVDAA not supported on this device\n",LOGPRINT_PREFIX);
649 continue;
650 }
651 else
652 {
653 pVdaa[k]->channelType = DAA;
654 }
655
656 if (pVdaa[k]->channelEnable)
657 {
658 /*Try to write innocuous register to test SPI is working*/
659 pVdaa[k]->WriteRegX(pVdaa[k]->pVdaaHWX,pVdaa[k]->channel,PCMRX_CNT_LO,0x5A);
660 data = pVdaa[k]->ReadRegX(pVdaa[k]->pVdaaHWX,pVdaa[k]->channel,PCMRX_CNT_LO);
661 if (data != 0x5A)
662 {
663 pVdaa[k]->error = RC_SPI_FAIL;
664 pVdaa[k]->channelEnable = FALSE;
665 DEBUG_PRINT(pVdaa[k], "%sVDAA %d not communicating\n",LOGPRINT_PREFIX,
666 pVdaa[k]->channel);
667 }
668 else
669 {
670 num_devices++;
671 }
672 }
673 }
674
675 if(num_devices == 0)
676 {
677 DEBUG_PRINT(*pVdaa, "%sNo DAA devices detected\n", LOGPRINT_PREFIX);
678 return RC_SPI_FAIL;
679 }
680
681 for (k=0; k<size; k++)
682 {
683 if(pVdaa[k]->channelType != DAA)
684 {
685 continue; /* Skip PROSLIC or UNDEFINED ports */
686 }
687 if (pVdaa[k]->channelEnable)
688 {
689
690 /* Apply General Configuration parameters */
691
692 /* No need to read-modify-write here since registers are in their reset state */
693 data = (Vdaa_General_Configuration.pwmm << 4) |
694 (Vdaa_General_Configuration.pwmEnable << 3);
695 pVdaa[k]->WriteRegX(pVdaa[k]->pVdaaHWX,pVdaa[k]->channel,CTRL1, data);
696
697 data = (Vdaa_General_Configuration.inte << 7) | (Vdaa_General_Configuration.intp
698 << 6) | 0x03;
699 pVdaa[k]->WriteRegX(pVdaa[k]->pVdaaHWX,pVdaa[k]->channel,CTRL2, data);
700
701 data = (Vdaa_General_Configuration.hssm << 3);
702 pVdaa[k]->WriteRegX(pVdaa[k]->pVdaaHWX,pVdaa[k]->channel,SMPL_CTRL, data);
703
704 data = (Vdaa_General_Configuration.iire << 4);
705 pVdaa[k]->WriteRegX(pVdaa[k]->pVdaaHWX,pVdaa[k]->channel,INTL_CTRL1, data);
706
707 data = (Vdaa_General_Configuration.rcald << 4);
708 pVdaa[k]->WriteRegX(pVdaa[k]->pVdaaHWX,pVdaa[k]->channel,RES_CALIB, data);
709
710 data = (Vdaa_General_Configuration.full2 << 4);
711 pVdaa[k]->WriteRegX(pVdaa[k]->pVdaaHWX,pVdaa[k]->channel,AC_TERM_CTRL, data);
712
713 data = (Vdaa_General_Configuration.lvfd) | (Vdaa_General_Configuration.filt <<
714 1) |
715 (Vdaa_General_Configuration.foh << 5) | (Vdaa_General_Configuration.full << 7);
716 pVdaa[k]->WriteRegX(pVdaa[k]->pVdaaHWX,pVdaa[k]->channel,DAA_CTRL5, data);
717
718 data = (Vdaa_General_Configuration.spim << 6);
719 pVdaa[k]->WriteRegX(pVdaa[k]->pVdaaHWX,pVdaa[k]->channel,PCM_SPI_CTRL, data);
720
721 data = (Vdaa_General_Configuration.cvp) | (Vdaa_General_Configuration.cvs << 2);
722 pVdaa[k]->WriteRegX(pVdaa[k]->pVdaaHWX,pVdaa[k]->channel,LN_VI_THRESH_INTE_CTRL,
723 data);
724
725 data = (Vdaa_General_Configuration.gce << 1) | (Vdaa_General_Configuration.rg1
726 << 2);
727 pVdaa[k]->WriteRegX(pVdaa[k]->pVdaaHWX,pVdaa[k]->channel,SPRK_QNCH_CTRL, data);
728
729 /* Enable Lineside Device */
730 Vdaa_PowerupLineside(pVdaa[k]);
731 }
732 }
733 DEBUG_PRINT(*pVdaa,"%sDAA initialization completed\n",LOGPRINT_PREFIX);
734 return RC_NONE;
735}
736
737/*
738** Function: Vdaa_ReadLinefeedStatus
739**
740** Description:
741** Read Status of Line Feed
742**
743** Returns:
744** RC_VDAA_ILOOP_OVLD if LCS >= 0x1F
745** - no overload
746**
747*/
748
749int Vdaa_ReadLinefeedStatus (vdaaChanType *pVdaa,int8 *vloop, int16 *iloop)
750{
751 int16 regTemp = 0x1F;
752 uInt8 iloop_reg; /* REG 12[4:0] = Loop current*/
753
754 TRACEPRINT( pVdaa, "\n", NULL);
755 if(pVdaa->channelType != DAA)
756 {
757 return RC_IGNORE;
758 }
759 regTemp &= ReadReg(pVdaaHW,pVdaa->channel,LSIDE_STAT);
760 iloop_reg = (uInt8)regTemp;
761 *iloop = (regTemp*LCS_SCALE_NUM) /
762 LCS_SCALE_DEN; /* Multiply the read result by 3.3mA/bit*/
763
764 *vloop = (int8) ReadReg(pVdaaHW,pVdaa->channel,LINE_VOLT_STAT);
765 if(*vloop & 0x80)
766 {
767 *vloop = ~(*vloop - 1)*(-1);
768 }
769
770 if (iloop_reg == 0x1F)
771 {
772 return RC_VDAA_ILOOP_OVLD;
773 }
774 return RC_NONE;
775}
776
777/*
778** Function: Vdaa_GetInterrupts
779**
780** Description:
781** Get Interrupts
782**
783** Returns:
784** number of interrupts
785**
786*/
787
788int Vdaa_GetInterrupts (vdaaChanType *pVdaa,vdaaIntType *pIntData)
789{
790 uInt8 data = 0;
791 int j;
792 TRACEPRINT( pVdaa, "\n", NULL);
793 pIntData->number = 0;
794
795 if(pVdaa->channelType != DAA)
796 {
797 return RC_IGNORE;
798 }
799
800 data = ReadReg(pVdaaHW,pVdaa->channel,INTE_SRC); /*Snapshot Interrupts*/
801 WriteReg(pVdaaHW,pVdaa->channel,INTE_SRC,~(data)); /*Clear interrupts*/
802
803 for (j=0; j<8; j++)
804 {
805 if (data &(1<<j))
806 {
807
808 pIntData->irqs[pIntData->number] = j;
809 pIntData->number++;
810
811 }
812 }
813 data = ReadReg(pVdaaHW,pVdaa->channel,LN_VI_THRESH_INTE_CTRL);
814
815 if (data &(0x08)) /*to determine if CVI Interrupt is set*/
816 {
817 pIntData->irqs[pIntData->number] = CVI;
818 pIntData->number++;
819 data &= ~(0x08);
820 WriteReg(pVdaaHW,pVdaa->channel,LN_VI_THRESH_INTE_CTRL,data);
821
822 }
823
824 return pIntData->number;
825}
826
827/*
828** Function: Vdaa_ClearInterrupts
829**
830** Description:
831** Clear Interrupts
832**
833** Returns:
834**
835**
836*/
837
838int Vdaa_ClearInterrupts (vdaaChanType *pVdaa)
839{
840 uInt8 data = 0;
841
842 TRACEPRINT( pVdaa, "\n", NULL);
843 if(pVdaa->channelType != DAA)
844 {
845 return RC_IGNORE;
846 }
847
848 WriteReg(pVdaaHW,pVdaa->channel,INTE_SRC,
849 0x00); /* Clear interrupts in REG 4 by writing 0's*/
850
851 /*Clear CVI interrupt by writing 0 at REG 44[3]*/
852 data = ReadReg(pVdaaHW,pVdaa->channel,LN_VI_THRESH_INTE_CTRL);
853 WriteReg(pVdaaHW,pVdaa->channel,LN_VI_THRESH_INTE_CTRL,data&0xF7);
854
855 return RC_NONE;
856}
857
858/*
859** Function: Vdaa_GetHookStatus
860**
861** Description:
862** Read VDAA Hook Status
863**
864** Return Values -
865** VDAA_ONHOOK
866** VDAA_OFFHOOK
867** VDAA_ONHOOK_MONITOR
868** RC_INVALID_HOOK_STATUS
869*/
870
871uInt8 Vdaa_GetHookStatus (vdaaChanType *pVdaa)
872{
873 uInt8 data;
874
875 TRACEPRINT( pVdaa, "\n", NULL);
876 if(pVdaa->channelType != DAA)
877 {
878 return RC_IGNORE;
879 }
880
881 data = ReadReg(pVdaaHW,pVdaa->channel,DAA_CTRL1);
882 data &= 0x09; /* Look at only ONHM and OH */
883
884 if((data & 0x80)&&(data & 0x01))
885 {
886 return VDAA_ONHOOK_MONITOR;
887 }
888 else if (data & 0x01)
889 {
890 return VDAA_OFFHOOK;
891 }
892 else
893 {
894 return VDAA_ONHOOK;
895 }
896}
897
898/*
899** Function: Vdaa_SetHookStatus
900**
901** Description:
902** Set VDAA Hook switch to ONHOOK, OFFHOOK,
903** or ONHOOK_MONITOR
904**
905*/
906
907int Vdaa_SetHookStatus (vdaaChanType *pVdaa,uInt8 newHookStatus)
908{
909 uInt8 data= 0 ;
910
911 TRACEPRINT( pVdaa, "hookstate = %u\n", (unsigned int) newHookStatus);
912
913 if(pVdaa->channelType != DAA)
914 {
915 return RC_IGNORE;
916 }
917
918 switch (newHookStatus)
919 {
920 case VDAA_DIG_LOOPBACK:
921 /*Setting REG6[4]=1,REG5[0]=0,REG5[3]=0*/
922 data = ReadReg(pVdaaHW,pVdaa->channel,DAA_CTRL2);
923 data |= 0x10;
924 WriteReg(pVdaaHW,pVdaa->channel,DAA_CTRL2,data);
925 data = ReadReg(pVdaaHW,pVdaa->channel,DAA_CTRL1);
926 data &= ~(0x09);
927 WriteReg(pVdaaHW,pVdaa->channel,DAA_CTRL1,data);
928 break;
929
930 case VDAA_ONHOOK:
931 /*Setting REG6[4]=0,REG5[0]=0,REG5[3]=0*/
932 data = ReadReg(pVdaaHW,pVdaa->channel,DAA_CTRL1);
933 data &= 0xF6;
934 WriteReg(pVdaaHW,pVdaa->channel,DAA_CTRL1,data);
935 data = ReadReg(pVdaaHW,pVdaa->channel,DAA_CTRL2);
936 data &= 0xEF;
937 WriteReg(pVdaaHW,pVdaa->channel,DAA_CTRL2,data);
938 break;
939
940 case VDAA_OFFHOOK:
941 /*Setting REG6[4]=0,REG5[0]=1,REG5[3]=0*/
942 data = ReadReg(pVdaaHW,pVdaa->channel,DAA_CTRL1);
943 data &= 0xF7;
944 data |= 0x01;
945 WriteReg(pVdaaHW,pVdaa->channel,DAA_CTRL1,data);
946 data = ReadReg(pVdaaHW,pVdaa->channel,DAA_CTRL2);
947 data &= 0xEF;
948 WriteReg(pVdaaHW,pVdaa->channel,DAA_CTRL2,data);
949 break;
950
951 case VDAA_ONHOOK_MONITOR:
952 /*Setting REG6[4]=0,REG5[0]=0,REG5[3]=1*/
953 data = ReadReg(pVdaaHW,pVdaa->channel,DAA_CTRL1);
954 data &= 0xFE;
955 data |= 0x08;
956 WriteReg(pVdaaHW,pVdaa->channel,DAA_CTRL1,data);
957 data = ReadReg(pVdaaHW,pVdaa->channel,DAA_CTRL2);
958 data &= 0xEF;
959 WriteReg(pVdaaHW,pVdaa->channel,DAA_CTRL2,data);
960 break;
961
962 default:
963 return RC_UNSUPPORTED_OPTION;
964 }
965
966 return RC_NONE;
967}
968
969/*
970** Function: Vdaa_SetLoopbackMode
971**
972** Description:
973** Loopback mode control
974**
975*/
976
977int Vdaa_SetLoopbackMode(vdaaChanType_ptr pVdaa, tLpbkMode lpbk_mode,
978 tLpbkStatus lpbk_status)
979{
980 uInt8 regData;
981
982 TRACEPRINT(pVdaa, "lpbk_mode = %u lpbk_status = %d\n", (unsigned int) lpbk_mode,
983 (unsigned int) lpbk_status);
984 if(pVdaa->channelType != DAA)
985 {
986 return RC_IGNORE;
987 }
988
989 switch(lpbk_mode)
990 {
991 case LPBK_NONE:
992 /* Disable all loopback types, regardless of lpbk_status */
993 regData = ReadReg(pVdaaHW,pVdaa->channel,CTRL1);
994 if(regData & 0x02)
995 {
996 WriteReg(pVdaaHW,pVdaa->channel,CTRL1, regData & ~(0x02));
997 }
998
999 regData = ReadReg(pVdaaHW,pVdaa->channel,DAA_CTRL3);
1000 if(regData & 0x01)
1001 {
1002 WriteReg(pVdaaHW,pVdaa->channel,DAA_CTRL3,0);
1003 }
1004
1005 regData = ReadReg(pVdaaHW,pVdaa->channel,PCM_SPI_CTRL);
1006 if(regData & 0x80)
1007 {
1008 WriteReg(pVdaaHW,pVdaa->channel,PCM_SPI_CTRL, regData & ~(0x80));
1009 }
1010 break;
1011
1012 case LPBK_IDL:
1013 if(lpbk_status)
1014 {
1015 regData = ReadReg(pVdaaHW,pVdaa->channel,CTRL1);
1016 WriteReg(pVdaaHW,pVdaa->channel,CTRL1, regData | 0x02);
1017 }
1018 else
1019 {
1020 regData = ReadReg(pVdaaHW,pVdaa->channel,CTRL1);
1021 WriteReg(pVdaaHW,pVdaa->channel,CTRL1, regData & ~(0x02));
1022 }
1023 break;
1024
1025 case LPBK_DDL:
1026 if(lpbk_status)
1027 {
1028 WriteReg(pVdaaHW,pVdaa->channel,DAA_CTRL3, 0x01);
1029 }
1030 else
1031 {
1032 WriteReg(pVdaaHW,pVdaa->channel,DAA_CTRL3, 0);
1033 }
1034 break;
1035
1036 case LPBK_PCML:
1037 if(lpbk_status)
1038 {
1039 regData = ReadReg(pVdaaHW,pVdaa->channel,PCM_SPI_CTRL);
1040 WriteReg(pVdaaHW,pVdaa->channel,PCM_SPI_CTRL, regData | 0x80);
1041 }
1042 else
1043 {
1044 regData = ReadReg(pVdaaHW,pVdaa->channel,PCM_SPI_CTRL);
1045 WriteReg(pVdaaHW,pVdaa->channel,PCM_SPI_CTRL, regData & ~(0x80));
1046 }
1047 break;
1048
1049 default:
1050 return RC_UNSUPPORTED_OPTION;
1051 }
1052
1053 return RC_NONE;
1054}
1055
1056/*
1057** Function: Vdaa_ADCCal
1058**
1059** Description:
1060** This function calibrates the VDAA ADC manually
1061**
1062*/
1063
1064int Vdaa_ADCCal (vdaaChanType_ptr pVdaa, int32 size)
1065{
1066 uInt8 regTemp = 0;
1067 int32 i;
1068
1069 TRACEPRINT(pVdaa, "size = %d\n", (int) size);
1070 if(pVdaa->channelType != DAA)
1071 {
1072 return RC_IGNORE;
1073 }
1074
1075 for(i = 0; i < size; i++)
1076 {
1077 /* Clear the previous ADC Calibration data by toggling CALZ*/
1078 regTemp = ReadReg(pVdaaHW,pVdaa->channel,INTL_CTRL2);
1079 regTemp |= 0x80;
1080 WriteReg(pVdaaHW,pVdaa->channel,INTL_CTRL2,regTemp);
1081 regTemp &= ~0x80;
1082 WriteReg(pVdaaHW,pVdaa->channel,INTL_CTRL2,regTemp);
1083
1084 regTemp = ReadReg(pVdaaHW,pVdaa->channel,INTL_CTRL2); /*disable auto cal*/
1085 regTemp |= 0x20;
1086 WriteReg(pVdaaHW,pVdaa->channel,INTL_CTRL2,regTemp);
1087
1088 regTemp |= 0x40; /*initiate manual cal*/
1089 WriteReg(pVdaaHW,pVdaa->channel,INTL_CTRL2,regTemp);
1090 regTemp &= ~0x40;
1091 WriteReg(pVdaaHW,pVdaa->channel,INTL_CTRL2,regTemp);
1092 pVdaa++;
1093 }
1094 return RC_NONE;
1095}
1096
1097/*
1098** Function: Vdaa_EnableWatchdog
1099**
1100** Description:
1101** Enables watchdog timer
1102**
1103*/
1104
1105int Vdaa_EnableWatchdog(vdaaChanType_ptr pVdaa)
1106{
1107 uInt8 regTemp;
1108
1109 TRACEPRINT(pVdaa, "\n", NULL);
1110 if(pVdaa->channelType != DAA)
1111 {
1112 return RC_IGNORE;
1113 }
1114
1115 regTemp = ReadReg(pVdaaHW,pVdaa->channel,CTRL2);
1116 WriteReg(pVdaaHW,pVdaa->channel,CTRL2,regTemp | 0x10);
1117
1118 return RC_NONE;
1119}
1120
1121/*
1122** Function: Vdaa_SetHybridEnable
1123**
1124** Description:
1125** Enables watchdog timer
1126**
1127*/
1128
1129int Vdaa_SetHybridEnable(vdaaChanType_ptr pVdaa, int enable)
1130{
1131 uInt8 regTemp;
1132 TRACEPRINT(pVdaa, "enable = %d\n", enable);
1133
1134 if(pVdaa->channelType != DAA)
1135 {
1136 return RC_IGNORE;
1137 }
1138
1139 regTemp = ReadReg(pVdaaHW,pVdaa->channel,CTRL2);
1140 if(enable)
1141 {
1142 WriteReg(pVdaaHW,pVdaa->channel,CTRL2,regTemp | 0x02);
1143 }
1144 else
1145 {
1146 WriteReg(pVdaaHW,pVdaa->channel,CTRL2,regTemp & ~(0x02));
1147 }
1148
1149 return RC_NONE;
1150}
1151
1152
1153/*
1154** Function: Vdaa_SoftReset
1155**
1156** Description:
1157** Execute soft reset
1158**
1159*/
1160
1161int Vdaa_SoftReset(vdaaChanType_ptr pVdaa)
1162{
1163 TRACEPRINT(pVdaa, "\n", NULL);
1164 if(pVdaa->channelType != DAA)
1165 {
1166 return RC_IGNORE;
1167 }
1168
1169 WriteReg(pVdaaHW,pVdaa->channel,CTRL1,0x80);
1170 return RC_NONE;
1171}
1172
1173/*
1174** Function: Vdaa_ReadFDTStatus
1175**
1176** Description:
1177** Read FDT bit
1178**
1179** Returns:
1180** 0 - Frame Not Detected
1181** 1 - Frame Detected
1182**
1183*/
1184
1185int Vdaa_ReadFDTStatus(vdaaChanType_ptr pVdaa)
1186{
1187 TRACEPRINT(pVdaa, "\n", NULL);
1188 return (ReadReg(pVdaaHW,pVdaa->channel,LSIDE_REV) & 0x40);
1189}
1190
1191/*
1192** Function: Vdaa_PowerupLineside
1193**
1194** Description:
1195** Power up lineside device
1196**
1197*/
1198
1199int Vdaa_PowerupLineside(vdaaChanType_ptr pVdaa)
1200{
1201 uInt8 data;
1202
1203 TRACEPRINT(pVdaa, "\n", NULL);
1204 if(pVdaa->channelType != DAA)
1205 {
1206 return RC_IGNORE;
1207 }
1208
1209 WriteReg(pVdaaHW,pVdaa->channel,DAA_CTRL2,0); /* Powerup lineside device */
1210 /* We do a double read to give the front end time to power up and sync up with the system side.. */
1211 data = ReadReg(pVdaaHW,pVdaa->channel,LSIDE_REV);
1212 data = 0;
1213 data = ReadReg(pVdaaHW,pVdaa->channel,LSIDE_REV);
1214 pVdaa->deviceId->lsRev= ((data&0x3C)>>2);
1215 data = pVdaa->ReadRegX(pVdaa->pVdaaHWX,pVdaa->channel,SYS_LINE_DEV_REV);
1216 pVdaa->deviceId->lsType= ((data&~(0xF))>>4);
1217
1218 return RC_NONE;
1219}
1220
1221/*
1222** Function: Vdaa_PowerdownLineside
1223**
1224** Description:
1225** Power down lineside device
1226**
1227*/
1228
1229int Vdaa_PowerdownLineside(vdaaChanType_ptr pVdaa)
1230{
1231 TRACEPRINT(pVdaa, "\n", NULL);
1232 if(pVdaa->channelType != DAA)
1233 {
1234 return RC_IGNORE;
1235 }
1236
1237 WriteReg(pVdaaHW,pVdaa->channel,DAA_CTRL2,0x10);
1238 return RC_NONE;
1239}
1240
1241/*
1242** Function: Vdaa_PrintDebugData
1243**
1244** Description:
1245** Dump of VDAA register space
1246**
1247** Input Parameters:
1248** pVdaa: pointer to SiVoiceChanType or vdaaChanType
1249**
1250*/
1251
1252int Vdaa_PrintDebugData (vdaaChanType *pVdaa)
1253{
1254#ifdef ENABLE_DEBUG
1255 int i;
1256 for (i=0; i<60; i++)
1257 {
1258 LOGPRINT ("%sRegister %d = %X\n",LOGPRINT_PREFIX,i,ReadReg(pVdaaHW,
1259 pVdaa->channel,i));
1260 }
1261#endif
1262 return RC_NONE;
1263}
1264
1265/*
1266** Function: Vdaa_InitLineInUseCheck
1267**
1268** Description:
1269** Set line in use test limits
1270**
1271** Input Parameters:
1272** liuCfg: pointer to vdaa_LIU_Config
1273** minOnV: minimum acceptable onhook voltage (below indicates parallel handset)
1274** minOffV: minimum acceptable offhook voltage (below indicates parallel handset)
1275** minOffI: minimum acceptable offhook loop current (below indicates parallel handset)
1276**
1277*/
1278
1279int Vdaa_InitLineInUseCheck(vdaa_LIU_Config *liuCfg, int8 minOnV, int8 minOffV,
1280 int16 minOffI)
1281{
1282 TRACEPRINT_NOCHAN("min0nV = %d minoffV = %d minOffI = %d\n", minOnV, minOffV,
1283 minOffI);
1284 liuCfg->status = PAR_HANDSET_NOT_DETECTED;
1285 liuCfg->min_onhook_vloop = minOnV;
1286 liuCfg->min_offhook_vloop = minOffV;
1287 liuCfg->min_offhook_iloop = minOffI;
1288 return RC_NONE;
1289}
1290
1291/*
1292** Function: Vdaa_CheckForLineInUse
1293**
1294** Description:
1295** Monitor LVCS to detect intrusion or parallel handset
1296**
1297** Input Parameters:
1298** pVdaa: pointer to SiVoiceChanType or vdaaChanType
1299** liuCfg: pointer to vdaa_LIU_Config
1300**
1301** Output Parameters:
1302**
1303** Return:
1304** VDAA_ONHOOK - line is onhook
1305** VDAA_OFFHOOK - line is offhook (in use)
1306**
1307*/
1308
1309uInt8 Vdaa_CheckForLineInUse(vdaaChanType *pVdaa, vdaa_LIU_Config *liuCfg)
1310{
1311 int8 vloop;
1312 int16 iloop;
1313
1314 TRACEPRINT(pVdaa, "\n", NULL);
1315 if(pVdaa->channelType != DAA)
1316 {
1317 return RC_IGNORE;
1318 }
1319
1320 /* Check voltage and current */
1321 Vdaa_ReadLinefeedStatus(pVdaa, &vloop,&iloop);
1322 if(vloop < 0)
1323 {
1324 vloop *= -1;
1325 }
1326 liuCfg->measured_iloop = iloop;
1327 liuCfg->measured_vloop = vloop;
1328 liuCfg->status = PAR_HANDSET_NOT_DETECTED;
1329
1330 /* Read hookswitch status */
1331 if(Vdaa_GetHookStatus(pVdaa) == VDAA_OFFHOOK)
1332 {
1333 if((vloop < liuCfg->min_offhook_vloop)||(iloop < liuCfg->min_offhook_iloop))
1334 {
1335 liuCfg->status = PAR_HANDSET_DETECTED;
1336 }
1337
1338 return VDAA_OFFHOOK;
1339 }
1340 else
1341 {
1342 if(vloop < liuCfg->min_onhook_vloop)
1343 {
1344 liuCfg->status = PAR_HANDSET_DETECTED;
1345 }
1346
1347 return VDAA_ONHOOK;
1348 }
1349}
1350