[][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/si_voice.c b/target/linux/mediatek/files-5.4/sound/soc/codecs/si3218x/src/si_voice.c
new file mode 100644
index 0000000..c30ee2c
--- /dev/null
+++ b/target/linux/mediatek/files-5.4/sound/soc/codecs/si3218x/src/si_voice.c
@@ -0,0 +1,563 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Author(s):
+ * laj
+ *
+ * Distributed by:
+ * Silicon Laboratories, Inc
+ *
+ * This file contains proprietary information.
+ * No dissemination allowed without prior written permission from
+ * Silicon Laboratories, Inc.
+ *
+ * File Description:
+ * This file contains common (ProSIC + DAA) functions.
+ *
+ */
+
+#include "../config_inc/si_voice_datatypes.h"
+#include "../inc/si_voice.h"
+#include "../config_inc/proslic_api_config.h"
+
+#ifdef ENABLE_DEBUG
+#define LOGPRINT_PREFIX "SiVoice: "
+#endif
+
+#ifdef SI3217X
+#include "si3217x.h"
+#include "si3217x_intf.h"
+#endif
+
+#ifdef SI3218X
+#include "../inc/si3218x.h"
+#include "../inc/si3218x_intf.h"
+#endif
+
+#ifdef SI3219X
+#include "si3219x.h"
+#include "si3219x_intf.h"
+#endif
+
+#ifdef SI3226X
+#include "si3226x.h"
+#include "si3226x_intf.h"
+#endif
+
+#ifdef SI3228X
+#include "si3228x.h"
+#include "si3228x_intf.h"
+#endif
+
+#define pCtrl(X)           (X)->deviceId->ctrlInterface
+#define pProHW(X)          pCtrl((X))->hCtrl
+#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))
+
+/*
+** Control object constructor/destructor
+*/
+int SiVoice_createControlInterfaces (SiVoiceControlInterfaceType **pCtrlIntf,
+                                     uInt32 interface_count)
+{
+  TRACEPRINT_NOCHAN("count = %lu\n", (unsigned long)interface_count);
+#ifndef DISABLE_MALLOC
+  *pCtrlIntf = SIVOICE_CALLOC(sizeof(SiVoiceControlInterfaceType),
+                              interface_count);
+  if(*pCtrlIntf == 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(pCtrlIntf);
+  SILABS_UNREFERENCED_PARAMETER(interface_count);
+  return RC_UNSUPPORTED_FEATURE;
+#endif
+}
+
+int SiVoice_destroyControlInterfaces ( SiVoiceControlInterfaceType **pCtrlIntf )
+{
+
+  TRACEPRINT_NOCHAN("\n",NULL);
+#ifndef DISABLE_MALLOC
+  if( pCtrlIntf && *pCtrlIntf)
+  {
+    SIVOICE_FREE ((SiVoiceControlInterfaceType *)*pCtrlIntf);
+    *pCtrlIntf = NULL;
+  }
+  return RC_NONE;
+#else
+  SILABS_UNREFERENCED_PARAMETER(pCtrlIntf);
+  return RC_UNSUPPORTED_FEATURE;
+#endif
+}
+
+/*
+** Device object constructor/destructor
+*/
+int SiVoice_createDevices (SiVoiceDeviceType **pDevice, uInt32 device_count)
+{
+
+  TRACEPRINT_NOCHAN("\n",NULL);
+#ifndef DISABLE_MALLOC
+  *pDevice = SIVOICE_CALLOC (sizeof(SiVoiceDeviceType), device_count);
+
+  if(*pDevice == 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(pDevice);
+  SILABS_UNREFERENCED_PARAMETER(device_count);
+  return RC_UNSUPPORTED_FEATURE;
+#endif
+}
+
+int SiVoice_destroyDevices (SiVoiceDeviceType **pDevice)
+{
+
+  TRACEPRINT_NOCHAN("\n", NULL);
+#ifndef DISABLE_MALLOC
+  if(pDevice && *pDevice)
+  {
+    SIVOICE_FREE ((SiVoiceDeviceType *)*pDevice);
+    *pDevice = NULL;
+  }
+  return RC_NONE;
+#else
+  SILABS_UNREFERENCED_PARAMETER(pDevice);
+  return RC_UNSUPPORTED_FEATURE;
+#endif
+}
+
+/*
+** Channel object constructor/destructor
+*/
+int SiVoice_createChannels (SiVoiceChanType_ptr *pChan, uInt32 channel_count)
+{
+
+  TRACEPRINT_NOCHAN("count = %lu\n", (unsigned long) channel_count);
+#ifndef DISABLE_MALLOC
+  *pChan = SIVOICE_CALLOC(sizeof(SiVoiceChanType),channel_count);
+  if(*pChan == 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(pChan);
+  SILABS_UNREFERENCED_PARAMETER(channel_count);
+  return RC_UNSUPPORTED_FEATURE;
+#endif
+}
+
+int SiVoice_destroyChannels (SiVoiceChanType_ptr *hProslic)
+{
+
+  TRACEPRINT_NOCHAN("\n",NULL);
+#ifndef DISABLE_MALLOC
+  if(hProslic && *hProslic)
+  {
+    SIVOICE_FREE ((SiVoiceChanType_ptr)*hProslic);
+    *hProslic = NULL;
+  }
+  return RC_NONE;
+#else
+  SILABS_UNREFERENCED_PARAMETER(hProslic);
+  return RC_UNSUPPORTED_FEATURE;
+#endif
+}
+
+/*
+** Host control linkage
+*/
+int SiVoice_setControlInterfaceCtrlObj (SiVoiceControlInterfaceType *pCtrlIntf,
+                                        void *hCtrl)
+{
+  TRACEPRINT_NOCHAN("\n",NULL);
+  pCtrlIntf->hCtrl = hCtrl;
+  return RC_NONE;
+}
+
+/*
+** Host reset linkage
+*/
+int SiVoice_setControlInterfaceReset (SiVoiceControlInterfaceType *pCtrlIntf,
+                                      ctrl_Reset_fptr Reset_fptr)
+{
+  TRACEPRINT_NOCHAN("\n",NULL);
+  pCtrlIntf->Reset_fptr = Reset_fptr;
+  return RC_NONE;
+}
+
+/*
+** Host register/RAM read/write linkage
+*/
+int SiVoice_setControlInterfaceWriteRegister (SiVoiceControlInterfaceType
+    *pCtrlIntf, ctrl_WriteRegister_fptr WriteRegister_fptr)
+{
+  TRACEPRINT_NOCHAN("\n",NULL);
+  pCtrlIntf->WriteRegister_fptr = WriteRegister_fptr;
+  return RC_NONE;
+}
+
+int SiVoice_setControlInterfaceReadRegister (SiVoiceControlInterfaceType
+    *pCtrlIntf, ctrl_ReadRegister_fptr ReadRegister_fptr)
+{
+  TRACEPRINT_NOCHAN("\n",NULL);
+  pCtrlIntf->ReadRegister_fptr = ReadRegister_fptr;
+  return RC_NONE;
+}
+
+int SiVoice_setControlInterfaceWriteRAM (SiVoiceControlInterfaceType *pCtrlIntf,
+    ctrl_WriteRAM_fptr WriteRAM_fptr)
+{
+  TRACEPRINT_NOCHAN("\n",NULL);
+  pCtrlIntf->WriteRAM_fptr = WriteRAM_fptr;
+  return RC_NONE;
+}
+
+int SiVoice_setControlInterfaceReadRAM (SiVoiceControlInterfaceType *pCtrlIntf,
+                                        ctrl_ReadRAM_fptr ReadRAM_fptr)
+{
+  TRACEPRINT_NOCHAN("\n",NULL);
+  pCtrlIntf->ReadRAM_fptr = ReadRAM_fptr;
+  return RC_NONE;
+}
+
+/*
+** Host timer linkage
+*/
+int SiVoice_setControlInterfaceTimerObj (SiVoiceControlInterfaceType *pCtrlIntf,
+    void *hTimer)
+{
+  TRACEPRINT_NOCHAN("\n",NULL);
+  pCtrlIntf->hTimer = hTimer;
+  return RC_NONE;
+}
+
+int SiVoice_setControlInterfaceDelay (SiVoiceControlInterfaceType *pCtrlIntf,
+                                      system_delay_fptr Delay_fptr)
+{
+  TRACEPRINT_NOCHAN("\n",NULL);
+  pCtrlIntf->Delay_fptr = Delay_fptr;
+  return RC_NONE;
+}
+
+int SiVoice_setControlInterfaceSemaphore (SiVoiceControlInterfaceType
+    *pCtrlIntf, ctrl_Semaphore_fptr semaphore_fptr)
+{
+  TRACEPRINT_NOCHAN("\n",NULL);
+  pCtrlIntf->Semaphore_fptr = semaphore_fptr;
+  return RC_NONE;
+}
+
+int SiVoice_setControlInterfaceTimeElapsed (SiVoiceControlInterfaceType
+    *pCtrlIntf, system_timeElapsed_fptr timeElapsed_fptr)
+{
+  TRACEPRINT_NOCHAN("\n",NULL);
+  pCtrlIntf->timeElapsed_fptr = timeElapsed_fptr;
+  return RC_NONE;
+}
+
+int SiVoice_setControlInterfaceGetTime (SiVoiceControlInterfaceType *pCtrlIntf,
+                                        system_getTime_fptr getTime_fptr)
+{
+  TRACEPRINT_NOCHAN("\n",NULL);
+  pCtrlIntf->getTime_fptr = getTime_fptr;
+  return RC_NONE;
+}
+
+/*
+** Channel object initialization
+*/
+int SiVoice_SWInitChan (SiVoiceChanType_ptr pChan,int channel,int chipType,
+                        SiVoiceDeviceType *pDeviceObj, SiVoiceControlInterfaceType *pCtrlIntf)
+{
+  TRACEPRINT_NOCHAN( "channel = %d chipType = %d\n", channel, chipType);
+  pChan->channel = (uInt8)channel;
+  pChan->deviceId = pDeviceObj;
+  pChan->deviceId->ctrlInterface = pCtrlIntf;
+  pChan->channelEnable=1;
+  pChan->error = RC_NONE;
+  pChan->debugMode = 0;
+  pChan->dcdc_polarity_invert = 0;
+#ifdef PROSLIC_BOM_DEFAULT
+  pChan->bomOption = PROSLIC_BOM_DEFAULT;
+#else
+  pChan->bomOption = 0;
+#endif
+
+  switch (chipType)
+  {
+    case SI3217X_TYPE:
+      pChan->deviceId->chipType = SI32171;
+      break;
+
+    case SI3218X_TYPE:
+      pChan->deviceId->chipType = SI32180;
+      break;
+
+    case SI3219X_TYPE:
+      pChan->deviceId->chipType = SI32190;
+      break;
+
+    case SI3226X_TYPE:
+      pChan->deviceId->chipType = SI32260;
+      break;
+
+    case SI3228X_TYPE:
+      pChan->deviceId->chipType = SI32280;
+      break;
+
+    case SI3050_TYPE:
+      pChan->deviceId->chipType = SI3050;
+      break;
+
+    default:
+      return RC_UNSUPPORTED_FEATURE;
+  }
+  return RC_NONE;
+}
+
+/*
+** Reset control
+*/
+int SiVoice_Reset (SiVoiceChanType_ptr pChan)
+{
+  TRACEPRINT_NOCHAN( "\n", NULL);
+  /*
+  ** assert reset, wait 250ms, release reset, wait 250ms
+  */
+  pChan->deviceId->ctrlInterface->Reset_fptr(
+    pChan->deviceId->ctrlInterface->hCtrl,1);
+
+  pChan->deviceId->ctrlInterface->Delay_fptr(
+    pChan->deviceId->ctrlInterface->hTimer,250);
+
+  pChan->deviceId->ctrlInterface->Reset_fptr(
+    pChan->deviceId->ctrlInterface->hCtrl,0);
+
+  pChan->deviceId->ctrlInterface->Delay_fptr(
+    pChan->deviceId->ctrlInterface->hTimer,250);
+
+  return RC_NONE;
+}
+
+/*
+** Debug Mode Control
+*/
+int SiVoice_setSWDebugMode (SiVoiceChanType_ptr pChan, int debugEn)
+{
+#ifdef ENABLE_DEBUG
+  TRACEPRINT_NOCHAN( "debugEn %d\n", debugEn);
+  pChan->debugMode = (0xFE & pChan->debugMode) | (debugEn != 0);
+#else
+  SILABS_UNREFERENCED_PARAMETER(pChan);
+  SILABS_UNREFERENCED_PARAMETER(debugEn);
+#endif
+  return RC_NONE;
+}
+
+/*
+** Trace Mode Control
+*/
+int SiVoice_setTraceMode (SiVoiceChanType_ptr pChan, int traceEn)
+{
+#ifdef ENABLE_TRACES
+  TRACEPRINT_NOCHAN( "debugEn %d\n", traceEn);
+  pChan->debugMode = (0xFD & pChan->debugMode) | ((traceEn != 0)<<1);
+#else
+  SILABS_UNREFERENCED_PARAMETER(pChan);
+  SILABS_UNREFERENCED_PARAMETER(traceEn);
+#endif
+  return RC_NONE;
+}
+
+/*
+** Error status
+*/
+int SiVoice_getErrorFlag (SiVoiceChanType_ptr pChan, int *error)
+{
+  TRACEPRINT( pChan, "\n", NULL);
+  *error = pChan->error;
+  return RC_NONE;
+}
+
+int SiVoice_clearErrorFlag (SiVoiceChanType_ptr pChan)
+{
+  TRACEPRINT( pChan, "\n", NULL);
+  pChan->error = RC_NONE;
+  return RC_NONE;
+}
+
+/*
+** Channel status
+*/
+int SiVoice_setChannelEnable (SiVoiceChanType_ptr pChan, int chanEn)
+{
+  TRACEPRINT( pChan, "enable = %d\n", chanEn);
+  pChan->channelEnable = chanEn;
+  return RC_NONE;
+}
+
+int SiVoice_getChannelEnable (SiVoiceChanType_ptr pChan, int *chanEn)
+{
+  TRACEPRINT( pChan, "\n", NULL);
+  *chanEn = pChan->channelEnable;
+  return RC_NONE;
+}
+
+uInt8 SiVoice_ReadReg(SiVoiceChanType_ptr hProslic,uInt8 addr)
+{
+  TRACEPRINT( hProslic, "addr = %u\n", (unsigned int)addr);
+  return ReadReg(hProslic, hProslic->channel, addr);
+}
+
+int SiVoice_WriteReg(SiVoiceChanType_ptr hProslic,uInt8 addr,uInt8 data)
+{
+  TRACEPRINT( hProslic, "addr = %u data = 0x%02X\n", (unsigned int)addr,
+              (unsigned int) data);
+  return WriteReg(hProslic, hProslic->channel, addr, data);
+}
+
+/*****************************************************************************************************/
+#if defined(SI3217X) || defined(SI3218X) || defined(SI3219X) || defined(SI3226X) || defined(SI3228X) 
+#include "../inc/proslic.h"
+
+/* Iterate through the number of channels to determine if it's a SLIC, DAA, or unknown. Rev ID and chiptype is
+ * also filled in.
+ */
+int SiVoice_IdentifyChannels(SiVoiceChanType_ptr *pProslic, int size,
+                             int *slicCount, int *daaCount)
+{
+  int i;
+  int rc = RC_NONE;
+  SiVoiceChanType_ptr currentChannel;
+
+  TRACEPRINT( *pProslic, "size = %d\n", size);
+
+  if(slicCount)
+  {
+    *slicCount = 0;
+  }
+  if(daaCount)
+  {
+    *daaCount = 0;
+  }
+
+  for(i = 0; i < size; i++)
+  {
+    currentChannel = pProslic[i];
+    /* SiVoice_SWInitChan() fills in the chipType initially with something the user provided, fill it
+     * in with the correct info.. The GetChipInfo may probe registers to compare them with their
+     * initial values, so this function MUST only be called after a chipset reset.
+     */
+#ifdef SI3217X
+    if (currentChannel->deviceId->chipType >= SI32171
+        && currentChannel->deviceId->chipType <= SI32179)
+    {
+      rc = Si3217x_GetChipInfo(currentChannel);
+    }
+#endif
+
+#ifdef SI3218X
+    if (currentChannel->deviceId->chipType >= SI32180
+        && currentChannel->deviceId->chipType <= SI32189)
+    {
+      rc = Si3218x_GetChipInfo(currentChannel);
+    }
+#endif
+
+#ifdef SI3219X
+    if ( IS_SI3219X(currentChannel->deviceId) )
+    {
+      rc = Si3219x_GetChipInfo(currentChannel);
+    }
+#endif
+
+#ifdef SI3226X
+    if (currentChannel->deviceId->chipType >= SI32260
+        && currentChannel->deviceId->chipType <= SI32269)
+    {
+      rc = Si3226x_GetChipInfo(currentChannel);
+    }
+#endif
+
+#ifdef SI3228X
+    if (currentChannel->deviceId->chipType >= SI32280
+        && currentChannel->deviceId->chipType <= SI32289)
+    {
+      rc = Si3228x_GetChipInfo(currentChannel);
+    }
+#endif
+
+    if(rc != RC_NONE)
+    {
+      return rc;
+    }
+
+    currentChannel->channelType = ProSLIC_identifyChannelType(currentChannel);
+    if(currentChannel->channelType == PROSLIC)
+    {
+      if(slicCount)
+      {
+        (*slicCount)++;
+      }
+    }
+    else if(currentChannel->channelType == DAA)
+    {
+      if(daaCount)
+      {
+        (*daaCount)++;
+      }
+    }
+#ifdef ENABLE_DEBUG
+    {
+      const char *dev_type = "UNKNOWN";
+      if(currentChannel->channelType == PROSLIC)
+      {
+        dev_type = "PROSLIC";
+      }
+      else if(currentChannel->channelType == DAA)
+      {
+        dev_type = "DAA";
+      }
+      LOGPRINT("%sChannel %d: Type = %s Rev = %d\n",
+               LOGPRINT_PREFIX, currentChannel->channel, dev_type,
+               currentChannel->deviceId->chipRev);
+
+    }
+#endif /* ENABLE_DEBUG */
+  }
+  return RC_NONE;
+}
+#endif
+
+/*
+** Function: ProSLIC_Version
+**
+** Description:
+** Return API version
+**
+** Returns:
+** string of the API release.
+*/
+
+extern const char *SiVoiceAPIVersion;
+char *SiVoice_Version()
+{
+  return (char *)SiVoiceAPIVersion;
+}
+