[][Add Proslic SI3218x audio codec driver]

[Description]
Add Proslic SI3218x audio codec driver

[Release-log]
N/A

Change-Id: I30edf714fda413b220b6a0f3e301a7bc3f899c08
Reviewed-on: https://gerrit.mediatek.inc/c/openwrt/feeds/mtk_openwrt_feeds/+/5396999
diff --git a/target/linux/mediatek/files-5.4/sound/soc/codecs/si3218x/src/proslic.c b/target/linux/mediatek/files-5.4/sound/soc/codecs/si3218x/src/proslic.c
new file mode 100644
index 0000000..7a75cc8
--- /dev/null
+++ b/target/linux/mediatek/files-5.4/sound/soc/codecs/si3218x/src/proslic.c
@@ -0,0 +1,4651 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Distributed by:
+ * Silicon Laboratories, Inc
+ *
+ * This file contains proprietary information.
+ * No dissemination allowed without prior written permission from
+ * Silicon Laboratories, Inc.
+ *
+ * File Description:
+ * This is the generic interface file for the ProSLIC drivers.
+ *
+ * Customers should be calling this level for ProSLIC specific
+ * functions (vs. chipset specific versions of the code)
+ *
+ */
+
+#include "../config_inc/si_voice_datatypes.h"
+#include "../inc/si_voice_ctrl.h"
+#include "../inc/si_voice_timer_intf.h"
+#include "../inc/proslic.h"
+#include "../config_inc/proslic_api_config.h"
+
+#ifdef ENABLE_DEBUG
+#define LOGPRINT_PREFIX "ProSLIC:"
+#endif
+
+#ifdef SI3217X
+#include "si3217x.h"
+#include "si3217x_intf.h"
+extern Si3217x_General_Cfg Si3217x_General_Configuration;
+#ifndef DISABLE_FSK_SETUP
+extern ProSLIC_FSK_Cfg Si3217x_FSK_Presets[];
+#endif
+#ifndef DISABLE_TONE_SETUP
+extern ProSLIC_Tone_Cfg Si3217x_Tone_Presets[];
+#endif
+
+#endif /* 17X */
+
+#ifdef SI3218X
+#include "../inc/si3218x.h"
+#include "../inc/si3218x_intf.h"
+extern Si3218x_General_Cfg Si3218x_General_Configuration;
+#ifndef DISABLE_FSK_SETUP
+extern ProSLIC_FSK_Cfg Si3218x_FSK_Presets[];
+#endif
+#ifndef DISABLE_TONE_SETUP
+extern ProSLIC_Tone_Cfg Si3218x_Tone_Presets[];
+#endif
+#endif /* 18X */ 
+
+#ifdef SI3219X
+#include "si3219x.h"
+#include "si3219x_intf.h"
+extern Si3219x_General_Cfg Si3219x_General_Configuration;
+#ifndef DISABLE_FSK_SETUP
+extern ProSLIC_FSK_Cfg Si3219x_FSK_Presets[];
+#endif
+#ifndef DISABLE_TONE_SETUP
+extern ProSLIC_Tone_Cfg Si3219x_Tone_Presets[];
+#endif
+#endif /* 19X */
+
+#ifdef SI3226X
+#include "si3226x.h"
+#include "si3226x_intf.h"
+extern Si3226x_General_Cfg Si3226x_General_Configuration;
+#ifndef DISABLE_FSK_SETUP
+extern ProSLIC_FSK_Cfg Si3226x_FSK_Presets[];
+#endif
+#ifndef DISABLE_TONE_SETUP
+extern ProSLIC_Tone_Cfg Si3226x_Tone_Presets[];
+#endif
+#endif /* 26X */
+
+#ifdef SI3228X
+#include "si3228x.h"
+#include "si3228x_intf.h"
+extern Si3228x_General_Cfg Si3228x_General_Configuration;
+#ifndef DISABLE_FSK_SETUP
+extern ProSLIC_FSK_Cfg Si3228x_FSK_Presets[];
+#endif
+#ifndef DISABLE_TONE_SETUP
+extern ProSLIC_Tone_Cfg Si3228x_Tone_Presets[];
+#endif
+
+#endif /* 28X */
+
+#define pCtrl(X)                                   (X)->deviceId->ctrlInterface
+#define pProHW(X)                                  pCtrl((X))->hCtrl
+#define WriteRAM(PCHAN, CHANNEL, RAMADDR, RAMDATA) (PCHAN)->deviceId->ctrlInterface->WriteRAM_fptr(pProHW(PCHAN), (CHANNEL), (RAMADDR), (RAMDATA))
+#define ReadRAM(PCHAN, CHANNEL, RAMADDR)           (PCHAN)->deviceId->ctrlInterface->ReadRAM_fptr(pProHW(PCHAN), (CHANNEL), (RAMADDR))
+#define SetSemaphore(X)                            (X)->deviceId->ctrlInterface->Semaphore_fptr
+#define ReadReg(PCHAN, CHANNEL, REGADDR)           (PCHAN)->deviceId->ctrlInterface->ReadRegister_fptr(pProHW(PCHAN), (CHANNEL), (REGADDR))
+#define WriteReg(PCHAN, CHANNEL, REGADDR, REGDATA) (PCHAN)->deviceId->ctrlInterface->WriteRegister_fptr(pProHW(PCHAN), (CHANNEL), (REGADDR), (REGDATA))
+
+/*
+** Timers
+*/
+#define TimeElapsed   pProslic->deviceId->ctrlInterface->timeElapsed_fptr
+#define getTime       pProslic->deviceId->ctrlInterface->getTime_fptr
+#define pProTimer	    pProslic->deviceId->ctrlInterface->hTimer
+#define Delay         pProslic->deviceId->ctrlInterface->Delay_fptr
+#define pProTimerX(X)	((X)->deviceId->ctrlInterface->hTimer)
+#define DelayX(X,Y)   ((X)->deviceId->ctrlInterface->Delay_fptr(pProTimerX(X),Y))
+
+#define PROSLIC_TIMEOUT_DCDC_DOWN 200 /* Number of 10 mSec ticks */
+
+/*****************************************************************************************************/
+int32 ProSLIC_ReadMADCScaled(proslicChanType_ptr hProslic,uInt16 addr,
+                             int32 scale)
+{
+  TRACEPRINT(hProslic,"addr: %u scale: %ld\n", addr, scale);
+#ifdef SI3217X
+  if (hProslic->deviceId->chipType >= SI32171
+      && hProslic->deviceId->chipType <= SI32179)
+  {
+    return Si3217x_ReadMADCScaled(hProslic,addr,scale);
+  }
+#endif
+
+#ifdef SI3218X
+  if (hProslic->deviceId->chipType >= SI32180
+      && hProslic->deviceId->chipType <= SI32189)
+  {
+    return Si3218x_ReadMADCScaled(hProslic,addr,scale);
+  }
+#endif
+
+#ifdef SI3219X
+  if ( IS_SI3219X(hProslic->deviceId) )
+  {
+    return Si3219x_ReadMADCScaled(hProslic,addr,scale);
+  }
+#endif
+
+#ifdef SI3226X
+  if (hProslic->deviceId->chipType >= SI32260
+      && hProslic->deviceId->chipType <= SI32269)
+  {
+    return Si3226x_ReadMADCScaled(hProslic,addr,scale);
+  }
+#endif
+
+#ifdef SI3228X
+  if (hProslic->deviceId->chipType >= SI32280
+      && hProslic->deviceId->chipType <= SI32289)
+  {
+    return Si3228x_ReadMADCScaled(hProslic,addr,scale);
+  }
+#endif
+
+  return -1;
+}
+
+/*****************************************************************************************************/
+ramData ProSLIC_ReadRAM(proslicChanType_ptr hProslic,uInt16 addr)
+{
+  TRACEPRINT(hProslic, "addr: %u\n", addr);
+  if(hProslic->channelType != PROSLIC)
+  {
+    return RC_IGNORE;
+  }
+  return (ReadRAM(hProslic, hProslic->channel, addr));
+}
+
+/*****************************************************************************************************/
+int ProSLIC_WriteRAM(proslicChanType_ptr hProslic,uInt16 addr, ramData data)
+{
+  TRACEPRINT(hProslic, "addr: %u data: 0x%04X\n", addr, data);
+  if(hProslic->channelType != PROSLIC)
+  {
+    return RC_IGNORE;
+  }
+  return (WriteRAM(hProslic, hProslic->channel, addr,data));
+}
+
+/*****************************************************************************************************/
+int ProSLIC_PrintDebugData(proslicChanType_ptr hProslic)
+{
+  TRACEPRINT(hProslic, "\n", NULL);
+#ifdef ENABLE_DEBUG
+  ProSLIC_PrintDebugReg(hProslic);
+  return ProSLIC_PrintDebugRAM(hProslic);
+#else
+  SILABS_UNREFERENCED_PARAMETER(hProslic);
+  return RC_NONE;
+#endif
+}
+
+/*****************************************************************************************************/
+int ProSLIC_PrintDebugReg(proslicChanType_ptr hProslic)
+{
+#ifdef ENABLE_DEBUG
+  uInt8 regAddr;
+  TRACEPRINT(hProslic, "\n", NULL);
+
+  /*
+     NOTE: Not all ProSLICs have defined values after location 99
+     (and have 1 location after that), but for simplicity, we print them anyway...
+  */
+  for(regAddr = 0; regAddr < 127; regAddr++)
+  {
+    LOGPRINT("%sRegister %03u = 0x%02X\n", LOGPRINT_PREFIX, regAddr,
+             ReadReg(hProslic, hProslic->channel, regAddr));
+  }
+#else
+  SILABS_UNREFERENCED_PARAMETER(hProslic);
+#endif
+
+  return RC_NONE;
+}
+
+/*****************************************************************************************************/
+/* NOTE: locations above 1024 are protected, the API disables protection during initialization, but if this
+   function is called prior to initialization, then UAM is not set and will impact the ReadRAM call...
+   Upper limit is based upon chipset type...
+*/
+int ProSLIC_PrintDebugRAM(proslicChanType_ptr hProslic)
+{
+#ifdef ENABLE_DEBUG
+  uInt16 ramAddr;
+  uInt16 maxAddr= 0;
+  TRACEPRINT(hProslic, "\n",NULL);
+
+  if(hProslic->channelType != PROSLIC)
+  {
+    return RC_IGNORE;
+  }
+
+#ifdef SI3217X
+  if (hProslic->deviceId->chipType >= SI32171
+      && hProslic->deviceId->chipType <= SI32179)
+  {
+    maxAddr = 1596;
+  }
+#endif
+
+#ifdef SI3218X
+  if (hProslic->deviceId->chipType >= SI32180
+      && hProslic->deviceId->chipType <= SI32189)
+  {
+    maxAddr = 1644;
+  }
+#endif
+
+#ifdef SI3219X
+  if ( IS_SI3219X(hProslic->deviceId) )
+  {
+    maxAddr = 1644;
+  }
+#endif
+
+#ifdef SI3226X
+  if (hProslic->deviceId->chipType >= SI32260
+      && hProslic->deviceId->chipType <= SI32269)
+  {
+    maxAddr = 1646;
+  }
+#endif
+
+#ifdef SI3228X
+  if (hProslic->deviceId->chipType >= SI32280
+      && hProslic->deviceId->chipType <= SI32289)
+  {
+    maxAddr = 1646;
+  }
+#endif
+
+  for(ramAddr = 0; ramAddr < maxAddr; ramAddr++)
+  {
+    LOGPRINT("%sRAM %04u = 0x%08X\n", LOGPRINT_PREFIX, ramAddr,
+             (unsigned int)(ReadRAM(hProslic, hProslic->channel, ramAddr)));
+  }
+#else
+  SILABS_UNREFERENCED_PARAMETER(hProslic);
+#endif /* ENABLE_DEBUG */
+  return RC_NONE;
+}
+
+/*****************************************************************************************************/
+/*
+** Function: isVerifiedProslic
+**
+** Description:
+** Determine if DAA or ProSLIC present
+**
+** Input Parameters:
+** pProslic: pointer to PROSLIC channel object
+**
+** Return:
+** channelType
+*/
+int ProSLIC_identifyChannelType(proslicChanType *pProslic)
+{
+  uInt8 data;
+  TRACEPRINT(pProslic, "\n",NULL);
+  /*
+  **  Register 13 (DAA) always has bits 0:1 set to 0 and bit 6 set to 1
+  **  Register 13 (PROSLIC) can have bits 0:1, and 4 set, while all others are undefined
+  **  Write 0x13 to Reg 13. The following return values are expected -
+  **
+  **   0x00 or 0xFF    :    No device present
+  **   0x4X            :    DAA
+  **   0x13            :    PROSLIC
+  */
+
+  WriteReg(pProslic,pProslic->channel,PROSLIC_REG_PCMTXHI,0x13);
+  Delay(pProTimer,5);
+
+  /* Now check if the value took */
+  data = ReadReg(pProslic,pProslic->channel,PROSLIC_REG_PCMTXHI);
+
+  if( data == 0x13)
+  {
+    return PROSLIC;
+  }
+  else if (data == 0x40)
+  {
+    return DAA;
+  }
+  else
+  {
+    return UNKNOWN;
+  }
+}
+
+/*****************************************************************************************************/
+int ProSLIC_VerifyControlInterface(proslicChanType_ptr hProslic)
+{
+  TRACEPRINT(hProslic, "\n",NULL);
+  if (ProSLIC_identifyChannelType(hProslic) != PROSLIC)
+  {
+    return RC_CHANNEL_TYPE_ERR;
+  }
+
+  /* Note: ProSLIC_identifyChannelType() did a register w/r test earlier */
+
+  /* Verify RAM rd/wr with innocuous RAM location */
+  WriteRAM(hProslic,hProslic->channel,PROSLIC_RAM_VERIFY_IO,0x12345678L);
+  if (ReadRAM(hProslic,hProslic->channel, PROSLIC_RAM_VERIFY_IO) != 0x12345678L)
+  {
+    hProslic->error = RC_SPI_FAIL;
+    DEBUG_PRINT(hProslic, "%sProslic %d RAM not communicating. RAM access fail.\n",
+                LOGPRINT_PREFIX, hProslic->channel);
+    return RC_SPI_FAIL;
+  }
+  return RC_NONE;
+}
+
+/*****************************************************************************************************/
+int ProSLIC_VerifyMasterStat(proslicChanType_ptr pProslic)
+{
+  uInt8 regData;
+
+  TRACEPRINT(pProslic, "\n", NULL);
+  WriteReg(pProslic,pProslic->channel, PROSLIC_REG_MSTRSTAT,
+           0xFF); /* Clear Master status */
+  regData = ReadReg(pProslic, pProslic->channel, PROSLIC_REG_MSTRSTAT);
+
+  if( regData != 0x1F )
+  {
+    return RC_SPI_FAIL;
+  }
+  else
+  {
+    return RC_NONE;
+  }
+}
+
+/*****************************************************************************************************/
+#ifdef SIVOICE_MULTI_BOM_SUPPORT
+int ProSLIC_Init_MultiBOM (proslicChanType_ptr *hProslic,int size, int preset)
+{
+  TRACEPRINT(*hProslic, "size: %d preset: %d\n", size, preset);
+#ifdef SI3217X
+  if ((*hProslic)->deviceId->chipType >= SI32171
+      && (*hProslic)->deviceId->chipType <= SI32179)
+  {
+    return Si3217x_Init_MultiBOM(hProslic,size,preset);
+  }
+#endif
+
+#ifdef SI3218X
+  if ((*hProslic)->deviceId->chipType >= SI32180
+      && (*hProslic)->deviceId->chipType <= SI32189)
+  {
+    return Si3218x_Init_MultiBOM(hProslic,size,preset);
+  }
+#endif
+
+#ifdef SI3219X
+  if ( IS_SI3219X((*hProslic)->deviceId) )
+  {
+    return Si3219x_Init_MultiBOM(hProslic,size,preset);
+  }
+#endif
+
+#ifdef SI3226X
+  if ((*hProslic)->deviceId->chipType >= SI32260
+      && (*hProslic)->deviceId->chipType <= SI32269)
+  {
+    return Si3226x_Init_MultiBOM(hProslic,size,preset);
+  }
+#endif
+
+#ifdef SI3228X
+  if ((*hProslic)->deviceId->chipType >= SI32280
+      && (*hProslic)->deviceId->chipType <= SI32289)
+  {
+    return Si3228x_Init_MultiBOM(hProslic,size,preset);
+  }
+#endif
+
+  return RC_COMPLETE_NO_ERR;
+}
+#endif
+
+/*****************************************************************************************************/
+int ProSLIC_Init (proslicChanType_ptr *hProslic,int size)
+{
+  TRACEPRINT(*hProslic, "size: %d\n", size);
+  return ProSLIC_Init_with_Options(hProslic, size, INIT_NO_OPT);
+}
+
+/*****************************************************************************************************/
+int ProSLIC_Reinit (proslicChanType_ptr *hProslic,int size)
+{
+  TRACEPRINT(*hProslic, "size: %d\n", size);
+  return ProSLIC_Init_with_Options(hProslic, size, INIT_REINIT);
+}
+
+/*****************************************************************************************************/
+int ProSLIC_Init_with_Options (proslicChanType_ptr *hProslic,int size,
+                               int option)
+{
+  TRACEPRINT(*hProslic, "size: %d option: %d\n", size, option);
+#ifdef SI3226X
+  if ((*hProslic)->deviceId->chipType >= SI32260
+      && (*hProslic)->deviceId->chipType <= SI32269)
+  {
+    return Si3226x_Init_with_Options(hProslic,size, option);
+  }
+#endif
+
+#ifdef SI3228X
+  if ((*hProslic)->deviceId->chipType >= SI32280
+      && (*hProslic)->deviceId->chipType <= SI32289)
+  {
+    return Si3228x_Init_with_Options(hProslic,size, option);
+  }
+#endif
+
+#ifdef SI3217X
+  if ((*hProslic)->deviceId->chipType >= SI32171
+      && (*hProslic)->deviceId->chipType <= SI32179)
+  {
+    return Si3217x_Init_with_Options(hProslic,size, option);
+  }
+#endif
+
+#ifdef SI3218X
+  if ((*hProslic)->deviceId->chipType >= SI32180
+      && (*hProslic)->deviceId->chipType <= SI32189)
+  {
+    return Si3218x_Init_with_Options(hProslic,size, option);
+  }
+#endif
+
+#ifdef SI3219X
+  if ( IS_SI3219X((*hProslic)->deviceId) )
+  {
+    return Si3219x_Init_with_Options(hProslic,size, option);
+  }
+#endif
+
+  return RC_IGNORE;
+}
+
+/*****************************************************************************************************/
+#if defined(SI3217X) || defined(SI3218X) || defined SI3226X || defined SI3228X || defined(SI3219X)
+/* Check patch data - returns TRUE if no error.*/
+static BOOLEAN ProSLIC_VerifyPatchData(proslicChanType *pProslic,
+                                       const ramData *data, uInt16 maxCount )
+{
+  int loop;
+  ramData read_data;
+  TRACEPRINT(pProslic, "dataptr: %p, count: %d\n", data, maxCount);
+
+  for(loop = 0; loop < maxCount; loop++)
+  {
+    if(*data)
+    {
+      read_data = ReadRAM(pProslic, pProslic->channel, PROSLIC_RAM_PRAM_DATA);
+      if( ((*data) << 9) != read_data)
+      {
+        return FALSE;
+      }
+    }
+    else
+    {
+      break;
+    }
+    data++;
+  }
+  return TRUE;
+}
+
+/* Check if the jump table is written correctly.. */
+static BOOLEAN ProSLIC_VerifyPatchJMPLow(proslicChanType *pProslic,
+    const uInt16 *data)
+{
+  uInt8 address = PATCH_JMPTBL_START_ADDR;
+  int regData;
+
+  TRACEPRINT(pProslic, "dataptr: %p\n", data);
+  for(address = PATCH_JMPTBL_START_ADDR;
+      address < (PATCH_JMPTBL_START_ADDR+(2*PATCH_NUM_LOW_ENTRIES)); address++)
+  {
+    if(*data)
+    {
+      regData = ReadReg(pProslic, pProslic->channel, address);
+      if(regData != ((*data) & 0xFF))
+      {
+        return FALSE;
+      }
+
+      address++;
+
+      regData = ReadReg(pProslic, pProslic->channel, address);
+      if(regData != (((*data)>>8) & 0xFF))
+      {
+        return FALSE;
+      }
+
+      data++;
+    }
+    else
+    {
+      break;
+    }
+  }
+  return TRUE;
+}
+
+#if defined SI3226X || defined SI3228X || defined SI3218X || defined SI3219X
+/* For chipsets supporting more than 8 jump entries, verify them */
+static BOOLEAN ProSLIC_VerifyPatchJMPHigh(proslicChanType *pProslic,
+    const uInt16 *data)
+{
+  uInt16 address = PATCH_JMPTBL_HIGH_ADDR;
+  ramData read_data;
+
+  TRACEPRINT(pProslic, "dataptr: %p\n", data);
+  for(address = PATCH_JMPTBL_HIGH_ADDR;
+      address < (PATCH_JMPTBL_HIGH_ADDR+PATCH_NUM_HIGH_ENTRIES); address++)
+  {
+    read_data = (ReadRAM(pProslic, pProslic->channel, address) & 0x1FFFL);
+    if(*data != read_data)
+    {
+      return FALSE;
+
+    }
+    data++;
+  }
+  return TRUE;
+}
+#endif /* SI3226X, SI3228X, SI3218X, SI3219X */
+
+static BOOLEAN ProSLIC_VerifyPatchSupportRAM(proslicChanType *pProslic, 
+                                           const uInt16 *ramAddr, const ramData *ramData)
+{
+  int i;
+
+  for(i = 0; ramAddr[i]; i++)
+  {
+    if( ReadRAM(pProslic, pProslic->channel, ramAddr[i]) != ramData[i])
+    {
+      return FALSE;
+    }
+  } 
+
+  return TRUE;
+}
+
+/* Load the first 8 jump table entries */
+static void ProSLIC_LoadPatchJMPLow(proslicChanType *pProslic, uInt8 channel,
+                                    const uInt16 *data)
+{
+  uInt8 address;
+
+  TRACEPRINT(pProslic, "chan: %d dataptr: %p\n", channel, data);
+
+  for(address = PATCH_JMPTBL_START_ADDR;
+      address < (PATCH_JMPTBL_START_ADDR+(2*PATCH_NUM_LOW_ENTRIES)); address++)
+  {
+    WriteReg(pProslic, channel, address,((*data) & 0xFF));
+    address++;
+    WriteReg(pProslic, channel, address,(((*data)>>8) & 0xFF));
+    data++;
+  }
+}
+
+/* Load Patch data */
+static void ProSLIC_LoadPatchData(proslicChanType *pProslic, uInt8 channel,
+                                  const ramData *data)
+{
+  int loop;
+
+  TRACEPRINT(pProslic, "chan: %d dataptr: %p\n", channel, data);
+  WriteRAM(pProslic, channel, PROSLIC_RAM_PRAM_ADDR, 0);
+
+  for(loop = 0; loop < PATCH_MAX_SIZE; loop++)
+  {
+    if(*data)
+    {
+      /* Can we take advantage of auto increment, if not, set the address */
+      if( (pProslic->deviceId->chipRev < 3)
+          && (channel == PROSLIC_CHAN_BROADCAST))
+      {
+        WriteRAM(pProslic, channel, PROSLIC_RAM_PRAM_ADDR, loop << 19);
+      }
+
+      WriteRAM(pProslic, channel, PROSLIC_RAM_PRAM_DATA, (*data) << 9);
+    }
+    else
+    {
+      return;
+    }
+    data++;
+  }
+}
+
+/* Load Support RAM - basically RAM address/data pairs to be written as part of the Patch process - do not call directly */
+void ProSLIC_LoadSupportRAM(proslicChanType *pProslic, uInt8 channel,
+                                   const uInt16 *address, const ramData *data)
+{
+  TRACEPRINT(pProslic, "chan: %d addressptr: %p dataptr: %p\n", channel, address,
+             data);
+  while( *address )
+  {
+    WriteRAM(pProslic, channel, *address, *data);
+    address++;
+    data++;
+  }
+}
+
+#if defined SI3226X || defined SI3228X || defined SI3218X || defined SI3219X
+/* Load Jump table high for chipsets supporting more than 8 jump entries */
+static void ProSLIC_LoadJMPHigh(proslicChanType *pProslic, uInt8 channel,
+                                const uInt16 *data)
+{
+  uInt16 loop;
+  TRACEPRINT(pProslic, "chan: %d dataptr: %p\n", channel, data);
+  for(loop = PATCH_JMPTBL_HIGH_ADDR;
+      loop < (PATCH_JMPTBL_HIGH_ADDR+PATCH_NUM_HIGH_ENTRIES); loop++)
+  {
+    WriteRAM(pProslic, channel, loop, ((*data) & 0x1FFFL) );
+    data++;
+  }
+}
+#endif /* SI3226X, SI3228X, SI3218X, SI3219X */
+
+/* Code assumes ProSLIC_LoadPatch has verified chip type. This is NOT meant to be called
+ * by the user directly.
+ */
+BOOLEAN ProSLIC_LoadPatch_extended(proslicChanType *pProslic,
+                                   const proslicPatch *pPatch, 
+                                   BOOLEAN is_broadcast, BOOLEAN is_second_chan)
+{
+  uInt8 channel;
+  const uInt16 jmp_disable[PATCH_NUM_LOW_ENTRIES] = {0,0,0,0,0,0,0,0};
+
+#if defined SI3226X || defined SI3228X || defined SI3218X ||defined SI3219X
+  BOOLEAN hasJmpTableHigh = FALSE;
+  const uInt16 jmphigh_disable[PATCH_NUM_HIGH_ENTRIES] = {0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL};
+#endif
+
+  TRACEPRINT(pProslic, "patchptr: %p bcast: %d\n", pPatch, is_broadcast);
+
+  if(pPatch == NULL)
+  {
+    return RC_NONE;
+  }
+
+  if(is_broadcast == TRUE)
+  {
+    channel = PROSLIC_CHAN_BROADCAST;
+  }
+  else
+  {
+    channel = pProslic->channel;
+  }
+
+  ProSLIC_SetUserMode(pProslic,TRUE, is_broadcast);
+
+  /* Disable Patch */
+  WriteReg(pProslic, channel, PROSLIC_REG_JMPEN, 0);
+  if(is_second_chan == FALSE)
+  {
+    DEBUG_PRINT(pProslic, "%sloading patch: %08lx\n", LOGPRINT_PREFIX,
+                 (long unsigned int)pPatch->patchSerial);
+
+    ProSLIC_LoadPatchJMPLow(pProslic, channel, jmp_disable);
+
+#if defined SI3226X || defined SI3228X || defined SI3218X || defined SI3219X
+    if( 0
+#ifdef SI3226X
+        || (pProslic->deviceId->chipType >= SI32260
+            && pProslic->deviceId->chipType <= SI32269)
+#endif
+#ifdef SI3228X
+        || (pProslic->deviceId->chipType >= SI32280
+            && pProslic->deviceId->chipType <= SI32289)
+#endif
+#ifdef SI3218X
+        || (pProslic->deviceId->chipType >= SI32180
+            && pProslic->deviceId->chipType <= SI32189)
+#endif
+#ifdef SI3219X
+        || ( IS_SI3219X(pProslic->deviceId) )
+#endif
+      )
+    {
+      hasJmpTableHigh = TRUE;
+      ProSLIC_LoadJMPHigh(pProslic, channel, jmphigh_disable);
+    }
+#endif
+
+    ProSLIC_LoadPatchData(pProslic, channel, pPatch->patchData);
+
+    WriteReg(pProslic, channel, PROSLIC_REG_RAM_ADDR_HI, 0);
+
+    ProSLIC_LoadPatchJMPLow(pProslic, channel, pPatch->patchEntries);
+
+#if defined SI3226X || defined SI3228X || defined SI3218X || defined SI3219X
+    if(hasJmpTableHigh == TRUE)
+    {
+      ProSLIC_LoadJMPHigh(pProslic, channel,
+                          &(pPatch->patchEntries[PATCH_NUM_LOW_ENTRIES]));
+    }
+#endif
+    WriteRAM(pProslic, channel, PROSLIC_RAM_PATCHID,
+             pPatch->patchSerial); /* write the patch ID */
+  } /* !second channel */
+
+  ProSLIC_LoadSupportRAM(pProslic, channel, pPatch->psRamAddr, pPatch->psRamData);
+
+  return RC_NONE;
+
+}
+
+#endif /* patch helper functions */
+
+int ProSLIC_LoadPatch (proslicChanType_ptr pProslic,const proslicPatch *pPatch)
+{
+  int rc;
+
+  if(pProslic->channelType != PROSLIC)
+  {
+    return RC_IGNORE;
+  }
+
+  if( (rc = ProSLIC_LoadPatch_extended(pProslic, pPatch, FALSE, FALSE) ) == RC_NONE)
+  {
+#ifdef DISABLE_VERIFY_PATCH
+    return WriteReg(pProslic, pProslic->channel, PROSLIC_REG_JMPEN, 1);
+#endif
+  }
+
+  return rc;
+}
+
+/*****************************************************************************************************/
+int ProSLIC_VerifyPatch (proslicChanType_ptr hProslic,const proslicPatch *pPatch)
+{
+  TRACEPRINT(hProslic, "patchptr: %p\n", pPatch);
+  if(hProslic->channelType != PROSLIC)
+  {
+    return RC_IGNORE;
+  }
+  if(pPatch == NULL)
+  {
+    return RC_NONE;
+  }
+
+  WriteReg(hProslic, hProslic->channel, PROSLIC_REG_JMPEN, 0);
+  WriteRAM(hProslic, hProslic->channel, PROSLIC_RAM_PRAM_ADDR, 0);
+
+  if(ProSLIC_VerifyPatchData(hProslic, pPatch->patchData,
+                             PATCH_MAX_SIZE) == FALSE)
+  {
+    DEBUG_PRINT(hProslic, "%sPatch data corrupted: channel %d\n",LOGPRINT_PREFIX,
+                hProslic->channel);
+    WriteRAM(hProslic, hProslic->channel, PROSLIC_RAM_PATCHID,
+             0UL); /* Mark patch as invalid */
+    return RC_PATCH_RAM_VERIFY_FAIL;
+  }
+
+  /*zero out RAM_ADDR_HI*/
+  WriteReg (hProslic, hProslic->channel, PROSLIC_REG_RAM_ADDR_HI,0);
+
+  if( ProSLIC_VerifyPatchJMPLow(hProslic, pPatch->patchEntries) == FALSE)
+  {
+    DEBUG_PRINT(hProslic,"%sPatch jumptable corrupted: channel %d\n",
+                LOGPRINT_PREFIX,hProslic->channel);
+    WriteRAM(hProslic, hProslic->channel, PROSLIC_RAM_PATCHID,
+             0UL); /* Mark patch as invalid */
+    return RC_PATCH_RAM_VERIFY_FAIL;
+  }
+
+#if defined SI3226X || defined SI3228X || defined SI3218X || defined SI3219X
+  if( 0
+#ifdef SI3226X
+      || (hProslic->deviceId->chipType >= SI32260
+          && hProslic->deviceId->chipType <= SI32269)
+#endif
+#ifdef SI3228X
+      || (hProslic->deviceId->chipType >= SI32280
+          && hProslic->deviceId->chipType <= SI32289)
+#endif
+#ifdef SI3218X
+      || (hProslic->deviceId->chipType >= SI32180
+          && hProslic->deviceId->chipType <= SI32189)
+#endif
+#ifdef SI3219X
+      || ( IS_SI3219X(hProslic->deviceId) )
+#endif
+    )
+
+  {
+    if( ProSLIC_VerifyPatchJMPHigh(hProslic,
+                                   &(pPatch->patchEntries[PATCH_NUM_LOW_ENTRIES])) == FALSE)
+    {
+      DEBUG_PRINT(hProslic,"%sPatch jumptable high corrupted: channel %d\n",
+                  LOGPRINT_PREFIX,hProslic->channel);
+      WriteRAM(hProslic, hProslic->channel, PROSLIC_RAM_PATCHID,
+               0UL); /* Mark patch as invalid */
+      return RC_PATCH_ENTRY_VERIFY_FAIL;
+    }
+  }
+
+#endif
+
+  if( ProSLIC_VerifyPatchSupportRAM( hProslic, pPatch->psRamAddr, pPatch->psRamData) == FALSE)
+  {
+      DEBUG_PRINT(hProslic,"%sPatch init data corrupted: channel %d\n",
+                  LOGPRINT_PREFIX,hProslic->channel);
+      WriteRAM(hProslic, hProslic->channel, PROSLIC_RAM_PATCHID,
+               0UL); /* Mark patch as invalid */
+      return RC_PATCH_ENTRY_VERIFY_FAIL;
+  }
+
+  WriteReg (hProslic, hProslic->channel, PROSLIC_REG_JMPEN,
+            1); /*enable the patch*/
+
+  return RC_NONE;
+}
+
+/*****************************************************************************************************/
+int ProSLIC_SetMuteStatus (proslicChanType_ptr pProslic,
+                           ProslicMuteModes muteEn)
+{
+
+  uInt8 regTemp;
+  uInt8 newRegValue;
+  TRACEPRINT(pProslic, "muteEn: %d\n", muteEn);
+
+  if(pProslic->channelType != PROSLIC)
+  {
+    return RC_IGNORE;
+  }
+
+  regTemp = ReadReg (pProslic,pProslic->channel,PROSLIC_REG_DIGCON);
+
+  WriteReg (pProslic,pProslic->channel,PROSLIC_REG_DIGCON,regTemp&~(0x3));
+  newRegValue = regTemp &~(0x3);
+
+  if (muteEn & PROSLIC_MUTE_RX)
+  {
+    newRegValue |= 1;
+  }
+
+  if (muteEn & PROSLIC_MUTE_TX)
+  {
+    newRegValue |= 2;
+  }
+
+  if(newRegValue != regTemp)
+  {
+    return WriteReg (pProslic,pProslic->channel,PROSLIC_REG_DIGCON,newRegValue);
+  }
+
+  return RC_COMPLETE_NO_ERR;
+}
+
+/*****************************************************************************************************/
+int ProSLIC_SetLoopbackMode (proslicChanType_ptr pProslic,
+                             ProslicLoopbackModes newMode)
+{
+  uInt8 regTemp, newValue;
+  TRACEPRINT(pProslic, "mode: %d\n", newMode);
+
+  if(pProslic->channelType != PROSLIC)
+  {
+    return RC_IGNORE;
+  }
+
+  newValue = regTemp = ReadReg (pProslic,pProslic->channel,PROSLIC_REG_LOOPBACK);
+
+  switch (newMode)
+  {
+    case PROSLIC_LOOPBACK_NONE:
+      newValue &= ~(0x11);
+      break;
+
+    case PROSLIC_LOOPBACK_DIG:
+      newValue |= 1;
+      break;
+
+    case PROSLIC_LOOPBACK_ANA:
+      newValue |= 0x10;
+      break;
+  }
+
+  if(newValue != regTemp)
+  {
+    return WriteReg (pProslic,pProslic->channel,PROSLIC_REG_LOOPBACK, newValue);
+  }
+  return RC_COMPLETE_NO_ERR;
+}
+
+/*****************************************************************************************************/
+int ProSLIC_EnableInterrupts (proslicChanType_ptr hProslic)
+{
+  TRACEPRINT(hProslic, "\n", NULL);
+  if(hProslic->channelType != PROSLIC)
+  {
+    return RC_IGNORE;
+  }
+#ifdef SI3217X
+  if (hProslic->deviceId->chipType >= SI32171
+      && hProslic->deviceId->chipType <= SI32179)
+  {
+    return Si3217x_EnableInterrupts(hProslic);
+  }
+#endif
+
+#ifdef SI3218X
+  if (hProslic->deviceId->chipType >= SI32180
+      && hProslic->deviceId->chipType <= SI32189)
+  {
+    return Si3218x_EnableInterrupts(hProslic);
+  }
+#endif
+
+#ifdef SI3219X
+  if ( IS_SI3219X(hProslic->deviceId) )
+  {
+    return Si3219x_EnableInterrupts(hProslic);
+  }
+#endif
+
+#ifdef SI3226X
+  if (hProslic->deviceId->chipType >= SI32260
+      && hProslic->deviceId->chipType <= SI32269)
+  {
+    return Si3226x_EnableInterrupts(hProslic);
+  }
+#endif
+
+#ifdef SI3228X
+  if (hProslic->deviceId->chipType >= SI32280
+      && hProslic->deviceId->chipType <= SI32289)
+  {
+    return Si3228x_EnableInterrupts(hProslic);
+  }
+#endif
+
+  return RC_COMPLETE_NO_ERR;
+}
+
+
+/*****************************************************************************************************/
+int ProSLIC_DisableInterrupts (proslicChanType_ptr hProslic)
+{
+#ifdef GCI_MODE
+  uInt8 data;
+#endif
+  uInt8 i;
+  TRACEPRINT(hProslic, "\n", NULL);
+
+  if(hProslic->channelType != PROSLIC)
+  {
+    return RC_IGNORE;
+  }
+
+  for(i = PROSLIC_REG_IRQEN1; i < PROSLIC_REG_IRQEN4; i++)
+  {
+    /* Disable the interrupts */
+    WriteReg(hProslic, hProslic->channel, i, 0);
+  }
+
+  /* Clear the pending interrupts */
+  for(i = PROSLIC_REG_IRQ1; i < PROSLIC_REG_IRQ4; i++)
+  {
+#ifdef GCI_MODE
+    data = ReadReg(hProslic, hProslic->channel, i);
+    WriteReg( hProslic, hProslic->channel, i, data);
+#else
+    (void)ReadReg(hProslic, hProslic->channel, i);
+#endif
+  }
+  return RC_NONE;
+}
+
+/*****************************************************************************************************/
+int ProSLIC_RingSetup (proslicChanType_ptr hProslic,int preset)
+{
+  TRACEPRINT(hProslic, "preset: %d\n", preset);
+#ifndef DISABLE_RING_SETUP
+  if(hProslic->channelType != PROSLIC)
+  {
+    return RC_IGNORE;
+  }
+#ifdef SI3217X
+  if (hProslic->deviceId->chipType >= SI32171
+      && hProslic->deviceId->chipType <= SI32179)
+  {
+    return Si3217x_RingSetup(hProslic,preset);
+  }
+#endif
+
+#ifdef SI3218X
+  if (hProslic->deviceId->chipType >= SI32180
+      && hProslic->deviceId->chipType <= SI32189)
+  {
+    return Si3218x_RingSetup(hProslic,preset);
+  }
+#endif
+
+#ifdef SI3219X
+  if ( IS_SI3219X(hProslic->deviceId) )
+  {
+    return Si3219x_RingSetup(hProslic,preset);
+  }
+#endif
+
+#ifdef SI3226X
+  if (hProslic->deviceId->chipType >= SI32260
+      && hProslic->deviceId->chipType <= SI32269)
+  {
+    return Si3226x_RingSetup(hProslic,preset);
+  }
+#endif
+#ifdef SI3228X
+  if (hProslic->deviceId->chipType >= SI32280
+      && hProslic->deviceId->chipType <= SI32289)
+  {
+    return Si3228x_RingSetup(hProslic,preset);
+  }
+#endif
+#else
+  SILABS_UNREFERENCED_PARAMETER(hProslic);
+  SILABS_UNREFERENCED_PARAMETER(preset);
+#endif /*DISABLE_RING_SETUP*/
+  return RC_COMPLETE_NO_ERR;
+}
+
+/*****************************************************************************************************/
+int ProSLIC_ToneGenSetup (proslicChanType_ptr hProslic,int preset)
+{
+  TRACEPRINT(hProslic, "preset: %d\n", preset);
+#ifndef DISABLE_TONE_SETUP
+  if(hProslic->channelType != PROSLIC)
+  {
+    return RC_IGNORE;
+  }
+#ifdef SI3217X
+  if (hProslic->deviceId->chipType >= SI32171
+      && hProslic->deviceId->chipType <= SI32179)
+  {
+    return ProSLIC_ToneGenSetupPtr(hProslic,&(Si3217x_Tone_Presets[preset]));
+  }
+#endif
+
+#ifdef SI3218X
+  if (hProslic->deviceId->chipType >= SI32180
+      && hProslic->deviceId->chipType <= SI32189)
+  {
+    return ProSLIC_ToneGenSetupPtr(hProslic, &(Si3218x_Tone_Presets[preset]));
+  }
+#endif
+
+#ifdef SI3219X
+  if ( IS_SI3219X(hProslic->deviceId) )
+  {
+    return ProSLIC_ToneGenSetupPtr(hProslic, &(Si3219x_Tone_Presets[preset]));
+  }
+#endif
+
+#ifdef SI3226X
+  if (hProslic->deviceId->chipType >= SI32260
+      && hProslic->deviceId->chipType <= SI32269)
+  {
+    return ProSLIC_ToneGenSetupPtr(hProslic, &(Si3226x_Tone_Presets[preset]));
+  }
+#endif
+#ifdef SI3228X
+  if (hProslic->deviceId->chipType >= SI32280
+      && hProslic->deviceId->chipType <= SI32289)
+  {
+    return ProSLIC_ToneGenSetupPtr(hProslic, &(Si3228x_Tone_Presets[preset]));
+  }
+#endif
+#else
+  SILABS_UNREFERENCED_PARAMETER(hProslic);
+  SILABS_UNREFERENCED_PARAMETER(preset);
+#endif /*DISABLE_TONE_SETUP*/
+  return RC_COMPLETE_NO_ERR;
+}
+
+/*****************************************************************************************************/
+int ProSLIC_FSKSetup (proslicChanType_ptr hProslic,int preset)
+{
+  TRACEPRINT(hProslic, "preset: %d\n", preset);
+#ifndef DISABLE_FSK_SETUP
+  if(hProslic->channelType != PROSLIC)
+  {
+    return RC_IGNORE;
+  }
+#ifdef SI3217X
+  if (hProslic->deviceId->chipType >= SI32171
+      && hProslic->deviceId->chipType <= SI32179)
+  {
+    return ProSLIC_FSKSetupPtr(hProslic, &Si3217x_FSK_Presets[preset]);
+  }
+#endif
+
+#ifdef SI3218X
+  if (hProslic->deviceId->chipType >= SI32180
+      && hProslic->deviceId->chipType <= SI32189)
+  {
+    return ProSLIC_FSKSetupPtr(hProslic, &Si3218x_FSK_Presets[preset]);
+  }
+#endif
+
+#ifdef SI3219X
+  if ( IS_SI3219X(hProslic->deviceId) )
+  {
+    return ProSLIC_FSKSetupPtr(hProslic, &Si3219x_FSK_Presets[preset]);
+  }
+#endif
+
+#ifdef SI3226X
+  if (hProslic->deviceId->chipType >= SI32260
+      && hProslic->deviceId->chipType <= SI32269)
+  {
+    return ProSLIC_FSKSetupPtr(hProslic, &Si3226x_FSK_Presets[preset]);
+  }
+#endif
+
+#ifdef SI3228X
+  if (hProslic->deviceId->chipType >= SI32280
+      && hProslic->deviceId->chipType <= SI32289)
+  {
+    return ProSLIC_FSKSetupPtr(hProslic,&Si3228x_FSK_Presets[preset]);
+  }
+#endif
+#else
+  SILABS_UNREFERENCED_PARAMETER(hProslic);
+  SILABS_UNREFERENCED_PARAMETER(preset);
+#endif /*DISABLE_FSK_SETUP*/
+  return RC_COMPLETE_NO_ERR;
+}
+
+/*****************************************************************************************************/
+int ProSLIC_ZsynthSetup (proslicChanType_ptr hProslic,int preset)
+{
+  TRACEPRINT(hProslic, "preset: %d\n", preset);
+#ifndef DISABLE_ZSYNTH_SETUP
+  if(hProslic->channelType != PROSLIC)
+  {
+    return RC_IGNORE;
+  }
+#ifdef SI3217X
+  if (hProslic->deviceId->chipType >= SI32171
+      && hProslic->deviceId->chipType <= SI32179)
+  {
+    return Si3217x_ZsynthSetup(hProslic,preset);
+  }
+#endif
+
+#ifdef SI3218X
+  if (hProslic->deviceId->chipType >= SI32180
+      && hProslic->deviceId->chipType <= SI32189)
+  {
+    return Si3218x_ZsynthSetup(hProslic,preset);
+  }
+#endif
+
+#ifdef SI3219X
+  if ( IS_SI3219X(hProslic->deviceId) )
+  {
+    return Si3219x_ZsynthSetup(hProslic,preset);
+  }
+#endif
+
+#ifdef SI3226X
+  if (hProslic->deviceId->chipType >= SI32260
+      && hProslic->deviceId->chipType <= SI32269)
+  {
+    return Si3226x_ZsynthSetup(hProslic,preset);
+  }
+#endif
+
+#ifdef SI3228X
+  if (hProslic->deviceId->chipType >= SI32280
+      && hProslic->deviceId->chipType <= SI32289)
+  {
+    return Si3228x_ZsynthSetup(hProslic,preset);
+  }
+#endif
+#else
+  SILABS_UNREFERENCED_PARAMETER(hProslic);
+  SILABS_UNREFERENCED_PARAMETER(preset);
+#endif /*DISABLE_ZSYNTH_SETUP*/
+  return RC_COMPLETE_NO_ERR;
+}
+
+/*****************************************************************************************************/
+#ifndef DISABLE_CI_SETUP
+int ProSLIC_GciCISetup (proslicChanType_ptr hProslic,int preset)
+{
+  TRACEPRINT(hProslic, "preset: %d\n", preset);
+  if(hProslic->channelType != PROSLIC)
+  {
+    return RC_IGNORE;
+  }
+#ifdef SI3217X
+  if (hProslic->deviceId->chipType >= SI32171
+      && hProslic->deviceId->chipType <= SI32179)
+  {
+    return Si3217x_GciCISetup(hProslic,preset);
+  }
+#endif
+
+#ifdef SI3226X
+  if (hProslic->deviceId->chipType >= SI32260
+      && hProslic->deviceId->chipType <= SI32269)
+  {
+    return Si3226x_GciCISetup(hProslic,preset);
+  }
+#endif
+
+#if !defined(SI3217X) && !defined(SI3226X)
+  SILABS_UNREFERENCED_PARAMETER(hProslic);
+  SILABS_UNREFERENCED_PARAMETER(preset);
+#endif
+
+  return RC_COMPLETE_NO_ERR;
+}
+#endif /*DISABLE_CI_SETUP*/
+
+/*****************************************************************************************************/
+int ProSLIC_TXAudioGainSetup (proslicChanType_ptr hProslic,int preset)
+{
+  TRACEPRINT(hProslic, "preset: %d\n", preset);
+#ifndef DISABLE_AUDIOGAIN_SETUP
+  if(hProslic->channelType != PROSLIC)
+  {
+    return RC_IGNORE;
+  }
+
+#ifdef SI3217X
+  if (hProslic->deviceId->chipType >= SI32171
+      && hProslic->deviceId->chipType <= SI32179)
+  {
+    return Si3217x_TXAudioGainSetup(hProslic,preset);
+  }
+#endif
+
+#ifdef SI3218X
+  if (hProslic->deviceId->chipType >= SI32180
+      && hProslic->deviceId->chipType <= SI32189)
+  {
+    return Si3218x_TXAudioGainSetup(hProslic,preset);
+  }
+#endif
+
+#ifdef SI3219X
+  if ( IS_SI3219X(hProslic->deviceId) )
+  {
+    return Si3219x_TXAudioGainSetup(hProslic,preset);
+  }
+#endif
+
+#ifdef SI3226X
+  if (hProslic->deviceId->chipType >= SI32260
+      && hProslic->deviceId->chipType <= SI32269)
+  {
+    return Si3226x_TXAudioGainSetup(hProslic,preset);
+  }
+#endif
+
+#ifdef SI3228X
+  if (hProslic->deviceId->chipType >= SI32280
+      && hProslic->deviceId->chipType <= SI32289)
+  {
+    return Si3228x_TXAudioGainSetup(hProslic,preset);
+  }
+#endif
+#else
+  SILABS_UNREFERENCED_PARAMETER(hProslic);
+  SILABS_UNREFERENCED_PARAMETER(preset);
+
+#endif /*DISABLE_AUDIOGAIN_SETUP*/
+  return RC_COMPLETE_NO_ERR;
+}
+
+/*****************************************************************************************************/
+int ProSLIC_RXAudioGainSetup (proslicChanType_ptr hProslic,int preset)
+{
+  TRACEPRINT(hProslic, "preset: %d\n", preset);
+#ifndef DISABLE_AUDIOGAIN_SETUP
+  if(hProslic->channelType != PROSLIC)
+  {
+    return RC_IGNORE;
+  }
+
+#ifdef SI3217X
+  if (hProslic->deviceId->chipType >= SI32171
+      && hProslic->deviceId->chipType <= SI32179)
+  {
+    return Si3217x_RXAudioGainSetup(hProslic,preset);
+  }
+#endif
+
+#ifdef SI3218X
+  if (hProslic->deviceId->chipType >= SI32180
+      && hProslic->deviceId->chipType <= SI32189)
+  {
+    return Si3218x_RXAudioGainSetup(hProslic,preset);
+  }
+#endif
+
+#ifdef SI3219X
+  if ( IS_SI3219X(hProslic->deviceId) )
+  {
+    return Si3219x_RXAudioGainSetup(hProslic,preset);
+  }
+#endif
+
+
+#ifdef SI3226X
+  if (hProslic->deviceId->chipType >= SI32260
+      && hProslic->deviceId->chipType <= SI32269)
+  {
+    return Si3226x_RXAudioGainSetup(hProslic,preset);
+  }
+#endif
+
+#ifdef SI3228X
+  if (hProslic->deviceId->chipType >= SI32280
+      && hProslic->deviceId->chipType <= SI32289)
+  {
+    return Si3228x_RXAudioGainSetup(hProslic,preset);
+  }
+#endif
+
+#else
+  SILABS_UNREFERENCED_PARAMETER(hProslic);
+  SILABS_UNREFERENCED_PARAMETER(preset);
+#endif /*DISABLE_AUDIOGAIN_SETUP*/
+  return RC_COMPLETE_NO_ERR;
+}
+
+/*****************************************************************************************************/
+int ProSLIC_TXAudioGainScale (proslicChanType_ptr hProslic,int preset,
+                              uInt32 pga_scale, uInt32 eq_scale)
+{
+  TRACEPRINT(hProslic, "preset: %d pga_scale: %u eq_scale: %u\n", preset,
+             pga_scale, eq_scale);
+#ifndef DISABLE_AUDIOGAIN_SETUP
+  if(hProslic->channelType != PROSLIC)
+  {
+    return RC_IGNORE;
+  }
+
+#ifdef SI3217X
+  if (hProslic->deviceId->chipType >= SI32171
+      && hProslic->deviceId->chipType <= SI32179)
+  {
+    return Si3217x_TXAudioGainScale(hProslic,preset,pga_scale,eq_scale);
+  }
+#endif
+
+#ifdef SI3218X
+  if (hProslic->deviceId->chipType >= SI32180
+      && hProslic->deviceId->chipType <= SI32189)
+  {
+    return Si3218x_TXAudioGainScale(hProslic,preset,pga_scale,eq_scale);
+  }
+#endif
+
+#ifdef SI3219X
+  if ( IS_SI3219X(hProslic->deviceId) )
+  {
+    return Si3219x_TXAudioGainScale(hProslic,preset,pga_scale,eq_scale);
+  }
+#endif
+
+#ifdef SI3226X
+  if (hProslic->deviceId->chipType >= SI32260
+      && hProslic->deviceId->chipType <= SI32269)
+  {
+    return Si3226x_TXAudioGainScale(hProslic,preset,pga_scale,eq_scale);
+  }
+#endif
+
+#ifdef SI3228X
+  if (hProslic->deviceId->chipType >= SI32280
+      && hProslic->deviceId->chipType <= SI32289)
+  {
+    return Si3228x_TXAudioGainScale(hProslic,preset,pga_scale,eq_scale);
+  }
+#endif
+
+#else
+  SILABS_UNREFERENCED_PARAMETER(hProslic);
+  SILABS_UNREFERENCED_PARAMETER(preset);
+#endif /*DISABLE_AUDIOGAIN_SETUP*/
+  return RC_COMPLETE_NO_ERR;
+}
+
+/*****************************************************************************************************/
+int ProSLIC_RXAudioGainScale (proslicChanType_ptr hProslic,int preset,
+                              uInt32 pga_scale, uInt32 eq_scale)
+{
+  TRACEPRINT(hProslic, "preset: %d pga_scale: %u eq_scale: %u\n", preset,
+             pga_scale, eq_scale);
+#ifndef DISABLE_AUDIOGAIN_SETUP
+  if(hProslic->channelType != PROSLIC)
+  {
+    return RC_IGNORE;
+  }
+#ifdef SI3217X
+  if (hProslic->deviceId->chipType >= SI32171
+      && hProslic->deviceId->chipType <= SI32179)
+  {
+    return Si3217x_RXAudioGainScale(hProslic,preset,pga_scale,eq_scale);
+  }
+#endif
+
+#ifdef SI3218X
+  if (hProslic->deviceId->chipType >= SI32180
+      && hProslic->deviceId->chipType <= SI32189)
+  {
+    return Si3218x_RXAudioGainScale(hProslic,preset,pga_scale,eq_scale);
+  }
+#endif
+
+#ifdef SI3219X
+  if ( IS_SI3219X(hProslic->deviceId) )
+  {
+    return Si3219x_RXAudioGainScale(hProslic,preset,pga_scale,eq_scale);
+  }
+#endif
+
+#ifdef SI3226X
+  if (hProslic->deviceId->chipType >= SI32260
+      && hProslic->deviceId->chipType <= SI32269)
+  {
+    return Si3226x_RXAudioGainScale(hProslic,preset,pga_scale,eq_scale);
+  }
+#endif
+
+#ifdef SI3228X
+  if (hProslic->deviceId->chipType >= SI32280
+      && hProslic->deviceId->chipType <= SI32289)
+  {
+    return Si3228x_RXAudioGainScale(hProslic,preset,pga_scale,eq_scale);
+  }
+#endif
+
+#else
+  SILABS_UNREFERENCED_PARAMETER(hProslic);
+  SILABS_UNREFERENCED_PARAMETER(preset);
+#endif /*DISABLE_AUDIOGAIN_SETUP*/
+  return RC_COMPLETE_NO_ERR;
+}
+
+/*****************************************************************************************************/
+int ProSLIC_AudioGainSetup (proslicChanType_ptr pProslic,int32 rxgain,
+                            int32 txgain,int preset)
+{
+  int rc;
+#ifndef DISABLE_AUDIOGAIN_SETUP
+  int atx_preset = TXACGAIN_SEL;
+  int arx_preset = RXACGAIN_SEL;
+  TRACEPRINT(pProslic, "rxgain: %d txgain: %d preset: %d\n", rxgain, txgain,
+             preset);
+
+  rc = ProSLIC_dbgSetTXGain(pProslic,txgain,preset,atx_preset);
+
+  if( rc  == RC_NONE)
+  {
+    rc = ProSLIC_TXAudioGainSetup(pProslic,TXACGAIN_SEL);
+  }
+
+  if( rc  == RC_NONE)
+  {
+    rc = ProSLIC_dbgSetRXGain(pProslic,rxgain,preset,arx_preset);
+  }
+
+  if( rc  == RC_NONE)
+  {
+    rc = ProSLIC_RXAudioGainSetup(pProslic,RXACGAIN_SEL);
+  }
+  return rc;
+#else
+  SILABS_UNREFERENCED_PARAMETER(pProslic);
+  SILABS_UNREFERENCED_PARAMETER(preset);
+  return RC_IGNORE;
+#endif /*DISABLE_AUDIOGAIN_SETUP*/
+}
+
+/*****************************************************************************************************/
+int ProSLIC_DCFeedSetup (proslicChanType_ptr hProslic,int preset)
+{
+  TRACEPRINT(hProslic, "preset: %d\n", preset);
+#ifndef DISABLE_DCFEED_SETUP
+  if(hProslic->channelType != PROSLIC)
+  {
+    return RC_IGNORE;
+  }
+
+#ifdef SI3217X
+  if (hProslic->deviceId->chipType >= SI32171
+      && hProslic->deviceId->chipType <= SI32179)
+  {
+    return Si3217x_DCFeedSetup(hProslic,preset);
+  }
+#endif
+
+#ifdef SI3218X
+  if (hProslic->deviceId->chipType >= SI32180
+      && hProslic->deviceId->chipType <= SI32189)
+  {
+    return Si3218x_DCFeedSetup(hProslic,preset);
+  }
+#endif
+
+#ifdef SI3219X
+  if ( IS_SI3219X(hProslic->deviceId) )
+  {
+    return Si3219x_DCFeedSetupCfg(hProslic, Si3219x_DCfeed_Presets, preset);
+  }
+#endif
+
+#ifdef SI3226X
+  if (hProslic->deviceId->chipType >= SI32260
+      && hProslic->deviceId->chipType <= SI32269)
+  {
+    return Si3226x_DCFeedSetup(hProslic,preset);
+  }
+#endif
+
+#ifdef SI3228X
+  if (hProslic->deviceId->chipType >= SI32280
+      && hProslic->deviceId->chipType <= SI32289)
+  {
+    return Si3228x_DCFeedSetup(hProslic,preset);
+  }
+#endif
+#else
+  SILABS_UNREFERENCED_PARAMETER(hProslic);
+  SILABS_UNREFERENCED_PARAMETER(preset);
+#endif /*DISABLE_DCFEED_SETUP*/
+  return RC_COMPLETE_NO_ERR;
+}
+
+/*****************************************************************************************************/
+int ProSLIC_DCFeedSetupCfg (proslicChanType_ptr hProslic,
+                            ProSLIC_DCfeed_Cfg *cfg, int preset)
+{
+  TRACEPRINT(hProslic, "cfgPtr = %p preset = %d\n", cfg, preset);
+#ifndef DISABLE_DCFEED_SETUP
+  if(hProslic->channelType != PROSLIC)
+  {
+    return RC_IGNORE;
+  }
+
+#ifdef SI3217X
+  if (hProslic->deviceId->chipType >= SI32171
+      && hProslic->deviceId->chipType <= SI32179)
+  {
+    return Si3217x_DCFeedSetupCfg(hProslic,cfg,preset);
+  }
+#endif
+
+#ifdef SI3218X
+  if (hProslic->deviceId->chipType >= SI32180
+      && hProslic->deviceId->chipType <= SI32189)
+  {
+    return Si3218x_DCFeedSetupCfg(hProslic,cfg,preset);
+  }
+#endif
+
+#ifdef SI3219X
+  if ( IS_SI3219X(hProslic->deviceId) )
+  {
+    return Si3219x_DCFeedSetupCfg(hProslic,cfg,preset);
+  }
+#endif
+
+#ifdef SI3226X
+  if (hProslic->deviceId->chipType >= SI32260
+      && hProslic->deviceId->chipType <= SI32269)
+  {
+    return Si3226x_DCFeedSetupCfg(hProslic,cfg,preset);
+  }
+#endif
+
+#ifdef SI3228X
+  if (hProslic->deviceId->chipType >= SI32280
+      && hProslic->deviceId->chipType <= SI32289)
+  {
+    return Si3228x_DCFeedSetupCfg(hProslic,cfg,preset);
+  }
+#endif
+
+#else
+  SILABS_UNREFERENCED_PARAMETER(hProslic);
+  SILABS_UNREFERENCED_PARAMETER(preset);
+  SILABS_UNREFERENCED_PARAMETER(cfg);
+#endif /*DISABLE_DCFEED_SETUP*/
+  return RC_COMPLETE_NO_ERR;
+}
+
+/*****************************************************************************************************/
+int ProSLIC_GPIOSetup (proslicChanType_ptr hProslic)
+{
+  TRACEPRINT(hProslic, "\n", NULL);
+#ifndef DISABLE_GPIO_SETUP
+  if(hProslic->channelType != PROSLIC)
+  {
+    return RC_IGNORE;
+  }
+
+#ifdef SI3217X
+  if (hProslic->deviceId->chipType >= SI32171
+      && hProslic->deviceId->chipType <= SI32179)
+  {
+    return Si3217x_GPIOSetup(hProslic);
+  }
+#endif
+
+#ifdef SI3226X
+  if (hProslic->deviceId->chipType >= SI32260
+      && hProslic->deviceId->chipType <= SI32269)
+  {
+    return Si3226x_GPIOSetup(hProslic);
+  }
+#endif
+
+#else
+  SILABS_UNREFERENCED_PARAMETER(hProslic);
+#endif /*DISABLE_GPIO_SETUP*/
+  return RC_COMPLETE_NO_ERR;
+}
+
+/*****************************************************************************************************/
+#ifndef DISABLE_PULSEMETERING
+int ProSLIC_PulseMeterSetup (proslicChanType_ptr hProslic,int preset)
+{
+  TRACEPRINT(hProslic, "preset = %d\n", preset);
+#ifndef DISABLE_PULSE_SETUP
+  if(hProslic->channelType != PROSLIC)
+  {
+    return RC_IGNORE;
+  }
+
+#ifdef SI3217X
+  if (hProslic->deviceId->chipType >= SI32171
+      && hProslic->deviceId->chipType <= SI32179)
+  {
+    return Si3217x_PulseMeterSetup(hProslic,preset);
+  }
+#endif
+
+#ifdef SI3218X
+  if (hProslic->deviceId->chipType >= SI32180
+      && hProslic->deviceId->chipType <= SI32189)
+  {
+    return Si3218x_PulseMeterSetup(hProslic,preset);
+  }
+#endif
+
+#ifdef SI3219X
+  if ( IS_SI3219X(hProslic->deviceId) )
+  {
+    return Si3219x_PulseMeterSetup(hProslic,preset);
+  }
+#endif
+
+#ifdef SI3226X
+  if (hProslic->deviceId->chipType >= SI32260
+      && hProslic->deviceId->chipType <= SI32269)
+  {
+    return Si3226x_PulseMeterSetup(hProslic,preset);
+  }
+#endif
+
+#ifdef SI3228X
+  if (hProslic->deviceId->chipType >= SI32280
+      && hProslic->deviceId->chipType <= SI32289)
+  {
+    return Si3228x_PulseMeterSetup(hProslic,preset);
+  }
+#endif
+
+#else
+  SILABS_UNREFERENCED_PARAMETER(hProslic);
+  SILABS_UNREFERENCED_PARAMETER(preset);
+#endif /*DISABLE_PULSE_SETUP*/
+  return RC_COMPLETE_NO_ERR;
+}
+#endif
+
+/*****************************************************************************************************/
+int ProSLIC_PCMSetup (proslicChanType_ptr hProslic,int preset)
+{
+  TRACEPRINT(hProslic, "preset = %d\n", preset);
+#ifndef DISABLE_PCM_SETUP
+  if(hProslic->channelType != PROSLIC)
+  {
+    return RC_IGNORE;
+  }
+
+#ifdef SI3217X
+  if (hProslic->deviceId->chipType >= SI32171
+      && hProslic->deviceId->chipType <= SI32179)
+  {
+    return Si3217x_PCMSetup(hProslic,preset);
+  }
+#endif
+
+#ifdef SI3218X
+  if (hProslic->deviceId->chipType >= SI32180
+      && hProslic->deviceId->chipType <= SI32189)
+  {
+    return Si3218x_PCMSetup(hProslic,preset);
+  }
+#endif
+
+#ifdef SI3219X
+  if ( IS_SI3219X(hProslic->deviceId) )
+  {
+    return Si3219x_PCMSetup(hProslic,preset);
+  }
+#endif
+
+#ifdef SI3226X
+  if (hProslic->deviceId->chipType >= SI32260
+      && hProslic->deviceId->chipType <= SI32269)
+  {
+    return Si3226x_PCMSetup(hProslic,preset);
+  }
+#endif
+
+#ifdef SI3228X
+  if (hProslic->deviceId->chipType >= SI32280
+      && hProslic->deviceId->chipType <= SI32289)
+  {
+    return Si3228x_PCMSetup(hProslic,preset);
+  }
+#endif
+#else
+  SILABS_UNREFERENCED_PARAMETER(hProslic);
+  SILABS_UNREFERENCED_PARAMETER(preset);
+#endif /*DISABLE_PCM_SETUP*/
+  return RC_COMPLETE_NO_ERR;
+}
+
+/*****************************************************************************************************/
+int ProSLIC_PCMTimeSlotSetup (proslicChanType_ptr pProslic, uInt16 rxcount,
+                              uInt16 txcount)
+{
+  uInt8 data;
+  TRACEPRINT(pProslic, "rx = %u tx = %u\n", rxcount, txcount);
+
+  if(pProslic->channelType != PROSLIC)
+  {
+    return RC_IGNORE;
+  }
+
+  data = txcount & 0xff;
+  WriteReg(pProslic,pProslic->channel,PROSLIC_REG_PCMTXLO,data);
+
+  data = ReadReg(pProslic,pProslic->channel,PROSLIC_REG_PCMTXHI);
+  data &= 0x10;  /* keep TX_EDGE bit */
+  data |= ((txcount >> 8)&0x03) ;
+  WriteReg(pProslic,pProslic->channel,PROSLIC_REG_PCMTXHI,data);
+
+  data = rxcount & 0xff;
+  WriteReg(pProslic,pProslic->channel,PROSLIC_REG_PCMRXLO,data);
+
+  data = (rxcount >> 8) & 0x3; /* PCMRXHI has only 2 bits for timeslot */
+  /* add to the calculated timeslot values the non timeslot bits */
+  data |= (ReadReg(pProslic,pProslic->channel,PROSLIC_REG_PCMRXHI) & 0xFC);
+  WriteReg(pProslic,pProslic->channel,PROSLIC_REG_PCMRXHI,data);
+
+  return RC_NONE;
+}
+
+/*****************************************************************************************************/
+typedef ProslicInt proslicIntTypeMap[SI_MAX_INTERRUPTS][8];
+
+static int ProSLIC_ReadInterruptsHelper(proslicChanType_ptr pProslic,
+                                        uInt8 *regData, uInt8 numChannels)
+{
+  uInt8 i;
+  uInt8 intsActive;
+  uInt8 *currentData = regData;
+  SILABS_UNREFERENCED_PARAMETER(numChannels);
+
+  intsActive = ReadReg(pProslic, pProslic->channel, PROSLIC_REG_IRQ0);
+
+#ifdef PROSLIC_OPTIMIZE_INTERRUPTS
+  /* For dual channel devices, we need to shift the upper nibble for the second channel
+     if the caller requested the second channel.  We determine this by channel ID being
+     even or odd.  If this is NOT true - for example a Si3217x and then a Si3226x chipset
+     configuration on the same daisychain, then this optimization logic will not work */
+#if defined(SI3226X) || defined(SI3228X)
+  if( (numChannels != 0) && ((pProslic->channel) & 0x1))
+  {
+    intsActive = intsActive >> 4;
+  }
+#endif /* Multichannel devices */
+#endif
+
+  /* If there are no interrupts, stop... return back to calling function */
+  if((intsActive &0xF) == 0)
+  {
+    return RC_IGNORE;
+  }
+
+  for(i = PROSLIC_REG_IRQ1; i <= PROSLIC_REG_IRQ4; i++)
+  {
+#ifdef PROSLIC_OPTIMIZE_INTERRUPTS
+    /* Read IRQn Register only if IRQ0 states there was an interrupt pending, otherwise
+       skip it. This eliminates unneeded SPI transactions.
+    */
+    if( (intsActive & (1<<(i-PROSLIC_REG_IRQ1))) == 0)
+    {
+      *currentData++ = 0;
+      continue;
+    }
+#endif
+    *currentData = (uInt8)ReadReg(pProslic, pProslic->channel, i);
+#ifdef GCI_MODDE
+    WriteReg(pProslic, pProslic->channel, i, *current_data);
+#endif
+    currentData++;
+  } /* for loop */
+
+  return RC_COMPLETE_NO_ERR;
+}
+
+/*
+ Reads IRQ0 to determine if an interrupt has occurred for the particular device,
+ if so, reads the interrupt register(s) that fired the interrupt and then
+ maps the interrupt(s) to the generic interrupt value to return to the caller.
+
+ Code assumes normal chipset/compatibility testing has already been done.
+*/
+static int ProSLIC_GetInterruptHelper(proslicChanType_ptr pProslic,
+                                      const proslicIntTypeMap intMap, proslicIntType *pIntData, uInt8 numChannels)
+{
+  int i,j;
+  uInt8 intData[SI_MAX_INTERRUPTS];
+  uInt8 *currentData;
+  uInt8 map, intCount;
+  BOOLEAN safetyInt = FALSE;
+
+  /* Initialize interrupt count to 0 */
+  pIntData-> number = 0;
+
+  if( ProSLIC_ReadInterruptsHelper(pProslic, intData, numChannels) == RC_IGNORE)
+  {
+    /* No interrupts for the given channel. */
+    return RC_NONE;
+  }
+
+  /* At this point we've collected all the registers, now decode the data */
+  currentData = intData;
+  intCount = 0;
+
+  for(i = 0; i < SI_MAX_INTERRUPTS; i++)
+  {
+    if(*currentData)
+    {
+      for(j = 0; j < 8; j++)
+      {
+        if( *currentData & (1<<j) )
+        {
+          map = intMap[i][j];
+          pIntData->irqs[intCount] = map;
+
+          if( (map == IRQ_P_HVIC)
+              || (map == IRQ_P_THERM) )
+          {
+            safetyInt = TRUE;
+          }
+
+          intCount++;
+        }
+      }
+    }
+    currentData++;
+  }
+  
+  pIntData->number = intCount;
+  
+  if( safetyInt == TRUE)
+  {
+    if(ProSLIC_isReinitRequired(pProslic))
+    {
+      return RC_REINIT_REQUIRED;
+    }
+  }
+
+  return pIntData->number;
+}
+
+
+int ProSLIC_GetInterrupts (proslicChanType_ptr hProslic,
+                           proslicIntType *pIntData)
+{
+  const proslicIntTypeMap interruptMap =
+  {
+    {IRQ_OSC1_T1, IRQ_OSC1_T2, IRQ_OSC2_T1, IRQ_OSC2_T2, IRQ_RING_T1, IRQ_RING_T2, IRQ_FSKBUF_AVAIL, IRQ_VBAT},
+    {IRQ_RING_TRIP, IRQ_LOOP_STATUS, IRQ_LONG_STAT, IRQ_VOC_TRACK, IRQ_DTMF, IRQ_INDIRECT, IRQ_RXMDM, IRQ_TXMDM},
+    {IRQ_P_HVIC, IRQ_P_THERM, IRQ_PQ3, IRQ_PQ4, IRQ_PQ5, IRQ_PQ6, IRQ_DSP, IRQ_MADC_FS},
+    {IRQ_USER_0, IRQ_USER_1, IRQ_USER_2, IRQ_USER_3, IRQ_USER_4, IRQ_USER_5, IRQ_USER_6, IRQ_USER_7}
+  };
+
+  pIntData->number=0;
+  /* TRACEPRINT(hProslic, "\n", NULL); */
+  if(hProslic->channelType != PROSLIC)
+  {
+    return RC_IGNORE;
+  }
+#if defined (SI3217X) || defined (SI3218X) || defined(SI3219X)
+  if (0
+#ifdef SI3217X
+      || (hProslic->deviceId->chipType >= SI32171
+          && hProslic->deviceId->chipType <= SI32179)
+#endif
+#ifdef SI3218X
+      || (hProslic->deviceId->chipType >= SI32180
+          && hProslic->deviceId->chipType <= SI32189)
+#endif
+#ifdef SI3219X
+      || ( IS_SI3219X(hProslic->deviceId) )
+#endif
+     )
+  {
+    return ProSLIC_GetInterruptHelper(hProslic, interruptMap, pIntData, 1);
+  }
+#endif
+#if defined (SI3226X) || defined (SI3228X)
+  if( 0
+#ifdef SI3226X
+      || (hProslic->deviceId->chipType >= SI32260
+          && hProslic->deviceId->chipType <= SI32269)
+#endif
+#ifdef SI3228X
+      || (hProslic->deviceId->chipType >= SI32280
+          && hProslic->deviceId->chipType <= SI32289)
+#endif
+    )
+  {
+    return ProSLIC_GetInterruptHelper(hProslic, interruptMap, pIntData, 2);
+  }
+#endif
+  return RC_COMPLETE_NO_ERR;
+}
+
+/*****************************************************************************************************/
+int ProSLIC_ReadHookStatus (proslicChanType_ptr pProslic,uInt8 *pHookStat)
+{
+  TRACEPRINT(pProslic, "\n", NULL);
+  *pHookStat = PROSLIC_ONHOOK;
+
+  if(pProslic->channelType != PROSLIC)
+  {
+    return RC_IGNORE;
+  }
+  if (ReadReg(pProslic,pProslic->channel,PROSLIC_REG_LCRRTP) & 2)
+  {
+    *pHookStat=PROSLIC_OFFHOOK;
+  }
+  return RC_NONE;
+}
+
+/*****************************************************************************************************/
+int ProSLIC_SetLinefeedStatus (proslicChanType_ptr pProslic, uInt8 newLinefeed)
+{
+  uInt8 lfState;
+  uInt8 irqen1=0;
+  TRACEPRINT(pProslic, "linefeed = %u\n", newLinefeed);
+  
+  if(pProslic->channelType != PROSLIC)
+  {
+    return RC_IGNORE;
+  }
+
+  /* Get the irqen1 setting - used to determine if vbat interrupt was set... */
+#ifdef SI3217X
+  if (pProslic->deviceId->chipType >= SI32171
+    && pProslic->deviceId->chipType <= SI32179)
+  {
+      irqen1 = Si3217x_General_Configuration.irqen1;
+  }
+#endif
+
+#ifdef SI3218X
+  if (pProslic->deviceId->chipType >= SI32180
+    && pProslic->deviceId->chipType <= SI32189)
+  {
+      irqen1 = Si3218x_General_Configuration.irqen1;
+  }
+#endif
+
+#ifdef SI3219X
+  if ( IS_SI3219X(pProslic->deviceId) )
+  {
+      irqen1 = Si3219x_General_Configuration.irqen1;
+  }
+#endif
+
+#ifdef SI3226X
+  if (pProslic->deviceId->chipType >= SI32260
+    && pProslic->deviceId->chipType <= SI32269)
+  {
+      irqen1 = Si3226x_General_Configuration.irqen1;
+  }
+#endif
+
+#ifdef SI3228X
+  if (pProslic->deviceId->chipType >= SI32280
+    && pProslic->deviceId->chipType <= SI32289)
+  {
+      irqen1 = Si3228x_General_Configuration.irqen1;
+  }
+#endif
+
+  if( (newLinefeed& 0xF)  == LF_RINGING )
+  {
+    uInt8 regTemp;
+
+    lfState = ReadReg(pProslic, pProslic->channel, PROSLIC_REG_LINEFEED);
+
+    /* Only change to ringing state if not ringing... */
+    if( (lfState & 0xF) != LF_RINGING )
+    {
+      if(irqen1 & 0x80)
+      {
+        /*disable vbat interrupt during ringing*/
+        regTemp = ReadReg(pProslic, pProslic->channel, PROSLIC_REG_IRQEN1 );
+        WriteReg (pProslic, pProslic->channel, PROSLIC_REG_IRQEN1, regTemp&(~0x80));
+      }
+
+      WriteReg(pProslic, pProslic->channel, PROSLIC_REG_LINEFEED, LF_RINGING);
+    }
+    else
+    {
+      return RC_IGNORE;
+    }
+  }
+  else
+  {
+    uInt8 autord;
+
+    /* Preserve the auto register so we can restore it at the end */
+    autord = ReadReg(pProslic, pProslic->channel, PROSLIC_REG_AUTORD );
+    WriteReg(pProslic, pProslic->channel, PROSLIC_REG_AUTORD, (autord & 0xFB) ); /* Disable AutoRD */
+
+    lfState = ReadReg(pProslic, pProslic->channel, PROSLIC_REG_LINEFEED);
+
+    if( (lfState & 0xF) == LF_RINGING ) 
+    {
+      WriteReg(pProslic, pProslic->channel, PROSLIC_REG_LINEFEED, newLinefeed);
+    }
+    else
+    {
+      /* We are already doing a state transition, abort request */
+      if( ((lfState & 0xF0) == (LF_RINGING << 4) )
+        && ( (lfState & 0xF) != LF_RINGING) )
+      {
+        WriteReg(pProslic, pProslic->channel, PROSLIC_REG_AUTORD, autord ); /* restore the autord bit */
+        return RC_IGNORE;
+      }
+
+      WriteReg(pProslic, pProslic->channel, PROSLIC_REG_LINEFEED, newLinefeed);
+    }
+    /* Restore autord */
+    WriteReg(pProslic, pProslic->channel, PROSLIC_REG_AUTORD, autord );
+
+    /* Restore IRQEN1 to what the user specified - if we changed it.. */
+    if(irqen1 & 0x80)
+    {
+      WriteReg (pProslic, pProslic->channel, PROSLIC_REG_IRQEN1, irqen1);
+    }
+  }
+  return RC_NONE;
+}
+
+/*****************************************************************************************************/
+int ProSLIC_SetLinefeedStatusBroadcast (proslicChanType_ptr hProslic,
+                                        uInt8 newLinefeed)
+{
+  TRACEPRINT(hProslic, "linefeed = %u\n", newLinefeed);
+  if(hProslic->channelType != PROSLIC)
+  {
+    return RC_IGNORE;
+  }
+
+  WriteReg(hProslic, PROSLIC_CHAN_BROADCAST, PROSLIC_REG_LINEFEED, newLinefeed);
+  return RC_COMPLETE_NO_ERR;
+}
+
+/*****************************************************************************************************/
+int ProSLIC_PolRev (proslicChanType_ptr pProslic,uInt8 abrupt,
+                    uInt8 newPolRevState)
+{
+  uInt8 data = 0;
+  TRACEPRINT(pProslic, "abrupt = %u newPolRevState = %u\n", abrupt,
+             newPolRevState);
+  if(pProslic->channelType != PROSLIC)
+  {
+    return RC_IGNORE;
+  }
+
+  switch (newPolRevState)
+  {
+    case POLREV_STOP:
+      data = 0;
+      break;
+    case POLREV_START:
+      data = 2;
+      break;
+    case WINK_START:
+      data = 6;
+      break;
+    case WINK_STOP:
+      data = 4;
+      break;
+  }
+
+  /* Cannot polrev/wink while low power mode is active */
+  ProSLIC_SetPowersaveMode(pProslic,PWRSAVE_DISABLE);
+
+  if (abrupt)
+  {
+    data |= 1;
+  }
+
+  WriteReg(pProslic, pProslic->channel, PROSLIC_REG_POLREV,data);
+
+  return RC_NONE;
+}
+
+/*****************************************************************************************************/
+int ProSLIC_GPIOControl (proslicChanType_ptr pProslic,uInt8 *pGpioData,
+                         uInt8 read)
+{
+  TRACEPRINT(pProslic, "\n", NULL);
+  if(pProslic->channelType != PROSLIC)
+  {
+    return RC_IGNORE;
+  }
+#if defined(SI3217X) || defined (SI3226X)
+  if( 0
+#ifdef SI3217X
+      || (pProslic->deviceId->chipType >= SI32171
+          && pProslic->deviceId->chipType <= SI32179)
+#endif
+#ifdef SI3226X
+      || (pProslic->deviceId->chipType >= SI32260
+          && pProslic->deviceId->chipType <= SI32269)
+#endif
+    )
+  {
+    if (read)
+    {
+      *pGpioData = 0xf & ReadReg(pProslic,pProslic->channel,PROSLIC_REG_GPIO);
+    }
+    else
+    {
+      WriteReg(pProslic,pProslic->channel,PROSLIC_REG_GPIO,
+               (*pGpioData)|(ReadReg(pProslic,pProslic->channel,PROSLIC_REG_GPIO)&0xf0));
+    }
+    return RC_NONE;
+  }
+#else
+  SILABS_UNREFERENCED_PARAMETER(read);
+  SILABS_UNREFERENCED_PARAMETER(pGpioData);
+#endif 
+  return RC_COMPLETE_NO_ERR;
+}
+
+/*****************************************************************************************************/
+/*
+** Optional Neon Message Waiting Support
+*/
+#ifdef SIVOICE_NEON_MWI_SUPPORT
+int ProSLIC_MWISetV (proslicChanType_ptr hProslic, uInt16 vpk_mag)
+{
+  uInt32 ram_val;
+  uInt8 max;
+  
+  TRACEPRINT(hProslic, "vpk_mag = %u\n", vpk_mag);
+  if(hProslic->channelType != PROSLIC)
+  {
+    return RC_IGNORE;
+  }
+  
+  /* Set the maximum MWI voltage according to the chipset */
+#if defined (SI3217X) || defined (SI3226X)
+  if( 0
+#ifdef SI3217X
+      || (hProslic->deviceId->chipType >= SI32171
+          && hProslic->deviceId->chipType <= SI32179)
+#endif
+#ifdef SI3226X
+      || (hProslic->deviceId->chipType >= SI32260
+          && hProslic->deviceId->chipType <= SI32269)
+#endif
+    )
+  {
+    max = SIL_MWI_VPK_MAX;
+  }
+#endif /*17x/26x */
+
+#if defined (SI3218X) || defined (SI3228X) || defined(SI3219X)
+  if( 0
+#ifdef SI3218X
+    || (hProslic->deviceId->chipType >= SI32180
+      && hProslic->deviceId->chipType <= SI32189)
+#endif
+
+#ifdef SI3228X
+    || (hProslic->deviceId->chipType >= SI32280
+      && hProslic->deviceId->chipType <= SI32289)
+#endif
+
+#ifdef SI3219X
+    || IS_SI3219X(hProslic->deviceId) 
+#endif
+
+#ifdef SI3228X
+      || (hProslic->deviceId->chipType >= SI32280
+          && hProslic->deviceId->chipType <= SI32289)
+#endif
+    )
+  {
+    max = SIL_MWI_VPK_MAX_LO;
+  }
+#endif /* 18x, 28x, 19x */
+
+  /* Voltage mod */
+  if(vpk_mag > 0)  /* Skip if 0 passed */
+  {
+    /* Clamp supplied value to allowable range */
+    if(vpk_mag > max)
+    {
+      vpk_mag = max;
+    }
+    if(vpk_mag < SIL_MWI_VPK_MIN)
+    {
+      vpk_mag = SIL_MWI_VPK_MIN;
+    }
+    ram_val = vpk_mag * SCALE_R_MADC * 1000L;
+    WriteRAM(hProslic,hProslic->channel,PROSLIC_RAM_MWI_V,ram_val);
+  }
+  return RC_COMPLETE_NO_ERR;
+}
+#endif
+
+/*****************************************************************************************************/
+#ifdef SIVOICE_NEON_MWI_SUPPORT
+int ProSLIC_MWIEnable (proslicChanType_ptr hProslic)
+{
+  uInt8 val;
+  ramData ram_val;
+  
+  TRACEPRINT(hProslic, "\n", NULL);
+  
+  /*
+  ** Check for conditions that would prevent enabling MWI
+  */
+  ProSLIC_ReadHookStatus(hProslic,&val);
+  if(val != PROSLIC_ONHOOK)
+  {
+    return RC_MWI_ENABLE_FAIL;
+  }
+  
+  val = ReadReg(hProslic,hProslic->channel,PROSLIC_REG_USERSTAT);
+
+  /* Check if PROSLIC and disabled MWI, if not, ignore this request. */
+  if( (hProslic->channelType != PROSLIC)
+       || (val & SIL_MWI_USTAT_SET ) )
+  {
+    return RC_IGNORE;
+  }
+  
+  /* Save parameters */
+  hProslic->mwiSave.ringof = ReadRAM(hProslic,hProslic->channel,PROSLIC_RAM_RINGOF);
+  hProslic->mwiSave.ringamp = ReadRAM(hProslic,hProslic->channel,PROSLIC_RAM_RINGAMP);
+  hProslic->mwiSave.vbatr_expect = ReadRAM(hProslic,hProslic->channel,PROSLIC_RAM_VBATR_EXPECT);
+  hProslic->mwiSave.vov_ring_bat = ReadRAM(hProslic,hProslic->channel,PROSLIC_RAM_VOV_RING_BAT);
+  hProslic->mwiSave.vov_ring_gnd = ReadRAM(hProslic,hProslic->channel,PROSLIC_RAM_VOV_RING_GND);
+  hProslic->mwiSave.rtacth = ReadRAM(hProslic,hProslic->channel,PROSLIC_RAM_RTACTH);
+  hProslic->mwiSave.rtdcth = ReadRAM(hProslic,hProslic->channel,PROSLIC_RAM_RTDCTH);
+  hProslic->mwiSave.iring_lim = ReadRAM(hProslic,hProslic->channel,PROSLIC_RAM_IRING_LIM);
+  hProslic->mwiSave.dcdc_rngtype = ReadRAM(hProslic,hProslic->channel,PROSLIC_RAM_DCDC_RNGTYPE);
+  hProslic->mwiSave.slope_ring = ReadRAM(hProslic,hProslic->channel,PROSLIC_RAM_SLOPE_RING);
+  hProslic->mwiSave.rtper = ReadRAM(hProslic,hProslic->channel,PROSLIC_RAM_RTPER);
+  hProslic->mwiSave.ringfr = ReadRAM(hProslic,hProslic->channel,PROSLIC_RAM_RINGFR);
+  hProslic->mwiSave.rtdcdb = ReadRAM(hProslic,hProslic->channel,PROSLIC_RAM_RTDCDB);
+  hProslic->mwiSave.lcrmask = ReadRAM(hProslic,hProslic->channel,PROSLIC_RAM_LCRMASK);
+  hProslic->mwiSave.dcdc_oithresh_lo = ReadRAM(hProslic,hProslic->channel,PROSLIC_RAM_DCDC_OITHRESH_LO);
+  hProslic->mwiSave.enhance = ReadReg(hProslic,hProslic->channel,PROSLIC_REG_ENHANCE);
+  hProslic->mwiSave.ringcon = ReadReg(hProslic,hProslic->channel,PROSLIC_REG_RINGCON);
+  hProslic->mwiSave.userstat =  val;
+  hProslic->mwiSave.linefeed = ReadReg(hProslic,hProslic->channel,PROSLIC_REG_LINEFEED);
+  
+  /* Modify parameters */
+  ProSLIC_SetLinefeedStatus(hProslic,LF_FWD_ACTIVE);
+  ram_val = ReadRAM(hProslic,hProslic->channel,PROSLIC_RAM_MWI_V);
+  WriteRAM(hProslic,hProslic->channel,PROSLIC_RAM_RINGOF,ram_val);
+  WriteRAM(hProslic,hProslic->channel,PROSLIC_RAM_RINGAMP,0x0L);
+
+  /* Set the VBATR_EXPECT according to the chipset */
+#if defined (SI3217X) || defined (SI3226X)
+  if( 0
+#ifdef SI3217X
+      || (hProslic->deviceId->chipType >= SI32171
+          && hProslic->deviceId->chipType <= SI32179)
+#endif
+#ifdef SI3226X
+      || (hProslic->deviceId->chipType >= SI32260
+          && hProslic->deviceId->chipType <= SI32269)
+#endif
+    )
+  {
+    ram_val = 0x7FFFFC2L;
+  }
+#endif
+
+#if defined (SI3218X) || defined (SI3228X) || defined(SI3219X)
+  if( 0
+#ifdef SI3218X
+      || (hProslic->deviceId->chipType >= SI32180
+          && hProslic->deviceId->chipType <= SI32189)
+#endif
+
+#ifdef SI3228X
+      || (hProslic->deviceId->chipType >= SI32280
+          && hProslic->deviceId->chipType <= SI32289)
+#endif
+
+#ifdef SI3219X
+    || IS_SI3219X(hProslic->deviceId) 
+#endif
+    )
+  {
+    ram_val = 0x06866635L;
+  }
+#endif /* 18x,28x, 19x */
+
+  WriteRAM(hProslic,hProslic->channel,PROSLIC_RAM_VBATR_EXPECT,ram_val);
+  WriteRAM(hProslic,hProslic->channel,PROSLIC_RAM_VOV_RING_BAT,0x0L);
+  WriteRAM(hProslic,hProslic->channel,PROSLIC_RAM_VOV_RING_GND,0x051EB80L);
+  WriteRAM(hProslic,hProslic->channel,PROSLIC_RAM_RTACTH,0x0FFFFFFFL);
+  WriteRAM(hProslic,hProslic->channel,PROSLIC_RAM_RTDCTH,0x38E38EL);
+  WriteRAM(hProslic,hProslic->channel,PROSLIC_RAM_IRING_LIM,0x380000L);
+  WriteRAM(hProslic,hProslic->channel,PROSLIC_RAM_DCDC_RNGTYPE,0x100000L);
+  WriteRAM(hProslic,hProslic->channel,PROSLIC_RAM_SLOPE_RING,0x15E5200EL);
+  WriteRAM(hProslic,hProslic->channel,PROSLIC_RAM_RTPER,0x50000L);
+  WriteRAM(hProslic,hProslic->channel,PROSLIC_RAM_RINGFR,0x07EFE000L);
+  WriteRAM(hProslic,hProslic->channel,PROSLIC_RAM_RTDCDB,0x0000A000L);
+  WriteRAM(hProslic,hProslic->channel,PROSLIC_RAM_LCRMASK,0x000F0000L);
+  ram_val = ReadRAM(hProslic,hProslic->channel,PROSLIC_RAM_DCDC_OITHRESH_HI);
+  WriteRAM(hProslic,hProslic->channel,PROSLIC_RAM_DCDC_OITHRESH_LO,ram_val);
+  WriteReg(hProslic,hProslic->channel,PROSLIC_REG_ENHANCE,hProslic->mwiSave.enhance&0xEF);
+  WriteReg(hProslic,hProslic->channel,PROSLIC_REG_RINGCON,0x00);
+  WriteReg(hProslic,hProslic->channel,PROSLIC_REG_USERSTAT,0x0C);
+  
+  return RC_COMPLETE_NO_ERR;
+}
+#endif
+
+/*****************************************************************************************************/
+#ifdef SIVOICE_NEON_MWI_SUPPORT
+int ProSLIC_MWIDisable (proslicChanType_ptr hProslic)
+{
+  TRACEPRINT(hProslic, "\n", NULL);
+
+  /* Check if PROSLIC and enabled MWI, if not, ignore this request. */
+  if( (hProslic->channelType != PROSLIC)
+       || !(ReadReg(hProslic,hProslic->channel,PROSLIC_REG_USERSTAT) & SIL_MWI_USTAT_SET ) )
+  {
+    return RC_IGNORE;
+  }
+
+  ProSLIC_SetLinefeedStatus(hProslic,LF_FWD_ACTIVE);
+  WriteRAM(hProslic,hProslic->channel,PROSLIC_RAM_RINGOF,hProslic->mwiSave.ringof);
+  WriteRAM(hProslic,hProslic->channel,PROSLIC_RAM_RINGAMP,hProslic->mwiSave.ringamp);
+  WriteRAM(hProslic,hProslic->channel,PROSLIC_RAM_VBATR_EXPECT,hProslic->mwiSave.vbatr_expect);
+  WriteRAM(hProslic,hProslic->channel,PROSLIC_RAM_VOV_RING_BAT,hProslic->mwiSave.vov_ring_bat);
+  WriteRAM(hProslic,hProslic->channel,PROSLIC_RAM_VOV_RING_GND,hProslic->mwiSave.vov_ring_gnd);
+  WriteRAM(hProslic,hProslic->channel,PROSLIC_RAM_RTACTH,hProslic->mwiSave.rtacth);
+  WriteRAM(hProslic,hProslic->channel,PROSLIC_RAM_RTDCTH,hProslic->mwiSave.rtdcth);
+  WriteRAM(hProslic,hProslic->channel,PROSLIC_RAM_IRING_LIM,hProslic->mwiSave.iring_lim);
+  WriteRAM(hProslic,hProslic->channel,PROSLIC_RAM_DCDC_RNGTYPE,hProslic->mwiSave.dcdc_rngtype);
+  WriteRAM(hProslic,hProslic->channel,PROSLIC_RAM_SLOPE_RING,hProslic->mwiSave.slope_ring);
+  WriteRAM(hProslic,hProslic->channel,PROSLIC_RAM_RTPER,hProslic->mwiSave.rtper);
+  WriteRAM(hProslic,hProslic->channel,PROSLIC_RAM_RINGFR,hProslic->mwiSave.ringfr);
+  WriteRAM(hProslic,hProslic->channel,PROSLIC_RAM_RTDCDB,hProslic->mwiSave.rtdcdb);
+  WriteRAM(hProslic,hProslic->channel,PROSLIC_RAM_LCRMASK,hProslic->mwiSave.lcrmask);
+  WriteRAM(hProslic,hProslic->channel,PROSLIC_RAM_DCDC_OITHRESH_LO,hProslic->mwiSave.dcdc_oithresh_lo);
+  WriteReg(hProslic,hProslic->channel,PROSLIC_REG_ENHANCE,hProslic->mwiSave.enhance);
+  WriteReg(hProslic,hProslic->channel,PROSLIC_REG_RINGCON,hProslic->mwiSave.ringcon);
+  WriteReg(hProslic,hProslic->channel,PROSLIC_REG_USERSTAT,hProslic->mwiSave.userstat);
+  ProSLIC_SetLinefeedStatus(hProslic,hProslic->mwiSave.linefeed);
+  
+  return RC_COMPLETE_NO_ERR;
+}
+#endif
+
+/*****************************************************************************************************/
+#ifdef SIVOICE_NEON_MWI_SUPPORT
+int ProSLIC_SetMWIState (proslicChanType_ptr hProslic,uInt8 flash_on)
+{
+  TRACEPRINT(hProslic, "flash_on = %u\n", flash_on);
+  /* Check if PROSLIC and enabled MWI, if not, ignore this request. */
+  if( (hProslic->channelType != PROSLIC)
+       || !(ReadReg(hProslic,hProslic->channel,PROSLIC_REG_USERSTAT) & SIL_MWI_USTAT_SET ) )
+  {
+    return RC_IGNORE;
+  }
+  
+  if(flash_on)
+  {
+    ProSLIC_SetLinefeedStatus(hProslic,LF_RINGING);
+  }
+  else
+  {
+    ProSLIC_SetLinefeedStatus(hProslic,LF_FWD_ACTIVE);
+  }
+  
+  return RC_COMPLETE_NO_ERR;
+}
+#endif
+
+/*****************************************************************************************************/
+#ifdef SIVOICE_NEON_MWI_SUPPORT
+int ProSLIC_GetMWIState (proslicChanType_ptr hProslic)
+{
+  TRACEPRINT(hProslic, "\n", NULL);
+  /* Check if PROSLIC and enabled MWI, if not, ignore this request. */
+  if( (hProslic->channelType != PROSLIC)
+       || !(ReadReg(hProslic,hProslic->channel,PROSLIC_REG_USERSTAT) & SIL_MWI_USTAT_SET ) )
+  {
+    return RC_IGNORE;
+  }
+  
+  if(ReadReg(hProslic,hProslic->channel,PROSLIC_REG_LINEFEED) == 0x44)
+  {
+    return SIL_MWI_FLASH_ON;
+  }
+  else
+  {
+    return SIL_MWI_FLASH_OFF;
+  }
+  
+  return RC_COMPLETE_NO_ERR;
+}
+#endif
+
+/******************************************************************************/
+#ifdef SIVOICE_NEON_MWI_SUPPORT
+int ProSLIC_MWIRampPoll(proslicChanType_ptr pProslic)
+{
+  uInt32 mwi_voltage;
+  
+  /* Check if PROSLIC and enabled MWI, if not, ignore this request. */
+  if( (pProslic->channelType != PROSLIC)
+       || !(ReadReg(pProslic,pProslic->channel,PROSLIC_REG_USERSTAT) & SIL_MWI_USTAT_SET ) )
+  {
+    return RC_IGNORE;
+  }
+  
+  switch(pProslic->mwiState.state)
+  {
+    case PROSLIC_MWI_RAMP_ON:
+    {
+      if(pProslic->mwiState.ticks == pProslic->mwiState.poll.steps)
+      {
+        mwi_voltage = pProslic->mwiState.poll.voff + pProslic->mwiState.poll.step_size;
+        WriteRAM(pProslic,pProslic->channel,PROSLIC_RAM_RINGOF,mwi_voltage);
+        ProSLIC_SetLinefeedStatus(pProslic,LF_RINGING);
+      }
+      else if(pProslic->mwiState.ticks == 0)
+      {
+        mwi_voltage = pProslic->mwiState.poll.von;
+        WriteRAM(pProslic,pProslic->channel,PROSLIC_RAM_RINGOF,mwi_voltage);
+        pProslic->mwiState.ticks = pProslic->mwiState.poll.onTime+1;
+        pProslic->mwiState.state = PROSLIC_MWI_ON;
+      }
+      else
+      {
+        mwi_voltage = pProslic->mwiState.poll.voff + pProslic->mwiState.poll.step_size*(pProslic->mwiState.poll.steps - pProslic->mwiState.ticks + 1);
+        WriteRAM(pProslic,pProslic->channel,PROSLIC_RAM_RINGOF,mwi_voltage);
+      }
+    }
+    break;
+
+    case PROSLIC_MWI_RAMP_OFF:
+    {
+      if(pProslic->mwiState.ticks == 0)
+      {
+        pProslic->mwiState.ticks = pProslic->mwiState.poll.offTime+1;
+        pProslic->mwiState.state = PROSLIC_MWI_OFF;
+        ProSLIC_SetLinefeedStatus(pProslic,LF_FWD_ACTIVE);
+        }
+      else 
+      {
+        mwi_voltage = pProslic->mwiState.poll.von - (pProslic->mwiState.poll.steps - pProslic->mwiState.ticks + 1)*pProslic->mwiState.poll.step_size;
+        WriteRAM(pProslic,pProslic->channel,PROSLIC_RAM_RINGOF,mwi_voltage);
+      }
+    break;
+    }
+    
+    case PROSLIC_MWI_ON:
+      if(pProslic->mwiState.ticks == 0)
+      {
+        pProslic->mwiState.ticks = pProslic->mwiState.poll.steps+1;
+        pProslic->mwiState.state = PROSLIC_MWI_RAMP_OFF;
+      }
+      break;
+      
+    case PROSLIC_MWI_OFF:
+      if(pProslic->mwiState.ticks == 0)
+      {
+        pProslic->mwiState.ticks = pProslic->mwiState.poll.steps+1;
+        pProslic->mwiState.state = PROSLIC_MWI_RAMP_ON;
+      }
+      break;
+
+    default:
+      /* Do nothing */
+      break;
+  }
+  (pProslic->mwiState.ticks)--; 
+
+  return RC_COMPLETE_NO_ERR;
+}
+#endif
+
+/******************************************************************************/
+#ifdef SIVOICE_NEON_MWI_SUPPORT
+int ProSLIC_MWIRampStart(proslicChanType_ptr pProslic, uInt32 steps, uInt32 onTime, uInt32 offTime)
+{
+  /* Check if PROSLIC and enabled MWI, if not, ignore this request. */
+  if( (pProslic->channelType != PROSLIC)
+       || !(ReadReg(pProslic,pProslic->channel,PROSLIC_REG_USERSTAT) & SIL_MWI_USTAT_SET ) )
+  {
+    return RC_IGNORE;
+  }
+  
+  pProslic->mwiState.poll.steps = steps-1;
+  pProslic->mwiState.poll.onTime = onTime;
+  pProslic->mwiState.poll.offTime = offTime;
+  
+  pProslic->mwiState.poll.von = ReadRAM(pProslic,pProslic->channel,PROSLIC_RAM_MWI_V);
+  pProslic->mwiState.poll.voff = (ReadRAM(pProslic,pProslic->channel,PROSLIC_RAM_V_VLIM)*5)/6;
+  pProslic->mwiState.poll.step_size = (pProslic->mwiState.poll.von - pProslic->mwiState.poll.voff)/steps;
+  
+  pProslic->mwiState.state = PROSLIC_MWI_RAMP_ON;
+  pProslic->mwiState.ticks = pProslic->mwiState.poll.steps;
+
+  return RC_COMPLETE_NO_ERR;
+}
+#endif
+
+/******************************************************************************/
+#ifdef SIVOICE_NEON_MWI_SUPPORT
+int ProSLIC_MWIRampStop(proslicChanType_ptr pProslic)
+{
+  /* Check if PROSLIC and enabled MWI, if not, ignore this request. */
+  if( (pProslic->channelType != PROSLIC)
+       || !(ReadReg(pProslic,pProslic->channel,PROSLIC_REG_USERSTAT) & SIL_MWI_USTAT_SET ) )
+  {
+    return RC_IGNORE;
+  }
+  pProslic->mwiState.state = PROSLIC_MWI_OFF;
+  
+  return RC_COMPLETE_NO_ERR;
+}
+#endif
+
+/*****************************************************************************************************/
+int ProSLIC_ToneGenStart (proslicChanType_ptr pProslic,uInt8 timerEn)
+{
+  uInt8 data;
+  TRACEPRINT(pProslic, "timerEn = %u\n", timerEn);
+  if(pProslic->channelType != PROSLIC)
+  {
+    return RC_IGNORE;
+  }
+  DEBUG_PRINT(pProslic, "%s%s on channel %d\n",LOGPRINT_PREFIX, __FUNCTION__,
+              pProslic->channel);
+
+  data = ReadReg(pProslic,pProslic->channel,PROSLIC_REG_OCON);
+  data |= 0x11 + (timerEn ? 0x66 : 0);
+  return WriteReg(pProslic,pProslic->channel,PROSLIC_REG_OCON,data);
+}
+
+/*****************************************************************************************************/
+int ProSLIC_ToneGenStop (proslicChanType_ptr pProslic)
+{
+  uInt8 data;
+  TRACEPRINT(pProslic, "\n", NULL);
+  if(pProslic->channelType != PROSLIC)
+  {
+    return RC_IGNORE;
+  }
+  DEBUG_PRINT(pProslic,"%s%s on channel %d\n",LOGPRINT_PREFIX, __FUNCTION__,
+              pProslic->channel);
+  data = ReadReg(pProslic,pProslic->channel,PROSLIC_REG_OCON);
+  data &= ~(0x77);
+  return WriteReg(pProslic,pProslic->channel,PROSLIC_REG_OCON,data);
+}
+
+/*****************************************************************************************************/
+int ProSLIC_RingStart (proslicChanType_ptr pProslic)
+{
+  TRACEPRINT(pProslic, "\n", NULL);
+  return(ProSLIC_SetLinefeedStatus(pProslic, LF_RINGING));
+}
+
+/*****************************************************************************************************/
+int ProSLIC_RingStop (proslicChanType_ptr pProslic)
+{
+  TRACEPRINT(pProslic, "\n", NULL);
+  return(ProSLIC_SetLinefeedStatus(pProslic, LF_FWD_ACTIVE));
+}
+
+#ifndef DISABLE_FSK_SETUP
+/*****************************************************************************************************/
+int ProSLIC_CheckCIDBuffer (proslicChanType_ptr pProslic, uInt8 *fsk_buf_avail)
+{
+  uInt8 data;
+  TRACEPRINT(pProslic, "\n", NULL);
+  if(pProslic->channelType != PROSLIC)
+  {
+    return RC_IGNORE;
+  }
+
+  data = ReadReg(pProslic,pProslic->channel, PROSLIC_REG_IRQ1);
+#ifdef GCI_MODE
+  WriteReg(pProslic,pProslic->channel, PROSLIC_REG_IRQ1,data); /*clear (for GCI)*/
+#endif
+  *fsk_buf_avail = (data&0x40) ? 1 : 0;
+  return RC_NONE;
+}
+
+/*****************************************************************************************************/
+int ProSLIC_EnableCID (proslicChanType_ptr pProslic)
+{
+  uInt8 data;
+  TRACEPRINT(pProslic, "\n", NULL);
+  if(pProslic->channelType != PROSLIC)
+  {
+    return RC_IGNORE;
+  }
+  DEBUG_PRINT(pProslic, "%sEnableCID on channel %d\n",LOGPRINT_PREFIX,
+              pProslic->channel);
+  WriteReg(pProslic,pProslic->channel,PROSLIC_REG_OCON,0);
+
+  data = ReadReg(pProslic,pProslic->channel,PROSLIC_REG_OMODE);
+  data |= 0xA;
+  WriteReg(pProslic,pProslic->channel,PROSLIC_REG_OMODE,data);
+
+  return(WriteReg(pProslic,pProslic->channel,PROSLIC_REG_OCON,0x5));
+}
+
+/*****************************************************************************************************/
+int ProSLIC_DisableCID (proslicChanType_ptr pProslic)
+{
+  uInt8 data;
+  TRACEPRINT(pProslic, "\n", NULL);
+
+  if(pProslic->channelType != PROSLIC)
+  {
+    return RC_IGNORE;
+  }
+  DEBUG_PRINT(pProslic, "%sDisableCID on channel %d\n",LOGPRINT_PREFIX,
+              pProslic->channel);
+  WriteReg(pProslic,pProslic->channel,PROSLIC_REG_OCON,0);
+  data = ReadReg(pProslic,pProslic->channel,PROSLIC_REG_OMODE);
+  data &= ~(0x8);
+
+  return(WriteReg(pProslic,pProslic->channel,PROSLIC_REG_OMODE,data));
+}
+
+/*****************************************************************************************************/
+int ProSLIC_SendCID (proslicChanType_ptr pProslic, uInt8 *buffer,
+                     uInt8 numBytes)
+{
+  TRACEPRINT(pProslic, "numBytes = %u\n", numBytes);
+
+  if(pProslic->channelType != PROSLIC)
+  {
+    return RC_IGNORE;
+  }
+  DEBUG_PRINT (pProslic, "%sSendCID on channel %d\n",LOGPRINT_PREFIX,
+               pProslic->channel);
+  while (numBytes-- > 0)
+  {
+    WriteReg(pProslic,pProslic->channel,PROSLIC_REG_FSKDAT,*(buffer++));
+  }
+  return RC_NONE;
+}
+
+/*****************************************************************************************************/
+int ProSLIC_ModifyCIDStartBits(proslicChanType_ptr pProslic,
+                               uInt8 enable_startStop)
+{
+  uInt8 data;
+  TRACEPRINT(pProslic, "enable_startStop = %u\n", enable_startStop);
+
+  if(pProslic->channelType != PROSLIC)
+  {
+    return RC_CHANNEL_TYPE_ERR;
+  }
+
+  data = ReadReg(pProslic,pProslic->channel,PROSLIC_REG_OMODE);
+
+  if(enable_startStop == FALSE)
+  {
+    data &= ~0x80;
+  }
+  else
+  {
+    data |= 0x80;
+  }
+
+  WriteReg(pProslic,pProslic->channel,PROSLIC_REG_OMODE,data);
+
+  return RC_NONE;
+}
+#endif /* DISABLE_FSK_SETUP */
+/*****************************************************************************************************/
+int ProSLIC_PCMStart (proslicChanType_ptr pProslic)
+{
+  uInt8 data;
+  TRACEPRINT(pProslic, "\n", NULL);
+
+  if(pProslic->channelType != PROSLIC)
+  {
+    return RC_IGNORE;
+  }
+  DEBUG_PRINT(pProslic, "%sPCMStart\n", LOGPRINT_PREFIX);
+  data = ReadReg(pProslic,pProslic->channel,PROSLIC_REG_PCMMODE);
+  data |= 0x10;
+
+  return WriteReg(pProslic,pProslic->channel,PROSLIC_REG_PCMMODE,data);
+}
+
+/*****************************************************************************************************/
+int ProSLIC_PCMStop (proslicChanType_ptr pProslic)
+{
+  uInt8 data;
+  TRACEPRINT(pProslic, "\n", NULL);
+
+  if(pProslic->channelType != PROSLIC)
+  {
+    return RC_IGNORE;
+  }
+
+  DEBUG_PRINT(pProslic, "%sPCMStart\n", LOGPRINT_PREFIX);
+  data = ReadReg(pProslic,pProslic->channel,PROSLIC_REG_PCMMODE);
+  data &= ~0x10;
+
+  return WriteReg(pProslic,pProslic->channel,PROSLIC_REG_PCMMODE,data);
+}
+
+#ifndef DISABLE_HOOKCHANGE
+/*****************************************************************************************************/
+/*
+** Function: ProSLIC_ResetDialPulseDetect
+**
+** Description:
+** reset dial pulse detection state machine (helper function for
+** ProSLIC_InitializeHookChangeDetect.
+*/
+static void ProSLIC_ResetDialPulseDetect(hookChangeType *pPulse)
+{
+  pPulse->currentPulseDigit = 0;
+  pPulse->lookingForTimeout = 0;
+}
+
+/*****************************************************************************************************/
+/*
+** Function: ProSLIC_InitializeHookChangeDetect
+**
+** Description:
+** Initialize dial pulse detection parameters
+*/
+int ProSLIC_InitializeHookChangeDetect(hookChangeType *pPulse,void *hookTime)
+{
+  TRACEPRINT_NOCHAN("\n", NULL);
+  pPulse->hookTime = hookTime;
+  pPulse->last_state_reported =  SI_HC_NO_ACTIVITY;
+  ProSLIC_ResetDialPulseDetect(pPulse);
+  return RC_NONE;
+}
+
+/*****************************************************************************************************/
+/*
+** Function: ProSLIC_HookChangeDetect
+**
+** Description:
+** implements pulse dial detection and should be called at every hook transition
+*/
+uInt8 ProSLIC_HookChangeDetect (proslicChanType *pProslic,
+                                hookChange_Cfg *pHookChangeCfg, hookChangeType *pHookChangeData)
+{
+  uInt8 hookStat;
+  int delta_time;
+
+  TRACEPRINT(pProslic, "\n", NULL);
+  if(pProslic->channelType != PROSLIC)
+  {
+    return RC_IGNORE;
+  }
+
+  TimeElapsed(pProTimer,pHookChangeData->hookTime,&delta_time);
+  ProSLIC_ReadHookStatus(pProslic,&hookStat);
+
+  /* Did we have a hook state change? */
+  if(hookStat !=  pHookChangeData->last_hook_state)
+  {
+    pHookChangeData->last_hook_state = hookStat;
+    getTime(pProTimer,pHookChangeData->hookTime);
+    pHookChangeData->lookingForTimeout = 1;
+    if (hookStat == PROSLIC_OFFHOOK)
+    {
+      if ((delta_time >= (pHookChangeCfg->minOnHook))
+          && (delta_time <= (pHookChangeCfg->maxOnHook)))
+      {
+        pHookChangeData->currentPulseDigit++;
+      }
+      else
+      {
+        /* Did we see a hook flash? */
+        if( (delta_time >= pHookChangeCfg->minHookFlash)
+            && (delta_time <= pHookChangeCfg->maxHookFlash) )
+        {
+          pHookChangeData->last_state_reported = SI_HC_HOOKFLASH;
+          ProSLIC_ResetDialPulseDetect(pHookChangeData);
+          return SI_HC_HOOKFLASH;
+        }
+      }
+    }
+
+    return SI_HC_NEED_MORE_POLLS;
+  }
+
+  if( (pHookChangeData->lookingForTimeout == 1)
+      && (delta_time >=  pHookChangeCfg->minInterDigit) )
+  {
+
+    if(delta_time  > pHookChangeCfg->minHook)
+    {
+      if(pHookChangeData->last_hook_state == PROSLIC_ONHOOK)
+      {
+        ProSLIC_ResetDialPulseDetect(pHookChangeData);
+        pHookChangeData->last_state_reported = SI_HC_ONHOOK_TIMEOUT;
+        return SI_HC_ONHOOK_TIMEOUT;
+      }
+
+      if(pHookChangeData->last_hook_state == PROSLIC_OFFHOOK)
+      {
+        ProSLIC_ResetDialPulseDetect(pHookChangeData);
+
+        /* Check if we saw either a pulse digit or hook flash prior to this,
+         * if so, we're already offhook, so do not report a offhook event,
+         * just stop polling.
+         */
+        if((pHookChangeData->last_state_reported == SI_HC_ONHOOK_TIMEOUT)
+            || (pHookChangeData->last_state_reported == SI_HC_NO_ACTIVITY) )
+        {
+          pHookChangeData->last_state_reported = SI_HC_OFFHOOK_TIMEOUT;
+          return SI_HC_OFFHOOK_TIMEOUT;
+        }
+        else
+        {
+          return SI_HC_NO_ACTIVITY;
+        }
+      }
+    }
+    else
+    {
+      uInt8 last_digit = pHookChangeData->currentPulseDigit;
+
+      if(last_digit)
+      {
+        pHookChangeData->last_state_reported = last_digit;
+        ProSLIC_ResetDialPulseDetect(pHookChangeData);
+        return last_digit;
+      }
+    }
+    return SI_HC_NEED_MORE_POLLS;
+  }
+
+  return SI_HC_NEED_MORE_POLLS;
+}
+#endif /* DISABLE_HOOKCHANGE */
+
+/*****************************************************************************************************/
+int ProSLIC_DTMFReadDigit (proslicChanType_ptr pProslic,uInt8 *pDigit)
+{
+  TRACEPRINT(pProslic, "\n", NULL);
+
+  if(pProslic->channelType != PROSLIC)
+  {
+    return RC_IGNORE;
+  }
+
+  DEBUG_PRINT(pProslic, "%sDTMFReadDigit on channel %d\n",LOGPRINT_PREFIX,
+              pProslic->channel);
+  *pDigit = ReadReg(pProslic,pProslic->channel,PROSLIC_REG_TONDTMF) & 0xf;
+
+  return RC_NONE;
+}
+
+/*****************************************************************************************************/
+int ProSLIC_PLLFreeRunStart (proslicChanType_ptr hProslic)
+{
+  uInt8 tmp;
+  TRACEPRINT(hProslic, "\n", NULL);
+
+  if(hProslic->channelType != PROSLIC)
+  {
+    return RC_IGNORE;
+  }
+
+  WriteReg(hProslic,hProslic->channel,PROSLIC_REG_ZCAL_EN,0x00);
+  tmp = ReadReg(hProslic,hProslic->channel,PROSLIC_REG_ENHANCE);
+
+  return(WriteReg(hProslic,hProslic->channel,PROSLIC_REG_ENHANCE,tmp|0x4));
+}
+
+/*****************************************************************************************************/
+int ProSLIC_PLLFreeRunStop (proslicChanType_ptr hProslic)
+{
+  uInt8 tmp;
+  TRACEPRINT(hProslic, "\n", NULL);
+
+  if(hProslic->channelType != PROSLIC)
+  {
+    return RC_IGNORE;
+  }
+
+  tmp = ReadReg(hProslic,hProslic->channel,PROSLIC_REG_ENHANCE);
+  WriteReg(hProslic,hProslic->channel,PROSLIC_REG_ENHANCE,tmp&~(0x4));
+
+  return WriteReg(hProslic,hProslic->channel,PROSLIC_REG_ZCAL_EN,0x04);
+}
+
+/*****************************************************************************************************/
+int ProSLIC_GetPLLFreeRunStatus (proslicChanType_ptr hProslic)
+{
+  uInt8 tmp;
+  TRACEPRINT(hProslic, "\n", NULL);
+
+  if(hProslic->channelType != PROSLIC)
+  {
+    return RC_IGNORE;
+  }
+
+  tmp = ReadReg(hProslic,hProslic->channel,PROSLIC_REG_ENHANCE);
+
+  if(tmp & 0x02)
+  {
+    return RC_PLL_FREERUN_ACTIVE;
+  }
+
+  return RC_NONE;
+}
+
+/*****************************************************************************************************/
+#ifndef DISABLE_PULSEMETERING
+int ProSLIC_PulseMeterEnable (proslicChanType_ptr hProslic)
+{
+  uInt8 widebandEn;
+  TRACEPRINT(hProslic, "\n", NULL);
+
+  if(hProslic->channelType != PROSLIC)
+  {
+    return RC_IGNORE;
+  }
+
+  widebandEn = ReadReg(hProslic,hProslic->channel,PROSLIC_REG_ENHANCE) & 0x01;
+
+  if (widebandEn)
+  {
+    DEBUG_PRINT (hProslic,
+                 "%s Pulse Metering is not supported while Wideband Mode is enabled.\n",
+                 LOGPRINT_PREFIX);
+  }
+
+#if defined (SI3217X) || defined (SI3218X) || defined (SI3226X) || defined (SI3228X) || defined(SI3219X)
+  if(!widebandEn && (0 
+#ifdef SI3217X
+      || (hProslic->deviceId->chipType >= SI32171
+          && hProslic->deviceId->chipType <= SI32179)
+#endif
+#ifdef SI3218X
+      ||(hProslic->deviceId->chipType >= SI32180
+         && hProslic->deviceId->chipType <= SI32189) 
+#endif
+#ifdef SI3219X
+      || (IS_SI3219X(hProslic->deviceId) )
+#endif
+#ifdef SI3226X
+      || (hProslic->deviceId->chipType >= SI32260
+          && hProslic->deviceId->chipType <= SI32269)
+#endif
+#ifdef SI3228X
+      || (hProslic->deviceId->chipType >= SI32280
+          && hProslic->deviceId->chipType <= SI32289 )
+#endif
+    ))
+  {
+    return WriteReg(hProslic,hProslic->channel,PROSLIC_REG_PMCON,ReadReg(hProslic,
+                    hProslic->channel,PROSLIC_REG_PMCON) | (0x01));
+  }
+#endif
+  return RC_COMPLETE_NO_ERR;
+}
+
+/*****************************************************************************************************/
+int ProSLIC_PulseMeterDisable (proslicChanType_ptr hProslic)
+{
+  TRACEPRINT(hProslic, "\n", NULL);
+
+  if(hProslic->channelType != PROSLIC)
+  {
+    return RC_IGNORE;
+  }
+
+  return(WriteReg(hProslic,hProslic->channel,PROSLIC_REG_PMCON,ReadReg(hProslic,
+                  hProslic->channel,PROSLIC_REG_PMCON) & ~(0x05)));
+}
+
+/*****************************************************************************************************/
+int ProSLIC_PulseMeterStart (proslicChanType_ptr hProslic)
+{
+  TRACEPRINT(hProslic, "\n", NULL);
+
+  if(hProslic->channelType != PROSLIC)
+  {
+    return RC_IGNORE;
+  }
+
+  return WriteReg(hProslic,hProslic->channel,PROSLIC_REG_PMCON,ReadReg(hProslic,
+                  hProslic->channel,PROSLIC_REG_PMCON) | (0x5));
+}
+
+/*****************************************************************************************************/
+int ProSLIC_PulseMeterStop (proslicChanType_ptr hProslic)
+{
+  TRACEPRINT(hProslic, "\n", NULL);
+
+  if(hProslic->channelType != PROSLIC)
+  {
+    return RC_IGNORE;
+  }
+
+#ifdef SI3217X
+  if (hProslic->deviceId->chipType >= SI32171
+      && hProslic->deviceId->chipType <= SI32179)
+  {
+    return(WriteReg(hProslic,hProslic->channel,PROSLIC_REG_PMCON,ReadReg(hProslic,
+                    hProslic->channel,PROSLIC_REG_PMCON) & ~(0x04)));
+  }
+#endif
+
+#ifdef SI3218X
+  if (hProslic->deviceId->chipType >= SI32180
+      && hProslic->deviceId->chipType <= SI32189)
+  {
+    return(WriteReg(hProslic,hProslic->channel,PROSLIC_REG_PMCON,ReadReg(hProslic,
+                    hProslic->channel,PROSLIC_REG_PMCON) & ~(0x04)));
+  }
+#endif
+
+#ifdef SI3219X
+  if ( IS_SI3219X(hProslic->deviceId) )
+  {
+    return(WriteReg(hProslic,hProslic->channel,PROSLIC_REG_PMCON,ReadReg(hProslic,
+                    hProslic->channel,PROSLIC_REG_PMCON) & ~(0x04)));
+  }
+#endif
+
+#ifdef SI3226X
+  if (hProslic->deviceId->chipType >= SI32260
+      && hProslic->deviceId->chipType <= SI32269)
+  {
+    return ProSLIC_PulseMeterDisable(hProslic);
+  }
+#endif
+
+#ifdef SI3228X
+  if (hProslic->deviceId->chipType >= SI32280
+      && hProslic->deviceId->chipType <= SI32289)
+  {
+    return ProSLIC_PulseMeterDisable(hProslic);
+  }
+#endif
+
+  return RC_COMPLETE_NO_ERR;
+}
+#endif /* DISABLE_PULSEMETERING */
+/*****************************************************************************************************/
+int ProSLIC_SetDCDCInversionFlag (proslicChanType_ptr hProslic, uInt8 flag)
+{
+  TRACEPRINT(hProslic, "flag = %u\n", flag);
+
+  if(hProslic->channelType != PROSLIC)
+  {
+    return RC_IGNORE;
+  }
+
+  hProslic->dcdc_polarity_invert = flag;
+
+  return RC_COMPLETE_NO_ERR;
+}
+
+
+int ProSLIC_PowerUpConverter (proslicChanType_ptr hProslic)
+{
+  if(hProslic->channelType != PROSLIC)
+  {
+    return RC_IGNORE;
+  }
+
+#ifdef SI3217X
+  if (hProslic->deviceId->chipType >= SI32171
+      && hProslic->deviceId->chipType <= SI32179)
+  {
+    return Si3217x_PowerUpConverter(hProslic);
+  }
+#endif
+
+#ifdef SI3218X
+  if (hProslic->deviceId->chipType >= SI32180
+      && hProslic->deviceId->chipType <= SI32189)
+  {
+    return Si3218x_PowerUpConverter(hProslic);
+  }
+#endif
+
+#ifdef SI3219X
+  if ( IS_SI3219X(hProslic->deviceId) )
+  {
+    return Si3219x_PowerUpConverter(hProslic);
+  }
+#endif
+
+#ifdef SI3226X
+  if (hProslic->deviceId->chipType >= SI32260
+      && hProslic->deviceId->chipType <= SI32269)
+  {
+    return Si3226x_PowerUpConverter(hProslic);
+  }
+#endif
+
+#ifdef SI3228X
+  if (hProslic->deviceId->chipType >= SI32280
+      && hProslic->deviceId->chipType <= SI32289)
+  {
+    return Si3228x_PowerUpConverter(hProslic);
+  }
+#endif
+
+  return RC_COMPLETE_NO_ERR;
+}
+/*****************************************************************************************************/
+static int ProSLIC_GetBatType(proslicChanType_ptr hProslic)
+{
+#ifdef SI3226X
+  if (hProslic->deviceId->chipType >= SI32260
+      && hProslic->deviceId->chipType <= SI32269)
+  {
+    return Si3226x_General_Configuration.batType;
+  }
+#endif
+
+#ifdef SI3228X
+  if (hProslic->deviceId->chipType >= SI32280
+      && hProslic->deviceId->chipType <= SI32289)
+  {
+    return Si3228x_General_Configuration.batType;
+  }
+#endif
+
+#if !defined(SI3226X) && !defined(SI3228X)
+  SILABS_UNREFERENCED_PARAMETER(hProslic);
+#endif
+  return BO_DCDC_UNKNOWN;
+}
+
+/*****************************************************************************************************/
+int ProSLIC_PowerDownConverter (proslicChanType_ptr pProslic)
+{
+  errorCodeType error = RC_NONE;
+  int32 vbat;
+  int timer = 0;
+
+  TRACEPRINT(pProslic, "\n", NULL);
+
+  if(pProslic->channelType != PROSLIC)
+  {
+    return RC_IGNORE;
+  }
+
+  /* Force channel out of powersavings mode and then put it in open state */
+  WriteReg(pProslic,pProslic->channel,PROSLIC_REG_LINEFEED,LF_FWD_OHT);
+  Delay(pProTimer,10);
+  WriteReg(pProslic,pProslic->channel,PROSLIC_REG_LINEFEED, LF_OPEN);
+  Delay(pProTimer,50);
+
+  /* Don't try to shutdown converter if we're using external supplies or if the
+     converter is already shutdown.
+  */
+  if((ProSLIC_GetBatType(pProslic) == BO_DCDC_EXTERNAL) ||
+      (ReadRAM(pProslic,pProslic->channel,PROSLIC_RAM_PD_DCDC) & 0x100000) )
+  {
+    return RC_NONE;
+  }
+
+  WriteRAM(pProslic,pProslic->channel,PROSLIC_RAM_PD_DCDC,0x900000L);
+  Delay(pProTimer,50);
+
+  do
+  {
+    vbat = ReadRAM(pProslic, pProslic->channel, PROSLIC_RAM_MADC_VBAT);
+    if(vbat & 0x10000000L)
+    {
+      vbat |= 0xF0000000L;
+    }
+    Delay(pProTimer,10);
+  }
+  while((vbat > COMP_5V) && (timer++ < PROSLIC_TIMEOUT_DCDC_DOWN));
+
+  DEBUG_PRINT(pProslic, "%s VBAT Down = %d.%d v\n", LOGPRINT_PREFIX,
+              (int)((vbat/SCALE_V_MADC)/1000),
+              SIVOICE_ABS(((vbat/SCALE_V_MADC) - (vbat/SCALE_V_MADC)/1000*1000)));
+
+  if(timer > PROSLIC_TIMEOUT_DCDC_DOWN)
+  {
+    /* Error handling - shutdown converter, disable channel, set error tag */
+    pProslic->channelEnable = 0;
+    pProslic->error = error = RC_VBAT_DOWN_TIMEOUT;
+    DEBUG_PRINT(pProslic, "%sDCDC Power Down timeout channel %d\n", LOGPRINT_PREFIX,
+                pProslic->channel);
+  }
+  return error;
+}
+
+/*****************************************************************************************************/
+int ProSLIC_LBCal (proslicChanType_ptr *pProslic, int size)
+{
+  int k;
+  int timeout;
+  uInt8 data;
+  uInt8 lfState, enhance_value;
+  TRACEPRINT(*pProslic, "size = %d\n", size);
+
+  if((*pProslic)->channelType != PROSLIC)
+  {
+    return RC_IGNORE;
+  }
+
+  /* For all channels, save settings, initiate LBCAL */
+  for(k = 0; k < size; k++)
+  {
+    if( (pProslic[k]->channelEnable) && (pProslic[k]->channelType == PROSLIC) )
+    {
+      DEBUG_PRINT(pProslic[k], "%sStarting LB Cal on channel %d\n", LOGPRINT_PREFIX,
+                  pProslic[k]->channel);
+      /* Preserve old settings */
+      lfState = ReadReg(pProslic[k], pProslic[k]->channel, PROSLIC_REG_LINEFEED);
+      enhance_value = ReadReg(pProslic[k], pProslic[k]->channel, PROSLIC_REG_ENHANCE);
+      ProSLIC_SetPowersaveMode(pProslic[k], PWRSAVE_DISABLE);
+      ProSLIC_SetLinefeedStatus(pProslic[k], LF_FWD_ACTIVE);
+      WriteReg(pProslic[k], pProslic[k]->channel, PROSLIC_REG_CALR0, CAL_LB_ALL);
+      WriteReg(pProslic[k], pProslic[k]->channel, PROSLIC_REG_CALR3,  0x80);
+      pProslic[k]->error = RC_CAL_TIMEOUT; /* Assume failure */
+
+      timeout = 0;
+      do
+      {
+        data = ReadReg(pProslic[k], pProslic[k]->channel, PROSLIC_REG_CALR3);
+        DelayX(*pProslic, 10);
+        timeout++;
+      }
+      while((data & 0x80) && (timeout < TIMEOUT_LB_CAL));
+
+      if( (data & 0x80) )
+      {
+        DEBUG_PRINT(pProslic[k], "%sLB Cal timeout on channel %d\n", LOGPRINT_PREFIX,
+                    pProslic[k]->channel);
+        WriteReg(pProslic[k], pProslic[k]->channel, PROSLIC_REG_LINEFEED, LF_OPEN);
+        return RC_CAL_TIMEOUT;
+      }
+      else
+      {
+        WriteReg(pProslic[k], pProslic[k]->channel, PROSLIC_REG_LINEFEED, lfState);
+        WriteReg(pProslic[k], pProslic[k]->channel, PROSLIC_REG_ENHANCE, enhance_value);
+        pProslic[k]->error = RC_NONE;
+      }
+    }
+  }
+  return RC_NONE;
+}
+
+/*****************************************************************************************************/
+#define PROSLIC_RAM_CMDAC_FWD 1476
+#define PROSLIC_RAM_CMDAC_REV 1477
+#define PROSLIC_RAM_CAL_TRNRD_DACT 1458
+#define PROSLIC_RAM_CAL_TRNRD_DACR 1459
+
+int ProSLIC_GetLBCalResult (proslicChanType *pProslic,int32 *result1,
+                            int32 *result2, int32 *result3, int32 *result4)
+{
+  TRACEPRINT(pProslic, "\n", NULL);
+
+  if(pProslic->channelType != PROSLIC)
+  {
+    return RC_IGNORE;
+  }
+
+  *result1 = ReadRAM(pProslic, pProslic->channel, PROSLIC_RAM_CMDAC_FWD);
+  *result2 = ReadRAM(pProslic, pProslic->channel, PROSLIC_RAM_CMDAC_REV);
+  *result3 = ReadRAM(pProslic, pProslic->channel, PROSLIC_RAM_CAL_TRNRD_DACT);
+  *result4 = ReadRAM(pProslic, pProslic->channel, PROSLIC_RAM_CAL_TRNRD_DACR);
+
+  return RC_NONE;
+}
+
+/*****************************************************************************************************/
+int ProSLIC_GetLBCalResultPacked (proslicChanType *pProslic,int32 *result)
+{
+  int32 results[4];
+  int rc;
+  TRACEPRINT(pProslic, "\n", NULL);
+
+  if(pProslic->channelType != PROSLIC)
+  {
+    return RC_IGNORE;
+  }
+
+  rc = ProSLIC_GetLBCalResult(pProslic, &(results[0]), &(results[1]),
+                             &(results[2]), &(results[3]));
+  if(rc == RC_NONE)
+  {
+    /*
+      Bits 31:24   CMDAC_FWD[25:18]
+      Bits 23:16   CMDAC_REV[25:18]
+      Bits 15:8    CAL_TRNRD_DACT[20:13]
+      Bits 7:0     CAL_TRNRD_DACR[20:13]
+    */
+    *result = (results[0]<<6) & 0xff000000L;
+    *result |=(results[1]>>1) & 0x00ff0000L;
+    *result |=(results[2]>>5) & 0x0000ff00L;
+    *result |=(results[3]>>13)& 0x000000ffL;
+  }
+
+  return rc;
+}
+
+/*****************************************************************************************************/
+int ProSLIC_LoadPreviousLBCal (proslicChanType *pProslic,int32 result1,
+                               int32 result2,int32 result3,int32 result4)
+{
+  TRACEPRINT(pProslic, "\n", NULL);
+  if(pProslic->channelType != PROSLIC)
+  {
+    return RC_IGNORE;
+  }
+
+  WriteRAM(pProslic,pProslic->channel,PROSLIC_RAM_CMDAC_FWD,result1);
+  WriteRAM(pProslic,pProslic->channel,PROSLIC_RAM_CMDAC_REV,result2);
+  WriteRAM(pProslic,pProslic->channel,PROSLIC_RAM_CAL_TRNRD_DACT,result3);
+  WriteRAM(pProslic,pProslic->channel,PROSLIC_RAM_CAL_TRNRD_DACR,result4);
+
+#ifdef API_TEST
+  ramVal = ReadRAM(pProslic,pProslic->channel,PROSLIC_RAM_CMDAC_FWD);
+  LOGPRINT ("%s UNPACKED CMDAC_FWD = %08x\n", LOGPRINT_PREFIX, ramVal);
+  ramVal = ReadRAM(pProslic, pProslic->channel,PROSLIC_RAM_CMDAC_REV);
+  LOGPRINT ("%s UNPACKED CMDAC_REF = %08x\n", LOGPRINT_PREFIX, ramVal);
+  ramVal = ReadRAM(pProslic,pProslic->channel,PROSLIC_RAM_CAL_TRNRD_DACT);
+  LOGPRINT ("%s UNPACKED CAL_TRNRD_DACT = %08x\n", LOGPRINT_PREFIX, ramVal);
+  ramVal = ReadRAM(pProslic,pProslic->channel,PROSLIC_RAM_CAL_TRNRD_DACR);
+  LOGPRINT ("%s UNPACKED CAL_TRNRD_DACR = %08x\n", LOGPRINT_PREFIX, ramVal);
+#endif
+
+  return RC_NONE;
+}
+
+/*****************************************************************************************************/
+int ProSLIC_LoadPreviousLBCalPacked (proslicChanType *pProslic,int32 *result)
+{
+  ramData ramVal[4];
+  TRACEPRINT(pProslic, "\n", NULL);
+
+  if(pProslic->channelType != PROSLIC)
+  {
+    return RC_IGNORE;
+  }
+  ramVal[0] = (*result&0xff000000L)>>6;
+  ramVal[1] = (*result&0x00ff0000L)<<1;
+  ramVal[2] = (*result&0x0000ff00L)<<5;
+  ramVal[3] = (*result&0x000000ffL)<<13;
+
+  return ProSLIC_LoadPreviousLBCal(pProslic, ramVal[0], ramVal[1], ramVal[2],
+                                   ramVal[3]);
+}
+
+/*****************************************************************************************************/
+int ProSLIC_dbgSetDCFeedVopen (proslicChanType *pProslic, uInt32 v_vlim_val,
+                               int32 preset)
+{
+  TRACEPRINT(pProslic, "v_vlim_val = %u preset = %d\n", v_vlim_val, preset);
+  if(pProslic->channelType != PROSLIC)
+  {
+    return RC_IGNORE;
+  }
+#ifdef SI3217X
+  if (pProslic->deviceId->chipType >= SI32171
+      && pProslic->deviceId->chipType <= SI32179)
+  {
+    return Si3217x_dbgSetDCFeedVopen (pProslic,v_vlim_val,preset);
+  }
+#endif
+
+#ifdef SI3218X
+  if (pProslic->deviceId->chipType >= SI32180
+      && pProslic->deviceId->chipType <= SI32189)
+  {
+    return Si3218x_dbgSetDCFeedVopen (pProslic,v_vlim_val,preset);
+  }
+#endif
+
+#ifdef SI3219X
+  if ( IS_SI3219X(pProslic->deviceId) )
+  {
+    return Si3219x_dbgSetDCFeedVopen (pProslic,v_vlim_val,preset);
+  }
+#endif
+
+#ifdef SI3226X
+  if (pProslic->deviceId->chipType >= SI32260
+      && pProslic->deviceId->chipType <= SI32269)
+  {
+    return Si3226x_dbgSetDCFeedVopen (pProslic,v_vlim_val,preset);
+  }
+#endif
+
+#ifdef SI3228X
+  if (pProslic->deviceId->chipType >= SI32280
+      && pProslic->deviceId->chipType <= SI32289)
+  {
+    return Si3228x_dbgSetDCFeedVopen (pProslic,v_vlim_val,preset);
+  }
+#endif
+
+  return RC_COMPLETE_NO_ERR;
+}
+
+/*****************************************************************************************************/
+int ProSLIC_dbgSetDCFeedIloop (proslicChanType *pProslic, uInt32 i_ilim_val,
+                               int32 preset)
+{
+  TRACEPRINT(pProslic, "i_ilim_val = %u preset = %d\n", i_ilim_val, preset);
+
+  if(pProslic->channelType != PROSLIC)
+  {
+    return RC_IGNORE;
+  }
+#ifdef SI3217X
+  if (pProslic->deviceId->chipType >= SI32171
+      && pProslic->deviceId->chipType <= SI32179)
+  {
+    return Si3217x_dbgSetDCFeedIloop (pProslic,i_ilim_val,preset);
+  }
+#endif
+
+#ifdef SI3218X
+  if (pProslic->deviceId->chipType >= SI32180
+      && pProslic->deviceId->chipType <= SI32189)
+  {
+    return Si3218x_dbgSetDCFeedIloop (pProslic,i_ilim_val,preset);
+  }
+#endif
+
+#ifdef SI3219X
+  if ( IS_SI3219X(pProslic->deviceId) )
+  {
+    return Si3219x_dbgSetDCFeedIloop (pProslic,i_ilim_val,preset);
+  }
+#endif
+
+#ifdef SI3226X
+  if (pProslic->deviceId->chipType >= SI32260
+      && pProslic->deviceId->chipType <= SI32269)
+  {
+    return Si3226x_dbgSetDCFeedIloop (pProslic,i_ilim_val,preset);
+  }
+#endif
+
+#ifdef SI3228X
+  if (pProslic->deviceId->chipType >= SI32280
+      && pProslic->deviceId->chipType <= SI32289)
+  {
+    return Si3228x_dbgSetDCFeedIloop (pProslic,i_ilim_val,preset);
+  }
+#endif
+
+  return RC_COMPLETE_NO_ERR;
+}
+
+/*****************************************************************************************************/
+int ProSLIC_dbgSetRinging (proslicChanType *pProslic,
+                           ProSLIC_dbgRingCfg *ringCfg, int preset)
+{
+  TRACEPRINT(pProslic, "preset = %d\n", preset);
+
+  if(pProslic->channelType != PROSLIC)
+  {
+    return RC_IGNORE;
+  }
+
+#ifdef SI3217X
+  if (pProslic->deviceId->chipType >= SI32171
+      && pProslic->deviceId->chipType <= SI32179)
+  {
+    return Si3217x_dbgSetRinging (pProslic,ringCfg,preset);
+  }
+#endif
+
+#ifdef SI3218X
+  if (pProslic->deviceId->chipType >= SI32180
+      && pProslic->deviceId->chipType <= SI32189)
+  {
+    return Si3218x_dbgSetRinging (pProslic,ringCfg,preset);
+  }
+#endif
+
+#ifdef SI3219X
+  if ( IS_SI3219X(pProslic->deviceId) )
+  {
+    return Si3219x_dbgSetRinging (pProslic,ringCfg,preset);
+  }
+#endif
+
+#ifdef SI3226X
+  if (pProslic->deviceId->chipType >= SI32260
+      && pProslic->deviceId->chipType <= SI32269)
+  {
+    return Si3226x_dbgSetRinging (pProslic,ringCfg,preset);
+  }
+#endif
+
+#ifdef SI3228X
+  if (pProslic->deviceId->chipType >= SI32280
+      && pProslic->deviceId->chipType <= SI32289)
+  {
+    return Si3228x_dbgSetRinging (pProslic,ringCfg,preset);
+  }
+#endif
+
+  return RC_COMPLETE_NO_ERR;
+}
+
+/*****************************************************************************************************/
+int ProSLIC_dbgSetRXGain (proslicChanType *pProslic, int32 gain,
+                          int impedance_preset, int audio_gain_preset)
+{
+  TRACEPRINT(pProslic, "gain = %d imp_preset = %d audio_gain_preset = %d\n", gain,
+             impedance_preset, audio_gain_preset);
+  if(pProslic->channelType != PROSLIC)
+  {
+    return RC_IGNORE;
+  }
+
+#ifdef SI3217X
+  if (pProslic->deviceId->chipType >= SI32171
+      && pProslic->deviceId->chipType <= SI32179)
+  {
+    return Si3217x_dbgSetRXGain (pProslic,gain,impedance_preset,audio_gain_preset);
+  }
+#endif
+
+#ifdef SI3218X
+  if (pProslic->deviceId->chipType >= SI32180
+      && pProslic->deviceId->chipType <= SI32189)
+  {
+    return Si3218x_dbgSetRXGain (pProslic,gain,impedance_preset,audio_gain_preset);
+  }
+#endif
+
+#ifdef SI3219X
+  if ( IS_SI3219X(pProslic->deviceId) )
+  {
+    return Si3219x_dbgSetRXGain (pProslic,gain,impedance_preset,audio_gain_preset);
+  }
+#endif
+
+#ifdef SI3226X
+  if (pProslic->deviceId->chipType >= SI32260
+      && pProslic->deviceId->chipType <= SI32269)
+  {
+    return Si3226x_dbgSetRXGain (pProslic,gain,impedance_preset,audio_gain_preset);
+  }
+#endif
+
+#ifdef SI3228X
+  if (pProslic->deviceId->chipType >= SI32280
+      && pProslic->deviceId->chipType <= SI32289)
+  {
+    return Si3228x_dbgSetRXGain (pProslic,gain,impedance_preset,audio_gain_preset);
+  }
+#endif
+
+  return RC_COMPLETE_NO_ERR;
+}
+
+/*****************************************************************************************************/
+int ProSLIC_dbgSetTXGain (proslicChanType *pProslic, int32 gain,
+                          int impedance_preset, int audio_gain_preset)
+{
+  TRACEPRINT(pProslic, "gain = %d imp_preset = %d audio_gain_preset = %d\n", gain,
+             impedance_preset, audio_gain_preset);
+
+  if(pProslic->channelType != PROSLIC)
+  {
+    return RC_IGNORE;
+  }
+
+#ifdef SI3217X
+  if (pProslic->deviceId->chipType >= SI32171
+      && pProslic->deviceId->chipType <= SI32179)
+  {
+    return Si3217x_dbgSetTXGain (pProslic,gain,impedance_preset,audio_gain_preset);
+  }
+#endif
+
+#ifdef SI3218X
+  if (pProslic->deviceId->chipType >= SI32180
+      && pProslic->deviceId->chipType <= SI32189)
+  {
+    return Si3218x_dbgSetTXGain (pProslic,gain,impedance_preset,audio_gain_preset);
+  }
+#endif
+
+#ifdef SI3219X
+  if ( IS_SI3219X(pProslic->deviceId) )
+  {
+    return Si3219x_dbgSetTXGain (pProslic,gain,impedance_preset,audio_gain_preset);
+  }
+#endif
+
+#ifdef SI3226X
+  if (pProslic->deviceId->chipType >= SI32260
+      && pProslic->deviceId->chipType <= SI32269)
+  {
+    return Si3226x_dbgSetTXGain (pProslic,gain,impedance_preset,audio_gain_preset);
+  }
+#endif
+
+#ifdef SI3228X
+  if (pProslic->deviceId->chipType >= SI32280
+      && pProslic->deviceId->chipType <= SI32289)
+  {
+    return Si3228x_dbgSetTXGain (pProslic,gain,impedance_preset,audio_gain_preset);
+  }
+#endif
+
+  return RC_COMPLETE_NO_ERR;
+}
+
+/*****************************************************************************************************/
+/*
+** Function: ProSLIC_LineMonitor
+**
+** Description:
+** Generic monitoring function
+**
+** Returns:
+** 0
+*/
+
+int ProSLIC_LineMonitor (proslicChanType *pProslic, proslicMonitorType *monitor)
+{
+  TRACEPRINT(pProslic, "\n", NULL);
+
+  if(pProslic->channelType != PROSLIC)
+  {
+    return RC_IGNORE;
+  }
+
+#ifdef SI3217X
+  if (pProslic->deviceId->chipType >= SI32171
+      && pProslic->deviceId->chipType <= SI32179)
+  {
+    return Si3217x_LineMonitor (pProslic, monitor);
+  }
+#endif
+
+#ifdef SI3218X
+  if (pProslic->deviceId->chipType >= SI32180
+      && pProslic->deviceId->chipType <= SI32189)
+  {
+    return Si3218x_LineMonitor (pProslic, monitor);
+  }
+#endif
+
+#ifdef SI3219X
+  if ( IS_SI3219X(pProslic->deviceId) )
+  {
+    return Si3219x_LineMonitor (pProslic, monitor);
+  }
+#endif
+
+#ifdef SI3226X
+  if (pProslic->deviceId->chipType >= SI32260
+      && pProslic->deviceId->chipType <= SI32269)
+  {
+    return Si3226x_LineMonitor (pProslic, monitor);
+  }
+#endif
+
+#ifdef SI3228X
+  if (pProslic->deviceId->chipType >= SI32280
+      && pProslic->deviceId->chipType <= SI32289)
+  {
+    return Si3228x_LineMonitor (pProslic, monitor);
+  }
+#endif
+
+  return RC_COMPLETE_NO_ERR;
+}
+
+/*****************************************************************************************************/
+/*
+** Function: ProSLIC_PSTNCheck
+**
+** Description:
+** Monitor for excessive longitudinal current, which
+** would be present if a live pstn line was connected
+** to the port.
+**
+** Returns:
+** 0 - no pstn detected
+** 1 - pstn detected
+*/
+int ProSLIC_PSTNCheck (proslicChanType *pProslic,
+                       proslicPSTNCheckObjType *pPSTNCheck)
+{
+  TRACEPRINT(pProslic, "\n", NULL);
+  if(pProslic->channelType != PROSLIC)
+  {
+    return RC_IGNORE;
+  }
+
+#ifdef SI3217X
+  if (pProslic->deviceId->chipType >= SI32171
+      && pProslic->deviceId->chipType <= SI32179)
+  {
+    return Si3217x_PSTNCheck (pProslic,pPSTNCheck);
+  }
+#endif
+
+#ifdef SI3218X
+  if (pProslic->deviceId->chipType >= SI32180
+      && pProslic->deviceId->chipType <= SI32189)
+  {
+    return Si3218x_PSTNCheck (pProslic,pPSTNCheck);
+  }
+#endif
+
+#ifdef SI3219X
+  if ( IS_SI3219X(pProslic->deviceId) )
+  {
+    return Si3219x_PSTNCheck (pProslic,pPSTNCheck);
+  }
+#endif
+
+#ifdef SI3226X
+  if (pProslic->deviceId->chipType >= SI32260
+      && pProslic->deviceId->chipType <= SI32269)
+  {
+    return Si3226x_PSTNCheck (pProslic,pPSTNCheck);
+  }
+#endif
+
+#ifdef SI3228X
+  if (pProslic->deviceId->chipType >= SI32280
+      && pProslic->deviceId->chipType <= SI32289)
+  {
+    return Si3228x_PSTNCheck (pProslic,pPSTNCheck);
+  }
+#endif
+
+  return RC_COMPLETE_NO_ERR;
+}
+
+/*****************************************************************************************************/
+/*
+** Function: ProSLIC_DiffPSTNCheck
+**
+** Description:
+** Monitor for excessive longitudinal current, which
+** would be present if a live pstn line was connected
+** to the port.
+**
+** Returns:
+** RC_NONE - test in progress
+** RC_IGNORE - non-ProSLIC channel
+** RC_COMPLETE_NO_ERR - ProSLIC does not support feature.
+** RC_PSTN_OPEN_FEMF | RC_COMPLETE_NO_ERR - test completed.
+**
+*/
+#ifdef PSTN_DET_ENABLE
+int ProSLIC_DiffPSTNCheck (proslicChanType *pProslic,
+                           proslicDiffPSTNCheckObjType *pPSTNCheck)
+{
+  TRACEPRINT(pProslic, "\n", NULL);
+
+  if(pProslic->channelType != PROSLIC)
+  {
+    return RC_IGNORE;
+  }
+
+#ifdef SI3217X
+  if (pProslic->deviceId->chipType >= SI32171
+      && pProslic->deviceId->chipType <= SI32179)
+  {
+    return Si3217x_DiffPSTNCheck (pProslic,pPSTNCheck);
+  }
+#endif
+
+#ifdef SI3218X
+  if (pProslic->deviceId->chipType >= SI32180
+      && pProslic->deviceId->chipType <= SI32189)
+  {
+    return Si3218x_DiffPSTNCheck (pProslic,pPSTNCheck);
+  }
+#endif
+
+#ifdef SI3219X
+  if ( IS_SI3219X(pProslic->deviceId) )
+  {
+    return Si3219x_DiffPSTNCheck (pProslic,pPSTNCheck);
+  }
+#endif
+
+#ifdef SI3226X
+  if (pProslic->deviceId->chipType >= SI32260
+      && pProslic->deviceId->chipType <= SI32269)
+  {
+    return Si3226x_DiffPSTNCheck (pProslic,pPSTNCheck);
+  }
+#endif
+
+#ifdef SI3228X
+  if (pProslic->deviceId->chipType >= SI32280
+      && pProslic->deviceId->chipType <= SI32289)
+  {
+    return Si3228x_DiffPSTNCheck (pProslic,pPSTNCheck);
+  }
+#endif
+
+  return RC_COMPLETE_NO_ERR;
+}
+#endif
+
+/*****************************************************************************************************/
+/*
+** Function: ProSLIC_CreatePSTNCheckObj
+**
+** Description:
+** Allocate memory for pstnCheckObj
+**
+** Returns:
+** RC_NONE
+** RC_NO_MEM if failed to allocate memory.
+** RC_UNSUPPORTED_FEATER if malloc disabled
+*/
+int ProSLIC_CreatePSTNCheckObjs(proslicPSTNCheckObjType_ptr *pstnCheckObj,
+                                unsigned int num_objs)
+{
+  TRACEPRINT_NOCHAN("num_objs = %u\n", num_objs);
+#ifndef DISABLE_MALLOC
+  *pstnCheckObj = SIVOICE_CALLOC(sizeof(proslicPSTNCheckObjType),num_objs);
+  if(*pstnCheckObj == NULL)
+  {
+#ifdef ENABLE_DEBUG
+    LOGPRINT("%s: %s: failed to allocate memory", LOGPRINT_PREFIX, __FUNCTION__);
+#endif
+    return RC_NO_MEM;
+  }
+  return RC_NONE;
+#else
+  SILABS_UNREFERENCED_PARAMETER(pstnCheckObj);
+  SILABS_UNREFERENCED_PARAMETER(num_objs);
+  return RC_UNSUPPORTED_FEATURE;
+#endif
+}
+
+/*****************************************************************************************************/
+/*
+** Function: ProSLIC_CreateDiffPSTNCheckObjs
+**
+** Description:
+** Allocate memory for proslicDiffPstnCheckObjs
+**
+** Returns:
+** RC_NONE
+** RC_NO_MEM if failed to allocate memory.
+** RC_UNSUPPORTED_FEATURE if malloc disabled
+*/
+
+#ifdef PSTN_DET_ENABLE
+int ProSLIC_CreateDiffPSTNCheckObjs(proslicDiffPSTNCheckObjType_ptr
+                                    *pstnCheckObj, unsigned int num_objs)
+{
+  TRACEPRINT_NOCHAN("num_objs = %u\n", num_objs);
+
+#ifndef DISABLE_MALLOC
+  *pstnCheckObj = SIVOICE_CALLOC(sizeof(proslicDiffPSTNCheckObjType),num_objs);
+  if(*pstnCheckObj == NULL)
+  {
+#ifdef ENABLE_DEBUG
+    LOGPRINT("%s: %s: failed to allocate memory", LOGPRINT_PREFIX, __FUNCTION__);
+#endif
+    return RC_NO_MEM;
+  }
+  return RC_NONE;
+#else
+  SILABS_UNREFERENCED_PARAMETER(pstnCheckObj);
+  SILABS_UNREFERENCED_PARAMETER(num_objs);
+  return RC_UNSUPPORTED_FEATURE;
+#endif
+}
+#endif
+
+/*****************************************************************************************************/
+/*
+** Function: ProSLIC_DestroyPSTNCheckObjs
+**
+** Description:
+** Free memory for pstnCheckObj
+**
+** Returns:
+** RC_NONE
+** RC_UNSUPPORTED_FEATER if malloc disabled
+*/
+int ProSLIC_DestroyPSTNCheckObjs(proslicPSTNCheckObjType_ptr *pstnCheckObj)
+{
+  TRACEPRINT_NOCHAN("\n", NULL);
+
+#ifndef DISABLE_MALLOC
+  if(pstnCheckObj)
+  {
+    SIVOICE_FREE((proslicPSTNCheckObjType_ptr)*pstnCheckObj);
+  }
+
+  return RC_NONE;
+
+#else
+  SILABS_UNREFERENCED_PARAMETER(pstnCheckObj);
+  return RC_UNSUPPORTED_FEATURE;
+#endif
+}
+
+/*****************************************************************************************************/
+/*
+** Function: ProSLIC_DestroyDiffPSTNCheckObjs
+**
+** Description:
+** Free memory for pstnDiffCheckObj
+**
+** Returns:
+** RC_NONE
+** RC_UNSUPPORTED_FEATER if malloc disabled
+*/
+#ifdef PSTN_DET_ENABLE
+int ProSLIC_DestroyDiffPSTNCheckObjs(proslicDiffPSTNCheckObjType_ptr
+                                     *pstnCheckObj)
+{
+  TRACEPRINT_NOCHAN("\n", NULL);
+
+#ifndef DISABLE_MALLOC
+  if(pstnCheckObj)
+  {
+    SIVOICE_FREE((proslicDiffPSTNCheckObjType_ptr)*pstnCheckObj);
+  }
+  return RC_NONE;
+#else
+  SILABS_UNREFERENCED_PARAMETER(pstnCheckObj);
+  return RC_UNSUPPORTED_FEATURE;
+#endif
+}
+#endif
+
+/*****************************************************************************************************/
+/*
+** Function: ProSLIC_InitPSTNCheckObj
+**
+** Description:
+** Initialize pstnCheckObj structure members
+**
+** Returns:
+** RC_NONE
+*/
+int ProSLIC_InitPSTNCheckObj(proslicPSTNCheckObjType_ptr pstnCheckObj,
+                             int32 avgThresh, int32 singleThresh, uInt8 samples)
+{
+  TRACEPRINT_NOCHAN("avgThres = %d singleThresh = %d samples = %u\n", avgThresh,
+                    avgThresh, samples);
+
+  pstnCheckObj->avgThresh = avgThresh;
+  pstnCheckObj->singleThresh = singleThresh;
+  pstnCheckObj->samples = samples;
+  pstnCheckObj->avgIlong = 0;
+  pstnCheckObj->count = 0;
+  pstnCheckObj->buffFull = 0;
+
+  return RC_NONE;
+}
+
+/*****************************************************************************************************/
+/*
+** Function: ProSLIC_InitDiffPSTNCheckObj
+**
+** Description:
+** Initialize pstnCheckObj structure members
+**
+** Returns:
+** RC_NONE
+*/
+#ifdef PSTN_DET_ENABLE
+int ProSLIC_InitDiffPSTNCheckObj(proslicDiffPSTNCheckObjType_ptr
+                                 pstnDiffCheckObj,
+                                 int preset1,
+                                 int preset2,
+                                 int entry_preset,
+                                 int femf_enable)
+{
+  TRACEPRINT_NOCHAN("p1 = %d p2 = %d ep = %d femf_enable = %d\n", preset1,
+                    preset2, entry_preset, femf_enable);
+
+  pstnDiffCheckObj->samples = PSTN_DET_DIFF_SAMPLES;
+  pstnDiffCheckObj->max_femf_vopen = PSTN_DET_MAX_FEMF;
+  pstnDiffCheckObj->entryDCFeedPreset = entry_preset;
+  pstnDiffCheckObj->dcfPreset1 = preset1;
+  pstnDiffCheckObj->dcfPreset2 = preset2;
+  pstnDiffCheckObj->femf_enable = femf_enable;
+  pstnDiffCheckObj->pState.stage = 0;
+  pstnDiffCheckObj->pState.sampleIterations = 0;
+  pstnDiffCheckObj->pState.waitIterations = 0;
+
+  return RC_NONE;
+}
+#endif
+
+/*****************************************************************************************************/
+/*
+** Function: ProSLIC_SetPwrsaveMode
+**
+** Description:
+** Enable or disable powersave mode
+**
+** Returns:
+** RC_NONE
+*/
+#define PROSLIC_REG_ENHANCE 47
+
+int ProSLIC_SetPowersaveMode (proslicChanType *pProslic, int pwrsave)
+{
+  uInt8 regData;
+  TRACEPRINT(pProslic, "pwrsave = %d\n", pwrsave);
+
+  if(pProslic->channelType != PROSLIC)
+  {
+    return RC_IGNORE;
+  }
+
+  regData = ReadReg(pProslic,pProslic->channel, PROSLIC_REG_ENHANCE);
+
+  if(pwrsave == PWRSAVE_DISABLE)
+  {
+#ifdef SI3217X
+    if (pProslic->deviceId->chipType >= SI32171
+        && pProslic->deviceId->chipType <= SI32179)
+    {
+      regData &= 0x27;
+    }
+    else
+    {
+#endif
+      regData &= 0x07;
+#ifdef SI3217X
+    }
+#endif
+  }
+  else
+  {
+    regData |= 0x10;
+  }
+
+  return WriteReg(pProslic,pProslic->channel, PROSLIC_REG_ENHANCE, regData);
+}
+
+/*****************************************************************************************************/
+/*
+** Function: ProSLIC_SetDAAEnable
+**
+** Description:
+** Enable or disable adjacent FXO (Si32178 only)
+**
+** Returns:
+** RC_NONE
+*/
+int ProSLIC_SetDAAEnable (proslicChanType *pProslic, int enable)
+{
+  TRACEPRINT(pProslic, "\n", NULL);
+
+  if(pProslic->channelType != PROSLIC)
+  {
+    return RC_IGNORE;
+  }
+
+#ifdef SI3217X
+  return Si3217x_SetDAAEnable (pProslic,enable);
+#else
+  SILABS_UNREFERENCED_PARAMETER(enable);
+  return RC_NONE;
+#endif
+}
+
+/*****************************************************************************************************/
+/*
+** Function: ProSLIC_SetUserMode
+**
+** Description: Enables User Access Mode (UAM) if the part supports it.
+**
+** Returns:
+** RC_NONE if successful.
+*/
+#define PROSLIC_REG_USERMODE_ENABLE 126
+
+int ProSLIC_SetUserMode(proslicChanType *pProslic,BOOLEAN isEnabled,
+                        BOOLEAN isBcast)
+{
+  uInt8 data;
+  uInt8 channel;
+
+  TRACEPRINT(pProslic, "enable = %d bcast = %d\n", (int)isEnabled, (int)isBcast);
+
+  if(isEnabled == FALSE)
+  {
+    return RC_NONE;
+  }
+
+  if( pProslic->channelType != PROSLIC )
+  {
+    return RC_UNSUPPORTED_FEATURE;
+  }
+
+  if(isBcast == TRUE)
+  {
+    channel = PROSLIC_CHAN_BROADCAST;
+  }
+  else
+  {
+    channel = pProslic->channel;
+  }
+
+  data = ReadReg(pProslic,pProslic->channel,
+                 PROSLIC_REG_USERMODE_ENABLE); /*we check first channel. we assume all channels same user mode state for broadcast */
+
+  if (((data&1) != 0) == isEnabled)
+  {
+    return RC_NONE;
+  }
+
+  WriteReg(pProslic,channel,PROSLIC_REG_USERMODE_ENABLE,2);
+  WriteReg(pProslic,channel,PROSLIC_REG_USERMODE_ENABLE,8);
+  WriteReg(pProslic,channel,PROSLIC_REG_USERMODE_ENABLE,0xe);
+  return WriteReg(pProslic,channel,PROSLIC_REG_USERMODE_ENABLE,0);
+}
+
+/*****************************************************************************************************/
+/*
+** Function: ProSLIC_isReinitRequired
+**
+** Description:
+** Checks for improper ring exit
+**
+** Returns:
+** RC_NONE                -  Reinit not required
+** RC_REINIT_REQUIRED     -  Corrupted state machine - reinit required
+**
+*/
+
+int ProSLIC_isReinitRequired(proslicChanType *pProslic)
+{
+  uInt8 lf;
+  ramData rkdc_sum;
+  TRACEPRINT(pProslic, "\n", NULL);
+
+  if( pProslic->channelType != PROSLIC)
+  {
+    return RC_IGNORE;
+  }
+
+  /* Check for improper ring exit which may cause dcfeed corruption */
+
+  lf = ReadReg(pProslic, pProslic->channel,PROSLIC_REG_LINEFEED);
+  rkdc_sum = ReadRAM(pProslic,pProslic->channel,PROSLIC_RAM_RDC_SUM);
+  DEBUG_PRINT(pProslic, "%sisReinitRequired: Linefeed = 0x%02X RDC_SUM = %d\n",
+              LOGPRINT_PREFIX, (int)lf, (int) rkdc_sum);
+  if((rkdc_sum & 0x400000)&&(lf != 0x44))
+  {
+    return RC_REINIT_REQUIRED;
+  }
+  else
+  {
+    return RC_NONE;
+  }
+}
+
+/*****************************************************************************************************/
+/*
+** Function: LoadRegTable
+**
+** Description:
+** Generic function to load register/RAM with predefined addr/value
+*/
+int ProSLIC_LoadRegTable (proslicChanType *pProslic, 
+                          const ProslicRAMInit *pRamTable,
+                          const ProslicRegInit *pRegTable, 
+                          int broadcast)
+{
+  uInt16 i;
+  uInt8 channel;
+
+  TRACEPRINT(pProslic, "bcast = %d\n", broadcast);
+  /* DAA doesn't have a RAM table.. skip it... */
+  if( (pRamTable != 0)
+      && (pProslic->channelType != PROSLIC) )
+  {
+    return RC_IGNORE;
+  }
+
+  if (broadcast)
+  {
+    channel = PROSLIC_CHAN_BROADCAST;
+  }
+  else
+  {
+    channel = pProslic->channel;
+  }
+
+  i=0;
+  if (pRamTable != 0)
+  {
+    while (pRamTable[i].address != 0xffff)
+    {
+      WriteRAM(pProslic,channel,pRamTable[i].address,pRamTable[i].initValue);
+      i++;
+    }
+  }
+  i=0;
+  if (pRegTable != 0)
+  {
+    while (pRegTable[i].address != 0xff)
+    {
+      WriteReg(pProslic,channel,pRegTable[i].address,pRegTable[i].initValue);
+      i++;
+    }
+  }
+
+  return RC_NONE;
+}
+
+/*****************************************************************************************************/
+/*
+** Function: LoadRegTables
+**
+** Description:
+** Generic function to load register/RAM with predefined addr/value
+*/
+
+int ProSLIC_LoadRegTables(proslicChanType_ptr *pProslic,
+                          const ProslicRAMInit *pRamTable, const ProslicRegInit *pRegTable, int size)
+{
+  int i;
+  TRACEPRINT(*pProslic, "size = %d\n", size);
+  for (i=0; i<size; i++)
+  {
+    if (pProslic[i]->channelEnable)
+    {
+      ProSLIC_LoadRegTable(pProslic[i],pRamTable,pRegTable,FALSE);
+    }
+  }
+  return RC_NONE;
+}
+
+/*****************************************************************************************************/
+int ProSLIC_UnsupportedFeatureNoArg(proslicChanType_ptr pProslic,
+                                    const char *function_name)
+{
+#ifdef ENABLE_DEBUG
+  LOGPRINT("%s: unsupported %s was called on channel %d\n", LOGPRINT_PREFIX,
+           function_name, pProslic->channel);
+#else
+  SILABS_UNREFERENCED_PARAMETER(pProslic);
+  SILABS_UNREFERENCED_PARAMETER(function_name);
+#endif
+  return RC_UNSUPPORTED_FEATURE;
+}
+
+/*****************************************************************************************************/
+/*
+** Function: ProSLIC_PSTN_delay_poll
+**
+** Description:
+** Delay function called within PSTN detection functions
+**
+** Return Value:
+** none
+*/
+#ifdef PSTN_DET_ENABLE
+void ProSLIC_PSTN_delay_poll(proslicTestStateType *pState, uInt16 delay)
+{
+  uInt16 delayCount;
+
+  if((delay/PSTN_DET_POLL_RATE) < 2)
+  {
+    delayCount = 0;
+  }
+  else
+  {
+    delayCount = (delay/PSTN_DET_POLL_RATE) - 2;
+  }
+
+  pState->waitIterations++;
+  if((pState->waitIterations == delayCount) || (delayCount == 0))
+  {
+    pState->waitIterations = 0;
+    pState->stage++;
+  }
+}
+#endif
+
+/*****************************************************************************************************/
+/*
+** Function: ProSLIC_Calibrate
+**
+** Description:
+** Performs calibration based on passed ptr to array of
+** desired CALRn settings.
+**
+** Starts calibration on all channels sequentially (not broadcast)
+** and continuously polls for completion.  Return error code if
+** CAL_EN does not clear for each enabled channel within the passed
+** timeout period.
+*/
+int ProSLIC_Calibrate(proslicChanType_ptr *pProslic, int maxChan, uInt8 *calr,
+                      int maxTime)
+{
+  int i,j, cal_en;
+  int cal_en_chan = 0;
+  int timer = 0;
+
+  TRACEPRINT(*pProslic, "maxChan = %d time = %d\n", maxChan, maxTime );
+
+  if ((*pProslic)->channelType != PROSLIC)
+  {
+    return RC_CHANNEL_TYPE_ERR;
+  }
+
+  for(i = 0; i < maxChan; i++)
+  {
+    if((pProslic[i]->channelEnable)&&(pProslic[i]->channelType == PROSLIC))
+    {
+      for(j = 0; j < 4; j++)
+      {
+        WriteReg(pProslic[i], pProslic[i]->channel, (PROSLIC_REG_CALR0+j), calr[j]);
+      }
+    }
+  }
+
+  /* Wait for calibration to complete */
+  do
+  {
+    cal_en = 0;
+    DelayX(*pProslic, 10);
+    for(i = 0; i < maxChan; i++)
+    {
+      if( (pProslic[i]->channelEnable) && (pProslic[i]->channelType == PROSLIC))
+      {
+        cal_en_chan = ReadReg(pProslic[i], pProslic[i]->channel, PROSLIC_REG_CALR3);
+        if( (cal_en_chan & 0x80) && (timer == maxTime) )
+        {
+          DEBUG_PRINT(pProslic[i], "%sCalibration timed out on channel %d\n",
+                      LOGPRINT_PREFIX, pProslic[i]->channel);
+          pProslic[i]->channelEnable = 0;
+          pProslic[i]->error = RC_CAL_TIMEOUT;
+        }
+        cal_en |= cal_en_chan;
+      }
+    }
+  }
+  while( (timer++ <= maxTime) && (cal_en & 0x80) );
+
+  if(timer <= maxTime)
+  {
+    return RC_NONE;
+  }
+  else
+  {
+    return RC_CAL_TIMEOUT;
+  }
+}
+/*****************************************************************************************************/
+/* This function is used by the xxxx_Init_with_Options - do not call this directly... */
+int ProSLIC_ReInit_helper(proslicChanType_ptr *pProslic, int size,
+                          initOptionsType init_option, int numChanPerDevice)
+{
+  int i;
+
+  /* Preserve linefeed state.. */
+  for(i = 0; i < size; i++)
+  {
+    pProslic[i]->scratch = ReadReg( pProslic[i], pProslic[i]->channel,
+                                   PROSLIC_REG_LINEFEED);
+    ProSLIC_PowerDownConverter( pProslic[i] );
+
+    /* Clear MSTRSTAT on a device basis */
+    if( (numChanPerDevice == 1) 
+      || ((numChanPerDevice == 2) && ((i&1) == 0)  ) )
+    {
+      ProSLIC_WriteReg(pProslic[i], PROSLIC_REG_MSTRSTAT, 0xFF); /* Clear master status register */
+    }
+  }
+
+  DelayX(*pProslic, 10); /* Wait to ensure system is powered down... */
+
+  /* Do a soft reset if reinit is requested...*/
+  if(init_option == INIT_REINIT)
+  {
+    for(i = 0; i < size; i++)
+    {
+      if(numChanPerDevice == 2) 
+      {
+        WriteReg(pProslic[i], (pProslic[i])->channel, PROSLIC_REG_RESET,
+                 (((pProslic[i])->channel)&1)+1); /* reset 1 channel at a time */
+      }
+      else
+      {
+        WriteReg(pProslic[i], (pProslic[i])->channel, PROSLIC_REG_RESET, 1);
+      }
+
+      pProslic[i]->error = RC_NONE; /* Clear any errors we may have seen in powering down the converter */
+    }
+    DelayX(*pProslic, 100); /* Wait for a soft reset */
+
+  }
+  return RC_NONE;
+}
+
+/*****************************************************************************************************/
+int ProSLIC_SoftReset(proslicChanType_ptr pProslic, uInt16 resetOptions)
+{
+  uInt8 data;
+
+  TRACEPRINT(pProslic, "reset option: %d\n",resetOptions);
+
+  /* We can't use channelType since it may not been set.  We assume at least 
+   * SWInit was called... */
+  if( pProslic->deviceId->chipType == SI3050 )
+  {
+    return RC_CHANNEL_TYPE_ERR;
+  }
+
+  /* Check if we're in free-run mode, if so abort */
+  data = ReadReg(pProslic, pProslic->channel, PROSLIC_REG_ENHANCE);
+
+  if(data & 0x6)
+  {
+    return RC_PLL_FREERUN_ACTIVE;
+  }
+
+  if(resetOptions & PROSLIC_BCAST_RESET)
+  {
+    return WriteReg(pProslic, PROSLIC_CHAN_BROADCAST, PROSLIC_REG_RESET, (uInt8)(resetOptions & 0xFF));
+  }
+  else
+  {
+    return WriteReg(pProslic, pProslic->channel, PROSLIC_REG_RESET, (uInt8)(resetOptions & 0xFF));
+  }
+}
+
+/*****************************************************************************************************/
+#ifndef DISABLE_TONE_SETUP
+int ProSLIC_ToneGenSetupPtr(proslicChanType_ptr pProslic, ProSLIC_Tone_Cfg *cfg)
+{
+  TRACEPRINT(pProslic, "\n",NULL);
+
+  if(pProslic->channelType != PROSLIC)
+  {
+    return RC_CHANNEL_TYPE_ERR;
+  }
+
+  WriteRAM(pProslic, pProslic->channel,PROSLIC_RAM_OSC1FREQ, cfg->osc1.freq);
+  WriteRAM(pProslic, pProslic->channel,PROSLIC_RAM_OSC1AMP, cfg->osc1.amp);
+  WriteRAM(pProslic, pProslic->channel,PROSLIC_RAM_OSC1PHAS, cfg->osc1.phas);
+  WriteReg(pProslic, pProslic->channel,PROSLIC_REG_O1TAHI,cfg->osc1.tahi);
+  WriteReg(pProslic, pProslic->channel,PROSLIC_REG_O1TALO,cfg->osc1.talo);
+  WriteReg(pProslic, pProslic->channel,PROSLIC_REG_O1TIHI,cfg->osc1.tihi);
+  WriteReg(pProslic, pProslic->channel,PROSLIC_REG_O1TILO,cfg->osc1.tilo);
+
+  WriteRAM(pProslic, pProslic->channel,PROSLIC_RAM_OSC2FREQ, cfg->osc2.freq);
+  WriteRAM(pProslic, pProslic->channel,PROSLIC_RAM_OSC2AMP, cfg->osc2.amp);
+  WriteRAM(pProslic, pProslic->channel,PROSLIC_RAM_OSC2PHAS, cfg->osc2.phas);
+  WriteReg(pProslic, pProslic->channel,PROSLIC_REG_O2TAHI,cfg->osc2.tahi);
+  WriteReg(pProslic, pProslic->channel,PROSLIC_REG_O2TALO,cfg->osc2.talo);
+  WriteReg(pProslic, pProslic->channel,PROSLIC_REG_O2TIHI,cfg->osc2.tihi);
+  WriteReg(pProslic, pProslic->channel,PROSLIC_REG_O2TILO,cfg->osc2.tilo);
+
+
+  WriteReg(pProslic, pProslic->channel,PROSLIC_REG_OMODE,cfg->omode);
+  return RC_NONE;
+}
+#endif /* DISABLE_TONE_SETUP */
+
+/*****************************************************************************************************/
+#ifndef DISABLE_FSK_SETUP
+int ProSLIC_FSKSetupPtr (proslicChanType_ptr pProslic, ProSLIC_FSK_Cfg *cfg)
+{
+  uInt8 data;
+  int i;
+
+  TRACEPRINT(pProslic, "\n",NULL);
+
+  if(pProslic->channelType != PROSLIC)
+  {
+    return RC_CHANNEL_TYPE_ERR;
+  }
+
+  WriteReg(pProslic,pProslic->channel,PROSLIC_REG_FSKDEPTH,
+           0x08); /* Clear Buffer */
+  WriteReg(pProslic,pProslic->channel,PROSLIC_REG_O1TAHI,0);
+  WriteReg(pProslic,pProslic->channel,PROSLIC_REG_O1TIHI,0);
+  WriteReg(pProslic,pProslic->channel,PROSLIC_REG_O1TILO,0);
+  WriteReg(pProslic,pProslic->channel,PROSLIC_REG_O1TALO,0x13);
+
+  data = ReadReg(pProslic,pProslic->channel,PROSLIC_REG_OMODE);
+  if (cfg->eightBit)
+  {
+    data |= 0x80;
+  }
+  else
+  {
+    data &= ~(0x80);
+  }
+  WriteReg(pProslic,pProslic->channel,PROSLIC_REG_FSKDEPTH,cfg->fskdepth);
+  WriteReg(pProslic,pProslic->channel,PROSLIC_REG_OMODE,data);
+
+  for(i = 0; i < 2; i++)
+  {
+    WriteRAM(pProslic,pProslic->channel,PROSLIC_RAM_FSK01+i,cfg->fsk[i]);
+    WriteRAM(pProslic,pProslic->channel,PROSLIC_RAM_FSKAMP0+i,cfg->fskamp[i]);
+    WriteRAM(pProslic,pProslic->channel,PROSLIC_RAM_FSKFREQ0+i,cfg->fskfreq[i]);
+  }
+  return RC_NONE;
+}
+#endif
+
+/*****************************************************************************************************/
+int ProSLIC_EnableFastRingStart(proslicChanType_ptr pProslic, BOOLEAN isEnabled)
+{
+  uInt8 data;
+
+  TRACEPRINT(pProslic, "\n",NULL);
+
+  if(pProslic->channelType != PROSLIC)
+  {
+    return RC_CHANNEL_TYPE_ERR;
+  }
+#if defined(SI3217X) && !defined(Si3217X_REVC_ONLY)
+  if (pProslic->deviceId->chipType >= SI32171
+      && pProslic->deviceId->chipType <= SI32179)
+  {
+    if(pProslic->deviceId->chipRev < 2)
+    {
+      return RC_UNSUPPORTED_FEATURE;
+    }
+  }
+#endif
+
+  data = ReadReg(pProslic, pProslic->channel, PROSLIC_REG_USERSTAT);
+
+  if( isEnabled )
+  {
+    data |= 8;
+  }
+  else
+  {
+    data &= ~8;
+  }
+
+  return WriteReg(pProslic, pProslic->channel, PROSLIC_REG_USERSTAT, data);
+}
+