]> rtime.felk.cvut.cz Git - sojka/nv-tegra/linux-3.10.git/commitdiff
asoc: es755: codec power & latency optimizations
authorSrinivas Anne <sanne@nvidia.com>
Sat, 22 Aug 2015 01:14:30 +0000 (18:14 -0700)
committermobile promotions <svcmobile_promotions@nvidia.com>
Thu, 12 Nov 2015 02:16:29 +0000 (18:16 -0800)
FW version: M90.5.2.12_B61231_NVidia_Hawkeye_MCFFillIn_STREAM.bin

Change Summary:
Audience mainline driver escore 1.5.0
DSP-bypass route for audio playback over headset/headphone.
enabled MP_sleep state during audio playback over headset/headphone
Warm-up latency optimizations
fixed capture latency regression
disable wired accessory detection during LP0
playback latency optimizations

Change-Id: Ib55046b864b8b79284eb5568f07195c75fe50e81
Signed-off-by: Srinivas Anne <sanne@nvidia.com>
Reviewed-on: http://git-master/r/830908
GVS: Gerrit_Virtual_Submit
Reviewed-by: Pierre Gervais <pgervais@nvidia.com>
33 files changed:
firmware/audience/es755/audience-es755-fw.bin
sound/soc/codecs/audience/Kconfig
sound/soc/codecs/audience/Makefile
sound/soc/codecs/audience/adnc-sensorhub-api.h [deleted file]
sound/soc/codecs/audience/es-a300-reg.h
sound/soc/codecs/audience/es-a300.c
sound/soc/codecs/audience/es-d300-route.c
sound/soc/codecs/audience/es-d300-route.h
sound/soc/codecs/audience/es-d300.c
sound/soc/codecs/audience/es-d300.h
sound/soc/codecs/audience/es755-access.h
sound/soc/codecs/audience/es755.c [changed mode: 0755->0644]
sound/soc/codecs/audience/es755.h [changed mode: 0755->0644]
sound/soc/codecs/audience/escore-cdev.c
sound/soc/codecs/audience/escore-i2c.c
sound/soc/codecs/audience/escore-i2c.h
sound/soc/codecs/audience/escore-i2s.c
sound/soc/codecs/audience/escore-list.c
sound/soc/codecs/audience/escore-pm.c
sound/soc/codecs/audience/escore-slim.c
sound/soc/codecs/audience/escore-spi.c
sound/soc/codecs/audience/escore-spi.h
sound/soc/codecs/audience/escore-uart-common.c
sound/soc/codecs/audience/escore-uart-common.h
sound/soc/codecs/audience/escore-uart.c
sound/soc/codecs/audience/escore-version.h
sound/soc/codecs/audience/escore-vs.c
sound/soc/codecs/audience/escore-vs.h
sound/soc/codecs/audience/escore.c
sound/soc/codecs/audience/escore.h [changed mode: 0755->0644]
sound/soc/codecs/audience/esxxx.h [new file with mode: 0644]
sound/soc/codecs/audience/mq100-sensorhub.h [deleted file]
sound/soc/tegra-alt/tegra_t210ref_mobile_es755_alt.c

index e31ae303ac9292c91a1f6ce995498f0ddd1bdce9..2457c3cda5d1f88d3da5a7863e5a65e8eba57b17 100644 (file)
Binary files a/firmware/audience/es755/audience-es755-fw.bin and b/firmware/audience/es755/audience-es755-fw.bin differ
index 6d9529b046cfede606dea7e625529f421f4a62a0..b347d6108a21bc95d8d645cc59ade851707b4698 100644 (file)
@@ -11,6 +11,17 @@ config SND_SOC_ES705_ESCORE
          * SLIMbus + SLIMbus and UART
          * I2C+I2S and SPI
 
+config SND_SOC_ES804_ESCORE
+        bool "eS804_escore"
+       select SND_SOC_ES_VS
+       ---help---
+         Enable support for Audience eS705 audio chip escore
+         Possible control+data and high bandwidth bus combinations:
+         * I2C+I2S and UART
+         * SPI+I2S and UART
+         * SLIMbus + SLIMbus and UART
+         * I2C+I2S and SPI
+
 config SND_SOC_ES704_ESCORE
        bool "eS704_escore"
        select SND_SOC_ES_VS
@@ -33,31 +44,41 @@ config SND_SOC_ES755
          * SLIMbus + SLIMbus and UART
          * I2C+I2S and SPI
 
-config MQ100_SENSOR_HUB
-        bool "mq100"
-       ---help---
-         Enable support for Audience Sensorhub interface
-         Possible control and high bandwidth bus combinations:
-         * I2C + UART
-         * I2C + SPI
-         * SPI
-         * UART
-
 config SND_SOC_ES705_EXTCLK_OVER_GPIO
        bool "Enable External Clock Control Over GPIO"
        ---help---
          This will enable external clock ON/OFF over GPIO
 
-config SND_SOC_ES705_CLOCK_INDEX
-       depends on (SND_SOC_ES705 || SND_SOC_ES705_ESCORE || SND_SOC_ES704_ESCORE || MQ100_SENSOR_HUB)
-       prompt "Audience es705 clock's index"
-       int
-       default 8
+config SND_SOC_ES854
+       bool "eS854"
+       select SND_SOC_ES_VS
        ---help---
-         Defines Audience es705 clock's index.
-         Supported clocks indexes
-         * 0 for 9600 MHz
-         * 8 for 19200 MHz
+         Enable support for Audience eS854 audio chip
+         Possible control+data and high bandwidth bus combinations:
+         * I2C+I2S and UART
+         * SPI+I2S and UART
+
+config SND_SOC_N100
+       bool "VS support for Multisensory SoC"
+       select SND_SOC_ES_VS
+       ---help---
+         Enable VQ support for multisensory
+
+config SND_SOC_ES857
+       bool "eS857"
+       select SND_SOC_ES_VS
+       ---help---
+         Enable support for Audience eS857 audio chip
+         Possible control+data and high bandwidth bus combinations:
+         * I2C+I2S and UART
+         * SPI+I2S and UART
+
+config OSP_SENSORHUB
+        bool "Escore support for Sensorhub"
+       ---help---
+         This will enable sensor hub configuration
+         OSP is Open Sensor Platform framework.
+         Audience sensorhub is compliant to OSP framework.
 
 # Legacy config options for eS705
 
@@ -154,31 +175,16 @@ config SND_SOC_ES705_UART_WAKEUP
        Ebabling this feature uses UART TX of host to wakeup eS705
        instead of wakeup gpio.
 
-config MQ100_SENSOR_HUB
-        bool "MQ100 Sensor driver support"
-               depends on SND_SOC_ES705_ESCORE
-       ---help---
-         This will enable MQ100 sensor hub configuration
 
 config SND_SOC_ES705_EXTCLK_OVER_GPIO
        bool "Enable External Clock Control Over GPIO"
        ---help---
-         This will enable external clock ON/OFF over GPIO
-
-config SND_SOC_ES705_CLOCK_INDEX
-       depends on (SND_SOC_ES705 || SND_SOC_ES705_ESCORE || SND_SOC_ES704_ESCORE)
-       prompt "Audience es705 clock's index"
-       int
-       default 8
-       ---help---
-         Defines Audience es705 clock's index.
-         Supported clocks indexes
-         * 0 for 9600 MHz
-         * 8 for 19200 MHz
+         This will enable external clock ON/OFF over 
+         GPIO
 
 # Options for escore infrastructure
 
-if SND_SOC_ES325 || SND_SOC_ES515 || SND_SOC_ES755 || SND_SOC_ES705_ESCORE || SND_SOC_ES704_ESCORE || MQ100_SENSOR_HUB
+if SND_SOC_ES325 || SND_SOC_ES515 || SND_SOC_ES755 || SND_SOC_ES705_ESCORE || SND_SOC_ES704_ESCORE || SND_SOC_ES804_ESCORE  || OSP_SENSORHUB || SND_SOC_ES854 || SND_SOC_ES857
 
 config SND_SOC_ES_I2S
        tristate
@@ -188,7 +194,9 @@ choice
        default SND_SOC_ES_SLIM
 
 config SND_SOC_ES_SLIM
-       bool "SLIMbus based codec" if SLIMBUS
+       bool "SLIMbus based codec"
+       select SLIMBUS
+       select MFD_CORE
        ---help---
          This enables SLIMbus as control interface
          as well as data interface to communicate
@@ -232,7 +240,7 @@ endchoice
 endif
 
 # High bandwidth bus support
-if SND_SOC_325 || SND_SOC_ES515 || SND_SOC_ES755 || SND_SOC_ES705_ESCORE || SND_SOC_ES704_ESCORE || MQ100_SENSOR_HUB
+if SND_SOC_325 || SND_SOC_ES515 || SND_SOC_ES755 || SND_SOC_ES705_ESCORE || SND_SOC_ES804_ESCORE ||SND_SOC_ES704_ESCORE || OSP_SENSORHUB || SND_SOC_ES854 || SND_SOC_ES857
 choice
        prompt "High Bandwidth Transport"
        default SND_SOC_ES_HIGH_BW_BUS_DEFAULT
@@ -280,37 +288,7 @@ config SND_SOC_ES_HIGH_BW_BUS_UART
 endchoice
 endif
 
-if SND_SOC_ES755 || SND_SOC_ES705_ESCORE || SND_SOC_ES704_ESCORE
-
-choice
-        prompt "Runtime Power Management mode"
-       default SND_SOC_ES_RUNTIME_SUSPEND_MODE_SLEEP
-       ---help---
-       There are two configuration modes for
-       runtime suspend case.
-       1. Sleep mode
-       2. CVQ suspend mode
-
-config SND_SOC_ES_RUNTIME_SUSPEND_MODE_SLEEP
-        bool "Normal Suspend"
-       ---help---
-       In this mode, chip will be put in normal
-       sleep mode i.e. sleep (for Audience DSPs
-       or MP sleep mode (for Audience Codecs)
-       when runtime suspend is called.
-
-config SND_SOC_ES_RUNTIME_SUSPEND_MODE_CVQ
-        bool "CVQ Suspend"
-       ---help---
-       In this mode, chip will be put in CVQ
-       suspend mode when runtime suspend is
-       called. Chip can be bought in normal mode
-       by speaking keyword or from resume.
-
-endchoice
-endif
-
-if SND_SOC_ES_HIGH_BW_BUS_UART && (SND_SOC_ES755 || SND_SOC_ES705 || SND_SOC_ES705_ESCORE || SND_SOC_ES704_ESCORE || MQ100_SENSOR_HUB)
+if SND_SOC_ES_HIGH_BW_BUS_UART && (SND_SOC_ES755 || SND_SOC_ES705 || SND_SOC_ES705_ESCORE || SND_SOC_ES704_ESCORE || SND_SOC_ES804_ESCORE || SND_SOC_ES854 || SND_SOC_ES857)
 
 config SND_SOC_ES_UART_SBL_BAUD
        prompt "UART baud rate for SBL mode"
@@ -358,7 +336,7 @@ config SND_SOC_ES_UART_VS_BAUD
          * 3072000
 
 config SND_SOC_ES_UARTHS_BAUD
-       depends on SND_SOC_ES_HIGH_BW_BUS_UART && (SND_SOC_ES755 || SND_SOC_ES705 || SND_SOC_ES705_ESCORE || SND_SOC_ES704_ESCORE || MQ100_SENSOR_HUB)
+       depends on SND_SOC_ES_HIGH_BW_BUS_UART && (SND_SOC_ES755 || SND_SOC_ES705 || SND_SOC_ES705_ESCORE ||SND_SOC_ES804_ESCORE|| SND_SOC_ES704_ESCORE || OSP_SENSORHUB || SND_SOC_ES854 || SND_SOC_ES857)
        prompt "UART baud rate for firmware download"
        int
        default 3000000
@@ -436,7 +414,7 @@ endchoice
 
 config SND_SOC_ES_VS
         bool "Voice Sense feature"
-       depends on SND_SOC_ES705 || SND_SOC_ES705_ESCORE || SND_SOC_ES704_ESCORE || SND_SOC_ES755 || SND_SOC_ES325
+       depends on SND_SOC_ES705 || SND_SOC_ES705_ESCORE || SND_SOC_ES804_ESCORE || SND_SOC_ES704_ESCORE || SND_SOC_ES755 || SND_SOC_ES325 || SND_SOC_ES854 || SND_SOC_ES857 || SND_SOC_N100
        ---help---
        This allows to select VS feature
 
@@ -471,4 +449,35 @@ config SND_SOC_ES_GPIO_A
        API Interrupt interface allows utilization of interrupt mode
        functionality:
 
+config SND_SOC_ES_VS_STREAMING
+        bool "VS Wakeup Streaming Mode"
+       depends on (SND_SOC_ES804_ESCORE || SND_SOC_ES705_ESCORE || SND_SOC_ES755 || SND_SOC_ES854 || SND_SOC_ES857)
+       ---help---
+       This adds support for VS streaming power state.
+       On VS wakeup the firmware wakes up in the VS
+       streaming mode. Post streaming the state has to
+       be switched to Normal mode.
+
+config SND_SOC_ES_AVOID_REPEAT_FW_DOWNLOAD
+        bool "Reduce Repeated Fw download across Power Transition"
+       depends on (SND_SOC_ES804_ESCORE || SND_SOC_ES705_ESCORE || SND_SOC_ES755 || SND_SOC_ES854 || SND_SOC_ES857)
+       ---help---
+       This adds support for reducing the number of FW
+       Download. In the New PCR platform, if a power
+       transition is done from NS --> VS with no Sleep
+       state in between, the FW Download needs to be
+       done only for the First Transition. Later on, we
+       only need to send Power transition Command. This
+       however is nullified if the chip enters Sleep state
+       any time in the middle
+
+config SND_SOC_ES_SPI_WRITE_DMA_MODE
+        bool "SPI Write When DMA mode enabled"
+       depends on (SND_SOC_ES_SPI || SND_SOC_ES_HIGH_BW_BUS_SPI)
+       ---help---
+       This adds support for spi write using DMA mode settings as DMA mode
+       expects kernel virtual address which has a mapping in physical memory.
+       This flag is mainly to be used when writing the buffer given by
+       user space.
+       E.g. Firmware download,Write Data Block from /etc/firmware.
 endmenu
index a96c95e7d88501593cbb63ad1e345cb7df8ee4f1..afed75f1b4b453b5efd17aa17bda9f7ad00d9b8a 100644 (file)
@@ -1,5 +1,7 @@
 snd-soc-es705-escore-objs := es705_escore.o escore-pm.o escore.o escore-list.o
 snd-soc-es755-objs := es755.o escore.o escore-pm.o escore-list.o es-d300.o es-a300.o es-d300-route.o
+snd-soc-es854-objs := es755.o escore.o escore-pm.o escore-list.o es-d300.o es-a350.o es-d300-route.o
+snd-soc-es857-objs := es755.o escore.o escore-pm.o escore-list.o es-d300.o es-a375.o es-d300-route.o
 snd-soc-escore-slim-objs += escore-slim.o
 snd-soc-escore-i2s-objs += escore-i2s.o
 snd-soc-escore-i2c-objs += escore-i2c.o
@@ -8,14 +10,19 @@ snd-soc-escore-cdev-objs += escore-cdev.o
 snd-soc-escore-uart-objs += escore-uart.o escore-uart-common.o
 snd-soc-escore-vs-objs += escore-vs.o
 snd-soc-es-spi-sensor-hub-objs := es705-sensorhub-demo.o
-adnc-mq100-sensorhub-objs := mq100-sensorhub.o escore-pm.o escore.o escore-list.o
+snd-soc-esn100-objs := es-n100.o
+escore-only-objs := escore.o escore-pm.o escore-list.o
 
 obj-$(CONFIG_SND_SOC_ES705_ESCORE)     += snd-soc-es705-escore.o
+obj-$(CONFIG_SND_SOC_ES804_ESCORE)     += snd-soc-es705-escore.o
 obj-$(CONFIG_SND_SOC_ES704_ESCORE)     += snd-soc-es705-escore.o
 obj-$(CONFIG_SND_SOC_ES325)    += snd-soc-es325.o
 obj-$(CONFIG_SND_SOC_ES515)    += snd-soc-es515.o
 obj-$(CONFIG_SND_SOC_ES755)    += snd-soc-es755.o
-obj-$(CONFIG_MQ100_SENSOR_HUB) += adnc-mq100-sensorhub.o
+obj-$(CONFIG_SND_SOC_ES854)    += snd-soc-es854.o
+obj-$(CONFIG_SND_SOC_N100)     += snd-soc-esn100.o
+obj-$(CONFIG_SND_SOC_ES857)    += snd-soc-es857.o
+obj-$(CONFIG_OSP_SENSORHUB)            += escore-only.o
 
 obj-$(CONFIG_SND_SOC_ES_SLIM)  += snd-soc-escore-slim.o
 ifneq ($(CONFIG_SND_SOC_ES_SLIM),y)
@@ -50,3 +57,4 @@ endif
 obj-$(CONFIG_SND_SOC_ES_CDEV)  += snd-soc-escore-cdev.o
 obj-$(CONFIG_SND_SOC_ES_VS)    += snd-soc-escore-vs.o
 obj-$(CONFIG_SND_SOC_ES_SPI_SENSOR_HUB)        += snd-soc-es-spi-sensor-hub.o
+
diff --git a/sound/soc/codecs/audience/adnc-sensorhub-api.h b/sound/soc/codecs/audience/adnc-sensorhub-api.h
deleted file mode 100644 (file)
index 1850d38..0000000
+++ /dev/null
@@ -1,78 +0,0 @@
-#ifndef ADNC_SENSORHUB_API_H
-#define ADNC_SENSORHUB_API_H
-
-
-struct mq100_extension_cb;
-
-/**
- * Register rdb callbacks
- * @param  callbacks - structure containing
- * callbacks from es705 rdb/wdb driver
- * @return
- */
-int mq100_register_extensions
-       (struct mq100_extension_cb *callbacks, void *priv);
-
-/**
- * Note: can we expect all of these
- * functions to be executed in process context?
- */
-struct mq100_extension_cb {
-       /**
-        * cookie using for callbacks
-        */
-       void *priv;
-
-       /**
-        * Callback when firmware has been downloaded, device has been
-        * initialized and is ready for rdb/wdb
-        *
-        * @param  es705_priv - es705 private data. this cookie will be
-        * returned with all calls to es705_wdb
-        * @return on success, a pointer to the callee's private data,
-        *         this cookie must be returned with every other callback
-        *         on failure, return NULL
-        */
-       void * (*probe)(void *es705);
-
-       /**
-        * This function is called when audience driver
-        * has detected the an interrupt from the device
-        * @param priv - cookie returned from probe()
-        */
-       void (*intr)(void *priv);
-
-       /**
-        * Callback whenever the device state changes.
-        * e.g. when firmware has been downloaded
-        * Use MQ100_STATE_XXX values for state param.
-        * @param priv - cookie returned from probe()
-        */
-       void (*status)(void *priv, u8 state);
-};
-
-/*
- * Writes buf to es705 using wdb
- * this function will prepend 0x802F 0xffff
- * @param: buf - wdb data
- * @param: len - length
- * @return: no. of bytes written
- */
-int mq100_wdb(const void *buf, int len);
-
-/* Max Size = PAGE_SIZE * 2 */
-/*
- * Reads buf from es705 using rdb
- * @param:
- * buf - rdb data Max Size supported - 2*PAGE_SIZE
- * Ensure buffer allocated has enough space for rdb
- *
- * buf - buffer pointer
- * id - type specifier
- * len - max. buf size
- *
- * @return: no. of bytes read
- */
-int mq100_rdb(void *buf, int len, int id);
-
-#endif
index 75ce2382e977dd15a395afc3a54ba46cd22b0357..d533a1d11ba5ca1df8a87eea83d84f997ce02f11 100644 (file)
-/*
- * es-a300-reg.h  --  Audience eS755 ALSA SoC Audio driver
- *
- * Copyright 2013 Audience, Inc.
- *
- * Author: Rajat Aggarwal <raggarwal@audience.com>
- *
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
+//***********************************************************************************
+// SCRIPT GENERATED FILE - DO NOT EDIT
+//
+// es-a300-reg.h
+//
+// This file contains the addresses for the codec hardware fields.  Addresses
+// are automatically extracted by script from the codec register spreadsheets.
+//
+// This file generated on 5/22/2015 at 10:58:03 AM
+//
+//***********************************************************************************
 
 #ifndef __ES_A300_REG_H__
 #define __ES_A300_REG_H__
 
 
-/*
- * Register values
- */
-
-/*
- * Power
- */
-
-#define ES_CHIP_CTRL                           0x00
-#define ES_OVERRIDE                            0x01
-#define ES_LDO_CTRL                            0x2B
-#define ES_LDO_ILIM                            0x36
-#define ES_LDO_TRIM                            0x2A
-#define ES_MICBIAS_CTRL                                0x02
-#define ES_MB_TRIM1                            0x34
-#define ES_MB_TRIM2                            0x35
-
-/*
- * Accessory Detection
- */
-
-#define ES_PLUGDET_CTRL                                0x33
-#define ES_BTN_CTRL1                           0x23
-#define ES_BTN_CTRL2                           0x24
-#define ES_BTN_CTRL3                           0x25
-#define ES_BTN_CTRL4                           0x32
-#define ES_ACC_INTERCEPT                       0x0E
-#define ES_PLUG_STAT                           0x3B
-#define ES_BTNDET_STAT                         0x26
-#define ES_INT1_STATE                          0x1F
-#define ES_INT1_MASK                           0x20
-#define ES_INT2_STATE                          0x21
-#define ES_INT2_MASK                           0x22
-
-/*
- * Analog Inputs
- */
-
-#define ES_MIC0_CTRL                           0x03
-#define ES_MIC1_CTRL                           0x05
-#define ES_MIC2_CTRL                           0x08
-#define ES_MICHS_CTRL                          0x0D
-#define ES_AUX_L_CTRL                          0x07
-#define ES_AUX_R_CTRL                          0x09
-#define ES_MIC_TUNE                            0x04
-#define ES_REC_TRIM                            0x06
-
-/*
- * ADC
- */
-
-#define ES_ADC_CTRL                            0x0A
-#define ES_VS_ADC_CTRL                         0x2E
-#define ES_ADC_BIAS_I                          0x2C
-#define ES_ADC_GAIN_DITH                       0x2D
-
-/*
- * Analog Ground Referenced Output
- */
-
-#define ES_HP_L_GAIN                           0x11
-#define ES_HP_L_CTRL                           0x12
-#define ES_HP_R_GAIN                           0x13
-#define ES_HP_R_CTRL                           0x14
-#define ES_HP_CHAIN_TRIM                       0x1D
-#define ES_EP_GAIN                             0x0F
-#define ES_EP_CTRL                             0x10
-#define ES_LO_L_GAIN                           0x19
-#define ES_LO_L_CTRL                           0x1A
-#define ES_LO_R_GAIN                           0x1B
-#define ES_LO_R_CTRL                           0x1C
-#define ES_CLASSG                              0x27
-#define ES_CP_CTRL                             0x1E
-
-/*
- * Loudspeaker Output
- */
-
-#define ES_SPKR_L_GAIN                         0x15
-#define ES_SPKR_L_CTRL                         0x16
-#define ES_SPKR_R_GAIN                         0x17
-#define ES_SPKR_R_CTRL                         0x18
-#define ES_SPKR_DEBUG                          0x28
-#define ES_SPKR_TRIM                           0x29
-#define ES_SPKR_ALC1                           0x30
-#define ES_SPKR_ALC2                           0x31
-
-/*
- * DAC
- */
-
-#define ES_DAC_CTRL                            0x0B
-#define ES_DAC_DEBUG                           0x0C
-
-
-/*
- * Digital
- */
-
-#define ES_DAC_DIG_EN                          0x40
-#define ES_DAC_DIG_CH                          0x41
-#define ES_DAC_DIG_CPF                         0x42
-#define ES_DAC_DIG_I2S1                                0x43
-#define ES_DAC_DIG_I2S2                                0x44
-#define ES_DAC_DIG_FS_SEL                      0x45
-#define ES_DAC_DIG_OS                          0x46
-#define ES_DAC_DIG_CIC                         0x47
-#define ES_DAC_DIG_SDM                         0x48
-#define ES_DAC_DIG_DS                          0x49
-#define ES_DAC_DIG_DRP_FLT_CFF_0               0x4A
-#define ES_DAC_DIG_DRP_FLT_CFF_1               0x4B
-#define ES_DAC_DIG_DRP_FLT_CFB_0               0x4C
-#define ES_DAC_DIG_DRP_FLT_CFB_1               0x4D
-#define ES_DAC_DIG_DRP_FLT_GAIN_0              0x4E
-#define ES_DAC_DIG_DRP_FLT_GAIN_1              0x4F
-#define ES_DAC_DIG_FILT_ER_SAT_FLAG            0x50
-#define ES_SQUELCH_CONTROL                     0x51
-#define ES_SQUELCH_THRESHOLD                   0x52
-#define ES_SQUELCH_TERM_CNT                    0x53
-#define ES_DEM_TERM_CNT                                0x54
-#define ES_DERM_ROT_LVL                                0x55
-
-#define ES_MAX_REGISTER                                0x55
-
-
-
-/*
- * Field Definitions.
- */
-
-/*
- * R0 (0x00) - Chip Control Register
- */
-
-#define ES_CHIP_EN_MASK                        0x01  /* CHIP_EN 1=Enable chip */
-#define ES_CHIP_EN_SHIFT                          0  /* CHIP_EN */
-#define ES_CHIP_EN_WIDTH                          1  /* CHIP_EN */
-#define ES_STANDBY_MASK                                0x02  /* STANDBY 1=Standby*/
-#define ES_STANDBY_SHIFT                          1  /* STANDBY */
-#define ES_STANDBY_WIDTH                          1  /* STANDBY */
-#define ES_LDO1_DIS_MASK                       0x04  /* LDO1_DIS 1=LDO1 OFF*/
-#define ES_LDO1_DIS_SHIFT                         2  /* LDO1_DIS */
-#define ES_LDO1_DIS_WIDTH                         1  /* LDO1_DIS */
-#define ES_LDO3_DIS_MASK                       0x08  /* LDO3_DIS 1=LDO3 OFF*/
-#define ES_LDO3_DIS_SHIFT                         3  /* LDO3_DIS */
-#define ES_LDO3_DIS_WIDTH                         1  /* LDO3_DIS */
-#define ES_LDO2_DIS_MASK                       0x10  /* LDO2_DIS 1=LDO2 OFF*/
-#define ES_LDO2_DIS_SHIFT                         4  /* LDO2_DIS */
-#define ES_LDO2_DIS_WIDTH                         1  /* LDO2_DIS */
-#define ES_DIV_FOR_5_6MHZ_MASK         0x20  /* 1=44.1KHz 0=48KHz */
-#define ES_DIV_FOR_5_6MHZ_SHIFT                   5  /* DIV_FOR_5_6MHZ */
-#define ES_DIV_FOR_5_6MHZ_WIDTH                   1  /* DIV_FOR_5_6MHZ */
-#define ES_SKIP_OUT_CAL_MASK           0x40  /* SKIP_OUT_CAL */
-#define ES_SKIP_OUT_CAL_SHIFT             6  /* SKIP_OUT_CAL */
-#define ES_SKIP_OUT_CAL_WIDTH             1  /* SKIP_OUT_CAL */
-#define ES_RGLTR28_DIS_MASK                    0x80  /* RGLTR28_DIS */
-#define ES_RGLTR28_DIS_SHIFT              7  /* RGLTR28_DIS */
-#define ES_RGLTR28_DIS_WIDTH              1  /* RGLTR28_DIS */
-
-
-/*
- * R1 (0x01) - Override
- */
-
-#define ES_AUTO_TSD_MASK                       0x01  /* AUTO_TSD */
-#define ES_AUTO_TSD_SHIFT                         0  /* AUTO_TSD */
-#define ES_AUTO_TSD_WIDTH                         1  /* AUTO_TSD */
-#define ES_FORCE_VCM_MASK                      0x02  /* FORCE_VCM */
-#define ES_FORCE_VCM_SHIFT                        1  /* FORCE_VCM */
-#define ES_FORCE_VCM_WIDTH                        1  /* FORCE_VCM */
-#define ES_FORCE_LDO1_MASK                     0x04  /* FORCE_LDO1 */
-#define ES_FORCE_LDO1_SHIFT                       2  /* FORCE_LDO1 */
-#define ES_FORCE_LDO1_WIDTH                       1  /* FORCE_LDO1 */
-#define ES_FORCE_LDO3_MASK                     0x08  /* FORCE_LDO3 */
-#define ES_FORCE_LDO3_SHIFT                       3  /* FORCE_LDO3 */
-#define ES_FORCE_LDO3_WIDTH                       1  /* FORCE_LDO3 */
-#define ES_FORCE_LDO2_MASK                     0x10  /* FORCE_LDO2 */
-#define ES_FORCE_LDO2_SHIFT                       4  /* FORCE_LDO2 */
-#define ES_FORCE_LDO2_WIDTH                       1  /* FORCE_LDO2 */
-#define ES_TSD_IGNORE_MASK                     0x20  /* TSD_IGNORE */
-#define ES_TSD_IGNORE_SHIFT                       5  /* TSD_IGNORE */
-#define ES_TSD_IGNORE_WIDTH                       1  /* TSD_IGNORE */
-#define ES_LVLO_IGNORE_MASK                    0x40  /* LVLO_IGNORE */
-#define ES_LVLO_IGNORE_SHIFT              6  /* LVLO_IGNORE */
-#define ES_LVLO_IGNORE_WIDTH              1  /* LVLO_IGNORE */
-#define ES_SD_RING_CLK_MASK                    0x80  /* SD_RING_CLK */
-#define ES_SD_RING_CLK_SHIFT              7  /* SD_RING_CLK */
-#define ES_SD_RING_CLK_WIDTH              1  /* SD_RING_CLK */
-
-
-/*
- * R2 (0x02) - Microphone Bias Control Register
- * Mode 0 => Pulldown
- * Mode 1 => Enable
- * Mode 2 => Hi-Z
- * Mode 3 => Bypass to 1.8V
- */
-
-#define ES_MBIAS0_MODE_MASK                    0x03  /* MBIAS0_MODE */
-#define ES_MBIAS0_MODE_SHIFT                      0  /* MBIAS0_MODE */
-#define ES_MBIAS0_MODE_WIDTH                      2  /* MBIAS0_MODE */
-#define ES_MBIAS1_MODE_MASK                    0x0C  /* MBIAS1_MODE */
-#define ES_MBIAS1_MODE_SHIFT                      2  /* MBIAS1_MODE */
-#define ES_MBIAS1_MODE_WIDTH                      2  /* MBIAS1_MODE */
-#define ES_MBIAS2_MODE_MASK                    0x30  /* MBIAS2_MODE */
-#define ES_MBIAS2_MODE_SHIFT                      4  /* MBIAS2_MODE */
-#define ES_MBIAS2_MODE_WIDTH                      2  /* MBIAS2_MODE */
-#define ES_MBIASHS_MODE_MASK                   0xC0  /* MBIASHS_MODE */
-#define ES_MBIASHS_MODE_SHIFT                     6  /* MBIASHS_MODE */
-#define ES_MBIASHS_MODE_WIDTH                     2  /* MBIASHS_MODE */
-
-
-/*
- * R3 (0x03) - MIC0 CTRL Register
- */
-
-#define ES_MIC0_ON_MASK                                0x01  /* MIC0_ON */
-#define ES_MIC0_ON_SHIFT                          0  /* MIC0_ON */
-#define ES_MIC0_ON_WIDTH                          1  /* MIC0_ON */
-#define ES_MIC0_GAIN_MASK                      0x3E  /* MIC0_GAIN */
-#define ES_MIC0_GAIN_SHIFT                        1  /* MIC0_GAIN */
-#define ES_MIC0_GAIN_WIDTH                        5  /* MIC0_GAIN */
-#define ES_MIC0_GAIN_MAX                       0x14  /* MIC0_GAIN */
-#define ES_MIC0_SE_MASK                                0x40  /* MIC0_SE */
-#define ES_MIC0_SE_SHIFT                          6  /* MIC0_SE */
-#define ES_MIC0_SE_WIDTH                          1  /* MIC0_SE */
-
-
-/*
- * R4 (0x04) - MIC Tune
- * Mode 0 => 100 kOhm input impedance
- * Mode 1 => 50 kOhm input impedance
- * Mode 2 => 25 kOhm input impedance
- * Mode 3 => Attenuate input by 3dB
- */
-
-#define ES_MIC0_ZIN_MODE_MASK                  0x03  /* MIC0_ZIN_MODE */
-#define ES_MIC0_ZIN_MODE_SHIFT                    0  /* MIC0_ZIN_MODE */
-#define ES_MIC0_ZIN_MODE_WIDTH                    2  /* MIC0_ZIN_MODE */
-#define ES_MIC1_ZIN_MODE_MASK                  0x0C  /* MIC1_ZIN_MODE */
-#define ES_MIC1_ZIN_MODE_SHIFT                    2  /* MIC1_ZIN_MODE */
-#define ES_MIC1_ZIN_MODE_WIDTH                    2  /* MIC1_ZIN_MODE */
-#define ES_MIC2_ZIN_MODE_MASK                  0x30  /* MIC2_ZIN_MODE */
-#define ES_MIC2_ZIN_MODE_SHIFT                    4  /* MIC2_ZIN_MODE */
-#define ES_MIC2_ZIN_MODE_WIDTH                    2  /* MIC2_ZIN_MODE */
-#define ES_MICHS_ZIN_MODE_MASK                 0xC0  /* MICHS_ZIN_MODE */
-#define ES_MICHS_ZIN_MODE_SHIFT                           6  /* MICHS_ZIN_MODE */
-#define ES_MICHS_ZIN_MODE_WIDTH                           2  /* MICHS_ZIN_MODE */
-
-
-/*
- * R5 (0x05) - MIC1 CTRL Register
- */
-
-#define ES_MIC1_ON_MASK                                0x01  /* MIC1_ON */
-#define ES_MIC1_ON_SHIFT                          0  /* MIC1_ON */
-#define ES_MIC1_ON_WIDTH                          1  /* MIC1_ON */
-#define ES_MIC1_GAIN_MASK                      0x3E  /* MIC1_GAIN */
-#define ES_MIC1_GAIN_SHIFT                        1  /* MIC1_GAIN */
-#define ES_MIC1_GAIN_WIDTH                        5  /* MIC1_GAIN */
-#define ES_MIC1_GAIN_MAX                       0x14  /* MIC1_GAIN */
-#define ES_MIC1_SE_MASK                                0x40  /* MIC1_SE */
-#define ES_MIC1_SE_SHIFT                          6  /* MIC1_SE */
-#define ES_MIC1_SE_WIDTH                          1  /* MIC1_SE */
-
-
-/*
- * R6 (0x06) - REC TRIM Register
- *
- * Zin Mode 0 => 100 kOhm input impedance
- * Zin Mode 1 => 50 kOhm input impedance
- * Zin Mode 2 => 25 kOhm input impedance
- * Zin Mode 3 => Attenuate input by 3dB
- *
- *  BIAS TRIM 0 => 2.5 uA
- *  BIAS TRIM 1 => 5.0 uA
- *  BIAS TRIM 2 => 0.63 uA
- *  BIAS TRIM 3 => 0.31 uA
- */
-
-#define ES_AUX_ZIN_MODE_MASK           0x03  /* AUX_ZIN_MODE */
-#define ES_AUX_ZIN_MODE_SHIFT             0  /* AUX_ZIN_MODE */
-#define ES_AUX_ZIN_MODE_WIDTH             2  /* AUX_ZIN_MODE */
-#define ES_REC_MUTE_MASK                       0x04  /* REC_MUTE */
-#define ES_REC_MUTE_SHIFT                         2  /* REC_MUTE */
-#define ES_REC_MUTE_WIDTH                         1  /* REC_MUTE */
-#define ES_TRIMDISABLE_MASK                    0x08  /* TRIMDISABLE */
-#define ES_TRIMDISABLE_SHIFT              3  /* TRIMDISABLE */
-#define ES_TRIMDISABLE_WIDTH              1  /* TRIMDISABLE */
-#define ES_FORCE_VCMBUF_MASK           0x10  /* FORCE_VCMBUF */
-#define ES_FORCE_VCMBUF_SHIFT             4  /* FORCE_VCMBUF */
-#define ES_FORCE_VCMBUF_WIDTH             1  /* FORCE_VCMBUF */
-#define ES_HI_PERF_MASK                                0x20  /* HI_PERF */
-#define ES_HI_PERF_SHIFT                          5  /* HI_PERF */
-#define ES_HI_PERF_WIDTH                          1  /* HI_PERF */
-#define ES_I_BIAS_TRIM_MASK                    0xC0  /* I_BIAS_TRIM */
-#define ES_I_BIAS_TRIM_SHIFT              6  /* I_BIAS_TRIM */
-#define ES_I_BIAS_TRIM_WIDTH              2  /* I_BIAS_TRIM */
-
-
-/*
- * R7 (0x07) - AUXL CTRL Register
- */
-
-#define ES_AUXL_ON_MASK                                0x01  /* AUXL_ON */
-#define ES_AUXL_ON_SHIFT                          0  /* AUXL_ON */
-#define ES_AUXL_ON_WIDTH                          1  /* AUXL_ON */
-#define ES_AUXL_GAIN_MASK                      0x3E  /* AUXL_GAIN */
-#define ES_AUXL_GAIN_SHIFT                        1  /* AUXL_GAIN */
-#define ES_AUXL_GAIN_WIDTH                        5  /* AUXL_GAIN */
-#define ES_AUXL_GAIN_MAX                       0x14  /* AUXL_GAIN */
-#define ES_AUX_STEREO_MASK                     0x40  /* AUX_STEREO */
-#define ES_AUX_STEREO_SHIFT                       6  /* AUX_STEREO */
-#define ES_AUX_STEREO_WIDTH                       1  /* AUX_STEREO */
-#define ES_AUX_SWAP_L_R_MASK           0x80  /* AUX_SWAP_L_R */
-#define ES_AUX_SWAP_L_R_SHIFT             7  /* AUX_SWAP_L_R */
-#define ES_AUX_SWAP_L_R_WIDTH             1  /* AUX_SWAP_L_R */
-
-
-/*
- * R8 (0x08) - MIC2 CTRL Register
- */
-
-#define ES_MIC2_ON_MASK                                0x01  /* MIC2_ON */
-#define ES_MIC2_ON_SHIFT                          0  /* MIC2_ON */
-#define ES_MIC2_ON_WIDTH                          1  /* MIC2_ON */
-#define ES_MIC2_GAIN_MASK                      0x3E  /* MIC2_GAIN */
-#define ES_MIC2_GAIN_SHIFT                        1  /* MIC2_GAIN */
-#define ES_MIC2_GAIN_WIDTH                        5  /* MIC2_GAIN */
-#define ES_MIC2_GAIN_MAX                       0x14  /* MIC2_GAIN */
-#define ES_MIC2_SE_MASK                                0x40  /* MIC2_SE */
-#define ES_MIC2_SE_SHIFT                          6  /* MIC2_SE */
-#define ES_MIC2_SE_WIDTH                          1  /* MIC2_SE */
-
-
-/*
- * R9 (0x09) - AUXR CTRL Register
- */
-
-#define ES_AUXR_ON_MASK                                0x01  /* AUXR_ON */
-#define ES_AUXR_ON_SHIFT                          0  /* AUXR_ON */
-#define ES_AUXR_ON_WIDTH                          1  /* AUXR_ON */
-#define ES_AUXR_GAIN_MASK                      0x3E  /* AUXR_GAIN */
-#define ES_AUXR_GAIN_SHIFT                        1  /* AUXR_GAIN */
-#define ES_AUXR_GAIN_WIDTH                        5  /* AUXR_GAIN */
-#define ES_AUXR_GAIN_MAX                       0x14  /* AUXR_GAIN */
-#define ES_AUXR_SE_MASK                                0x40  /* AUXR_SE */
-#define ES_AUXR_SE_SHIFT                          6  /* AUXR_SE */
-#define ES_AUXR_SE_WIDTH                          1  /* AUXR_SE */
-
-
-/*
- * R10 (0x0A) - ADC CTRL Register
- */
-
-#define ES_ADC0_ON_MASK                                0x01  /* ADC0_ON */
-#define ES_ADC0_ON_SHIFT                            0  /* ADC0_ON */
-#define ES_ADC0_ON_WIDTH                            1  /* ADC0_ON */
-#define ES_ADC1_ON_MASK                                0x02  /* ADC1_ON */
-#define ES_ADC1_ON_SHIFT                            1  /* ADC1_ON */
-#define ES_ADC1_ON_WIDTH                            1  /* ADC1_ON */
-#define ES_ADC2_ON_MASK                                0x04  /* ADC2_ON */
-#define ES_ADC2_ON_SHIFT                            2  /* ADC2_ON */
-#define ES_ADC2_ON_WIDTH                            1  /* ADC2_ON */
-#define ES_ADC3_ON_MASK                                0x08  /* ADC3_ON */
-#define ES_ADC3_ON_SHIFT                            3  /* ADC3_ON */
-#define ES_ADC3_ON_WIDTH                            1  /* ADC3_ON */
-#define ES_ADC1_IN_SEL_MASK                    0x10  /* ADC1_IN_SEL */
-#define ES_ADC1_IN_SEL_SHIFT                        4  /* ADC1_IN_SEL */
-#define ES_ADC1_IN_SEL_WIDTH                        1  /* ADC1_IN_SEL */
-#define ES_ADC2_IN_SEL_MASK                    0x20  /* ADC2_IN_SEL */
-#define ES_ADC2_IN_SEL_SHIFT                        5  /* ADC2_IN_SEL */
-#define ES_ADC2_IN_SEL_WIDTH                        1  /* ADC2_IN_SEL */
-#define ES_ADC_MUTE_MASK                       0x40  /* ADC_MUTE */
-#define ES_ADC_MUTE_SHIFT                           6  /* ADC_MUTE */
-#define ES_ADC_MUTE_WIDTH                           1  /* ADC_MUTE */
-#define ES_ADC_GAIN_H_MASK                     0x80  /* ADC_GAIN_H */
-#define ES_ADC_GAIN_H_SHIFT                         7  /* ADC_GAIN_H */
-#define ES_ADC_GAIN_H_WIDTH                         1  /* ADC_GAIN_H */
-
-
-/*
- * R11 (0x0B) - DAC CTRL Register
- */
-
-#define ES_DAC0L_ON                            0x01  /* DAC0L_ON */
-#define ES_DAC0L_ON_MASK                       0x01  /* DAC0L_ON */
-#define ES_DAC0L_ON_SHIFT                           0  /* DAC0L_ON */
-#define ES_DAC0L_ON_WIDTH                           1  /* DAC0L_ON */
-#define ES_DAC0R_ON                            0x02  /* DAC0R_ON */
-#define ES_DAC0R_ON_MASK                       0x02  /* DAC0R_ON */
-#define ES_DAC0R_ON_SHIFT                           1  /* DAC0R_ON */
-#define ES_DAC0R_ON_WIDTH                           1  /* DAC0R_ON */
-#define ES_DAC1L_ON                            0x04  /* DAC1L_ON */
-#define ES_DAC1L_ON_MASK                       0x04  /* DAC1L_ON */
-#define ES_DAC1L_ON_SHIFT                           2  /* DAC1L_ON */
-#define ES_DAC1L_ON_WIDTH                           1  /* DAC1L_ON */
-#define ES_DAC1R_ON                            0x08  /* DAC1R_ON */
-#define ES_DAC1R_ON_MASK                       0x08  /* DAC1R_ON */
-#define ES_DAC1R_ON_SHIFT                           3  /* DAC1R_ON */
-#define ES_DAC1R_ON_WIDTH                           1  /* DAC1R_ON */
-#define ES_SQUELCH_DIS_MASK                    0x40  /* SQUELCH_DIS */
-#define ES_SQUELCH_DIS_SHIFT                        6  /* SQUELCH_DIS */
-#define ES_SQUELCH_DIS_WIDTH                        1  /* SQUELCH_DIS */
-#define ES_DAC_TRIM_DIS_MASK                   0x80  /* DAC_TRIM_DIS */
-#define ES_DAC_TRIM_DIS_SHIFT                       7  /* DAC_TRIM_DIS */
-#define ES_DAC_TRIM_DIS_WIDTH                       1  /* DAC_TRIM_DIS */
-
-
-/*
- * R13 (0x0D) - MICHS CTRL Register
- */
-
-#define ES_MICHS_ON_MASK                               0x01  /* MICHS_ON */
-#define ES_MICHS_ON_SHIFT                         0  /* MICHS_ON */
-#define ES_MICHS_ON_WIDTH                         1  /* MICHS_ON */
-#define ES_MICHS_GAIN_MASK                     0x3E  /* MICHS_GAIN */
-#define ES_MICHS_GAIN_SHIFT                       1  /* MICHS_GAIN */
-#define ES_MICHS_GAIN_WIDTH                       5  /* MICHS_GAIN */
-#define ES_MICHS_GAIN_MAX                      0x14  /* MICHS_GAIN */
-#define ES_MICHS_SE_MASK                               0x40  /* MICHS_SE */
-#define ES_MICHS_SE_SHIFT                         6  /* MICHS_SE */
-#define ES_MICHS_SE_WIDTH                         1  /* MICHS_SE */
-#define ES_MICHS_IN_SEL_MASK                           0x80  /* MICHS_IN_SEL */
-#define ES_MICHS_IN_SEL_SHIFT                     7  /* MICHS_IN_SEL */
-#define ES_MICHS_IN_SEL_WIDTH                     1  /* MICHS_IN_SEL */
-
-
-/*
- * R15 (0x0F) - Earphone Gain Register
- */
-
-#define ES_EP_GAIN_MASK                                0x0F  /* EP_GAIN */
-#define ES_EP_GAIN_SHIFT                            0  /* EP_GAIN */
-#define ES_EP_GAIN_WIDTH                            4  /* EP_GAIN */
-#define ES_EP_GAIN_MAX                         0x0F  /* EP_GAIN */
-#define ES_EP_MUTE                             0x80  /* EP_MUTE */
-#define ES_EP_MUTE_MASK                                0x80  /* EP_MUTE */
-#define ES_EP_MUTE_SHIFT                            7  /* EP_MUTE */
-#define ES_EP_MUTE_WIDTH                            1  /* EP_MUTE */
-
-
-/*
- * R16 (0x10) - Earphone Ctrl Register
- */
-
-#define ES_EP_ON                               0x01  /* EP_ON */
-#define ES_EP_ON_MASK                          0x01  /* EP_ON */
-#define ES_EP_ON_SHIFT                              0  /* EP_ON */
-#define ES_EP_ON_WIDTH                              1  /* EP_ON */
-#define ES_DAC0L_TO_EP                         0x02  /* DAC0L_TO_EP */
-#define ES_DAC0L_TO_EP_MASK                    0x02  /* DAC0L_TO_EP */
-#define ES_DAC0L_TO_EP_SHIFT                        1  /* DAC0L_TO_EP */
-#define ES_DAC0L_TO_EP_WIDTH                        1  /* DAC0L_TO_EP */
-#define ES_AUXL_TO_EP                          0x04  /* AUXL_TO_EP */
-#define ES_AUXL_TO_EP_MASK                     0x04  /* AUXL_TO_EP */
-#define ES_AUXL_TO_EP_SHIFT                         2  /* AUXL_TO_EP */
-#define ES_AUXL_TO_EP_WIDTH                         1  /* AUXL_TO_EP */
-#define ES_EP_M_PD_MASK                                0x10  /* EP_M_PD */
-#define ES_EP_M_PD_SHIFT                                    4  /* EP_M_PD */
-#define ES_EP_M_PD_WIDTH                                    1  /* EP_M_PD */
-#define ES_EP_P_PD_MASK                                0x20  /* EP_P_PD */
-#define ES_EP_P_PD_SHIFT                                    5  /* EP_P_PD */
-#define ES_EP_P_PD_WIDTH                                    1  /* EP_P_PD */
-#define ES_EP_BIAS_CUR_MASK                    0xC0  /* EP_BIAS_CUR */
-#define ES_EP_BIAS_CUR_SHIFT                        6  /* EP_BIAS_CUR */
-#define ES_EP_BIAS_CUR_WIDTH                        2  /* EP_BIAS_CUR */
-
-
-/*
- * R17 (0x11) - Headphone Left Gain Register
- */
-
-#define ES_HPL_GAIN_MASK                       0x0F  /* HPL_GAIN */
-#define ES_HPL_GAIN_SHIFT                         0  /* HPL_GAIN */
-#define ES_HPL_GAIN_WIDTH                         4  /* HPL_GAIN */
-#define ES_HPL_GAIN_MAX                                0x0F  /* HPL_GAIN */
-#define ES_HPL_PD_MASK                         0x10  /* HPL_PD */
-#define ES_HPL_PD_SHIFT                                   4  /* HPL_PD */
-#define ES_HPL_PD_WIDTH                                   1  /* HPL_PD */
-#define ES_HPL_BIAS_CUR_MASK           0x60  /* HPL_BIAS_CUR */
-#define ES_HPL_BIAS_CUR_SHIFT             5  /* HPL_BIAS_CUR */
-#define ES_HPL_BIAS_CUR_WIDTH             2  /* HPL_BIAS_CUR */
-#define ES_HPL_MUTE                            0x80  /* HPL_MUTE */
-#define ES_HPL_MUTE_MASK                       0x80  /* HPL_MUTE */
-#define ES_HPL_MUTE_SHIFT                           7  /* HPL_MUTE */
-#define ES_HPL_MUTE_WIDTH                           1  /* HPL_MUTE */
-
-
-/*
- * R18 (0x12) - Headphone Left Ctrl Register
- */
-
-#define ES_HPL_ON                              0x01  /* HPL_ON */
-#define ES_HPL_ON_MASK                         0x01  /* HPL_ON */
-#define ES_HPL_ON_SHIFT                                     0  /* HPL_ON */
-#define ES_HPL_ON_WIDTH                                     1  /* HPL_ON */
-#define ES_DAC0L_TO_HPL                                0x02  /* DAC0L_TO_HPL */
-#define ES_DAC0L_TO_HPL_MASK                   0x02  /* DAC0L_TO_HPL */
-#define ES_DAC0L_TO_HPL_SHIFT                       1  /* DAC0L_TO_HPL */
-#define ES_DAC0L_TO_HPL_WIDTH                       1  /* DAC0L_TO_HPL */
-#define ES_AUXL_TO_HPL                         0x04  /* AUXL_TO_HPL */
-#define ES_AUXL_TO_HPL_MASK                    0x04  /* AUXL_TO_HPL */
-#define ES_AUXL_TO_HPL_SHIFT                        3  /* AUXL_TO_HPL */
-#define ES_AUXL_TO_HPL_WIDTH                        1  /* AUXL_TO_HPL */
-
-
-/*
- * R19 (0x13) - Headphone Right Gain Register
- */
-
-#define ES_HPR_GAIN_MASK                       0x0F  /* HPR_GAIN */
-#define ES_HPR_GAIN_SHIFT                           0  /* HPR_GAIN */
-#define ES_HPR_GAIN_WIDTH                           4  /* HPR_GAIN */
-#define ES_HPR_GAIN_MAX                                0x0F  /* HPR_GAIN */
-#define ES_HPR_PD_MASK                         0x10  /* HPR_PD */
-#define ES_HPR_PD_SHIFT                                     4  /* HPR_PD */
-#define ES_HPR_PD_WIDTH                                     1  /* HPR_PD */
-#define ES_HPR_BIAS_CUR_MASK                   0x60  /* HPR_BIAS_CUR */
-#define ES_HPR_BIAS_CUR_SHIFT                       5  /* HPR_BIAS_CUR */
-#define ES_HPR_BIAS_CUR_WIDTH                       2  /* HPR_BIAS_CUR */
-#define ES_HPR_MUTE                            0x80  /* HPR_MUTE */
-#define ES_HPR_MUTE_MASK                       0x80  /* HPR_MUTE */
-#define ES_HPR_MUTE_SHIFT                           7  /* HPR_MUTE */
-#define ES_HPR_MUTE_WIDTH                           1  /* HPR_MUTE */
-
-
-/*
- * R20 (0x14) - Headphone Right Ctrl Register
- */
-
-#define ES_HPR_ON                              0x01  /* HPR_ON */
-#define ES_HPR_ON_MASK                         0x01  /* HPR_ON */
-#define ES_HPR_ON_SHIFT                                     0  /* HPR_ON */
-#define ES_HPR_ON_WIDTH                                     1  /* HPR_ON */
-#define ES_DAC0R_TO_HPR                                0x02  /* DAC0R_TO_HPR */
-#define ES_DAC0R_TO_HPR_MASK                   0x02  /* DAC0R_TO_HPR */
-#define ES_DAC0R_TO_HPR_SHIFT                       1  /* DAC0R_TO_HPR */
-#define ES_DAC0R_TO_HPR_WIDTH                       1  /* DAC0R_TO_HPR */
-#define ES_AUXR_TO_HPR                         0x04  /* AUXR_TO_HPR */
-#define ES_AUXR_TO_HPR_MASK                    0x04  /* AUXR_TO_HPR */
-#define ES_AUXR_TO_HPR_SHIFT                        3  /* AUXR_TO_HPR */
-#define ES_AUXR_TO_HPR_WIDTH                        1  /* AUXR_TO_HPR */
-
-
-
-/*
- * R21 (0x15) - Speaker Left Gain Register
- */
-
-#define ES_SPKRL_GAIN_MASK                     0x1F  /* SPKRL_GAIN */
-#define ES_SPKRL_GAIN_SHIFT                         0  /* SPKRL_GAIN */
-#define ES_SPKRL_GAIN_WIDTH                         5  /* SPKRL_GAIN */
-#define ES_SPKRL_GAIN_MAX                              0x1F  /* SPKRL_GAIN */
-#define ES_MONO_EN_MASK                                0x40  /* MONO_EN */
-#define ES_MONO_EN_SHIFT                            6  /* MONO_EN */
-#define ES_MONO_EN_WIDTH                            1  /* MONO_EN */
-#define ES_SPKRL_MUTE                          0x80  /* SPKRL_MUTE */
-#define ES_SPKRL_MUTE_MASK                     0x80  /* SPKRL_MUTE */
-#define ES_SPKRL_MUTE_SHIFT                         7  /* SPKRL_MUTE */
-#define ES_SPKRL_MUTE_WIDTH                         1  /* SPKRL_MUTE */
-
-
-/*
- * R22 (0x16) - Speaker Left Ctrl Register
- */
-
-#define ES_SPKRL_ON                            0x01  /* SPKRL_ON */
-#define ES_SPKRL_ON_MASK                               0x01  /* SPKRL_ON */
-#define ES_SPKRL_ON_SHIFT                                   0  /* SPKRL_ON */
-#define ES_SPKRL_ON_WIDTH                                   1  /* SPKRL_ON */
-#define ES_DAC0L_TO_SPKRL                      0x02  /* DAC0L_TO_SPKRL */
-#define ES_DAC0L_TO_SPKRL_MASK         0x02  /* DAC0L_TO_SPKRL */
-#define ES_DAC0L_TO_SPKRL_SHIFT                     1  /* DAC0L_TO_SPKRL */
-#define ES_DAC0L_TO_SPKRL_WIDTH                     1  /* DAC0L_TO_SPKRL */
-#define ES_DAC1L_TO_SPKRL                      0x04  /* DAC1L_TO_SPKRL */
-#define ES_DAC1L_TO_SPKRL_MASK         0x04  /* DAC1L_TO_SPKRL */
-#define ES_DAC1L_TO_SPKRL_SHIFT                     2  /* DAC1L_TO_SPKRL */
-#define ES_DAC1L_TO_SPKRL_WIDTH                     1  /* DAC1L_TO_SPKRL */
-#define ES_AUXL_TO_SPKRL                       0x08  /* AUXL_TO_SPKRL */
-#define ES_AUXL_TO_SPKRL_MASK          0x08  /* AUXL_TO_SPKRL */
-#define ES_AUXL_TO_SPKRL_SHIFT              3  /* AUXL_TO_SPKRL */
-#define ES_AUXL_TO_SPKRL_WIDTH              1  /* AUXL_TO_SPKRL */
-
-
-/*
- * R23 (0x17) - Speaker Right Gain Register
- */
-
-#define ES_SPKRR_GAIN_MASK                     0x1F  /* SPKRR_GAIN */
-#define ES_SPKRR_GAIN_SHIFT                         0  /* SPKRR_GAIN */
-#define ES_SPKRR_GAIN_WIDTH                         5  /* SPKRR_GAIN */
-#define ES_SPKRR_GAIN_MAX                              0x1F  /* SPKRR_GAIN */
-#define ES_SPKRR_MUTE                          0x80  /* SPKRR_MUTE */
-#define ES_SPKRR_MUTE_MASK                     0x80  /* SPKRR_MUTE */
-#define ES_SPKRR_MUTE_SHIFT                         7  /* SPKRR_MUTE */
-#define ES_SPKRR_MUTE_WIDTH                         1  /* SPKRR_MUTE */
-
-
-/*
- * R24 (0x18) - Speaker Right Ctrl Register
- */
-
-#define ES_SPKRR_ON                            0x01  /* SPKRR_ON */
-#define ES_SPKRR_ON_MASK                       0x01  /* SPKRR_ON */
-#define ES_SPKRR_ON_SHIFT                           0  /* SPKRR_ON */
-#define ES_SPKRR_ON_WIDTH                           1  /* SPKRR_ON */
-#define ES_DAC0R_TO_SPKRR                      0x02  /* DAC0R_TO_SPKRR */
-#define ES_DAC0R_TO_SPKRR_MASK         0x02  /* DAC0R_TO_SPKRR */
-#define ES_DAC0R_TO_SPKRR_SHIFT                     1  /* DAC0R_TO_SPKRR */
-#define ES_DAC0R_TO_SPKRR_WIDTH                     1  /* DAC0R_TO_SPKRR */
-#define ES_DAC1R_TO_SPKRR                      0x04  /* DAC1R_TO_SPKRR */
-#define ES_DAC1R_TO_SPKRR_MASK         0x04  /* DAC1R_TO_SPKRR */
-#define ES_DAC1R_TO_SPKRR_SHIFT                     2  /* DAC1R_TO_SPKRR */
-#define ES_DAC1R_TO_SPKRR_WIDTH                     1  /* DAC1R_TO_SPKRR */
-#define ES_AUXR_TO_SPKRR                       0x08  /* AUXR_TO_SPKRR */
-#define ES_AUXR_TO_SPKRR_MASK          0x08  /* AUXR_TO_SPKRR */
-#define ES_AUXR_TO_SPKRR_SHIFT              3  /* AUXR_TO_SPKRR */
-#define ES_AUXR_TO_SPKRR_WIDTH              1  /* AUXR_TO_SPKRR */
-
-
-/*
- * R25 (0x19) - Line Output Left Gain Register
- */
-
-#define ES_LO_L_GAIN_MASK                      0x0F  /* LO_L_GAIN */
-#define ES_LO_L_GAIN_SHIFT                          0  /* LO_L_GAIN */
-#define ES_LO_L_GAIN_WIDTH                          4  /* LO_L_GAIN */
-#define ES_LO_L_GAIN_MAX                       0x0F  /* LO_L_GAIN */
-#define ES_LO_L_MUTE                           0x80  /* LO_L_MUTE */
-#define ES_LO_L_MUTE_MASK                      0x80  /* LO_L_MUTE */
-#define ES_LO_L_MUTE_SHIFT                          7  /* LO_L_MUTE */
-#define ES_LO_L_MUTE_WIDTH                          1  /* LO_L_MUTE */
-
-/*
- * R26 (0x1A) - Line Output Left Ctrl Register
- */
-
-#define ES_LO_L_ON                             0x01  /* LO_L_ON */
-#define ES_LO_L_ON_MASK                                0x01  /* LO_L_ON */
-#define ES_LO_L_ON_SHIFT                            0  /* LO_L_ON */
-#define ES_LO_L_ON_WIDTH                            1  /* LO_L_ON */
-#define ES_DAC1L_TO_LO_L                       0x02  /* DAC1L_TO_LO_L */
-#define ES_DAC1L_TO_LO_L_MASK                  0x02  /* DAC1L_TO_LO_L */
-#define ES_DAC1L_TO_LO_L_SHIFT                      1  /* DAC1L_TO_LO_L */
-#define ES_DAC1L_TO_LO_L_WIDTH                      1  /* DAC1L_TO_LO_L */
-#define ES_LO_L_STARTUP_PULLDN_MASK            0x20  /* LO_L_STARTUP_PULLDN */
-#define ES_LO_L_STARTUP_PULLDN_SHIFT           5  /* LO_L_STARTUP_PULLDN */
-#define ES_LO_L_STARTUP_PULLDN_WIDTH           1  /* LO_L_STARTUP_PULLDN */
-#define ES_LO_TRIM_DIS                         0x80  /* LO_TRIM_DIS */
-#define ES_LO_TRIM_DIS_MASK                    0x80  /* LO_TRIM_DIS */
-#define ES_LO_TRIM_DIS_SHIFT                        7  /* LO_TRIM_DIS */
-#define ES_LO_TRIM_DIS_WIDTH                        1  /* LO_TRIM_DIS */
-
-
-/*
- * R27 (0x1B) - Line Output Right Gain Register
- */
-
-#define ES_LO_R_GAIN_MASK                      0x0F  /* LO_R_GAIN */
-#define ES_LO_R_GAIN_SHIFT                          0  /* LO_R_GAIN */
-#define ES_LO_R_GAIN_WIDTH                          4  /* LO_R_GAIN */
-#define ES_LO_R_GAIN_MAX                       0x0F  /* LO_R_GAIN */
-#define ES_LO_R_MUTE                           0x80  /* LO_R_MUTE */
-#define ES_LO_R_MUTE_MASK                      0x80  /* LO_R_MUTE */
-#define ES_LO_R_MUTE_SHIFT                          7  /* LO_R_MUTE */
-#define ES_LO_R_MUTE_WIDTH                          1  /* LO_R_MUTE */
-
-
-/*
- * R24 (0x1C) - Line Output Right Ctrl Register
- */
-
-#define ES_LO_R_ON                             0x01  /* LO_R_ON */
-#define ES_LO_R_ON_MASK                                0x01  /* LO_R_ON */
-#define ES_LO_R_ON_SHIFT                            0  /* LO_R_ON */
-#define ES_LO_R_ON_WIDTH                            1  /* LO_R_ON */
-#define ES_DAC1R_TO_LO_R                       0x02  /* DAC1R_TO_LO_R */
-#define ES_DAC1R_TO_LO_R_MASK                  0x02  /* DAC1R_TO_LO_R */
-#define ES_DAC1R_TO_LO_R_SHIFT                      1  /* DAC1R_TO_LO_R */
-#define ES_DAC1R_TO_LO_R_WIDTH                      1  /* DAC1R_TO_LO_R */
-
-/*
- * R33 (0x21) - INT1 STATE
- */
-
-#define ES_THM_SDN_INT_MASK                    0x01  /* THM_SDN_INT */
-#define ES_THM_SDN_INT_SHIFT              0  /* THM_SDN_INT */
-#define ES_THM_SDN_INT_WIDTH              1  /* THM_SDN_INT */
-#define ES_LINEOUT_SC_INT_MASK         0x02  /* LINEOUT_SC_INT */
-#define ES_LINEOUT_SC_INT_SHIFT                   1  /* LINEOUT_SC_INT */
-#define ES_LINEOUT_SC_INT_WIDTH                   1  /* LINEOUT_SC_INT */
-#define ES_SPKR_L_SC_INT_MASK          0x04  /* SPKR_L_SC_INT */
-#define ES_SPKR_L_SC_INT_SHIFT            2  /* SPKR_L_SC_INT */
-#define ES_SPKR_L_SC_INT_WIDTH            1  /* SPKR_L_SC_INT */
-#define ES_SPKR_R_SC_INT_MASK          0x08  /* SPKR_R_SC_INT */
-#define ES_SPKR_R_SC_INT_SHIFT            3  /* SPKR_R_SC_INT */
-#define ES_SPKR_R_SC_INT_WIDTH            1  /* SPKR_R_SC_INT */
-#define ES_HP_SC_INT_MASK                      0x10  /* HP_SC_INT */
-#define ES_HP_SC_INT_SHIFT                4  /* HP_SC_INT */
-#define ES_HP_SC_INT_WIDTH                1  /* HP_SC_INT */
-#define ES_EP_SC_INT_MASK                      0x20  /* EP_SC_INT */
-#define ES_EP_SC_INT_SHIFT                5  /* EP_SC_INT */
-#define ES_EP_SC_INT_WIDTH                1  /* EP_SC_INT */
-
-
-/*
- * R34 (0x22) - INT1 MASK
- */
-
-#define ES_THM_SDN_MASK_MASK                   0x01  /* THM_SDN_MASK */
-#define ES_THM_SDN_MASK_SHIFT             0  /* THM_SDN_MASK */
-#define ES_THM_SDN_MASK_WIDTH             1  /* THM_SDN_MASK */
-#define ES_LINEOUT_SC_MASK_MASK                0x02  /* LINEOUT_SC_MASK */
-#define ES_LINEOUT_SC_MASK_SHIFT                  1  /* LINEOUT_SC_MASK */
-#define ES_LINEOUT_SC_MASK_WIDTH                  1  /* LINEOUT_SC_MASK */
-#define ES_SPKR_L_SC_MASK_MASK         0x04  /* SPKR_L_SC_MASK */
-#define ES_SPKR_L_SC_MASK_SHIFT                   2  /* SPKR_L_SC_MASK */
-#define ES_SPKR_L_SC_MASK_WIDTH                   1  /* SPKR_L_SC_MASK */
-#define ES_SPKR_R_SC_MASK_MASK         0x08  /* SPKR_R_SC_MASK */
-#define ES_SPKR_R_SC_MASK_SHIFT                   3  /* SPKR_R_SC_MASK */
-#define ES_SPKR_R_SC_MASK_WIDTH                   1  /* SPKR_R_SC_MASK */
-#define ES_HP_SC_MASK_MASK                     0x10  /* HP_SC_MASK */
-#define ES_HP_SC_MASK_SHIFT               4  /* HP_SC_MASK */
-#define ES_HP_SC_MASK_WIDTH               1  /* HP_SC_MASK */
-#define ES_EP_SC_MASK_MASK                     0x20  /* EP_SC_MASK */
-#define ES_EP_SC_MASK_SHIFT               5  /* EP_SC_MASK */
-#define ES_EP_SC_MASK_WIDTH               1  /* EP_SC_MASK */
-
-/*
- * R48 (0x30) - SPKR ALC1
- */
-
-#define BYPASS_ALC_MASK        0x80 /* BYPASS_ALC_MASK */
-#define BYPASS_ALC_SHIFT       7    /* BYPASS_ALC_SHIFT */
-#define BYPASS_ALC_WIDTH       1    /* BYPASS_ALC_WIDTH */
-
-/*
- * R52 (0x34) - MB TRIM1
- */
-
-#define ES_LD02_TRIM_MASK              0x3
-#define ES_LD02_TRIM_SHIFT             6
-#define ES_LD02_TRIM_WIDTH             2
-#define ES_MBHS_TRIM_MASK              0x7
-#define ES_MBHS_TRIM_SHIFT             3
-#define ES_MBHS_TRIM_WIDTH             3
-#define ES_MB2_TRIM_MASK               0x7
-#define ES_MB2_TRIM_SHIFT              0
-#define ES_MB2_TRIM_WIDTH              3
-
-/*
- * R53 (0x35) - MB TRIM2
- */
-
-#define ES_LD02_PD_MODE_MASK           0x3
-#define ES_LD02_PD_MODE_SHIFT          6
-#define ES_LD02_PD_MODE_WIDTH          2
-#define ES_MB1_TRIM_MASK               0x7
-#define ES_MB1_TRIM_SHIFT              3
-#define ES_MB1_TRIM_WIDTH              3
-#define ES_MB0_TRIM_MASK               0x7
-#define ES_MB0_TRIM_SHIFT              0
-#define ES_MB0_TRIM_WIDTH              3
-
-/*
- * R60 (0x40) - DAC Digital Enable Register
- */
-
-#define ES_DAC0_LEFT_EN                                0x01  /* DAC0_LEFT_EN */
-#define ES_DAC0_LEFT_EN_MASK                   0x01  /* DAC0_LEFT_EN */
-#define ES_DAC0_LEFT_EN_SHIFT                       0  /* DAC0_LEFT_EN */
-#define ES_DAC0_LEFT_EN_WIDTH                       1  /* DAC0_LEFT_EN */
-#define ES_DAC0_RIGHT_EN                       0x02  /* DAC0_RIGHT_EN */
-#define ES_DAC0_RIGHT_EN_MASK                  0x02  /* DAC0_RIGHT_EN */
-#define ES_DAC0_RIGHT_EN_SHIFT                      1  /* DAC0_RIGHT_EN */
-#define ES_DAC0_RIGHT_EN_WIDTH                      1  /* DAC0_RIGHT_EN */
-#define ES_DAC1_LEFT_EN                                0x04  /* DAC1_LEFT_EN */
-#define ES_DAC1_LEFT_EN_MASK                   0x04  /* DAC1_LEFT_EN */
-#define ES_DAC1_LEFT_EN_SHIFT                       2  /* DAC1_LEFT_EN */
-#define ES_DAC1_LEFT_EN_WIDTH                       1  /* DAC1_LEFT_EN */
-#define ES_DAC1_RIGHT_EN                       0x08  /* DAC1_RIGHT_EN */
-#define ES_DAC1_RIGHT_EN_MASK                  0x08  /* DAC1_RIGHT_EN */
-#define ES_DAC1_RIGHT_EN_SHIFT                      3  /* DAC1_RIGHT_EN */
-#define ES_DAC1_RIGHT_EN_WIDTH                      1  /* DAC1_RIGHT_EN */
-#define ES_DAC_CLK_EN                          0x10  /* DAC_CLK_EN */
-#define ES_DAC_CLK_EN_MASK                     0x10  /* DAC_CLK_EN */
-#define ES_DAC_CLK_EN_SHIFT                         4  /* DAC_CLK_EN */
-#define ES_DAC_CLK_EN_WIDTH                         1  /* DAC_CLK_EN */
-#define ES_DIG_CLK_EN                          0x20  /* DIG_CLK_EN */
-#define ES_DIG_CLK_EN_MASK                     0x20  /* DIG_CLK_EN */
-#define ES_DIG_CLK_EN_SHIFT                         5  /* DIG_CLK_EN */
-#define ES_DIG_CLK_EN_WIDTH                         1  /* DIG_CLK_EN */
-#define ES_I2S_MODE                            0x40  /* 1=master 0=slave */
-#define ES_I2S_MODE_MASK                       0x40  /* I2S_MODE */
-#define ES_I2S_MODE_SHIFT                           6  /* I2S_MODE */
-#define ES_I2S_MODE_WIDTH                           1  /* I2S_MODE */
-#define ES_I2S_LEFT_JUSTIFIED                  0x80  /* 1=Left justified */
-#define ES_I2S_LEFT_JUSTIFIED_MASK             0x80  /* I2S_LEFT_JUSTIFIED */
-#define ES_I2S_LEFT_JUSTIFIED_SHIFT                 7  /* I2S_LEFT_JUSTIFIED */
-#define ES_I2S_LEFT_JUSTIFIED_WIDTH                 1  /* I2S_LEFT_JUSTIFIED */
-
-
-/*
- * R61 (0x41) - DAC Digital Channel Register
- */
-
-#define ES_I2S_CH                              0x01  /* 1=4 chn 0=2 chn */
-#define ES_I2S_CH_MASK                         0x01  /* I2S_CH */
-#define ES_I2S_CH_SHIFT                                     0  /* I2S_CH */
-#define ES_I2S_CH_WIDTH                                     1  /* I2S_CH */
-#define ES_I2S_PIN_EN                          0x02  /* 1=I2s clock 0=mclk */
-#define ES_I2S_PIN_EN_MASK                     0x02  /* I2S_PIN_EN */
-#define ES_I2S_PIN_EN_SHIFT                         1  /* I2S_PIN_EN */
-#define ES_I2S_PIN_EN_WIDTH                         1  /* I2S_PIN_EN */
-#define ES_I2S_CLK_SEL                         0x04  /* 1=mclk/2 0=mclk */
-#define ES_I2S_CLK_SEL_MASK                    0x04  /* I2S_CLK_SEL */
-#define ES_I2S_CLK_SEL_SHIFT                        2  /* I2S_CLK_SEL */
-#define ES_I2S_CLK_SEL_WIDTH                        1  /* I2S_CLK_SEL */
-#define ES_I2S_CLK_SEL_CLKDIV2                 0x08  /* 1=clk/2 0=clk */
-#define ES_I2S_CLK_SEL_CLKDIV2_MASK            0x08  /* I2S_CLK_SEL_CLKDIV2*/
-#define ES_I2S_CLK_SEL_CLKDIV2_SHIFT                3  /* I2S_CLK_SEL_CLKDIV2*/
-#define ES_I2S_CLK_SEL_CLKDIV2_WIDTH                1  /* I2S_CLK_SEL_CLKDIV2*/
-#define ES_CLK_SOURCE                          0x10  /* 1=mclk 0=i2s_clk_in*/
-#define ES_CLK_SOURCE_MASK                     0x10  /* CLK_SOURCE */
-#define ES_CLK_SOURCE_SHIFT                         4  /* CLK_SOURCE */
-#define ES_CLK_SOURCE_WIDTH                         1  /* CLK_SOURCE */
-
-
-/*
- * R63 (0x43) - DAC Digital I2S1 Register
- */
-
-#define ES_BITS_PER_SAMPLE_MASK                        0x1F  /* BITS_PER_SAMPLE */
-#define ES_BITS_PER_SAMPLE_SHIFT                  0  /* BITS_PER_SAMPLE */
-#define ES_BITS_PER_SAMPLE_WIDTH                  5  /* BITS_PER_SAMPLE */
-#define ES_FS_POL_MASK                         0x60  /* FS_POL */
-#define ES_FS_POL_SHIFT                             5  /* FS_POL */
-#define ES_FS_POL_WIDTH                             2  /* FS_POL */
-#define ES_CLK_POL_MASK                                0x80  /* CLK_POL */
-#define ES_CLK_POL_SHIFT                            7  /* CLK_POL */
-#define ES_CLK_POL_WIDTH                            1  /* CLK_POL */
-
-
-/*
- * R65 (0x45) - Frame Sync Selection Register
- */
-
-#define ES_FS_SEL_MASK                 0x03  /* FS_SEL */
-#define ES_FS_SEL_SHIFT                   0  /* FS_SEL */
-#define ES_FS_SEL_WIDTH                   2  /* FS_SEL */
-#define ES_FS_OVERRIDE_MASK            0x04  /* FS_OVERRIDE */
-#define ES_FS_OVERRIDE_SHIFT              2  /* FS_OVERRIDE */
-#define ES_FS_OVERRIDE_WIDTH              1  /* FS_OVERRIDE */
+#define ES_MIC0_GAIN_MAX                     0x14
+#define ES_MIC1_GAIN_MAX                     0x14
+#define ES_MIC2_GAIN_MAX                     0x14
+#define ES_MICHS_GAIN_MAX                    0x14
+#define ES_AUXL_GAIN_MAX                     0x14
+#define ES_AUXR_GAIN_MAX                     0x14
+#define ES_EP_GAIN_MAX                       0x0F
+#define ES_HPL_GAIN_MAX                      0x0F
+#define ES_HPR_GAIN_MAX                      0x0F
+#define ES_SPKR_L_GAIN_MAX                   0x1F
+#define ES_SPKR_R_GAIN_MAX                   0x1F
+#define ES_LO_L_GAIN_MAX                     0x0F
+#define ES_LO_R_GAIN_MAX                     0x0F
+
+#define ES_CHIP_EN                           0x0000
+#define ES_CHIP_EN_MASK                      0x01
+#define ES_CHIP_EN_SHIFT                     0
+#define ES_CHIP_EN_WIDTH                     1
+
+#define ES_STANDBY                           0x0001
+#define ES_STANDBY_MASK                      0x01
+#define ES_STANDBY_SHIFT                     0
+#define ES_STANDBY_WIDTH                     1
+
+#define ES_MBIAS0_MODE                       0x0010
+#define ES_MBIAS0_MODE_MASK                  0x03
+#define ES_MBIAS0_MODE_SHIFT                 0
+#define ES_MBIAS0_MODE_WIDTH                 2
+
+#define ES_MBIAS1_MODE                       0x0011
+#define ES_MBIAS1_MODE_MASK                  0x03
+#define ES_MBIAS1_MODE_SHIFT                 0
+#define ES_MBIAS1_MODE_WIDTH                 2
+
+#define ES_MBIAS2_MODE                       0x0012
+#define ES_MBIAS2_MODE_MASK                  0x03
+#define ES_MBIAS2_MODE_SHIFT                 0
+#define ES_MBIAS2_MODE_WIDTH                 2
+
+#define ES_MIC0_ON                           0x0014
+#define ES_MIC0_ON_MASK                      0x01
+#define ES_MIC0_ON_SHIFT                     0
+#define ES_MIC0_ON_WIDTH                     1
+
+#define ES_MIC0_GAIN                         0x0015
+#define ES_MIC0_GAIN_MASK                    0x1F
+#define ES_MIC0_GAIN_SHIFT                   0
+#define ES_MIC0_GAIN_WIDTH                   5
+
+#define ES_MIC0_ZIN_MODE                     0x0017
+#define ES_MIC0_ZIN_MODE_MASK                0x03
+#define ES_MIC0_ZIN_MODE_SHIFT               0
+#define ES_MIC0_ZIN_MODE_WIDTH               2
+
+#define ES_MIC1_ZIN_MODE                     0x0018
+#define ES_MIC1_ZIN_MODE_MASK                0x03
+#define ES_MIC1_ZIN_MODE_SHIFT               0
+#define ES_MIC1_ZIN_MODE_WIDTH               2
+
+#define ES_MIC2_ZIN_MODE                     0x0019
+#define ES_MIC2_ZIN_MODE_MASK                0x03
+#define ES_MIC2_ZIN_MODE_SHIFT               0
+#define ES_MIC2_ZIN_MODE_WIDTH               2
+
+#define ES_MICHS_ZIN_MODE                    0x001A
+#define ES_MICHS_ZIN_MODE_MASK               0x03
+#define ES_MICHS_ZIN_MODE_SHIFT              0
+#define ES_MICHS_ZIN_MODE_WIDTH              2
+
+#define ES_MIC1_ON                           0x001B
+#define ES_MIC1_ON_MASK                      0x01
+#define ES_MIC1_ON_SHIFT                     0
+#define ES_MIC1_ON_WIDTH                     1
+
+#define ES_MIC1_GAIN                         0x001C
+#define ES_MIC1_GAIN_MASK                    0x1F
+#define ES_MIC1_GAIN_SHIFT                   0
+#define ES_MIC1_GAIN_WIDTH                   5
+
+#define ES_AUX_ZIN_MODE                      0x001E
+#define ES_AUX_ZIN_MODE_MASK                 0x03
+#define ES_AUX_ZIN_MODE_SHIFT                0
+#define ES_AUX_ZIN_MODE_WIDTH                2
+
+#define ES_REC_MUTE                          0x001F
+#define ES_REC_MUTE_MASK                     0x01
+#define ES_REC_MUTE_SHIFT                    0
+#define ES_REC_MUTE_WIDTH                    1
+
+#define ES_AUXL_ON                           0x0024
+#define ES_AUXL_ON_MASK                      0x01
+#define ES_AUXL_ON_SHIFT                     0
+#define ES_AUXL_ON_WIDTH                     1
+
+#define ES_AUXL_GAIN                         0x0025
+#define ES_AUXL_GAIN_MASK                    0x1F
+#define ES_AUXL_GAIN_SHIFT                   0
+#define ES_AUXL_GAIN_WIDTH                   5
+
+#define ES_MIC2_ON                           0x0028
+#define ES_MIC2_ON_MASK                      0x01
+#define ES_MIC2_ON_SHIFT                     0
+#define ES_MIC2_ON_WIDTH                     1
+
+#define ES_MIC2_GAIN                         0x0029
+#define ES_MIC2_GAIN_MASK                    0x1F
+#define ES_MIC2_GAIN_SHIFT                   0
+#define ES_MIC2_GAIN_WIDTH                   5
+
+#define ES_AUXR_ON                           0x002C
+#define ES_AUXR_ON_MASK                      0x01
+#define ES_AUXR_ON_SHIFT                     0
+#define ES_AUXR_ON_WIDTH                     1
+
+#define ES_AUXR_GAIN                         0x002D
+#define ES_AUXR_GAIN_MASK                    0x1F
+#define ES_AUXR_GAIN_SHIFT                   0
+#define ES_AUXR_GAIN_WIDTH                   5
+
+#define ES_ADC0_ON                           0x0030
+#define ES_ADC0_ON_MASK                      0x01
+#define ES_ADC0_ON_SHIFT                     0
+#define ES_ADC0_ON_WIDTH                     1
+
+#define ES_ADC1_ON                           0x0031
+#define ES_ADC1_ON_MASK                      0x01
+#define ES_ADC1_ON_SHIFT                     0
+#define ES_ADC1_ON_WIDTH                     1
+
+#define ES_ADC2_ON                           0x0032
+#define ES_ADC2_ON_MASK                      0x01
+#define ES_ADC2_ON_SHIFT                     0
+#define ES_ADC2_ON_WIDTH                     1
+
+#define ES_ADC3_ON                           0x0033
+#define ES_ADC3_ON_MASK                      0x01
+#define ES_ADC3_ON_SHIFT                     0
+#define ES_ADC3_ON_WIDTH                     1
+
+#define ES_ADC1_IN_SEL                       0x0034
+#define ES_ADC1_IN_SEL_MASK                  0x01
+#define ES_ADC1_IN_SEL_SHIFT                 0
+#define ES_ADC1_IN_SEL_WIDTH                 1
+
+#define ES_ADC2_IN_SEL                       0x0035
+#define ES_ADC2_IN_SEL_MASK                  0x01
+#define ES_ADC2_IN_SEL_SHIFT                 0
+#define ES_ADC2_IN_SEL_WIDTH                 1
+
+#define ES_ADC_MUTE                          0x0036
+#define ES_ADC_MUTE_MASK                     0x01
+#define ES_ADC_MUTE_SHIFT                    0
+#define ES_ADC_MUTE_WIDTH                    1
+
+#define ES_MICHS_ON                          0x0042
+#define ES_MICHS_ON_MASK                     0x01
+#define ES_MICHS_ON_SHIFT                    0
+#define ES_MICHS_ON_WIDTH                    1
+
+#define ES_MICHS_GAIN                        0x0043
+#define ES_MICHS_GAIN_MASK                   0x1F
+#define ES_MICHS_GAIN_SHIFT                  0
+#define ES_MICHS_GAIN_WIDTH                  5
+
+#define ES_MICHS_IN_SEL                      0x0045
+#define ES_MICHS_IN_SEL_MASK                 0x01
+#define ES_MICHS_IN_SEL_SHIFT                0
+#define ES_MICHS_IN_SEL_WIDTH                1
+
+#define ES_EP_GAIN                           0x004B
+#define ES_EP_GAIN_MASK                      0x0F
+#define ES_EP_GAIN_SHIFT                     0
+#define ES_EP_GAIN_WIDTH                     4
+
+#define ES_EP_MUTE                           0x004E
+#define ES_EP_MUTE_MASK                      0x01
+#define ES_EP_MUTE_SHIFT                     0
+#define ES_EP_MUTE_WIDTH                     1
+
+#define ES_EP_ON                             0x004F
+#define ES_EP_ON_MASK                        0x01
+#define ES_EP_ON_SHIFT                       0
+#define ES_EP_ON_WIDTH                       1
+
+#define ES_DAC0L_TO_EP                       0x0050
+#define ES_DAC0L_TO_EP_MASK                  0x01
+#define ES_DAC0L_TO_EP_SHIFT                 0
+#define ES_DAC0L_TO_EP_WIDTH                 1
+
+#define ES_HPL_GAIN                          0x0055
+#define ES_HPL_GAIN_MASK                     0x0F
+#define ES_HPL_GAIN_SHIFT                    0
+#define ES_HPL_GAIN_WIDTH                    4
+
+#define ES_HPL_MUTE                          0x0058
+#define ES_HPL_MUTE_MASK                     0x01
+#define ES_HPL_MUTE_SHIFT                    0
+#define ES_HPL_MUTE_WIDTH                    1
+
+#define ES_HPL_ON                            0x0059
+#define ES_HPL_ON_MASK                       0x01
+#define ES_HPL_ON_SHIFT                      0
+#define ES_HPL_ON_WIDTH                      1
+
+#define ES_DAC0L_TO_HPL                      0x005A
+#define ES_DAC0L_TO_HPL_MASK                 0x01
+#define ES_DAC0L_TO_HPL_SHIFT                0
+#define ES_DAC0L_TO_HPL_WIDTH                1
+
+#define ES_HPR_GAIN                          0x0060
+#define ES_HPR_GAIN_MASK                     0x0F
+#define ES_HPR_GAIN_SHIFT                    0
+#define ES_HPR_GAIN_WIDTH                    4
+
+#define ES_HPR_MUTE                          0x0063
+#define ES_HPR_MUTE_MASK                     0x01
+#define ES_HPR_MUTE_SHIFT                    0
+#define ES_HPR_MUTE_WIDTH                    1
+
+#define ES_HPR_ON                            0x0064
+#define ES_HPR_ON_MASK                       0x01
+#define ES_HPR_ON_SHIFT                      0
+#define ES_HPR_ON_WIDTH                      1
+
+#define ES_DAC0R_TO_HPR                      0x0065
+#define ES_DAC0R_TO_HPR_MASK                 0x01
+#define ES_DAC0R_TO_HPR_SHIFT                0
+#define ES_DAC0R_TO_HPR_WIDTH                1
+
+#define ES_SPKRL_GAIN                        0x006B
+#define ES_SPKRL_GAIN_MASK                   0x1F
+#define ES_SPKRL_GAIN_SHIFT                  0
+#define ES_SPKRL_GAIN_WIDTH                  5
+
+#define ES_SPKRL_MUTE                        0x006E
+#define ES_SPKRL_MUTE_MASK                   0x01
+#define ES_SPKRL_MUTE_SHIFT                  0
+#define ES_SPKRL_MUTE_WIDTH                  1
+
+#define ES_SPKRL_ON                          0x006F
+#define ES_SPKRL_ON_MASK                     0x01
+#define ES_SPKRL_ON_SHIFT                    0
+#define ES_SPKRL_ON_WIDTH                    1
+
+#define ES_DAC0L_TO_SPKRL                    0x0070
+#define ES_DAC0L_TO_SPKRL_MASK               0x01
+#define ES_DAC0L_TO_SPKRL_SHIFT              0
+#define ES_DAC0L_TO_SPKRL_WIDTH              1
+
+#define ES_DAC1L_TO_SPKRL                    0x0071
+#define ES_DAC1L_TO_SPKRL_MASK               0x01
+#define ES_DAC1L_TO_SPKRL_SHIFT              0
+#define ES_DAC1L_TO_SPKRL_WIDTH              1
+
+#define ES_SPKRR_GAIN                        0x0075
+#define ES_SPKRR_GAIN_MASK                   0x1F
+#define ES_SPKRR_GAIN_SHIFT                  0
+#define ES_SPKRR_GAIN_WIDTH                  5
+
+#define ES_SPKRR_MUTE                        0x0077
+#define ES_SPKRR_MUTE_MASK                   0x01
+#define ES_SPKRR_MUTE_SHIFT                  0
+#define ES_SPKRR_MUTE_WIDTH                  1
+
+#define ES_SPKRR_ON                          0x0078
+#define ES_SPKRR_ON_MASK                     0x01
+#define ES_SPKRR_ON_SHIFT                    0
+#define ES_SPKRR_ON_WIDTH                    1
+
+#define ES_DAC0R_TO_SPKRR                    0x0079
+#define ES_DAC0R_TO_SPKRR_MASK               0x01
+#define ES_DAC0R_TO_SPKRR_SHIFT              0
+#define ES_DAC0R_TO_SPKRR_WIDTH              1
+
+#define ES_DAC1R_TO_SPKRR                    0x007A
+#define ES_DAC1R_TO_SPKRR_MASK               0x01
+#define ES_DAC1R_TO_SPKRR_SHIFT              0
+#define ES_DAC1R_TO_SPKRR_WIDTH              1
+
+#define ES_LO_L_GAIN                         0x007E
+#define ES_LO_L_GAIN_MASK                    0x0F
+#define ES_LO_L_GAIN_SHIFT                   0
+#define ES_LO_L_GAIN_WIDTH                   4
+
+#define ES_LO_L_MUTE                         0x0081
+#define ES_LO_L_MUTE_MASK                    0x01
+#define ES_LO_L_MUTE_SHIFT                   0
+#define ES_LO_L_MUTE_WIDTH                   1
+
+#define ES_LO_L_ON                           0x0082
+#define ES_LO_L_ON_MASK                      0x01
+#define ES_LO_L_ON_SHIFT                     0
+#define ES_LO_L_ON_WIDTH                     1
+
+#define ES_DAC1L_TO_LO_L                     0x0083
+#define ES_DAC1L_TO_LO_L_MASK                0x01
+#define ES_DAC1L_TO_LO_L_SHIFT               0
+#define ES_DAC1L_TO_LO_L_WIDTH               1
+
+#define ES_LO_R_GAIN                         0x008A
+#define ES_LO_R_GAIN_MASK                    0x0F
+#define ES_LO_R_GAIN_SHIFT                   0
+#define ES_LO_R_GAIN_WIDTH                   4
+
+#define ES_LO_R_MUTE                         0x008D
+#define ES_LO_R_MUTE_MASK                    0x01
+#define ES_LO_R_MUTE_SHIFT                   0
+#define ES_LO_R_MUTE_WIDTH                   1
+
+#define ES_LO_R_ON                           0x008E
+#define ES_LO_R_ON_MASK                      0x01
+#define ES_LO_R_ON_SHIFT                     0
+#define ES_LO_R_ON_WIDTH                     1
+
+#define ES_DAC1R_TO_LO_R                     0x008F
+#define ES_DAC1R_TO_LO_R_MASK                0x01
+#define ES_DAC1R_TO_LO_R_SHIFT               0
+#define ES_DAC1R_TO_LO_R_WIDTH               1
+
+#define ES_VC_ADC_ON                         0x00ED
+#define ES_VC_ADC_ON_MASK                    0x01
+#define ES_VC_ADC_ON_SHIFT                   0
+#define ES_VC_ADC_ON_WIDTH                   1
+
+#define ES_MB2_TRIM                          0x0100
+#define ES_MB2_TRIM_MASK                     0x07
+#define ES_MB2_TRIM_SHIFT                    0
+#define ES_MB2_TRIM_WIDTH                    3
+
+#define ES_MBHS_TRIM                         0x0101
+#define ES_MBHS_TRIM_MASK                    0x07
+#define ES_MBHS_TRIM_SHIFT                   0
+#define ES_MBHS_TRIM_WIDTH                   3
+
+#define ES_LD02_TRIM                         0x0102
+#define ES_LD02_TRIM_MASK                    0x03
+#define ES_LD02_TRIM_SHIFT                   0
+#define ES_LD02_TRIM_WIDTH                   2
+
+#define ES_MB0_TRIM                          0x0103
+#define ES_MB0_TRIM_MASK                     0x07
+#define ES_MB0_TRIM_SHIFT                    0
+#define ES_MB0_TRIM_WIDTH                    3
+
+#define ES_MB1_TRIM                          0x0104
+#define ES_MB1_TRIM_MASK                     0x07
+#define ES_MB1_TRIM_SHIFT                    0
+#define ES_MB1_TRIM_WIDTH                    3
+
+#define ES_SQUELCH_THRESHOLD                 0x014C
+#define ES_SQUELCH_THRESHOLD_MASK            0x07
+#define ES_SQUELCH_THRESHOLD_SHIFT           0
+#define ES_SQUELCH_THRESHOLD_WIDTH           3
+
+#define ES_SQUELCH_TERM_CNT                  0x014D
+#define ES_SQUELCH_TERM_CNT_MASK             0x0F
+#define ES_SQUELCH_TERM_CNT_SHIFT            0
+#define ES_SQUELCH_TERM_CNT_WIDTH            4
+
+
+
+#define ES_MAX_REGISTER             0x014F
+
 
 int es_analog_add_snd_soc_controls(struct snd_soc_codec *codec);
 int es_analog_add_snd_soc_dapm_controls(struct snd_soc_codec *codec);
 int es_analog_add_snd_soc_route_map(struct snd_soc_codec *codec);
 
-
 #endif
index 9a76912c25c2dd05473c6885291ff5404cab66fe..eb8153462f5b0afb84c794f1af60fb515ecb1c61 100644 (file)
@@ -18,7 +18,6 @@
 #include "es-a300-reg.h"
 
 static DECLARE_TLV_DB_SCALE(spkr_tlv, -3600, 200, 1);
-static DECLARE_TLV_DB_SCALE(lo_tlv, -2200, 200, 1);
 static DECLARE_TLV_DB_SCALE(ep_tlv, -2200, 200, 1);
 static DECLARE_TLV_DB_SCALE(aux_tlv, 0, 150, 0);
 static DECLARE_TLV_DB_SCALE(mic_tlv, 0, 150, 0);
@@ -33,66 +32,14 @@ static const unsigned int hp_tlv[] = {
        12, 15, TLV_DB_SCALE_ITEM(-600, 200, 0),
 };
 
-static const char * const aux_mono_text[] = {
-       "Mono", "Stereo"
-};
-
-static const struct soc_enum auxl_mono_enum =
-       SOC_ENUM_SINGLE(ES_AUX_L_CTRL, ES_AUX_STEREO_SHIFT,
-               ARRAY_SIZE(aux_mono_text), aux_mono_text);
-
-static const struct soc_enum auxr_mono_enum =
-       SOC_ENUM_SINGLE(ES_AUX_R_CTRL, ES_AUX_STEREO_SHIFT,
-               ARRAY_SIZE(aux_mono_text), aux_mono_text);
-
-static const char * const i2s_ch_text[] = {
-       "2", "4",
-};
-
-static const struct soc_enum i2s_ch_enum =
-       SOC_ENUM_SINGLE(ES_DAC_DIG_CH, ES_I2S_CH_SHIFT,
-               ARRAY_SIZE(i2s_ch_text), i2s_ch_text);
-
-static const char * const fs_sel_text[] = {
-       "48", "96", "192",
-};
-
-static const struct soc_enum fs_sel_enum =
-       SOC_ENUM_SINGLE(ES_DAC_DIG_FS_SEL, ES_FS_SEL_SHIFT,
-               ARRAY_SIZE(fs_sel_text), fs_sel_text);
-
 static const char * const michs_sel_mux_text[] = {
        "MIC0_PGA", "MIC1_PGA",
 };
 
 static const struct soc_enum michs_sel_mux_enum =
-       SOC_ENUM_SINGLE(ES_MICHS_CTRL, ES_MICHS_IN_SEL_SHIFT,
+       SOC_ENUM_SINGLE(ES_MICHS_IN_SEL, ES_MICHS_IN_SEL_SHIFT,
                ARRAY_SIZE(michs_sel_mux_text), michs_sel_mux_text);
 
-static const char * const micx_input_type_text[] = {
-       "Differential", "Single Ended",
-};
-
-static const struct soc_enum mic0_input_type_enum =
-       SOC_ENUM_SINGLE(ES_MIC0_CTRL, ES_MIC0_SE_SHIFT,
-               ARRAY_SIZE(micx_input_type_text), micx_input_type_text);
-
-static const struct soc_enum mic1_input_type_enum =
-       SOC_ENUM_SINGLE(ES_MIC1_CTRL, ES_MIC1_SE_SHIFT,
-               ARRAY_SIZE(micx_input_type_text), micx_input_type_text);
-
-static const struct soc_enum mic2_input_type_enum =
-       SOC_ENUM_SINGLE(ES_MIC2_CTRL, ES_MIC2_SE_SHIFT,
-               ARRAY_SIZE(micx_input_type_text), micx_input_type_text);
-
-static const struct soc_enum michs_input_type_enum =
-       SOC_ENUM_SINGLE(ES_MICHS_CTRL, ES_MICHS_SE_SHIFT,
-               ARRAY_SIZE(micx_input_type_text), micx_input_type_text);
-
-static const struct soc_enum auxin_input_type_enum =
-       SOC_ENUM_SINGLE(ES_AUX_R_CTRL, ES_AUXR_SE_SHIFT,
-               ARRAY_SIZE(micx_input_type_text), micx_input_type_text);
-
 static const char * const micx_bias_output_voltage_text[] = {
        "1.6V", "1.8V", "2.0V", "2.2V", "2.4V", "2.6V", "2.8V", "3.0V",
 };
@@ -101,26 +48,47 @@ static const unsigned int micx_bias_output_voltage_value[] = {
        0, 1, 2, 3, 4, 5, 6, 7,
 };
 
+static const char * const lo_gain_text[] = {
+       "mute", "-6db", "-4db", "-2db", "0db", "2db",
+};
+
+static const unsigned int lo_gain_value[] = {
+       0, 9, 10, 11, 12, 13,
+};
+
+static const struct soc_enum lol_gain_enum =
+       SOC_VALUE_ENUM_SINGLE(ES_LO_L_GAIN, ES_LO_L_GAIN_SHIFT,
+               ES_LO_L_GAIN_MASK, ARRAY_SIZE(lo_gain_text),
+                       lo_gain_text,
+                       lo_gain_value);
+
+static const struct soc_enum lor_gain_enum =
+       SOC_VALUE_ENUM_SINGLE(ES_LO_R_GAIN, ES_LO_R_GAIN_SHIFT,
+               ES_LO_R_GAIN_MASK, ARRAY_SIZE(lo_gain_text),
+                       lo_gain_text,
+                       lo_gain_value);
+
 static const struct soc_enum mic0_bias_output_voltage_enum =
-       SOC_VALUE_ENUM_SINGLE(ES_MB_TRIM2, ES_MB0_TRIM_SHIFT,
+       SOC_VALUE_ENUM_SINGLE(ES_MB0_TRIM, ES_MB0_TRIM_SHIFT,
                ES_MB0_TRIM_MASK, ARRAY_SIZE(micx_bias_output_voltage_text),
                        micx_bias_output_voltage_text,
                        micx_bias_output_voltage_value);
 
+
 static const struct soc_enum mic1_bias_output_voltage_enum =
-       SOC_VALUE_ENUM_SINGLE(ES_MB_TRIM2, ES_MB1_TRIM_SHIFT,
+       SOC_VALUE_ENUM_SINGLE(ES_MB1_TRIM, ES_MB1_TRIM_SHIFT,
                ES_MB1_TRIM_MASK, ARRAY_SIZE(micx_bias_output_voltage_text),
                        micx_bias_output_voltage_text,
                        micx_bias_output_voltage_value);
 
 static const struct soc_enum mic2_bias_output_voltage_enum =
-       SOC_VALUE_ENUM_SINGLE(ES_MB_TRIM1, ES_MB2_TRIM_SHIFT,
+       SOC_VALUE_ENUM_SINGLE(ES_MB2_TRIM, ES_MB2_TRIM_SHIFT,
                ES_MB2_TRIM_MASK, ARRAY_SIZE(micx_bias_output_voltage_text),
                        micx_bias_output_voltage_text,
                        micx_bias_output_voltage_value);
 
 static const struct soc_enum michs_bias_output_voltage_enum =
-       SOC_VALUE_ENUM_SINGLE(ES_MB_TRIM1, ES_MBHS_TRIM_SHIFT,
+       SOC_VALUE_ENUM_SINGLE(ES_MBHS_TRIM, ES_MBHS_TRIM_SHIFT,
                ES_MBHS_TRIM_MASK, ARRAY_SIZE(micx_bias_output_voltage_text),
                        micx_bias_output_voltage_text,
                        micx_bias_output_voltage_value);
@@ -129,22 +97,34 @@ static const char * const micx_zin_mode_text[] = {
        "100kohm", "50kohm", "25kohm", "Attenuate by 3dB",
 };
 
+static const char * const squelch_mode_texts[] = {
+       "Off", "On"
+};
+static const unsigned int squelch_mode_value[] = {
+       0, 3,
+};
+
 static const struct soc_enum mic0_zin_mode_enum =
-       SOC_ENUM_SINGLE(ES_MIC_TUNE, ES_MIC0_ZIN_MODE_SHIFT,
+       SOC_ENUM_SINGLE(ES_MIC0_ZIN_MODE, ES_MIC0_ZIN_MODE_SHIFT,
                ARRAY_SIZE(micx_zin_mode_text), micx_zin_mode_text);
 
 static const struct soc_enum mic1_zin_mode_enum =
-       SOC_ENUM_SINGLE(ES_MIC_TUNE, ES_MIC1_ZIN_MODE_SHIFT,
+       SOC_ENUM_SINGLE(ES_MIC1_ZIN_MODE, ES_MIC1_ZIN_MODE_SHIFT,
                ARRAY_SIZE(micx_zin_mode_text), micx_zin_mode_text);
 
 static const struct soc_enum mic2_zin_mode_enum =
-       SOC_ENUM_SINGLE(ES_MIC_TUNE, ES_MIC2_ZIN_MODE_SHIFT,
+       SOC_ENUM_SINGLE(ES_MIC2_ZIN_MODE, ES_MIC2_ZIN_MODE_SHIFT,
                ARRAY_SIZE(micx_zin_mode_text), micx_zin_mode_text);
 
 static const struct soc_enum michs_zin_mode_enum =
-       SOC_ENUM_SINGLE(ES_MIC_TUNE, ES_MICHS_ZIN_MODE_SHIFT,
+       SOC_ENUM_SINGLE(ES_MICHS_ZIN_MODE, ES_MICHS_ZIN_MODE_SHIFT,
                ARRAY_SIZE(micx_zin_mode_text), micx_zin_mode_text);
 
+static const struct soc_enum squelch_mode_enum =
+       SOC_VALUE_ENUM_SINGLE(ES_SQUELCH_THRESHOLD, ES_SQUELCH_THRESHOLD_SHIFT,
+               ES_SQUELCH_THRESHOLD_MASK, ARRAY_SIZE(squelch_mode_texts),
+               squelch_mode_texts, squelch_mode_value);
+
 static const char * const bps_text[] = {
        "0", "16", "20", "24", "32",
 };
@@ -153,77 +133,55 @@ static const unsigned int bps_value_text[] = {
        0, 15, 19, 23, 31,
 };
 
-static const struct soc_enum bps_enum =
-       SOC_VALUE_ENUM_SINGLE(ES_DAC_DIG_I2S1, ES_BITS_PER_SAMPLE_SHIFT,
-               ES_BITS_PER_SAMPLE_MASK, ARRAY_SIZE(bps_text),
-                       bps_text, bps_value_text);
-
 const struct snd_kcontrol_new es_codec_snd_controls[] = {
 
-       SOC_SINGLE("Bypass Alc", ES_SPKR_ALC1, BYPASS_ALC_SHIFT, 0x01, 0),
-       SOC_DOUBLE_R_TLV("SPKR Gain", ES_SPKR_L_GAIN, ES_SPKR_R_GAIN,
+       SOC_DOUBLE_R_TLV("SPKR Gain", ES_SPKRL_GAIN, ES_SPKRR_GAIN,
                        0, 0x1F, 0, spkr_tlv),
-       SOC_DOUBLE_R_TLV("LO Gain", ES_LO_L_GAIN, ES_LO_R_GAIN,
-                       0, 0x0F, 0, lo_tlv),
-       SOC_DOUBLE_R_TLV("HP Gain", ES_HP_L_GAIN, ES_HP_R_GAIN,
+       SOC_DOUBLE_R_TLV("HP Gain", ES_HPL_GAIN, ES_HPR_GAIN,
                        0, 0x0F, 0, hp_tlv),
-       SOC_DOUBLE_R_TLV("AUXIN Gain", ES_AUX_L_CTRL, ES_AUX_R_CTRL,
+       SOC_DOUBLE_R_TLV("AUXIN Gain", ES_AUXL_ON, ES_AUXR_ON,
                        1, 0x14, 0, aux_tlv),
 
 
-       SOC_SINGLE_TLV("SPKRL Gain", ES_SPKR_L_GAIN, ES_SPKRL_GAIN_SHIFT,
-                       ES_SPKRL_GAIN_MAX, 0, spkr_tlv),
-       SOC_SINGLE_TLV("SPKRR Gain", ES_SPKR_R_GAIN, ES_SPKRR_GAIN_SHIFT,
-                       ES_SPKRR_GAIN_MAX, 0, spkr_tlv),
-       SOC_SINGLE_TLV("LOL Gain", ES_LO_L_GAIN, ES_LO_L_GAIN_SHIFT,
-                       ES_LO_L_GAIN_MAX, 0, lo_tlv),
-       SOC_SINGLE_TLV("LOR Gain", ES_LO_R_GAIN, ES_LO_R_GAIN_SHIFT,
-                       ES_LO_R_GAIN_MAX, 0, lo_tlv),
-       SOC_SINGLE_TLV("HPL Gain", ES_HP_L_GAIN, ES_HPL_GAIN_SHIFT,
+       SOC_SINGLE_TLV("SPKRL Gain", ES_SPKRL_GAIN, ES_SPKRL_GAIN_SHIFT,
+                       ES_SPKR_L_GAIN_MAX, 0, spkr_tlv),
+       SOC_SINGLE_TLV("SPKRR Gain", ES_SPKRR_GAIN, ES_SPKRR_GAIN_SHIFT,
+                       ES_SPKR_R_GAIN_MAX, 0, spkr_tlv),
+       SOC_VALUE_ENUM("LOL Gain", lol_gain_enum),
+       SOC_VALUE_ENUM("LOR Gain", lor_gain_enum),
+       SOC_SINGLE_TLV("HPL Gain", ES_HPL_GAIN, ES_HPL_GAIN_SHIFT,
                        ES_HPL_GAIN_MAX, 0, hp_tlv),
-       SOC_SINGLE_TLV("HPR Gain", ES_HP_R_GAIN, ES_HPR_GAIN_SHIFT,
+       SOC_SINGLE_TLV("HPR Gain", ES_HPR_GAIN, ES_HPR_GAIN_SHIFT,
                        ES_HPR_GAIN_MAX, 0, hp_tlv),
        SOC_SINGLE_TLV("EP Gain", ES_EP_GAIN, ES_EP_GAIN_SHIFT,
                        ES_EP_GAIN_MAX, 0, ep_tlv),
-       SOC_SINGLE_TLV("AUXINL Gain", ES_AUX_L_CTRL, ES_AUXL_GAIN_SHIFT,
+       SOC_SINGLE_TLV("AUXINL Gain", ES_AUXL_GAIN, ES_AUXL_GAIN_SHIFT,
                        ES_AUXL_GAIN_MAX, 0, aux_tlv),
-       SOC_SINGLE_TLV("AUXINR Gain", ES_AUX_R_CTRL, ES_AUXR_GAIN_SHIFT,
+       SOC_SINGLE_TLV("AUXINR Gain", ES_AUXR_GAIN, ES_AUXR_GAIN_SHIFT,
                        ES_AUXR_GAIN_MAX, 0, aux_tlv),
 
 
-       SOC_SINGLE_TLV("MIC0 Gain", ES_MIC0_CTRL, ES_MIC0_GAIN_SHIFT,
+       SOC_SINGLE_TLV("MIC0 Gain", ES_MIC0_GAIN, ES_MIC0_GAIN_SHIFT,
                        ES_MIC0_GAIN_MAX, 0, mic_tlv),
-       SOC_SINGLE_TLV("MIC1 Gain", ES_MIC1_CTRL, ES_MIC1_GAIN_SHIFT,
+       SOC_SINGLE_TLV("MIC1 Gain", ES_MIC1_GAIN, ES_MIC1_GAIN_SHIFT,
                        ES_MIC1_GAIN_MAX, 0, mic_tlv),
-       SOC_SINGLE_TLV("MIC2 Gain", ES_MIC2_CTRL, ES_MIC2_GAIN_SHIFT,
+       SOC_SINGLE_TLV("MIC2 Gain", ES_MIC2_GAIN, ES_MIC2_GAIN_SHIFT,
                        ES_MIC2_GAIN_MAX, 0, mic_tlv),
-       SOC_SINGLE_TLV("MICHS Gain", ES_MICHS_CTRL, ES_MICHS_GAIN_SHIFT,
+       SOC_SINGLE_TLV("MICHS Gain", ES_MICHS_GAIN, ES_MICHS_GAIN_SHIFT,
                        ES_MICHS_GAIN_MAX, 0, mic_tlv),
 
 
-       SOC_ENUM("AUXL Mono", auxl_mono_enum),
-       SOC_ENUM("AUXR Mono", auxr_mono_enum),
-       SOC_SINGLE("ADC Mute", ES_ADC_CTRL, ES_ADC_MUTE_SHIFT, 1, 0),
-       SOC_SINGLE("EP Mute", ES_EP_GAIN, ES_EP_MUTE_SHIFT, 1, 0),
-       SOC_SINGLE("HPL Mute", ES_HP_L_GAIN, ES_HPL_MUTE_SHIFT, 1, 0),
-       SOC_SINGLE("HPR Mute", ES_HP_R_GAIN, ES_HPR_MUTE_SHIFT, 1, 0),
-       SOC_SINGLE("SPKRL Mute", ES_SPKR_L_GAIN, ES_SPKRL_MUTE_SHIFT, 1, 0),
-       SOC_SINGLE("SPKRR Mute", ES_SPKR_R_GAIN, ES_SPKRR_MUTE_SHIFT, 1, 0),
-       SOC_SINGLE("LOL Mute", ES_LO_L_GAIN, ES_LO_L_MUTE_SHIFT, 1, 0),
-       SOC_SINGLE("LOR Mute", ES_LO_R_GAIN, ES_LO_R_MUTE_SHIFT, 1, 0),
-
-       SOC_ENUM("I2S Channels", i2s_ch_enum),
-       SOC_ENUM("FrameSync SEL", fs_sel_enum),
-       SOC_VALUE_ENUM("Bits per Sample", bps_enum),
+       SOC_SINGLE("ADC Mute", ES_ADC_MUTE, ES_ADC_MUTE_SHIFT, 1, 0),
+       SOC_SINGLE("EP Mute", ES_EP_MUTE, ES_EP_MUTE_SHIFT, 1, 0),
+       SOC_SINGLE("HPL Mute", ES_HPL_MUTE, ES_HPL_MUTE_SHIFT, 1, 0),
+       SOC_SINGLE("HPR Mute", ES_HPR_MUTE, ES_HPR_MUTE_SHIFT, 1, 0),
+       SOC_SINGLE("SPKRL Mute", ES_SPKRL_MUTE, ES_SPKRL_MUTE_SHIFT, 1, 0),
+       SOC_SINGLE("SPKRR Mute", ES_SPKRR_MUTE, ES_SPKRR_MUTE_SHIFT, 1, 0),
+       SOC_SINGLE("LOL Mute", ES_LO_L_MUTE, ES_LO_L_MUTE_SHIFT, 1, 0),
+       SOC_SINGLE("LOR Mute", ES_LO_R_MUTE, ES_LO_R_MUTE_SHIFT, 1, 0),
 
        SOC_ENUM("MICHS SEL MUX", michs_sel_mux_enum),
 
-       SOC_ENUM("MIC0 Input Type", mic0_input_type_enum),
-       SOC_ENUM("MIC1 Input Type", mic1_input_type_enum),
-       SOC_ENUM("MIC2 Input Type", mic2_input_type_enum),
-       SOC_ENUM("MICHS Input Type", michs_input_type_enum),
-       SOC_ENUM("AUXIN Input Type", auxin_input_type_enum),
-
        SOC_VALUE_ENUM("MIC0 Bias Output Voltage",
                        mic0_bias_output_voltage_enum),
        SOC_VALUE_ENUM("MIC1 Bias Output Voltage",
@@ -237,6 +195,10 @@ const struct snd_kcontrol_new es_codec_snd_controls[] = {
        SOC_ENUM("MIC1 Input Impedance Mode", mic1_zin_mode_enum),
        SOC_ENUM("MIC2 Input Impedance Mode", mic2_zin_mode_enum),
        SOC_ENUM("MICHS Input Impedance Mode", michs_zin_mode_enum),
+
+       SOC_VALUE_ENUM("Squelch", squelch_mode_enum),
+       SOC_SINGLE("Squelch Count Threshold", ES_SQUELCH_TERM_CNT,
+                       ES_SQUELCH_TERM_CNT_SHIFT, 15, 0),
 };
 
 static const char * const adc1_mux_text[] = {
@@ -244,7 +206,7 @@ static const char * const adc1_mux_text[] = {
 };
 
 static const struct soc_enum adc1_mux_enum =
-       SOC_ENUM_SINGLE(ES_ADC_CTRL, ES_ADC1_IN_SEL_SHIFT,
+       SOC_ENUM_SINGLE(ES_ADC1_IN_SEL, ES_ADC1_IN_SEL_SHIFT,
                ARRAY_SIZE(adc1_mux_text), adc1_mux_text);
 
 static const struct snd_kcontrol_new adc1_mux =
@@ -255,7 +217,7 @@ static const char * const adc2_mux_text[] = {
 };
 
 static const struct soc_enum adc2_mux_enum =
-       SOC_ENUM_SINGLE(ES_ADC_CTRL, ES_ADC2_IN_SEL_SHIFT,
+       SOC_ENUM_SINGLE(ES_ADC2_IN_SEL, ES_ADC2_IN_SEL_SHIFT,
                ARRAY_SIZE(adc2_mux_text), adc2_mux_text);
 
 static const struct snd_kcontrol_new adc2_mux =
@@ -263,61 +225,62 @@ static const struct snd_kcontrol_new adc2_mux =
 
 
 static const struct snd_kcontrol_new ep_mix[] = {
-       SOC_DAPM_SINGLE("DAC0L", ES_EP_CTRL, ES_DAC0L_TO_EP_SHIFT, 1, 0),
-       SOC_DAPM_SINGLE("AUXL", ES_EP_CTRL, ES_AUXL_TO_EP_SHIFT, 1, 0),
+       SOC_DAPM_SINGLE("DAC0L", ES_DAC0L_TO_EP, ES_DAC0L_TO_EP_SHIFT, 1, 0),
 };
 
 static const struct snd_kcontrol_new hpl_mix[] = {
-       SOC_DAPM_SINGLE("DAC0L", ES_HP_L_CTRL, ES_DAC0L_TO_HPL_SHIFT, 1, 0),
-       SOC_DAPM_SINGLE("AUXL", ES_HP_L_CTRL, ES_AUXL_TO_HPL_SHIFT, 1, 0),
+       SOC_DAPM_SINGLE("DAC0L", ES_DAC0L_TO_HPL, ES_DAC0L_TO_HPL_SHIFT, 1, 0),
 };
 
 static const struct snd_kcontrol_new hpr_mix[] = {
-       SOC_DAPM_SINGLE("DAC0R", ES_HP_R_CTRL, ES_DAC0R_TO_HPR_SHIFT, 1, 0),
-       SOC_DAPM_SINGLE("AUXR", ES_HP_R_CTRL, ES_AUXR_TO_HPR_SHIFT, 1, 0),
+       SOC_DAPM_SINGLE("DAC0R", ES_DAC0R_TO_HPR, ES_DAC0R_TO_HPR_SHIFT, 1, 0),
 };
 
 static const struct snd_kcontrol_new spkrl_mix[] = {
-       SOC_DAPM_SINGLE("DAC0L", ES_SPKR_L_CTRL, ES_DAC0L_TO_SPKRL_SHIFT, 1, 0),
-       SOC_DAPM_SINGLE("DAC1L", ES_SPKR_L_CTRL, ES_DAC1L_TO_SPKRL_SHIFT, 1, 0),
-       SOC_DAPM_SINGLE("AUXL", ES_SPKR_L_CTRL, ES_AUXL_TO_SPKRL_SHIFT, 1, 0),
+       SOC_DAPM_SINGLE("DAC0L", ES_DAC0L_TO_SPKRL, ES_DAC0L_TO_SPKRL_SHIFT,
+                                                               1, 0),
+       SOC_DAPM_SINGLE("DAC1L", ES_DAC1L_TO_SPKRL, ES_DAC1L_TO_SPKRL_SHIFT,
+                                                                1, 0),
 };
 
 static const struct snd_kcontrol_new spkrr_mix[] = {
-       SOC_DAPM_SINGLE("DAC0R", ES_SPKR_R_CTRL, ES_DAC0R_TO_SPKRR_SHIFT, 1, 0),
-       SOC_DAPM_SINGLE("DAC1R", ES_SPKR_R_CTRL, ES_DAC1R_TO_SPKRR_SHIFT, 1, 0),
-       SOC_DAPM_SINGLE("AUXR", ES_SPKR_R_CTRL, ES_AUXR_TO_SPKRR_SHIFT, 1, 0),
+       SOC_DAPM_SINGLE("DAC0R", ES_DAC0R_TO_SPKRR, ES_DAC0R_TO_SPKRR_SHIFT,
+                                                                1, 0),
+       SOC_DAPM_SINGLE("DAC1R", ES_DAC1R_TO_SPKRR, ES_DAC1R_TO_SPKRR_SHIFT,
+                                                                1, 0),
 };
 
 static const struct snd_kcontrol_new lo_l_mix[] = {
-       SOC_DAPM_SINGLE("DAC1L", ES_LO_L_CTRL, ES_DAC1L_TO_LO_L_SHIFT, 1, 0),
+       SOC_DAPM_SINGLE("DAC1L", ES_DAC1L_TO_LO_L, ES_DAC1L_TO_LO_L_SHIFT,
+                                                               1, 0),
 };
 
 static const struct snd_kcontrol_new lo_r_mix[] = {
-       SOC_DAPM_SINGLE("DAC1R", ES_LO_R_CTRL, ES_DAC1R_TO_LO_R_SHIFT, 1, 0),
+       SOC_DAPM_SINGLE("DAC1R", ES_DAC1R_TO_LO_R, ES_DAC1R_TO_LO_R_SHIFT,
+                                                               1, 0),
 };
 
-static const struct snd_kcontrol_new michs_control =
-       SOC_DAPM_SINGLE("Switch", ES_MICHS_CTRL, ES_MICHS_ON_SHIFT, 1, 0);
+static const char *const mic0_pga_mux_names[] = {
+       "NONE", "MIC-0", "MIC-HS"
+};
 
-static int es_lo_enable(struct snd_soc_dapm_widget *w,
-       struct snd_kcontrol *kcontrol, int event)
-{
-       struct snd_soc_codec *codec = w->codec;
-       pr_debug("%s LO event %d\n", __func__, event);
-
-       switch (event) {
-       case SND_SOC_DAPM_PRE_PMU:
-               snd_soc_update_bits(codec, ES_LO_L_CTRL, ES_LO_TRIM_DIS_MASK,
-                       ES_LO_TRIM_DIS);
-               break;
-       case SND_SOC_DAPM_POST_PMD:
-               snd_soc_update_bits(codec, ES_LO_L_CTRL, ES_LO_TRIM_DIS_MASK,
-                       0);
-               break;
-       }
-       return 0;
-}
+static const struct soc_enum mic0_pga_mux_enum =
+       SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(mic0_pga_mux_names),
+                       mic0_pga_mux_names);
+
+static const struct snd_kcontrol_new mic0_pga_mux_controls =
+       SOC_DAPM_ENUM_VIRT("Switch", mic0_pga_mux_enum);
+
+static const char *const mic1_pga_mux_names[] = {
+       "NONE", "MIC-1", "MIC-HS"
+};
+
+static const struct soc_enum mic1_pga_mux_enum =
+       SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(mic1_pga_mux_names),
+                       mic1_pga_mux_names);
+
+static const struct snd_kcontrol_new mic1_pga_mux_controls =
+       SOC_DAPM_ENUM_VIRT("Switch", mic1_pga_mux_enum);
 
 static int mic_event(struct snd_soc_dapm_widget *w,
                struct snd_kcontrol *k, int event)
@@ -327,33 +290,31 @@ static int mic_event(struct snd_soc_dapm_widget *w,
 
        if (SND_SOC_DAPM_EVENT_ON(event)) {
                if (!strncmp(w->name, "MIC0", 4))
-                       snd_soc_update_bits(codec, ES_MIC0_CTRL,
-                                       ES_MIC0_ON_MASK, 1);
+                       snd_soc_write(codec, ES_MIC0_ON, 1);
                else if (!strncmp(w->name, "MIC1", 4))
-                       snd_soc_update_bits(codec, ES_MIC1_CTRL,
-                                       ES_MIC1_ON_MASK, 1);
+                       snd_soc_write(codec, ES_MIC1_ON, 1);
                else if (!strncmp(w->name, "MIC2", 4))
-                       snd_soc_update_bits(codec, ES_MIC2_CTRL,
-                                       ES_MIC2_ON_MASK, 1);
+                       snd_soc_write(codec, ES_MIC2_ON, 1);
+               else if (!strncmp(w->name, "MICHS", 5))
+                       snd_soc_write(codec, ES_MICHS_ON, 1);
                else {
-                       pr_err("%s() Invalid Mic Widget ON = %s\n",
-                                       __func__, w->name);
+                       pr_err("%s: Invalid Mic Widget ON = %s\n",
+                              __func__, w->name);
                        return -EINVAL;
                }
 
        } else {
                if (!strncmp(w->name, "MIC0", 4))
-                       snd_soc_update_bits(codec, ES_MIC0_CTRL,
-                               ES_MIC0_ON_MASK, 0);
+                       snd_soc_write(codec, ES_MIC0_ON, 0);
                else if (!strncmp(w->name, "MIC1", 4))
-                       snd_soc_update_bits(codec, ES_MIC1_CTRL,
-                               ES_MIC1_ON_MASK, 0);
+                       snd_soc_write(codec, ES_MIC1_ON, 0);
                else if (!strncmp(w->name, "MIC2", 4))
-                       snd_soc_update_bits(codec, ES_MIC2_CTRL,
-                               ES_MIC2_ON_MASK, 0);
+                       snd_soc_write(codec, ES_MIC2_ON, 0);
+               else if (!strncmp(w->name, "MICHS", 5))
+                       snd_soc_write(codec, ES_MICHS_ON, 0);
                else {
-                       pr_err("%s() Invalid Mic Widget OFF = %s\n",
-                                       __func__, w->name);
+                       pr_err("%s: Invalid Mic Widget OFF = %s\n",
+                              __func__, w->name);
                        return -EINVAL;
                }
        }
@@ -366,7 +327,7 @@ const struct snd_soc_dapm_widget es_codec_dapm_widgets[] = {
        SND_SOC_DAPM_MIC("MIC0", mic_event),
        SND_SOC_DAPM_MIC("MIC1", mic_event),
        SND_SOC_DAPM_MIC("MIC2", mic_event),
-       SND_SOC_DAPM_MIC("MICHS", NULL),
+       SND_SOC_DAPM_MIC("MICHS", mic_event),
        SND_SOC_DAPM_MIC("AUXINM", NULL),
        SND_SOC_DAPM_MIC("AUXINP", NULL),
 
@@ -376,31 +337,29 @@ const struct snd_soc_dapm_widget es_codec_dapm_widgets[] = {
        SND_SOC_DAPM_SPK("SPKRL", NULL),
        SND_SOC_DAPM_SPK("SPKRR", NULL),
        SND_SOC_DAPM_OUTPUT("EP"),
-       /* Dummy EP Right output */
-       SND_SOC_DAPM_OUTPUT("EPR"),
        SND_SOC_DAPM_LINE("AUXOUTL", NULL),
        SND_SOC_DAPM_LINE("AUXOUTR", NULL),
 
        /* Microphone bias */
-       /*SND_SOC_DAPM_SUPPLY("MICHS Bias", ES_MICBIAS_CTRL,
-               ES_MBIASHS_MODE_SHIFT, 0, NULL, 0),
-       SND_SOC_DAPM_SUPPLY("MIC0 Bias", ES_MICBIAS_CTRL,
-               ES_MBIAS0_MODE_SHIFT, 0, NULL, 0),*/
-       SND_SOC_DAPM_SUPPLY("MIC1 Bias", ES_MICBIAS_CTRL,
+       SND_SOC_DAPM_SUPPLY("MIC0 Bias", ES_MBIAS0_MODE,
+               ES_MBIAS0_MODE_SHIFT, 0, NULL, 0),
+       SND_SOC_DAPM_SUPPLY("MIC1 Bias", ES_MBIAS1_MODE,
                ES_MBIAS1_MODE_SHIFT, 0, NULL, 0),
-       SND_SOC_DAPM_SUPPLY("MIC2 Bias", ES_MICBIAS_CTRL,
+       SND_SOC_DAPM_SUPPLY("MIC2 Bias", ES_MBIAS2_MODE,
                ES_MBIAS2_MODE_SHIFT, 0, NULL, 0),
 
-       /* Mic headset Switch ON/OFF */
-       SND_SOC_DAPM_SWITCH("MICHS ON", SND_SOC_NOPM, 0, 0, &michs_control),
+       SND_SOC_DAPM_VIRT_MUX("MIC0 PGA Mux", SND_SOC_NOPM, 0, 0,
+               &mic0_pga_mux_controls),
 
+       SND_SOC_DAPM_VIRT_MUX("MIC1 PGA Mux", SND_SOC_NOPM, 0, 0,
+               &mic1_pga_mux_controls),
        /* ADC */
-       SND_SOC_DAPM_ADC("ADC0", NULL, ES_ADC_CTRL, ES_ADC0_ON_SHIFT, 0),
+       SND_SOC_DAPM_ADC("ADC0", NULL, ES_ADC0_ON, ES_ADC0_ON_SHIFT, 0),
        SND_SOC_DAPM_MUX("ADC1 MUX", SND_SOC_NOPM, 0, 0, &adc1_mux),
-       SND_SOC_DAPM_ADC("ADC1", NULL, ES_ADC_CTRL, ES_ADC1_ON_SHIFT, 0),
+       SND_SOC_DAPM_ADC("ADC1", NULL, ES_ADC1_ON, ES_ADC1_ON_SHIFT, 0),
        SND_SOC_DAPM_MUX("ADC2 MUX", SND_SOC_NOPM, 0, 0, &adc2_mux),
-       SND_SOC_DAPM_ADC("ADC2", NULL, ES_ADC_CTRL, ES_ADC2_ON_SHIFT, 0),
-       SND_SOC_DAPM_ADC("ADC3", NULL, ES_ADC_CTRL, ES_ADC3_ON_SHIFT, 0),
+       SND_SOC_DAPM_ADC("ADC2", NULL, ES_ADC2_ON, ES_ADC2_ON_SHIFT, 0),
+       SND_SOC_DAPM_ADC("ADC3", NULL, ES_ADC3_ON, ES_ADC3_ON_SHIFT, 0),
 
        /* DAC */
        SND_SOC_DAPM_DAC("DAC0L", NULL, SND_SOC_NOPM, 0, 0),
@@ -411,7 +370,6 @@ const struct snd_soc_dapm_widget es_codec_dapm_widgets[] = {
        /* Earphone Mixer */
        SND_SOC_DAPM_MIXER("EP MIXER", SND_SOC_NOPM, 0, 0,
                ep_mix, ARRAY_SIZE(ep_mix)),
-
        /* Headphone Mixer */
        SND_SOC_DAPM_MIXER("HPL MIXER", SND_SOC_NOPM, 0, 0,
                hpl_mix, ARRAY_SIZE(hpl_mix)),
@@ -431,25 +389,23 @@ const struct snd_soc_dapm_widget es_codec_dapm_widgets[] = {
                lo_r_mix, ARRAY_SIZE(lo_r_mix)),
 
        /* Output PGAs */
-       SND_SOC_DAPM_PGA("SPKRL PGA", ES_SPKR_L_CTRL, ES_SPKRL_ON_SHIFT,
+       SND_SOC_DAPM_PGA("SPKRL PGA", ES_SPKRL_ON, ES_SPKRL_ON_SHIFT,
                0, NULL, 0),
-       SND_SOC_DAPM_PGA("SPKRR PGA", ES_SPKR_R_CTRL, ES_SPKRR_ON_SHIFT,
+       SND_SOC_DAPM_PGA("SPKRR PGA", ES_SPKRR_ON, ES_SPKRR_ON_SHIFT,
                0, NULL, 0),
-       SND_SOC_DAPM_PGA("HPL PGA", ES_HP_L_CTRL, ES_HPL_ON_SHIFT, 0, NULL, 0),
-       SND_SOC_DAPM_PGA("HPR PGA", ES_HP_R_CTRL, ES_HPR_ON_SHIFT, 0, NULL, 0),
-       SND_SOC_DAPM_PGA_E("LOL PGA", ES_LO_L_CTRL, ES_LO_L_ON_SHIFT, 0, NULL,
-               0, es_lo_enable, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
-       SND_SOC_DAPM_PGA_E("LOR PGA", ES_LO_R_CTRL, ES_LO_R_ON_SHIFT, 0, NULL,
-               0, es_lo_enable, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
-       SND_SOC_DAPM_PGA("EP PGA", ES_EP_CTRL, ES_EP_ON_SHIFT, 0, NULL, 0),
+       SND_SOC_DAPM_PGA("HPL PGA", ES_HPL_ON, ES_HPL_ON_SHIFT, 0, NULL, 0),
+       SND_SOC_DAPM_PGA("HPR PGA", ES_HPR_ON, ES_HPR_ON_SHIFT, 0, NULL, 0),
+       SND_SOC_DAPM_PGA("LOL PGA", ES_LO_L_ON, ES_LO_L_ON_SHIFT, 0, NULL, 0),
+       SND_SOC_DAPM_PGA("LOR PGA", ES_LO_R_ON, ES_LO_R_ON_SHIFT, 0, NULL, 0),
+       SND_SOC_DAPM_PGA("EP PGA", ES_EP_ON, ES_EP_ON_SHIFT, 0, NULL, 0),
 
        /* Input PGAs */
        SND_SOC_DAPM_PGA("MIC0 PGA", SND_SOC_NOPM, 0, 0, NULL, 0),
        SND_SOC_DAPM_PGA("MIC1 PGA", SND_SOC_NOPM, 0, 0, NULL, 0),
        SND_SOC_DAPM_PGA("MIC2 PGA", SND_SOC_NOPM, 0, 0, NULL, 0),
-       SND_SOC_DAPM_PGA("AUXINL PGA", ES_AUX_L_CTRL, ES_AUXL_ON_SHIFT, 0,
+       SND_SOC_DAPM_PGA("AUXINL PGA", ES_AUXL_ON, ES_AUXL_ON_SHIFT, 0,
                NULL, 0),
-       SND_SOC_DAPM_PGA("AUXINR PGA", ES_AUX_R_CTRL, ES_AUXR_ON_SHIFT, 0,
+       SND_SOC_DAPM_PGA("AUXINR PGA", ES_AUXR_ON, ES_AUXR_ON_SHIFT,    0,
                NULL, 0),
 
 };
@@ -459,19 +415,19 @@ static const struct snd_soc_dapm_route intercon[] = {
 
        /* Capture path */
 
-       /*{"MICHS", NULL, "MICHS Bias"},
-       {"MIC0", NULL, "MIC0 Bias"},*/
+       {"MIC0", NULL, "MIC0 Bias"},
        {"MIC1", NULL, "MIC1 Bias"},
        {"MIC2", NULL, "MIC2 Bias"},
 
-       {"MICHS ON", "Switch", "MICHS"},
+       {"MIC0 PGA Mux", "MIC-0", "MIC0"},
+       {"MIC0 PGA Mux", "MIC-HS", "MICHS"},
+       {"MIC0 PGA", NULL, "MIC0 PGA Mux"},
+
+       {"MIC1 PGA Mux", "MIC-1", "MIC1"},
+       {"MIC1 PGA Mux", "MIC-HS", "MICHS"},
+       {"MIC1 PGA", NULL, "MIC1 PGA Mux"},
 
-       /*{"MIC0 PGA", NULL, "MIC0"},*/
-       {"MIC0 PGA", NULL, "MICHS ON"},
-       {"MIC1 PGA", NULL, "MIC1"},
-       {"MIC1 PGA", NULL, "MICHS ON"},
        {"MIC2 PGA", NULL, "MIC2"},
-       {"MIC2 PGA", NULL, "MICHS ON"},
 
        {"AUXINL PGA", NULL, "AUXINP"},
        {"AUXINR PGA", NULL, "AUXINM"},
@@ -490,20 +446,15 @@ static const struct snd_soc_dapm_route intercon[] = {
 
        {"SPKRL MIXER", "DAC0L", "DAC0L"},
        {"SPKRL MIXER", "DAC1L", "DAC1L"},
-       {"SPKRL MIXER", "AUXL", "AUXINL PGA"},
 
        {"SPKRR MIXER", "DAC0R", "DAC0R"},
        {"SPKRR MIXER", "DAC1R", "DAC1R"},
-       {"SPKRR MIXER", "AUXR", "AUXINR PGA"},
 
        {"HPL MIXER", "DAC0L", "DAC0L"},
-       {"HPL MIXER", "AUXL", "AUXINL PGA"},
 
        {"HPR MIXER", "DAC0R", "DAC0R"},
-       {"HPR MIXER", "AUXR", "AUXINR PGA"},
 
        {"EP MIXER", "DAC0L", "DAC0L"},
-       {"EP MIXER", "AUXL", "AUXINL PGA"},
 
        {"LOL MIXER", "DAC1L", "DAC1L"},
 
@@ -524,8 +475,6 @@ static const struct snd_soc_dapm_route intercon[] = {
        {"SPKRL", NULL, "SPKRL PGA"},
        {"SPKRR", NULL, "SPKRR PGA"},
        {"EP", NULL, "EP PGA"},
-       /* Dummy entry */
-       {"EPR", NULL, "DAC0R"},
 
 };
 
@@ -533,8 +482,13 @@ int es_analog_add_snd_soc_controls(struct snd_soc_codec *codec)
 {
        int rc;
 
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)
        rc = snd_soc_add_codec_controls(codec, es_codec_snd_controls,
                        ARRAY_SIZE(es_codec_snd_controls));
+#else
+       rc = snd_soc_add_controls(codec, es_codec_snd_controls,
+                       ARRAY_SIZE(es_codec_snd_controls));
+#endif
 
        return rc;
 }
index 2cb7f968d94bc36b968e24c6bc43f1658fadd758..8e9b5c1593aebefa013d43b5c5aff97a99a46b95 100644 (file)
@@ -160,7 +160,7 @@ enum {
        PT_VP_CSOUT1_MUX,
        PT_VP_FEOUT1_MUX,
        PT_VP_AO1_MUX,
-       PT_VP_MO2_MUX,
+       PT_VP_AO2_MUX,
        PT_VP_OUT_MUX_LEN,
 };
 
@@ -248,10 +248,10 @@ static struct route_tbl es_pt_vp_out_route_tbl[PT_VP_OUT_MUX_LEN] = {
                .cmd_len = 1,
                .chn_mgr_mask = BIT(TXCHMGR4),
        },
-       [PT_VP_MO2_MUX] = {
+       [PT_VP_AO2_MUX] = {
                .cmd[0] = ES_API_WORD(ES_SET_MUX_CMD,
                                ES300_DATA_PATH(0, 0, TXCHMGR5)),
-               .mux_type = PASS_MO2,
+               .mux_type = PASS_AO2,
                .cmd_len = 1,
                .chn_mgr_mask = BIT(TXCHMGR5),
        },
@@ -266,46 +266,170 @@ struct es_mux_info es_pt_vp_mux_info = {
        .out_tbl = &es_pt_vp_out_route_tbl,
 };
 
-/* DHWPT Mux ENUM */
+/* AudioFocus Mux ENUM */
 enum {
-       DHWPT_PASSIN1_MUX,
-       DHWPT_PASSIN2_MUX,
-       DHWPT_PRIMARY_MUX,
-       DHWPT_SECONDARY_MUX,
-       DHWPT_FEIN_MUX,
-       DHWPT_IN_MUX_LEN,
+       AF_PASSIN1_MUX,
+       AF_PASSIN2_MUX,
+       AF_PRIMARY_MUX,
+       AF_SECONDARY_MUX,
+       AF_TERTIARY_MUX,
+
+       AF_IN_MUX_LEN,
 };
+
 enum {
-       DHWPT_PASSOUT1_MUX,
-       DHWPT_PASSOUT2_MUX,
-       DHWPT_CSOUT1_MUX,
-       DHWPT_FEOUT1_MUX,
-       DHWPT_AO1_MUX,
-       DHWPT_MO2_MUX,
-       DHWPT_OUT_MUX_LEN,
+       AF_PASSOUT1_MUX,
+       AF_PASSOUT2_MUX,
+       AF_CSOUT1_MUX,
+       AF_CSOUT2_MUX,
+       AF_AO1_MUX,
+       AF_AO2_MUX,
+
+       AF_OUT_MUX_LEN,
 };
 
-static struct route_tbl es_dhwpt_in_route_tbl[DHWPT_IN_MUX_LEN] = {
-       [DHWPT_PASSIN1_MUX] = {
-               .cmd[0] = ES_API_WORD(0xB05A, 0x3FF3),
+static struct route_tbl es_audiofocus_in_route_tbl[AF_IN_MUX_LEN] = {
+       [AF_PASSIN1_MUX] = {
+               .cmd[0] = ES_API_WORD(ES_SET_PATH_CMD,
+                               (ES300_DATA_PATH(0, 0, RXCHMGR3))),
                .mux_type = ES_PASSIN1_MUX,
                .cmd_len = 1,
                .chn_mgr_mask = BIT(RXCHMGR3),
        },
-       [DHWPT_PASSIN2_MUX] = {
-               .cmd[0] = ES_API_WORD(0xB05A, 0x3FF4),
+       [AF_PASSIN2_MUX] = {
+               .cmd[0] = ES_API_WORD(ES_SET_MUX_CMD,
+                               ES300_DATA_PATH(0, 0, RXCHMGR4)),
                .mux_type = ES_PASSIN2_MUX,
                .cmd_len = 1,
                .chn_mgr_mask = BIT(RXCHMGR4),
        },
-       [DHWPT_PRIMARY_MUX] = {
+       [AF_PRIMARY_MUX] = {
+               .cmd[0] = ES_API_WORD(ES_SET_MUX_CMD,
+                               ES300_DATA_PATH(0, 0, RXCHMGR0)),
+               .mux_type = ES_AF_PRI_MUX,
+               .cmd_len = 1,
+               .chn_mgr_mask = BIT(RXCHMGR0),
+       },
+       [AF_SECONDARY_MUX] = {
+               .cmd[0] = ES_API_WORD(ES_SET_MUX_CMD,
+                               ES300_DATA_PATH(0, 0, RXCHMGR1)),
+               .mux_type = ES_AF_SEC_MUX,
+               .cmd_len = 1,
+               .chn_mgr_mask = BIT(RXCHMGR1),
+       },
+       [AF_TERTIARY_MUX] = {
+               .cmd[0] = ES_API_WORD(ES_SET_MUX_CMD,
+                               ES300_DATA_PATH(0, 0, RXCHMGR2)),
+               .cmd[1] = ES_API_WORD(0xB05B, 0x0202),
+               .cmd[2] = ES_API_WORD(0xB064, 0x0058),
+               .cmd[3] = ES_API_WORD(0xB064, 0x0142),
+               .cmd[4] = ES_API_WORD(0xB063, 0x0205),
+               .cmd[5] = ES_API_WORD(0xB068, 0x0500),
+               .mux_type = ES_AF_TER_MUX,
+               .cmd_len = 6,
+               .chn_mgr_mask = BIT(RXCHMGR2),
+       },
+};
+
+static struct route_tbl es_audiofocus_out_route_tbl[AF_OUT_MUX_LEN] = {
+       [AF_PASSOUT1_MUX] = {
+               .cmd[0] = ES_API_WORD(ES_SET_MUX_CMD,
+                               ES300_DATA_PATH(0, 0, TXCHMGR0)),
+               .mux_type = PASS_AUDOUT1,
+               .cmd_len = 1,
+               .chn_mgr_mask = BIT(TXCHMGR0),
+       },
+       [AF_PASSOUT2_MUX] = {
+               .cmd[0] = ES_API_WORD(ES_SET_MUX_CMD,
+                               ES300_DATA_PATH(0, 0, TXCHMGR5)),
+               .mux_type = PASS_AUDOUT2,
+               .cmd_len = 1,
+               .chn_mgr_mask = BIT(TXCHMGR5),
+       },
+       [AF_CSOUT1_MUX] = {
+               .cmd[0] = ES_API_WORD(ES_SET_MUX_CMD,
+                               ES300_DATA_PATH(0, 0, TXCHMGR1)),
+               .mux_type = AUDIOFOCUS_CSOUT1,
+               .cmd_len = 1,
+               .chn_mgr_mask = BIT(TXCHMGR1),
+       },
+       [AF_CSOUT2_MUX] = {
+               .cmd[0] = ES_API_WORD(ES_SET_MUX_CMD,
+                               ES300_DATA_PATH(0, 0, TXCHMGR2)),
+               .mux_type = AUDIOFOCUS_CSOUT2,
+               .cmd_len = 1,
+               .chn_mgr_mask = BIT(TXCHMGR2),
+       },
+       [AF_AO1_MUX] = {
+               .cmd[0] = ES_API_WORD(ES_SET_MUX_CMD,
+                               ES300_DATA_PATH(0, 0, TXCHMGR3)),
+               .mux_type = PASS_AO1,
+               .cmd_len = 1,
+               .chn_mgr_mask = BIT(TXCHMGR3),
+       },
+       [AF_AO2_MUX] = {
+               .cmd[0] = ES_API_WORD(ES_SET_MUX_CMD,
+                               ES300_DATA_PATH(0, 0, TXCHMGR4)),
+               .mux_type = PASS_AO2,
+               .cmd_len = 1,
+               .chn_mgr_mask = BIT(TXCHMGR4),
+       },
+};
+
+struct es_mux_info es_audiofocus_mux_info = {
+       .in_mux_start = AF_PASSIN1_MUX,
+       .in_mux_len = AF_IN_MUX_LEN,
+       .out_mux_start = AF_PASSOUT1_MUX,
+       .out_mux_len = AF_OUT_MUX_LEN,
+       .in_tbl = &es_audiofocus_in_route_tbl,
+       .out_tbl = &es_audiofocus_out_route_tbl,
+};
+
+/* Barge-In Mux ENUM */
+enum {
+       BRG_PASSIN1_MUX,
+       BRG_PASSIN2_MUX,
+       BRG_PRIMARY_MUX,
+       BRG_SECONDARY_MUX,
+       BRG_FEIN_MUX,
+
+       BRG_IN_MUX_LEN,
+};
+
+enum {
+       BRG_PASSOUT1_MUX,
+       BRG_PASSOUT2_MUX,
+       BRG_CSOUT1_MUX,
+       BRG_CSOUT2_MUX,
+       BRG_AO1_MUX,
+       BRG_AO2_MUX,
+
+       BRG_OUT_MUX_LEN,
+};
+
+static struct route_tbl es_bargein_in_route_tbl[BRG_IN_MUX_LEN] = {
+       [BRG_PASSIN1_MUX] = {
+               .cmd[0] = ES_API_WORD(ES_SET_PATH_CMD,
+                               (ES300_DATA_PATH(0, 0, RXCHMGR3))),
+               .mux_type = ES_PASSIN1_MUX,
+               .cmd_len = 1,
+               .chn_mgr_mask = BIT(RXCHMGR3),
+       },
+       [BRG_PASSIN2_MUX] = {
+               .cmd[0] = ES_API_WORD(ES_SET_MUX_CMD,
+                               ES300_DATA_PATH(0, 0, RXCHMGR4)),
+               .mux_type = ES_PASSIN2_MUX,
+               .cmd_len = 1,
+               .chn_mgr_mask = BIT(RXCHMGR4),
+       },
+       [BRG_PRIMARY_MUX] = {
                .cmd[0] = ES_API_WORD(ES_SET_MUX_CMD,
                                ES300_DATA_PATH(0, 0, RXCHMGR0)),
                .mux_type = ES_PRIMARY_MUX,
                .cmd_len = 1,
                .chn_mgr_mask = BIT(RXCHMGR0),
        },
-       [DHWPT_SECONDARY_MUX] = {
+       [BRG_SECONDARY_MUX] = {
                .cmd[0] = ES_API_WORD(ES_SET_MUX_CMD,
                                ES300_DATA_PATH(0, 0, RXCHMGR1)),
                .cmd[1] = ES_API_WORD(0xB05B, 0x0101),
@@ -317,7 +441,7 @@ static struct route_tbl es_dhwpt_in_route_tbl[DHWPT_IN_MUX_LEN] = {
                .cmd_len = 6,
                .chn_mgr_mask = BIT(RXCHMGR1),
        },
-       [DHWPT_FEIN_MUX] = {
+       [BRG_FEIN_MUX] = {
                .cmd[0] = ES_API_WORD(ES_SET_MUX_CMD,
                                ES300_DATA_PATH(0, 0, RXCHMGR2)),
                .cmd[1] = ES_API_WORD(0xB05B, 0x0203),
@@ -331,56 +455,148 @@ static struct route_tbl es_dhwpt_in_route_tbl[DHWPT_IN_MUX_LEN] = {
        },
 };
 
-static struct route_tbl es_dhwpt_out_route_tbl[DHWPT_OUT_MUX_LEN] = {
-       [DHWPT_PASSOUT1_MUX] = {
-               .cmd[0] = ES_API_WORD(0xB05A, 0x3FFA),
+static struct route_tbl es_bargein_out_route_tbl[BRG_OUT_MUX_LEN] = {
+       [BRG_PASSOUT1_MUX] = {
+               .cmd[0] = ES_API_WORD(ES_SET_MUX_CMD,
+                               ES300_DATA_PATH(0, 0, TXCHMGR0)),
                .mux_type = PASS_AUDOUT1,
                .cmd_len = 1,
                .chn_mgr_mask = BIT(TXCHMGR0),
        },
-       [DHWPT_PASSOUT2_MUX] = {
-               .cmd[0] = ES_API_WORD(0xB05A, 0x3FFB),
+       [BRG_PASSOUT2_MUX] = {
+               .cmd[0] = ES_API_WORD(ES_SET_MUX_CMD,
+                               ES300_DATA_PATH(0, 0, TXCHMGR5)),
                .mux_type = PASS_AUDOUT2,
                .cmd_len = 1,
+               .chn_mgr_mask = BIT(TXCHMGR5),
+       },
+       [BRG_CSOUT1_MUX] = {
+               .cmd[0] = ES_API_WORD(ES_SET_MUX_CMD,
+                               ES300_DATA_PATH(0, 0, TXCHMGR1)),
+               .mux_type = VP_CSOUT1,
+               .cmd_len = 1,
                .chn_mgr_mask = BIT(TXCHMGR1),
        },
-       [DHWPT_CSOUT1_MUX] = {
+       [BRG_CSOUT2_MUX] = {
                .cmd[0] = ES_API_WORD(ES_SET_MUX_CMD,
                                ES300_DATA_PATH(0, 0, TXCHMGR2)),
-               .mux_type = VP_CSOUT1,
+               .mux_type = VP_CSOUT2,
                .cmd_len = 1,
                .chn_mgr_mask = BIT(TXCHMGR2),
        },
-       [DHWPT_FEOUT1_MUX] = {
+       [BRG_AO1_MUX] = {
                .cmd[0] = ES_API_WORD(ES_SET_MUX_CMD,
                                ES300_DATA_PATH(0, 0, TXCHMGR3)),
-               .mux_type = VP_FEOUT1,
+               .mux_type = PASS_AO1,
                .cmd_len = 1,
                .chn_mgr_mask = BIT(TXCHMGR3),
        },
-       [DHWPT_AO1_MUX] = {
+       [BRG_AO2_MUX] = {
                .cmd[0] = ES_API_WORD(ES_SET_MUX_CMD,
                                ES300_DATA_PATH(0, 0, TXCHMGR4)),
-               .mux_type = PASS_AO1,
+               .mux_type = PASS_AO2,
                .cmd_len = 1,
                .chn_mgr_mask = BIT(TXCHMGR4),
        },
-       [DHWPT_MO2_MUX] = {
+};
+
+struct es_mux_info es_bargein_mux_info = {
+       .in_mux_start = BRG_PASSIN1_MUX,
+       .in_mux_len = BRG_IN_MUX_LEN,
+       .out_mux_start = BRG_PASSOUT1_MUX,
+       .out_mux_len = BRG_OUT_MUX_LEN,
+       .in_tbl = &es_bargein_in_route_tbl,
+       .out_tbl = &es_bargein_out_route_tbl,
+};
+
+/* KalaOK Mux ENUM */
+enum {
+       KALAOK_PASSIN1_MUX,
+       KALAOK_PASSIN2_MUX,
+       KALAOK_PASSIN3_MUX,
+
+       KALAOK_IN_MUX_LEN,
+};
+
+enum {
+       KALAOK_PASSOUT1_MUX,
+       KALAOK_PASSOUT2_MUX,
+       KALAOK_PASSOUT3_MUX,
+       KALAOK_AO1_MUX,
+       KALAOK_AO2_MUX,
+
+       KALAOK_OUT_MUX_LEN,
+};
+
+static struct route_tbl es_kalaok_in_route_tbl[KALAOK_IN_MUX_LEN] = {
+       [KALAOK_PASSIN1_MUX] = {
+               .cmd[0] = ES_API_WORD(ES_SET_PATH_CMD,
+                               (ES300_DATA_PATH(0, 0, RXCHMGR0))),
+               .mux_type = ES_PASSIN1_MUX,
+               .cmd_len = 1,
+               .chn_mgr_mask = BIT(RXCHMGR0),
+       },
+       [KALAOK_PASSIN2_MUX] = {
                .cmd[0] = ES_API_WORD(ES_SET_MUX_CMD,
-                               ES300_DATA_PATH(0, 0, TXCHMGR5)),
-               .mux_type = PASS_MO2,
+                               ES300_DATA_PATH(0, 0, RXCHMGR1)),
+               .mux_type = ES_PASSIN2_MUX,
                .cmd_len = 1,
-               .chn_mgr_mask = BIT(TXCHMGR5),
+               .chn_mgr_mask = BIT(RXCHMGR1),
+       },
+       [KALAOK_PASSIN3_MUX] = {
+               .cmd[0] = ES_API_WORD(ES_SET_MUX_CMD,
+                               ES300_DATA_PATH(0, 0, RXCHMGR2)),
+               .mux_type = ES_PASSIN3_MUX,
+               .cmd_len = 1,
+               .chn_mgr_mask = BIT(RXCHMGR2),
+       },
+};
+
+static struct route_tbl es_kalaok_out_route_tbl[KALAOK_OUT_MUX_LEN] = {
+       [KALAOK_PASSOUT1_MUX] = {
+               .cmd[0] = ES_API_WORD(ES_SET_MUX_CMD,
+                               ES300_DATA_PATH(0, 0, TXCHMGR0)),
+               .mux_type = PASS_AUDOUT1,
+               .cmd_len = 1,
+               .chn_mgr_mask = BIT(TXCHMGR0),
+       },
+       [KALAOK_PASSOUT2_MUX] = {
+               .cmd[0] = ES_API_WORD(ES_SET_MUX_CMD,
+                               ES300_DATA_PATH(0, 0, TXCHMGR1)),
+               .mux_type = PASS_AUDOUT2,
+               .cmd_len = 1,
+               .chn_mgr_mask = BIT(TXCHMGR1),
+       },
+       [KALAOK_PASSOUT3_MUX] = {
+               .cmd[0] = ES_API_WORD(ES_SET_MUX_CMD,
+                               ES300_DATA_PATH(0, 0, TXCHMGR2)),
+               .mux_type = PASS_AUDOUT3,
+               .cmd_len = 1,
+               .chn_mgr_mask = BIT(TXCHMGR2),
+       },
+       [KALAOK_AO1_MUX] = {
+               .cmd[0] = ES_API_WORD(ES_SET_MUX_CMD,
+                               ES300_DATA_PATH(0, 0, TXCHMGR3)),
+               .mux_type = PASS_AO1,
+               .cmd_len = 1,
+               .chn_mgr_mask = BIT(TXCHMGR3),
+       },
+       [KALAOK_AO2_MUX] = {
+               .cmd[0] = ES_API_WORD(ES_SET_MUX_CMD,
+                               ES300_DATA_PATH(0, 0, TXCHMGR4)),
+               .mux_type = PASS_AO2,
+               .cmd_len = 1,
+               .chn_mgr_mask = BIT(TXCHMGR4),
        },
 };
 
-struct es_mux_info es_dhwpt_mux_info = {
-       .in_mux_start = DHWPT_PASSIN1_MUX,
-       .in_mux_len = DHWPT_IN_MUX_LEN,
-       .out_mux_start = DHWPT_PASSOUT1_MUX,
-       .out_mux_len = DHWPT_OUT_MUX_LEN,
-       .in_tbl = &es_dhwpt_in_route_tbl,
-       .out_tbl = &es_dhwpt_out_route_tbl,
+struct es_mux_info es_kalaok_mux_info = {
+       .in_mux_start = KALAOK_PASSIN1_MUX,
+       .in_mux_len = KALAOK_IN_MUX_LEN,
+       .out_mux_start = KALAOK_PASSOUT1_MUX,
+       .out_mux_len = KALAOK_OUT_MUX_LEN,
+       .in_tbl = &es_kalaok_in_route_tbl,
+       .out_tbl = &es_kalaok_out_route_tbl,
 };
 
 void prepare_mux_cmd(int mux, u32 *msg, u32 *msg_len,
index e298260d3d8e84ce093da04f016d1c8e54c7d4ad..1943aef8081f1f005dfc86d822199952a41a3315 100644 (file)
@@ -28,8 +28,8 @@ enum {
        VP_CSOUT2,
        VP_FEOUT1,
        VP_FEOUT2,
-       AUDIOZOOM_CSOUT,
-       AUDIOZOOM_AOUT1,
+       AUDIOFOCUS_CSOUT1,
+       AUDIOFOCUS_CSOUT2,
        MM_AUDOUT1,
        MM_AUDOUT2,
        MM_PASSOUT1,
@@ -41,7 +41,7 @@ enum {
        PASS_AUDOUT3,
        PASS_AUDOUT4,
        PASS_AO1,
-       PASS_MO2,
+       PASS_AO2,
        MONOUT1,
        MONOUT2,
        MONOUT3,
@@ -60,12 +60,12 @@ enum {
        VP,
        PT,
        MM,
-       AUDIOZOOM,
+       AUDIOFOCUS,
        VP_MM,
        PT_VP,
        PT_VP_DSM,
        VP_DSM,
-       AZ_DSM,
+       AF_DSM,
        PT_COPY,
        PT_4CH,
        VP_2CSOUT,
@@ -73,9 +73,11 @@ enum {
 };
 #endif
 /* MUX info structure for each base route */
-extern struct es_mux_info es_dhwpt_mux_info;
+extern struct es_mux_info es_kalaok_mux_info;
+extern struct es_mux_info es_bargein_mux_info;
 extern struct es_mux_info es_pt_vp_mux_info;
 extern struct es_mux_info es_vp_mux_info;
+extern struct es_mux_info es_audiofocus_mux_info;
 
 /* Helper routines to build commands for any base route */
 void prepare_mux_cmd(int mux, u32 *msg, u32 *msg_len,
index ae239ebdc48a251390dd07790ec9c7473d372f66..0ee2524299e7703893b1af273c23564ea693ca4f 100644 (file)
 #include "es-d300.h"
 #include "es-d300-route.h"
 
+
+/* Switch initialization */
+static struct switch_setting es_d300_switch[SW_MAX] = {
+       [SWIN1] = {
+               .value_cmd[0] = 0x90660009, /* Input 0 */
+               .value_cmd[1] = 0x90660109, /* Input 1 */
+               .value = 0, /* Default Value */
+       },
+       [SWIN2] = {
+               .value_cmd[0] = 0x9066000A, /* Input 0 */
+               .value_cmd[1] = 0x9066010A, /* Input 1 */
+               .value = 0, /* Default Value */
+       },
+       [SWOUT0] = {
+               .value_cmd[0] = 0x90660000, /* Output 0 */
+               .value_cmd[1] = 0x90660100, /* Output 1 */
+               .value = 0, /* Default Value */
+       },
+       [SWOUT1] = {
+               .value_cmd[0] = 0x90660001, /* Output 0 */
+               .value_cmd[1] = 0x90660101, /* Output 1 */
+               .value = 0, /* Default Value */
+       },
+       [SWOUT2] = {
+               .value_cmd[0] = 0x90660002, /* Output 0 */
+               .value_cmd[1] = 0x90660102, /* Output 1 */
+               .value = 0, /* Default Value */
+       },
+       [SWOUT3] = {
+               .value_cmd[0] = 0x90660003, /* Output 0 */
+               .value_cmd[1] = 0x90660103, /* Output 1 */
+               .value = 0, /* Default Value */
+       },
+};
+
 struct cachedcmd_t {
        u8 reg;
-       u8 refcnt;
 };
 
 struct cachedcmd_t prev_cmdlist[ES_API_ADDR_MAX];
@@ -57,27 +91,15 @@ struct channel_id {
 static struct cachedcmd_t **cachedcmd_list;
 static int es_vp_tx;
 static int es_vp_rx;
-static int es_az_tx;
-static int es_az_rx;
+static int es_af_tx;
+static int es_af_rx;
 
 #define LEFT_CAPTURE           0x1
 #define RIGHT_CAPTURE          0x2
 #define MONO_CAPTURE           (LEFT_CAPTURE)
 #define STEREO_CAPTURE         (LEFT_CAPTURE | RIGHT_CAPTURE)
 
-#define OUTPUT_NONE    0x0
-#define OUTPUT_AO1     0x1
-#define OUTPUT_MO2     0x2
-#define OUTPUT_PO1     0x4
-#define OUTPUT_PO2     0x8
-
-/* Used to provide mixed output on a single channel output */
-#define OUTPUT_MIXED_MONO      (OUTPUT_AO1)
-
-/* Used to copy the stereo output to extra two channels output */
-#define OUTPUT_PT_COPY         (OUTPUT_AO1 | OUTPUT_MO2)
-
-/* Mask to keep track of chmgrs set by UCM */
+/* Mask to keep track of chmgrs set by UCM per algorithm type*/
 static u16 chn_mgr_mask[ALGO_MAX];
 
 static const u8 pcm_port[] = { 0x0, 0xA, 0xB, 0xC };
@@ -126,53 +148,25 @@ static const u16 es300_input_mux_text_to_api[] = {
 static const char * const proc_block_output_texts[] = {
        "None",
        "VP CSOUT1", "VP CSOUT2", "VP FEOUT1", "VP FEOUT2",
-       "AudioZoom CSOUT",
-       "AudioZoom AOUT1",
+       "AudioFocus CSOUT1",
+       "AudioFocus CSOUT2",
        "MM AUDOUT1", "MM AUDOUT2", "MM PASSOUT1", "MM PASSOUT2",
        "MM MONOUT1", "MM MONOUT2",
        "Pass AUDOUT1", "Pass AUDOUT2", "Pass AUDOUT3", "Pass AUDOUT4",
-       "Pass AO1", "Pass MO2",
+       "Pass AO1", "Pass AO2",
        "MONOUT1", "MONOUT2", "MONOUT3", "MONOUT4",
+       "PCM0.0", "PCM0.1", "PCM0.2", "PCM0.3",
+       "PCM1.0", "PCM1.1", "PCM1.2", "PCM1.3",
+       "PCM2.0", "PCM2.1", "PCM2.2", "PCM2.3",
 };
 
-static const u16 es300_output_mux_text_to_api[] = {
-       0xffff, /* Default value for all output MUXes */
-
-       /* VP outputs */
-       ES300_PATH_ID(TXCHMGR0, ES300_CSOUT1),
-       ES300_PATH_ID(TXCHMGR1, ES300_CSOUT2),
-       ES300_PATH_ID(TXCHMGR2, ES300_FEOUT1),
-       ES300_PATH_ID(TXCHMGR3, ES300_FEOUT2),
-
-       /* AudioZoom */
-       ES300_PATH_ID(TXCHMGR0, ES300_CSOUT1),
-       ES300_PATH_ID(TXCHMGR1, ES300_AUDOUT1),
-
-       /* MM AUDOUT */
-       ES300_PATH_ID(TXCHMGR0, ES300_AUDOUT1),
-       ES300_PATH_ID(TXCHMGR1, ES300_AUDOUT2),
-
-       /* MM PASSOUT */
-       ES300_PATH_ID(TXCHMGR4, ES300_PASSOUT1),
-       ES300_PATH_ID(TXCHMGR5, ES300_PASSOUT2),
-
-       /* MM MONOUT */
-       ES300_PATH_ID(TXCHMGR2, ES300_MM_MONOUT1),
-       ES300_PATH_ID(TXCHMGR3, ES300_MM_MONOUT2),
-
-       /* Passthru AUDOUT */
-       ES300_PATH_ID(TXCHMGR0, ES300_PASSOUT1),
-       ES300_PATH_ID(TXCHMGR1, ES300_PASSOUT2),
-       ES300_PATH_ID(TXCHMGR2, ES300_PASSOUT3),
-       ES300_PATH_ID(TXCHMGR3, ES300_PASSOUT4),
-       ES300_PATH_ID(TXCHMGR4, ES300_AUDOUT1),
-       ES300_PATH_ID(TXCHMGR5, ES300_MONOUT2),
-
-       /* UI Tone MONOUT */
-       ES300_PATH_ID(TXCHMGR1, ES300_MONOUT1),
-       ES300_PATH_ID(TXCHMGR2, ES300_MONOUT2),
-       ES300_PATH_ID(0, ES300_MONOUT3),
-       ES300_PATH_ID(0, ES300_MONOUT4),
+
+static const char * const pri_pb_mode_texts[] = {
+       "Off", "Stereo"
+};
+
+static const char * const sec_pb_mode_texts[] = {
+       "Off", "Mixed Mono", "Stereo"
 };
 
 struct out_mux_map es_out_mux_map[] = {
@@ -201,18 +195,11 @@ struct out_mux_map es_out_mux_map[] = {
 };
 
 static const u32 es_base_route_preset[ALGO_MAX] = {
-       [VP] = 0x90311771,
-       [VP_MM] = 0x90311777,
-       [PASSTHRU_VP] = 0x90311785,
-       [AUDIOZOOM] = 0x90311774,
-#if defined(CONFIG_SND_SOC_ES_SLIM)
-       [MM] = 0x90311773,
-       [PASSTHRU] = 0x90311776,
-#else
-       [MM] = 0x90311772,
-       [PASSTHRU] = 0x9031177D,
-#endif
-       [DHWPT] = 0x9031178F,
+       [VP] = 0xB0311771,
+       [AUDIOFOCUS] = 0xB031179B,
+       [PASSTHRU_VP] = 0xB0311785,
+       [BARGE_IN] = 0xB0311799,
+       [KALA_OK] = 0xB031179A,
 };
 
 static const struct es_ch_mgr_max es_chn_mgr_max[ALGO_MAX] = {
@@ -220,50 +207,41 @@ static const struct es_ch_mgr_max es_chn_mgr_max[ALGO_MAX] = {
                .rx = VP_RXCHMGR_MAX,
                .tx = VP_TXCHMGR_MAX,
        },
-       [MM] = {
-               .rx = MM_RXCHMGR_MAX,
-               .tx = MM_TXCHMGR_MAX,
-       },
-       [VP_MM] = {
-               .rx = VP_MM_RXCHMGR_MAX,
-               .tx = VP_MM_TXCHMGR_MAX,
+       [AUDIOFOCUS] = {
+               .tx = AUDIOFOCUS_TXCHMGR_MAX,
        },
        [PASSTHRU_VP] = {
                .tx = PT_VP_TXCHMGR_MAX,
        },
-       [DHWPT] = {
-               .rx = DHWPT_RXCHMGR_MAX,
-               .tx = DHWPT_TXCHMGR_MAX,
+       [BARGE_IN] = {
+               .tx = BARGE_IN_TXCHMGR_MAX,
+       },
+       [KALA_OK] = {
+               .rx = KALA_OK_RXCHMGR_MAX,
+               .tx = KALA_OK_TXCHMGR_MAX,
        },
 };
 
-static u32 switch_arr[] = {
-       [SWIN1_I0] = 0x90660009,
-       [SWIN1_I1] = 0x90660109,
-       [SWIN2_I0] = 0x9066000A,
-       [SWIN2_I1] = 0x9066010A,
-       [SWOUT0_O1] = 0x90660100,
-       [SWOUT1_O1] = 0x90660101,
-       [SWOUT2_O1] = 0x90660102,
-       [SWOUT3_O1] = 0x90660103,
-};
-
-static int escore_set_switch(int id)
+/* This function must be called with access_lock acquired */
+static int _es_set_switch(int id)
 {
        struct escore_priv *escore = &escore_priv;
        u32 cmd, resp;
        int rc = 0;
+       int switch_value = 0;
+
+       switch_value = es_d300_switch[id].value;
+       cmd = es_d300_switch[id].value_cmd[switch_value];
+       cmd = cmd | (1 << ES_SC_BIT);
 
        /*
         * The delay is required to make sure the route is active.
         * Without delay, the switch settings are not coming into
         * effect.
         */
-       usleep_range(1000, 1005);
-       cmd = switch_arr[id];
+       usleep_range(5000, 5005);
 
-       mutex_lock(&escore->api_mutex);
-       rc = escore->bus.ops.cmd(escore, cmd, &resp);
+       rc = escore_cmd(escore, cmd, &resp);
        if (rc) {
                pr_err("%s(): Error %d setting switch preset %x\n",
                                __func__, rc, cmd);
@@ -271,44 +249,133 @@ static int escore_set_switch(int id)
        }
 
        /*
-       cmd = ES_SYNC_CMD << 16;
-       rc = escore->bus.ops.cmd(escore, cmd, &resp);
-       if (rc) {
-               pr_err("%s(): Error %d in sending sync cmd\n",
-                               __func__, rc);
-               goto err;
-       }
-       */
+        * For ES_POWER_LEVEL_x power saving mode other than ES_POWER_LEVEL_6,
+        * need delay after switch cmd based on ES_POWER_LEVEL_x.
+        */
+       if (escore->power_saving_mode != ES_POWER_LEVEL_DISABLE &&
+           escore->algo_type == PASSTHRU_VP &&
+           escore->power_saving_mode < ES_POWER_LEVEL_6)
+               msleep(5 * (ES_POWER_LEVEL_6 - escore->power_saving_mode));
+
 err:
-       mutex_unlock(&escore->api_mutex);
        return rc;
 }
 
-static int es300_codec_stop_algo(struct escore_priv *escore)
+/* This function must be called with access_lock acquired */
+int _es_stop_route(struct escore_priv *escore, u8 stream_type)
 {
        u32 stop_route_cmd = ES_STOP_ROUTE<<16;
        u32 resp;
        int ret = 0;
 
-       /* Disable DHWPT if enabled */
-       if (escore->algo_type == DHWPT) {
-               u32 cmd = escore->dhwpt_cmd & 0xFFFF0000;
-               ret = escore_cmd(escore, cmd, &resp);
-               if (ret) {
-                       pr_err("%s: Disabling DHWPT failed = %d\n",
-                                       __func__, ret);
-                       return ret;
-               }
+
+       /* If XML disable sequence is not started before stop route,
+        * set algo_type_off to algo_type */
+       if (escore->algo_type_off == ALGO_NONE)
+               escore->algo_type_off = escore->algo_type;
+
+       /* Check which algo is turned off with below check */
+       if (escore->algo_type == DHWPT || escore->algo_type == PASSTHRU_VP) {
+
+               if (stream_type == ES_TYPE_PB && escore->dhwpt_mode)
+                       escore->algo_type_off = DHWPT;
+               else
+                       escore->algo_type_off = PASSTHRU_VP;
        }
 
-       /* Stop the route */
-       ret = escore_cmd(escore, stop_route_cmd, &resp);
-       if (ret) {
-               pr_err("%s: Route stop failed\n", __func__);
-               return ret;
+
+       pr_debug("%s **** Stop route Algo type %d for stream type %d ******* \n", __func__,escore->algo_type_off, stream_type);
+
+
+       /* Stop the route first, except when stopping DHWPT use cases */
+       if (escore->algo_type_off != DHWPT) {
+               if (escore->algo_type_off == PASSTHRU_VP &&
+                                       escore->dhwpt_enabled &&
+                                       !escore->dhwpt_mode &&
+                                       escore->dhwpt_cmd) {
+
+                       u32 cmd = escore->dhwpt_cmd & 0xFFFF0000;
+                       ret = escore_cmd(escore, cmd, &resp);
+                       if (ret) {
+                               pr_err("%s: Disabling DHWPT failed = %d\n",
+                                               __func__, ret);
+                               return ret;
+                       }
+
+                       /* Require 1ms delay between stop route and DHWPT to avoid noise */
+                       usleep_range(5000, 5005);
+               }
+
+
+               if (escore->base_route_setup) {
+                       ret = escore_cmd(escore, stop_route_cmd, &resp);
+                       if (ret) {
+                               pr_err("%s: Route stop failed, ret = %d\n", __func__,
+                                               ret);
+                               return ret;
+                       }
+
+                       escore->base_route_setup = 0;
+               }
+
+               /* When stopping capture route and DHWPT playback is running,
+                * restore chip to MP_Sleep mode */
+               if (escore->algo_type_off == PASSTHRU_VP && escore->dhwpt_capture_on)
+                       escore->dhwpt_capture_on = 0;
+
+               if (escore->mp_sleep_requested && escore->dhwpt_mode && !escore->dhwpt_capture_on) {
+                       pr_debug("%s(): Put chip back into mp_sleep\n", __func__);
+                       ret = es755_enter_mp_sleep();
+                       if (ret) {
+                               pr_err("%s: es755_enter_mp_sleep failed = %d\n",
+                                               __func__, ret);
+                               return ret;
+                       }
+               }
+
+       } else {
+
+               if (escore->dhwpt_mode) {
+
+                       if (!escore->dhwpt_capture_on) {
+
+                               /* Disable DHWPT if enabled, or when stopping DHWPT use cases */
+                               u32 cmd = escore->dhwpt_cmd & 0xFFFF0000;
+
+                               /* Bring the chip from MP Sleep mode to Normal mode before
+                                * sending any commands */
+                               ret = es755_exit_mp_sleep();
+                               if (ret) {
+                                       pr_err("%s(): es755_exit_mp_sleep() fail %d\n",
+                                                       __func__, ret);
+                                       return ret;
+                               }
+
+                               ret = escore_cmd(escore, cmd, &resp);
+                               if (ret) {
+                                       pr_err("%s: Disabling DHWPT failed = %d\n",
+                                                       __func__, ret);
+                                       return ret;
+                               }
+                       } else {
+
+                               pr_debug("%s(): Seems DHWPT capture is on. Skip disabling DHWPT\n", __func__);
+                       }
+
+                       escore->dhwpt_mode = 0;
+               }
        }
 
+
        escore->current_preset = 0;
+       /* Reset algo_preset so that it is not accidently set for a
+       * diffeent route, UCM is responsible to set this algo preset
+       * for every use case
+       */
+       escore->algo_preset_one = 0;
+       escore->algo_preset_two = 0;
+       //escore->algo_type_off = ALGO_NONE;
+
        return ret;
 }
 
@@ -319,260 +386,150 @@ static void update_chan_id(u32 *msg, int chan_id)
        *msg |= ES_API_WORD(ES_SET_PATH_CMD,
                        ES300_DATA_PATH(0x0, chan_id, 0x0));
 }
+
+static int setup_dhwpt_msg(u32 *msg, int mux)
+{
+       pr_debug("****** %s() *********:\n", __func__);
+       switch (mux) {
+       case ES_PASSIN1_MUX:
+               msg[0] = 0xB05A3FF3;
+               break;
+       case ES_PASSIN2_MUX:
+               msg[0] = 0xB05A3FF4;
+               break;
+       case PASS_AUDOUT1:
+               msg[0] = 0xB05A3FFA;
+               chn_mgr_mask[PASSTHRU_VP] |= BIT(TXCHMGR0);
+               break;
+       case PASS_AUDOUT2:
+               msg[0] = 0xB05A3FFB;
+               chn_mgr_mask[PASSTHRU_VP] |= BIT(TXCHMGR1);
+               break;
+       default:
+               return 0;
+       }
+       return sizeof(msg[0]);
+}
+
 static int convert_input_mux_to_cmd(struct escore_priv *escore, int reg)
 {
        unsigned int value;
-       int msg_len = escore->api_access[reg].write_msg_len;
+       int msg_len;
        u32 msg[ES_CMD_ACCESS_WR_MAX] = {0};
-       u16 port, chnum;
-       u16 ch_mgr;
-       u8 path_id = 0;
-       u8 update_cmds = 0;
-       u8 update_chmgr_mask = 1;
+       u16 port;
        int mux = cachedcmd_list[escore->algo_type][reg].reg;
+       struct es_mux_info *in_mux_info = NULL;
+       u8 algo_type = escore->algo_type;
 
-       memcpy((char *)msg, (char *)escore->api_access[reg].write_msg,
-                       msg_len);
        value = es300_input_mux_text_to_api[mux];
 
        pr_debug("%s(): reg = %d mux = %d\n", __func__, reg, mux);
-       msg[0] |= value;
-       path_id = msg[1] & 0xFF;
-       ch_mgr = ES_CHMGR_DATAPATH(msg[0]);
-
-       switch (escore->algo_type) {
-       case AUDIOZOOM:
-               if (reg == ES_TERTIARY_MUX) {
-                       /* Connect RxChMgr2.o0 */
-                       msg[2] = ES_API_WORD(ES_CONNECT_CMD,
-                                       ES300_ENDPOINT(FILTER_RXCHANMGR2, OUT,
-                                               RxChMgr_o0));
-                       msg_len += sizeof(*msg);
-
-                       /* Connect AZ.i2 */
-                       msg[3] = ES_API_WORD(ES_CONNECT_CMD,
-                                       ES300_ENDPOINT(FILTER_AZ, IN, az_i2));
-                       msg_len += sizeof(*msg);
-
-                       /* Set Rate 48k */
-                       msg[4] = ES_API_WORD(ES_SET_RATE_CMD,
-                                       ES300_RATE(FILTER_RXCHANMGR2, 3));
-                       msg_len += sizeof(*msg);
-
-                       /* Set Rate 48k */
-                       msg[5] = ES_API_WORD(ES_SET_GROUP_CMD,
-                                       ES300_GROUP(FILTER_RXCHANMGR2, 0));
-                       msg_len += sizeof(*msg);
-
-               } else if (reg == ES_AZ_AI1_MUX) {
-                       port = (value >> 9) & 0x1f;
-                       chnum = (value >> 4) & 0x1f;
-
-                       /* Update the data path */
-                       msg[0] = ES_API_WORD(ES_SET_MUX_CMD,
-                                       ES300_DATA_PATH(port, chnum, RXCHMGR3));
-
-                       /* Set corresponding path id */
-                       msg[1] = ES_API_WORD(ES_SET_PATH_ID_CMD,
-                               ES300_PATH_ID(RXCHMGR3, path_id));
-
-                       msg_len = 8;
-                       chn_mgr_mask[escore->algo_type] |= 1 << RXCHMGR3;
-                       update_chmgr_mask = 0;
 
+       switch (algo_type) {
+       case VP:
+               in_mux_info = &es_vp_mux_info;
+               break;
+       case PASSTHRU_VP:
+               in_mux_info = &es_pt_vp_mux_info;
+               if (escore->dhwpt_enabled) {
+                       msg_len = setup_dhwpt_msg(msg, reg);
+                       if (msg_len)
+                               goto queue_msg;
                }
                break;
-
-       case PASSTHRU:
+       case BARGE_IN:
+               in_mux_info = &es_bargein_mux_info;
                break;
-
-       case MM:
-               update_cmds = 1;
-               port = (value >> 9) & 0x1f;
-               chnum = (value >> 4) & 0x1f;
-
-               switch (reg) {
-               case ES_MM_PASSIN1_MUX:
-                       ch_mgr = RXCHMGR4;
-                       break;
-               case ES_MM_PASSIN2_MUX:
-                       ch_mgr = RXCHMGR5;
-                       break;
-               default:
-                       update_cmds = 0;
-                       break;
-               }
-
-               if (update_cmds) {
-                       /* Update the data path */
-                       msg[0] = ES_API_WORD(ES_SET_MUX_CMD,
-                                       ES300_DATA_PATH(port, chnum, ch_mgr));
-
-                       /* Set corresponding path id */
-                       msg[1] = ES_API_WORD(ES_SET_PATH_ID_CMD,
-                                       ES300_PATH_ID(ch_mgr, path_id));
-
-                       msg_len = 8;
-                       chn_mgr_mask[escore->algo_type] |= 1 << ch_mgr;
-                       update_chmgr_mask = 0;
-               }
+       case KALA_OK:
+               in_mux_info = &es_kalaok_mux_info;
+               break;
+       case AUDIOFOCUS:
+               in_mux_info = &es_audiofocus_mux_info;
                break;
+       default:
+               pr_err("%s(): Invalid algo type:%d\n", __func__, algo_type);
+               return -EINVAL;
+       }
 
-       case VP_MM:
-               update_cmds = 1;
-               port = (value >> 9) & 0x1f;
-               chnum = (value >> 4) & 0x1f;
+       prepare_mux_cmd(reg, msg, &msg_len, &chn_mgr_mask[algo_type],
+                       in_mux_info, CMD_INPUT);
 
-               switch (reg) {
-               case ES_AUDIN1_MUX:
-                       ch_mgr = RXCHMGR8;
-                       break;
-               case ES_AUDIN2_MUX:
-                       ch_mgr = RXCHMGR9;
-                       break;
-               default:
-                       update_cmds = 0;
-                       break;
-               }
+       msg[0] |= value;
 
-               if (update_cmds) {
-                       /* Update the data path */
-                       msg[0] = ES_API_WORD(ES_SET_MUX_CMD,
-                                       ES300_DATA_PATH(port, chnum, ch_mgr));
+       port = (msg[0] >> 9) & 0x1f;
 
-                       /* Set corresponding path id */
-                       msg[1] = ES_API_WORD(ES_SET_PATH_ID_CMD,
-                                       ES300_PATH_ID(ch_mgr, path_id));
+       /* For BAS-3205, in case of PT_VP route and PCM0 port and 16bits,
+        * set channel number to 0 for PassIN1 and 2 for PassIN2 */
+       if (PCM0 == port && PASSTHRU_VP == algo_type &&
+           (SNDRV_PCM_FORMAT_S32_LE == escore->pcm_format ||
+            SNDRV_PCM_FORMAT_S32_BE == escore->pcm_format)) {
 
-                       msg_len = 8;
-                       chn_mgr_mask[escore->algo_type] |= 1 << ch_mgr;
-                       update_chmgr_mask = 0;
-               }
-               break;
-       case VP:
-               prepare_mux_cmd(reg, msg, &msg_len,
-                               &chn_mgr_mask[escore->algo_type],
-                               &es_vp_mux_info, CMD_INPUT);
-               msg[0] |= value;
-               update_chmgr_mask = 0;
-               break;
-
-       case DHWPT:
-               /* Unused channel managers in base route 6031 */
-               chn_mgr_mask[escore->algo_type] |= BIT(RXCHMGR5);
-               prepare_mux_cmd(reg, msg, &msg_len,
-                               &chn_mgr_mask[escore->algo_type],
-                               &es_dhwpt_mux_info, CMD_INPUT);
-               if (reg != ES_PASSIN1_MUX && reg != ES_PASSIN2_MUX) {
-                       msg[0] |= value;
-                       update_chmgr_mask = 0;
-               } else {
-                       goto done;
-               }
-               break;
-       case PASSTHRU_VP:
-               prepare_mux_cmd(reg, msg, &msg_len,
-                               &chn_mgr_mask[escore->algo_type],
-                               &es_pt_vp_mux_info, CMD_INPUT);
-               msg[0] |= value;
-               update_chmgr_mask = 0;
-               break;
+               if (ES_PASSIN1_MUX == reg)
+                       channel_ids[algo_type][port].rx_chan_id = 0;
+               else if (ES_PASSIN2_MUX == reg)
+                       channel_ids[algo_type][port].rx_chan_id = 2;
        }
 
-       port = (msg[0] >> 9) & 0x1f;
-       update_chan_id(&msg[0],
-                       channel_ids[escore->algo_type][port].rx_chan_id);
-       channel_ids[escore->algo_type][port].rx_chan_id++;
+       update_chan_id(&msg[0], channel_ids[algo_type][port].rx_chan_id);
+       channel_ids[algo_type][port].rx_chan_id++;
 
-       if (update_chmgr_mask)
-               chn_mgr_mask[escore->algo_type] |= 1 << ch_mgr;
-done:
+queue_msg:
        return escore_queue_msg_to_list(escore, (char *)msg, msg_len);
 }
 
 static int convert_output_mux_to_cmd(struct escore_priv *escore, int reg)
 {
-       unsigned int value;
-       int msg_len = escore->api_access[reg].write_msg_len;
+       int msg_len;
        u32 msg[ES_CMD_ACCESS_WR_MAX] = {0};
-       u16 port, ch_mgr;
-       u8 path_id = 0;
-       u8 update_chmgr_mask = 1, update_msgs = 1;
+       u16 port;
        u32 i;
        int mux = cachedcmd_list[escore->algo_type][reg].reg;
-
-       memcpy((char *)msg, (char *)escore->api_access[reg].write_msg,
-                               msg_len);
-       value = es300_output_mux_text_to_api[mux];
+       struct es_mux_info *out_mux_info = NULL;
+       u8 algo_type = escore->algo_type;
 
        pr_debug("%s(): reg = %d mux = %d\n", __func__, reg, mux);
 
-       path_id = value & 0x3f;
-       ch_mgr = (value >> 8) & 0xf;
-
-       switch (escore->algo_type) {
+       switch (algo_type) {
        case VP:
-               prepare_mux_cmd(mux, msg, &msg_len,
-                               &chn_mgr_mask[escore->algo_type],
-                               &es_vp_mux_info, CMD_OUTPUT);
-               for (i = 0; i < ARRAY_SIZE(es_out_mux_map); i++) {
-                       if (es_out_mux_map[i].mux_id == reg) {
-                               msg[0] |= es_out_mux_map[i].port_desc;
-                               break;
-                       }
-               }
-               update_chmgr_mask = 0;
-               update_msgs = 0;
-               break;
-       case AUDIOZOOM:
-               break;
-       case MM:
-               break;
-       case PASSTHRU:
+               out_mux_info = &es_vp_mux_info;
                break;
        case PASSTHRU_VP:
-               prepare_mux_cmd(mux, msg, &msg_len,
-                               &chn_mgr_mask[escore->algo_type],
-                               &es_pt_vp_mux_info, CMD_OUTPUT);
-               for (i = 0; i < ARRAY_SIZE(es_out_mux_map); i++) {
-                       if (es_out_mux_map[i].mux_id == reg) {
-                               msg[0] |= es_out_mux_map[i].port_desc;
-                               break;
-                       }
+               out_mux_info = &es_pt_vp_mux_info;
+               if (escore->dhwpt_enabled) {
+                       msg_len = setup_dhwpt_msg(msg, mux);
+                       if (msg_len)
+                               goto queue_msg;
                }
-               update_chmgr_mask = 0;
-               update_msgs = 0;
                break;
-       case DHWPT:
-               prepare_mux_cmd(mux, msg, &msg_len,
-                               &chn_mgr_mask[escore->algo_type],
-                               &es_dhwpt_mux_info, CMD_OUTPUT);
-               for (i = 0; i < ARRAY_SIZE(es_out_mux_map); i++) {
-                       if (es_out_mux_map[i].mux_id == reg) {
-                               if (mux != PASS_AUDOUT1 && mux != PASS_AUDOUT2)
-                                       msg[0] |= es_out_mux_map[i].port_desc;
-                               else
-                                       goto done;
-                       }
-               }
-               update_chmgr_mask = 0;
-               update_msgs = 0;
+       case BARGE_IN:
+               out_mux_info = &es_bargein_mux_info;
+               break;
+       case KALA_OK:
+               out_mux_info = &es_kalaok_mux_info;
+               break;
+       case AUDIOFOCUS:
+               out_mux_info = &es_audiofocus_mux_info;
                break;
+       default:
+               pr_err("%s(): Invalid algo type:%d\n", __func__, algo_type);
+               return -EINVAL;
        }
 
-       port = (msg[0] >> 9) & 0x1f;
-       update_chan_id(&msg[0],
-                       channel_ids[escore->algo_type][port].tx_chan_id);
-       channel_ids[escore->algo_type][port].tx_chan_id++;
+       prepare_mux_cmd(mux, msg, &msg_len, &chn_mgr_mask[algo_type],
+                       out_mux_info, CMD_OUTPUT);
 
-       if (update_msgs) {
-               msg[0] |= ES300_DATA_PATH(0, 0, ch_mgr);
-               msg[1] |= ES300_PATH_ID(ch_mgr, path_id);
+       for (i = 0; i < ARRAY_SIZE(es_out_mux_map); i++) {
+               if (es_out_mux_map[i].mux_id == reg) {
+                       msg[0] |= es_out_mux_map[i].port_desc;
+                       break;
+               }
        }
 
-       if (update_chmgr_mask)
-               chn_mgr_mask[escore->algo_type] |= 1 << ch_mgr;
-done:
+       port = (msg[0] >> 9) & 0x1f;
+       update_chan_id(&msg[0], channel_ids[algo_type][port].tx_chan_id);
+       channel_ids[algo_type][port].tx_chan_id++;
+
+queue_msg:
        return escore_queue_msg_to_list(escore, (char *)msg, msg_len);
 }
 
@@ -581,6 +538,7 @@ static void set_chmgr_null(struct escore_priv *escore)
        u32 msg = ES_SET_MUX_NULL;
        int i;
        u16 mask = chn_mgr_mask[escore->algo_type];
+
        pr_debug("%s: mask %04x\n", __func__, mask);
 
        /* Set RXCHMGR NULL */
@@ -617,6 +575,14 @@ static int add_algo_base_route(struct escore_priv *escore)
        escore->current_preset =  msg & 0xFFFF;
        rc = escore_queue_msg_to_list(escore, (char *)&msg, sizeof(msg));
 
+/*
+       if (!rc && escore->dhwpt_enabled) {
+               msg = escore->dhwpt_cmd;
+               rc = escore_queue_msg_to_list(escore,
+                               (char *)&msg, sizeof(msg));
+       }
+*/
+
        /* Configure command completion mode */
        if (escore->cmd_compl_mode == ES_CMD_COMP_INTR) {
                cmd |= escore->pdata->gpio_a_irq_type;
@@ -627,21 +593,11 @@ static int add_algo_base_route(struct escore_priv *escore)
        return rc;
 }
 
-static void es_clear_route(struct escore_priv *escore)
-{
-
-       pr_debug("%s\n", __func__);
-
-       if (escore->algo_type == AUDIOZOOM) {
-               es_az_tx = ES_AZ_NONE;
-               es_az_rx = ES_AZ_NONE;
-       }
-}
-
-static int es_set_algo_rate(struct escore_priv *escore, int algo)
+/* This function must be called with access_lock acquired */
+static int _es_set_algo_rate(struct escore_priv *escore, int algo)
 {
        int rc = 0;
-       u32 filter;
+       u32 filter = FILTER_RESERVED;
        u32 rate_msg, resp;
 
        switch (algo) {
@@ -655,8 +611,8 @@ static int es_set_algo_rate(struct escore_priv *escore, int algo)
        case PASSTHRU:
                filter = FILTER_PASSTHRU;
                break;
-       case AUDIOZOOM:
-               filter = FILTER_AZ;
+       case AUDIOFOCUS:
+               filter = FILTER_AF;
                break;
        default:
                pr_err("%s(): Algorithm rate not supported for algo type:%d\n",
@@ -678,27 +634,227 @@ static int es_set_algo_rate(struct escore_priv *escore, int algo)
                 * By clearing BIT 29 will clear the STAGE bit in a command
                 * and make it a COMMIT command.
                 */
-               /* clear_bit(ES_SC_BIT, (unsigned long *) &rate_msg); */
-
-               /* On Loki, crash is observed with clear_bit API.
-               Replaced clear_bit API with bit wise operation */
                rate_msg &= ~(1 << ES_SC_BIT);
-
                rc = escore_cmd(escore, rate_msg, &resp);
                if (rc)
                        pr_err("%s(): Fail to set algorithm rate :%d\n",
                                        __func__, rc);
+
+       }
+       return rc;
+}
+
+/* This function must be called with access_lock acquired */
+static int _es_set_digital_gain(struct escore_priv *escore)
+{
+       int rc   = 0, i;
+       u32 cmd  = 0;
+       u32 resp = 0;
+
+       if (NULL == escore) {
+               pr_err("%s(): Null pointer.\n", __func__);
+               return -EINVAL;
+       }
+
+       for (i = 0; i < ES_DIGITAL_GAIN_MAX_NUM; i++) {
+               if (0 != escore->digital_gain[i]) {
+                       pr_debug("%s: Set digital gain 0x%x on path ID %d.\n",
+                                __func__,
+                                escore->digital_gain[i],
+                                i);
+
+                       /* Select path ID */
+                       cmd = (ES_SELECT_ENDPOINT<<16) | i;
+                       rc = escore_cmd(escore, cmd, &resp);
+                       if (rc) {
+                               dev_err(escore_priv.dev,
+                                       "%s(): Select Endpoint failed: %d\n",
+                                       __func__, rc);
+                               escore->digital_gain[i] = 0;
+                               return rc;
+                       }
+
+                       /* Set digital output gain */
+                       cmd = (ES_SET_DIGITAL_GAIN<<16) | escore->digital_gain[i];
+                       rc = escore_cmd(escore, cmd, &resp);
+                       if (rc) {
+                               dev_err(escore_priv.dev,
+                                       "%s(): Set Digital Gain failed: %d\n",
+                                       __func__, rc);
+                               escore->digital_gain[i] = 0;
+                               return rc;
+                       }
+               }
        }
+
        return rc;
 }
 
-static int es_set_final_route(struct escore_priv *escore)
+/* This function must be called with access_lock acquired */
+int es_change_power_state_normal(struct escore_priv *escore)
+{
+       int rc = 0;
+       u32 cmd, resp;
+
+       pr_debug("%s\n", __func__);
+
+       /* If codec event is detected in CVQ mode, firmware remains in CVQ mode.
+        * At this point CVQ resume triggered by escore_pm_get_sync() (called
+        * from ISR) doesn't do resume and return 0. Hence firmware remains in
+        * CVQ mode. Because of RPM get sync call, RPM status is RPM_ACTIVE.
+        * Now before suspend is executed if any audio usecase is run, because
+        * of RPM_ACTIVE status, runtime resume will not be called and all
+        * audio related commands will be sent in CVQ mode.
+        * These commands should be sent in NORMAL mode only.
+        * This check brings chip into BOSKO mode (Normal Power State) before
+        * sending any audio related commands.
+        */
+       if (escore->escore_power_state == ES_SET_POWER_STATE_VS_OVERLAY) {
+
+               /* Set flag to Wait for API Interrupt */
+               escore_set_api_intr_wait(escore);
+
+               /* change power state to Normal*/
+               cmd = (ES_SET_POWER_STATE << 16) | ES_SET_POWER_STATE_NORMAL;
+               rc = escore_cmd_nopm(escore, cmd, &resp);
+               if (rc < 0) {
+                       dev_err(escore->dev, "%s() power state cmd failed %d\n",
+                                               __func__, rc);
+                       return rc;
+               }
+
+               if (escore->pdata->gpioa_gpio != -1) {
+                       /* Wait for API Interrupt to confirm
+                        * that device is ready to accept commands */
+                       rc = escore_api_intr_wait_completion(escore);
+                       if (rc)
+                               return rc;
+               } else
+                       msleep(escore->delay.vs_to_normal);
+
+               escore->mode = STANDARD;
+               escore->escore_power_state = ES_SET_POWER_STATE_NORMAL;
+       }
+
+       if (escore->dhwpt_mode) {
+               /* Exit MP Sleep mode */
+               rc = es755_exit_mp_sleep();
+               if (rc) {
+                       dev_err(escore->dev,
+                               "%s(): es755_exit_mp_sleep() fail %d\n",
+                               __func__, rc);
+               }
+       }
+
+       return rc;
+
+}
+
+static int _es_set_algo_switch(struct escore_priv *escore)
+{
+       int algo_type = escore->algo_type;
+       int pri, fein;
+       int rc = 0;
+       int i;
+
+       switch (algo_type) {
+       case PASSTHRU_VP:
+       case BARGE_IN:
+               pri = cachedcmd_list[algo_type][ES_PRIMARY_MUX].reg;
+               fein = cachedcmd_list[algo_type][ES_FEIN_MUX].reg;
+
+               /* Decide the capture use-case out of three:
+                * 1. mono capture
+                * 2. stereo capture
+                * 3. mono to stereo capture
+                */
+               switch (escore->capture_mode) {
+               /* Only possible case at the moment */
+               case STEREO_CAPTURE:
+                       if (pri && fein) {
+                               /* Stereo capture */
+                               es_d300_switch[SWIN1].value = 0;
+                       } else if (pri) {
+                               /* mono to stereo capture */
+                               es_d300_switch[SWIN1].value = 1;
+                       }
+                       break;
+               default:
+                       pr_err("%s(): Invalid capture mode:%d\n", __func__,
+                                       escore->capture_mode);
+               }
+               break;
+       case AUDIOFOCUS:
+               switch (escore->capture_mode) {
+               case STEREO_CAPTURE:
+                       /* Stereo capture */
+                       es_d300_switch[SWOUT3].value = 1;
+                       break;
+               default:
+                       /* mono to capture */
+                       es_d300_switch[SWOUT3].value = 0;
+               }
+               break;
+       default:
+               pr_debug("%s(): Switch settings not supported for algo :%d\n",
+                               __func__, algo_type);
+       }
+
+       for (i = 0; i < SW_MAX; i++) {
+               if (!es_d300_switch[i].value)
+                       continue;
+
+               rc = _es_set_switch(i);
+               if (rc) {
+                       pr_err("%s(): Failure in switch settings\n", __func__);
+                       rc = -EIO;
+                       break;
+               }
+       }
+
+       return rc;
+}
+/* This function must be called with access_lock acquired */
+static int _es_set_final_route(struct escore_priv *escore)
 {
        int rc = 0, i;
        u16 preset;
+       u32 resp = 0;
+       u32 msg;
 
        pr_debug("%s\n", __func__);
 
+       /* DHWPT playback case */
+       if (escore->algo_type == DHWPT) {
+               if (escore->dhwpt_capture_on)
+                       pr_debug("%s(): ****** Seem capture is present. DHWPT is already sent **********\n",__func__);
+               else {
+                       /* Before setting DHWPT configurations, ensure that normal route setup is inactive. */
+                       if (atomic_read(&escore->active_streams)) {
+                               pr_debug("%s(): ** Stop route before sending DHWPT ****\n",__func__);
+                               _es_stop_route(escore, ES_TYPE_NONE);
+                               /* Require 1ms delay between stop route and DHWPT to avoid noise */
+                               usleep_range(5000, 5005);
+                       }
+
+                       rc = escore_cmd(escore, escore->dhwpt_cmd, &resp);
+                       if (rc < 0) {
+                               pr_err("%s(): Error %d in sending DHWPT command\n",__func__, rc);
+                               return rc;
+                       }
+               }
+
+               escore->dhwpt_mode = 1;
+               return rc;
+       }
+
+       rc =  es_change_power_state_normal(escore);
+       if (rc) {
+               pr_err("%s(): Power state transition failed %d\n",
+                       __func__, rc);
+               return rc;
+       }
+
        if ((escore->algo_type == VP) && !escore->vp_asr) {
                if (es_vp_tx != ES_VP_TX_INIT ||
                                es_vp_rx != ES_VP_RX_INIT) {
@@ -706,13 +862,6 @@ static int es_set_final_route(struct escore_priv *escore)
                                es_vp_rx, es_vp_tx);
                        return 0;
                }
-       } else if (escore->algo_type == AUDIOZOOM) {
-               if (es_az_tx != ES_AZ_TX_INIT ||
-                               es_az_rx != ES_AZ_RX_INIT) {
-                       pr_debug("%s AZ not ready rx=%d tx=%d\n", __func__,
-                               es_az_rx, es_az_tx);
-                       return 0;
-               }
        }
 
        preset = es_base_route_preset[escore->algo_type] & 0xFFFF;
@@ -729,17 +878,30 @@ static int es_set_final_route(struct escore_priv *escore)
                        pr_debug("%s(): Skip same preset %x\n", __func__, preset);
                        return 0;
                }
-               es300_codec_stop_algo(escore);
+               _es_stop_route(escore, ES_TYPE_NONE);
        }
 
        /* If the new use-case is started and still there are pending streams
         * from previous use-case, just go ahead and write the new route to
         * firmware after stopping the current route. The stream count will
-        * anyway will be decremented when the HAL layer stops the PCM stream
+        * anyway be decremented when the HAL layer stops the PCM stream
         * of previous use-case. */
-       else if (unlikely(atomic_read(&escore->active_streams)))
-               es300_codec_stop_algo(escore);
-
+       else if (unlikely(atomic_read(&escore->active_streams)) && !escore->dhwpt_mode)
+               _es_stop_route(escore, ES_TYPE_NONE);
+
+       if (escore->algo_type == PASSTHRU_VP && !escore->dhwpt_enabled && escore->dhwpt_mode) {
+               dev_err(escore_priv.dev, "%s(): **** WARNING: PT_VP route called even DHWPT playback is ON ****\n",__func__);
+               dev_err(escore_priv.dev, "%s(): **** Forcibly stopping DHWPT playback ****\n",__func__);
+               /* Disable DHWPT if enabled, or when stopping DHWPT use cases */
+               msg = escore->dhwpt_cmd & 0xFFFF0000;
+               rc = escore_cmd(escore, msg, &resp);
+               if (rc) {
+                       pr_err("%s: Disabling DHWPT failed = %d\n",
+                                       __func__, rc);
+                       return rc;
+               }
+               escore->dhwpt_mode = 0;
+       }
        escore_flush_msg_list(escore);
 
        /* Reset the channel manager mask */
@@ -748,7 +910,13 @@ static int es_set_final_route(struct escore_priv *escore)
        /* Reset channel ids */
        memset(&channel_ids[escore->algo_type], 0x0,
                        sizeof(channel_ids[escore->algo_type]));
-       escore_flush_msg_list(escore);
+
+       if (escore->dhwpt_enabled && !escore->dhwpt_mode) {
+               msg = escore->dhwpt_cmd;
+               rc = escore_queue_msg_to_list(escore,
+                               (char *)&msg, sizeof(msg));
+       }
+
 
        for (i = ES_PRIMARY_MUX; i <= ES_PASSIN4_MUX; i++) {
                if (cachedcmd_list[escore->algo_type][i].reg != 0) {
@@ -759,28 +927,26 @@ static int es_set_final_route(struct escore_priv *escore)
        }
 
        escore->capture_mode = 0;
-       escore->output_mode = 0;
        for (i = ES_DAC0_0_MUX; i <= ES_SBUSTX5_MUX; i++) {
-               if (escore->algo_type == PASSTHRU_VP
-                               || escore->algo_type == DHWPT) {
+               if (escore->algo_type == PASSTHRU_VP ||
+                               escore->algo_type == BARGE_IN) {
                        int mux = cachedcmd_list[escore->algo_type][i].reg;
                        switch (mux) {
-                       case PASS_AO1:
-                               escore->output_mode |= OUTPUT_AO1;
-                               break;
-                       case PASS_MO2:
-                               escore->output_mode |= OUTPUT_MO2;
-                               break;
-                       case PASS_AUDOUT1:
-                               escore->output_mode |= OUTPUT_PO1;
-                               break;
-                       case PASS_AUDOUT2:
-                               escore->output_mode |= OUTPUT_PO2;
-                               break;
                        case VP_CSOUT1:
                                escore->capture_mode |= LEFT_CAPTURE;
                                break;
                        case VP_FEOUT1:
+                       case VP_CSOUT2:
+                               escore->capture_mode |= RIGHT_CAPTURE;
+                               break;
+                       }
+               } else if (escore->algo_type == AUDIOFOCUS) {
+                       int mux = cachedcmd_list[escore->algo_type][i].reg;
+                       switch (mux) {
+                       case AUDIOFOCUS_CSOUT1:
+                               escore->capture_mode |= LEFT_CAPTURE;
+                               break;
+                       case AUDIOFOCUS_CSOUT2:
                                escore->capture_mode |= RIGHT_CAPTURE;
                                break;
                        }
@@ -793,71 +959,58 @@ static int es_set_final_route(struct escore_priv *escore)
        }
 
        /* Setup AEC if enabled */
-       if (escore->vp_aec) {
+       if (escore->algo_type == PASSTHRU_VP && escore->vp_aec && !escore->dhwpt_enabled) {
                escore_queue_msg_to_list(escore, (char *)pt_vp_aec_msgblk,
                                sizeof(pt_vp_aec_msgblk));
        }
-       /* add umbrella base route */
-       rc = add_algo_base_route(escore);
-       if (!rc)
-               escore_write_msg_list(escore);
 
-       memcpy(prev_cmdlist, cachedcmd_list[escore->algo_type],
-                       sizeof(prev_cmdlist));
+       /* Set power level if enabled */
+       if (escore->power_saving_mode != ES_POWER_LEVEL_DISABLE &&
+               escore->algo_type == PASSTHRU_VP) {
+               rc = escore_cmd(escore,
+                       (ES_SET_POWER_LEVEL << 16)|escore->power_saving_mode,
+                        &resp);
 
-       /* Do necessary switch settings */
-       if (escore->algo_type == PASSTHRU_VP || escore->algo_type == DHWPT) {
-               int pri, fein;
-
-               pri = cachedcmd_list[escore->algo_type][ES_PRIMARY_MUX].reg;
-               fein = cachedcmd_list[escore->algo_type][ES_FEIN_MUX].reg;
-
-               if (escore->output_mode & OUTPUT_PO1)
-                       escore_set_switch(SWOUT0_O1);
-               if (escore->output_mode & OUTPUT_PO2)
-                       escore_set_switch(SWOUT1_O1);
-
-               if ((escore->output_mode & OUTPUT_PT_COPY) == OUTPUT_PT_COPY) {
-                       /* PT Copy use case which uses both A01 and MO2 */
-                       escore_set_switch(SWIN2_I1);
-                       escore_set_switch(SWOUT3_O1);
-                       escore_set_switch(SWOUT2_O1);
-               } else if ((escore->output_mode & OUTPUT_MIXED_MONO) ==
-                               OUTPUT_MIXED_MONO) {
-                       /* Mixed mono use case - which uses only AO1 */
-                       escore_set_switch(SWIN2_I0);
-                       escore_set_switch(SWOUT3_O1);
-               }
+               if (rc)
+                       pr_warn("%s(): Error %d setting Power Saving Level" \
+                               " resp = 0x%x\n", __func__, rc, resp);
+       }
 
-               /* Decide the capture use-case out of three:
-                * 1. mono capture
-                * 2. stereo capture
-                * 3. mono to stereo capture
-                */
-               switch (escore->capture_mode) {
-               case MONO_CAPTURE:
-                       /* No switch settings required  - dead code */
-                       break;
-               case STEREO_CAPTURE:
-                       if (pri && fein) {
-                               /* Stereo capture */
-                               escore_set_switch(SWIN1_I0);
-                       } else if (pri) {
-                               /* mono to stereo capture */
-                               escore_set_switch(SWIN1_I1);
-                       }
-                       break;
-               }
+       /* add umbrella base route */
+       rc = add_algo_base_route(escore);
+       if (!rc)
+               escore_write_msg_list(escore);
+
+       escore->base_route_setup = 1;
+
+       if (escore->algo_type == PASSTHRU_VP && escore->dhwpt_enabled)
+               escore->dhwpt_capture_on = 1;
+
+       memcpy(prev_cmdlist, cachedcmd_list[escore->algo_type],
+                       sizeof(prev_cmdlist));
+
+       /* Do necessary switch settings */
+       rc = _es_set_algo_switch(escore);
+       if (rc) {
+               pr_err("%s(): Switch settings failed :%d\n", __func__, rc);
+               goto exit;
        }
 
        if (escore->algo_preset_one != 0) {
                usleep_range(5000, 5005);
                pr_debug("%s:add algo preset one: %d", __func__,
                                escore->algo_preset_one);
-               rc = escore_write(NULL, ES_PRESET, escore->algo_preset_one);
+               rc = escore_cmd(escore, ((ES_SET_PRESET << 16) |
+                                       (1 << ES_SC_BIT) |
+                                       escore->algo_preset_one),
+                                       &resp);
                if (rc)
                        dev_err(escore_priv.dev, "%s(): Set Algo Preset one failed:%d\n",
                                __func__, rc);
+               /* Reset algo_preset so that it is not accidently set for a
+               * diffeent route, UCM is responsible to set this algo preset
+               * for every use case
+               */
                escore->algo_preset_one = 0;
        }
 
@@ -865,16 +1018,49 @@ static int es_set_final_route(struct escore_priv *escore)
                usleep_range(5000, 5005);
                pr_debug("%s:add algo preset two: %d", __func__,
                                escore->algo_preset_two);
-               rc = escore_write(NULL, ES_PRESET, escore->algo_preset_two);
+               rc = escore_cmd(escore, ((ES_SET_PRESET << 16) |
+                                       (1 << ES_SC_BIT) |
+                                       escore->algo_preset_two),
+                                       &resp);
                if (rc)
                        dev_err(escore_priv.dev, "%s(): Set Algo Preset two failed:%d\n",
                                __func__, rc);
+               /* Reset algo_preset so that it is not accidently set for a
+               * diffeent route, UCM is responsible to set this algo preset
+               * for every use case
+               */
                escore->algo_preset_two = 0;
        }
 
+       /* Send sync command */
+       rc = escore_cmd(escore, (ES_SYNC_CMD << 16), &resp);
+       if (rc < 0)
+               pr_warn("%s(): Error %d sending sync command",
+                       __func__, rc);
+
+       if (escore->hpf_mode != 0) {
+               rc = escore_cmd(escore,
+                               (ES_SELECT_HPF_MODE << 16)|escore->hpf_mode,
+                               &resp);
+
+               if (rc) {
+                       pr_warn("%s(): Error %d selecting HPF mode" \
+                                       " resp = 0x%x\n", __func__, rc, resp);
+                       goto exit;
+               }
+       }
+
+       rc = _es_set_digital_gain(escore);
+       if (rc) {
+               pr_err("%s(): Failed to set digital gain:%d\n",
+                       __func__, rc);
+               return rc;
+       }
+
        if (cachedcmd_list[escore->algo_type][ES_ALGO_SAMPLE_RATE].reg)
-               rc = es_set_algo_rate(escore, escore->algo_type);
+               rc = _es_set_algo_rate(escore, escore->algo_type);
 
+exit:
        return rc;
 }
 
@@ -910,7 +1096,9 @@ static int es300_codec_enable_slimtx(struct snd_soc_dapm_widget *w,
                if (escore->slim_dai_data[dai_id].ch_act ==
                                escore->slim_dai_data[dai_id].ch_tot) {
 
-                       ret = es_set_final_route(escore);
+                       mutex_lock(&escore->access_lock);
+                       ret = _es_set_final_route(escore);
+                       mutex_unlock(&escore->access_lock);
                        if (!ret) {
                                ret = escore_cfg_slim_tx(escore->gen0_client,
                                        escore->slim_dai_data[dai_id].ch_num,
@@ -918,7 +1106,6 @@ static int es300_codec_enable_slimtx(struct snd_soc_dapm_widget *w,
                                        escore->slim_dai_data[dai_id].rate);
                                atomic_inc(&escore->active_streams);
                        }
-
                }
                break;
        case SND_SOC_DAPM_POST_PMD:
@@ -952,12 +1139,13 @@ static int es300_codec_enable_slimtx(struct snd_soc_dapm_widget *w,
                                pm_runtime_mark_last_busy(codec->dev->parent);
                                pm_runtime_put(codec->dev->parent);
                        }
-                       if (!ret)
-                               es_clear_route(escore);
 
                }
-               if (atomic_read(&escore->active_streams) == 0)
-                       ret = es300_codec_stop_algo(escore);
+               if (atomic_read(&escore->active_streams) == 0) {
+                       mutex_lock(&escore->access_lock);
+                       ret = _es_stop_route(escore, ES_TYPE_CAP);
+                       mutex_unlock(&escore->access_lock);
+               }
        }
        return ret;
 }
@@ -992,7 +1180,9 @@ static int es300_codec_enable_slimrx(struct snd_soc_dapm_widget *w,
                if (escore->slim_dai_data[dai_id].ch_act ==
                                escore->slim_dai_data[dai_id].ch_tot) {
 
-                       ret = es_set_final_route(escore);
+                       mutex_lock(&escore->access_lock);
+                       ret = _es_set_final_route(escore);
+                       mutex_unlock(&escore->access_lock);
                        if (!ret) {
                                ret = escore_cfg_slim_rx(escore->gen0_client,
                                        escore->slim_dai_data[dai_id].ch_num,
@@ -1000,6 +1190,7 @@ static int es300_codec_enable_slimrx(struct snd_soc_dapm_widget *w,
                                        escore->slim_dai_data[dai_id].rate);
                                atomic_inc(&escore->active_streams);
                        }
+
                }
                break;
        case SND_SOC_DAPM_POST_PMD:
@@ -1032,11 +1223,12 @@ static int es300_codec_enable_slimrx(struct snd_soc_dapm_widget *w,
                                pm_runtime_mark_last_busy(codec->dev->parent);
                                pm_runtime_put(codec->dev->parent);
                        }
-                       if (!ret)
-                               es_clear_route(escore);
                }
-               if (atomic_read(&escore->active_streams) == 0)
-                       ret = es300_codec_stop_algo(escore);
+               if (atomic_read(&escore->active_streams) == 0) {
+                       mutex_lock(&escore->access_lock);
+                       ret = _es_stop_route(escore, ES_TYPE_PB);
+                       mutex_unlock(&escore->access_lock);
+               }
        }
        return ret;
 }
@@ -1072,6 +1264,7 @@ static int es300_codec_enable_i2srx(struct snd_soc_dapm_widget *w,
 
        pr_debug("%s(): event:%d\n", __func__, event);
 
+       mutex_lock(&codec->mutex);
        switch (event) {
        case SND_SOC_DAPM_POST_PMU:
                for (j = 0; j < escore->dai_nr; j++) {
@@ -1083,13 +1276,18 @@ static int es300_codec_enable_i2srx(struct snd_soc_dapm_widget *w,
                        }
                }
 
+               pr_debug("%s: START RX PMU Active channels Act %d Total %d\n", __func__,
+                               escore->i2s_dai_data[dai_id].rx_ch_act, escore->i2s_dai_data[dai_id].rx_ch_tot);
                if (escore->i2s_dai_data[dai_id].rx_ch_act ==
                                escore->i2s_dai_data[dai_id].rx_ch_tot) {
-                       ret = es_set_final_route(escore);
-                       msleep(20);
+
+                       mutex_lock(&escore->access_lock);
+                       ret = _es_set_final_route(escore);
+                       mutex_unlock(&escore->access_lock);
+
                        atomic_inc(&escore->active_streams);
                }
-               pr_debug("%s: RX PMU Active channels %d Active streams %d\n", __func__,
+               pr_debug("%s: END RX PMU Active channels %d Active streams %d\n", __func__,
                        escore->i2s_dai_data[dai_id].rx_ch_act, escore->active_streams);
                break;
        case SND_SOC_DAPM_POST_PMD:
@@ -1102,17 +1300,39 @@ static int es300_codec_enable_i2srx(struct snd_soc_dapm_widget *w,
                        }
                }
 
+               pr_debug("%s: BEGIN RX PMD Active channels %d Active streams %d\n", __func__,
+                       escore->i2s_dai_data[dai_id].rx_ch_act, escore->active_streams);
                if (!escore->i2s_dai_data[dai_id].rx_ch_act) {
-                       es_clear_route(escore);
 
+/*
                        if (atomic_read(&escore->active_streams) &&
-                               atomic_dec_and_test(&escore->active_streams))
-                               ret = es300_codec_stop_algo(escore);
+                               atomic_dec_and_test(&escore->active_streams)) {
+                               mutex_lock(&escore->access_lock);
+                               ret = _es_stop_route(escore,ES_TYPE_PB);
+                               mutex_unlock(&escore->access_lock);
+                       }
+*/
+                       /* Decrease active streams count if non-zero */
+                       if (atomic_read(&escore->active_streams)) {
+                               atomic_dec(&escore->active_streams);
+
+                               /* If no active stream exist, or only DHWPT
+                                * stream active, call _es_stop_route() */
+                               if (!atomic_read(&escore->active_streams) ||
+                                   (atomic_read(&escore->active_streams) == 1
+                                    && escore->dhwpt_mode)) {
+                                       mutex_lock(&escore->access_lock);
+                                       ret = _es_stop_route(escore,ES_TYPE_PB);
+                                       mutex_unlock(&escore->access_lock);
+                               }
+                       }
+
                }
-               pr_debug("%s: RX PMD Active channels %d Active streams %d\n", __func__,
+               pr_debug("%s: END RX PMD Active channels %d Active streams %d\n", __func__,
                        escore->i2s_dai_data[dai_id].rx_ch_act, escore->active_streams);
                break;
        }
+       mutex_unlock(&codec->mutex);
        return ret;
 }
 static int es300_codec_enable_i2stx(struct snd_soc_dapm_widget *w,
@@ -1126,6 +1346,7 @@ static int es300_codec_enable_i2stx(struct snd_soc_dapm_widget *w,
 
        pr_debug("%s(): event:%d\n", __func__, event);
 
+       mutex_lock(&codec->mutex);
        switch (event) {
        case SND_SOC_DAPM_POST_PMU:
                for (j = 0; j < escore->dai_nr; j++) {
@@ -1137,13 +1358,18 @@ static int es300_codec_enable_i2stx(struct snd_soc_dapm_widget *w,
                        }
                }
 
+               pr_debug("%s: BEGIN TX PMU Active channels %d Active streams %d\n", __func__,
+                       escore->i2s_dai_data[dai_id].tx_ch_act, escore->active_streams);
                if (escore->i2s_dai_data[dai_id].tx_ch_act ==
                                escore->i2s_dai_data[dai_id].tx_ch_tot) {
 
-                       ret = es_set_final_route(escore);
+                       mutex_lock(&escore->access_lock);
+                       ret = _es_set_final_route(escore);
+                       mutex_unlock(&escore->access_lock);
+
                        atomic_inc(&escore->active_streams);
                }
-               pr_debug("%s: TX PMU Active channels %d Active streams %d\n", __func__,
+               pr_debug("%s: END TX PMU Active channels %d Active streams %d\n", __func__,
                        escore->i2s_dai_data[dai_id].tx_ch_act, escore->active_streams);
                break;
        case SND_SOC_DAPM_POST_PMD:
@@ -1156,17 +1382,30 @@ static int es300_codec_enable_i2stx(struct snd_soc_dapm_widget *w,
                        }
                }
 
+               pr_debug("%s: BEGIN TX PMD Active channels %d Active streams %d DHWPT mode %d\n", __func__,
+                       escore->i2s_dai_data[dai_id].tx_ch_act, escore->active_streams,escore->dhwpt_mode);
+
                if (!escore->i2s_dai_data[dai_id].tx_ch_act) {
-                       es_clear_route(escore);
+                       /* Decrease active streams count if non-zero */
+                       if (atomic_read(&escore->active_streams)) {
+                               atomic_dec(&escore->active_streams);
 
-                       if (atomic_read(&escore->active_streams) &&
-                               atomic_dec_and_test(&escore->active_streams))
-                               ret = es300_codec_stop_algo(escore);
+                               /* If no active stream exist, or only DHWPT
+                                * stream active, call _es_stop_route() */
+                               if (!atomic_read(&escore->active_streams) ||
+                                   (atomic_read(&escore->active_streams) == 1
+                                    && escore->dhwpt_mode)) {
+                                       mutex_lock(&escore->access_lock);
+                                       ret = _es_stop_route(escore,ES_TYPE_CAP);
+                                       mutex_unlock(&escore->access_lock);
+                               }
+                       }
                }
-               pr_debug("%s: TX PMD Active channels %d Active streams %d\n", __func__,
+               pr_debug("%s: END TX PMD Active channels %d Active streams %d\n", __func__,
                        escore->i2s_dai_data[dai_id].tx_ch_act, escore->active_streams);
                break;
        }
+       mutex_unlock(&codec->mutex);
        return ret;
 }
 #endif
@@ -1180,7 +1419,7 @@ static int get_noise_suppression(struct snd_kcontrol *kcontrol,
        unsigned int reg = e->reg;
        u16 value;
 
-       value = escore_read(codec, reg);
+       value = escore_read_locked(codec, reg);
 
        ucontrol->value.enumerated.item[0] = value;
 
@@ -1206,7 +1445,7 @@ static int put_noise_suppression(struct snd_kcontrol *kcontrol,
        pr_debug("%s: Noise Suppression value %u\n", __func__, value);
        value = value << 8;
 
-       return escore_write(codec, reg, value);
+       return escore_write_locked(codec, reg, value);
 }
 
 static int put_aec_mode(struct snd_kcontrol *kcontrol,
@@ -1225,7 +1464,7 @@ static int put_aec_mode(struct snd_kcontrol *kcontrol,
        }
        pr_debug("%s: AEC mode value %u\n", __func__, value);
 
-       return escore_write(codec, reg, value);
+       return escore_write_locked(codec, reg, value);
 }
 
 static int get_aec_mode(struct snd_kcontrol *kcontrol,
@@ -1237,7 +1476,7 @@ static int get_aec_mode(struct snd_kcontrol *kcontrol,
        unsigned int reg = e->reg;
        u16 value;
 
-       value = escore_read(codec, reg);
+       value = escore_read_locked(codec, reg);
 
        if (value > ES_MAX_AEC_MODE)
                pr_err("%s(): Invalid value %d\n", __func__, value);
@@ -1249,7 +1488,7 @@ static int get_aec_mode(struct snd_kcontrol *kcontrol,
        return 0;
 }
 
-static int put_az_mode(struct snd_kcontrol *kcontrol,
+static int put_af_mode(struct snd_kcontrol *kcontrol,
                struct snd_ctl_elem_value *ucontrol)
 {
        struct snd_soc_codec *codec = escore_priv.codec;
@@ -1257,19 +1496,25 @@ static int put_az_mode(struct snd_kcontrol *kcontrol,
                (struct soc_enum *)kcontrol->private_value;
        unsigned int reg = e->reg;
        unsigned int value = ucontrol->value.enumerated.item[0];
+       struct escore_priv *escore = snd_soc_codec_get_drvdata(codec);
 
-       if (value > ES_MAX_AZ_MODE) {
+       if (escore->mode != AF) {
+               pr_err("%s(): Chip not in AF state\n", __func__);
+               return -EAGAIN;
+       }
+
+       if (value > ES_MAX_AF_MODE) {
                pr_err("%s(): Invalid value %d for the control\n", __func__,
                                value);
                return -EINVAL;
        }
 
-       pr_debug("%s: Audio Zoom mode value %u\n", __func__, value);
+       pr_debug("%s: Audio Focus mode value %u\n", __func__, value);
 
-       return escore_write(codec, reg, value);
+       return escore_write_locked(codec, reg, value);
 }
 
-static int get_az_mode(struct snd_kcontrol *kcontrol,
+static int get_af_mode(struct snd_kcontrol *kcontrol,
                struct snd_ctl_elem_value *ucontrol)
 {
        struct snd_soc_codec *codec = escore_priv.codec;
@@ -1277,15 +1522,22 @@ static int get_az_mode(struct snd_kcontrol *kcontrol,
                (struct soc_enum *)kcontrol->private_value;
        unsigned int reg = e->reg;
        u16 value;
+       struct escore_priv *escore = snd_soc_codec_get_drvdata(codec);
+
+       if (escore->mode != AF) {
+               pr_err("%s(): Chip not in AF state\n", __func__);
+               return -EAGAIN;
+       }
 
-       value = escore_read(codec, reg);
+       value = escore_read_locked(codec, reg);
 
-       if (value > ES_MAX_AZ_MODE)
-               pr_err("%s(): Invalid value %d\n", __func__, value);
+       if (value > ES_MAX_AF_MODE)
+               pr_err("%s(): Invalid value %d (%d)\n",
+                      __func__, value, (signed short)(value));
 
        ucontrol->value.enumerated.item[0] = value;
 
-       pr_debug("%s: Audio Zoom mode value %u\n", __func__, value);
+       pr_debug("%s: Audio Focus mode value %u\n", __func__, value);
 
        return 0;
 }
@@ -1347,7 +1599,7 @@ static int put_cmd_compl_mode_sel(struct snd_kcontrol *kcontrol,
 
        /* Set the suppress response bit */
        cmd |= BIT(ES_SR_BIT);
-       rc = escore_cmd(escore, cmd, &resp);
+       rc = escore_cmd_locked(escore, cmd, &resp);
        if (rc < 0) {
                pr_err("%s(): Error %d to set command mode", __func__, rc);
                return rc;
@@ -1374,7 +1626,7 @@ static int es300_get_algo_state(struct snd_kcontrol *kcontrol,
 static int es300_put_algo_state(struct snd_kcontrol *kcontrol,
                struct snd_ctl_elem_value *ucontrol)
 {
-       int ret = 0, algo_type = NONE;
+       int ret = 0, algo_type = ALGO_NONE;
        struct snd_soc_codec *codec = escore_priv.codec;
        struct escore_priv *escore = snd_soc_codec_get_drvdata(codec);
        struct soc_enum *e =
@@ -1382,9 +1634,9 @@ static int es300_put_algo_state(struct snd_kcontrol *kcontrol,
        unsigned int reg = e->reg;
        unsigned int value = ucontrol->value.enumerated.item[0];
 
+       mutex_lock(&codec->mutex);
        pr_debug("%s(): %s algo :%s\n", __func__, (value) ? "Enabling" :
                        "Disabling", kcontrol->id.name);
-
        /* Use 0th array to store the algo status */
        cachedcmd_list[0][reg].reg = value;
        switch (reg) {
@@ -1400,8 +1652,14 @@ static int es300_put_algo_state(struct snd_kcontrol *kcontrol,
        case ES_ALGORITHM_PT_VP:
                algo_type = PASSTHRU_VP;
                break;
-       case ES_ALGORITHM_AZ:
-               algo_type = AUDIOZOOM;
+       case ES_ALGORITHM_AF:
+               algo_type = AUDIOFOCUS;
+               break;
+       case ES_ALGORITHM_BRG:
+               algo_type = BARGE_IN;
+               break;
+       case ES_ALGORITHM_KALAOK:
+               algo_type = KALA_OK;
                break;
        case ES_ALGORITHM_DHWPT:
                algo_type = DHWPT;
@@ -1415,8 +1673,12 @@ static int es300_put_algo_state(struct snd_kcontrol *kcontrol,
        if (ret < 0)
                goto out;
 
-       if (value)
+       if (value) {
                escore->algo_type = algo_type;
+
+               if (!atomic_read(&escore->active_streams))
+                       escore->algo_type_off = ALGO_NONE;
+       }
        else {
                /* During the disable sequence the algo_type will not be
                 * updated. Use the algo_type_off as the array index to reset
@@ -1439,6 +1701,7 @@ static int es300_put_algo_state(struct snd_kcontrol *kcontrol,
                escore->algo_type_off = algo_type;
        }
 out:
+       mutex_unlock(&codec->mutex);
        return ret;
 }
 static int es300_put_algo_rate(struct snd_kcontrol *kcontrol,
@@ -1451,7 +1714,11 @@ static int es300_put_algo_rate(struct snd_kcontrol *kcontrol,
        unsigned int reg = e->reg;
        int ret = 0;
        unsigned int value = ucontrol->value.enumerated.item[0];
+
+       mutex_lock(&codec->mutex);
        cachedcmd_list[escore->algo_type][reg].reg = value;
+       mutex_unlock(&codec->mutex);
+
        return ret;
 }
 static int get_control_enum(struct snd_kcontrol *kcontrol,
@@ -1484,9 +1751,11 @@ static int put_input_route_value(struct snd_kcontrol *kcontrol,
        int rc = 0;
        u8 algo_type;
 
+       mutex_lock(&codec->mutex);
        if (mux >= ARRAY_SIZE(proc_block_input_texts) || mux < 0) {
-               pr_err("%s(): Invalid input mux:%d Max valid value:%lu\n",
+               pr_err("%s(): Invalid input mux:%d Max valid value:%d\n",
                        __func__, mux, ARRAY_SIZE(proc_block_input_texts));
+               mutex_unlock(&codec->mutex);
                return -EINVAL;
        }
 
@@ -1497,15 +1766,20 @@ static int put_input_route_value(struct snd_kcontrol *kcontrol,
        if (!mux && atomic_read(&escore->active_streams))
                goto exit;
 
-#if (defined(CONFIG_ARCH_OMAP) || defined(CONFIG_ARCH_EXYNOS) || \
-       defined(CONFIG_X86_32) || defined(CONFIG_ARCH_TEGRA))
+#if (defined(KERNEL_VERSION_3_2_0) && defined(CONFIG_ARCH_OMAP))
+       rc = snd_soc_dapm_mux_update_power(widget, kcontrol, 1, mux, e);
+#elif (defined(CONFIG_ARCH_OMAP) || defined(CONFIG_ARCH_EXYNOS) || \
+               defined(CONFIG_X86_32) || defined(CONFIG_ARCH_TEGRA) || \
+               defined(CONFIG_ARCH_MSM8994))
        rc = snd_soc_dapm_mux_update_power(widget, kcontrol, mux, e);
 #else
        rc = snd_soc_dapm_mux_update_power(widget, kcontrol, 1, mux, e);
 #endif
 
 exit:
-       pr_debug("put input control %s (%d) val %s (%d)\n", kcontrol->id.name, reg, proc_block_input_texts[mux], mux);
+       pr_debug("put input control %s (%d) val %s\n", kcontrol->id.name,reg,
+                               proc_block_input_texts[mux]);
+       mutex_unlock(&codec->mutex);
 
        return rc;
 }
@@ -1525,7 +1799,8 @@ static int get_input_route_value(struct snd_kcontrol *kcontrol,
        /* TBD: translation */
        /* value = escore_read(NULL, reg); */
        ucontrol->value.enumerated.item[0] = value;
-       pr_debug("get input control %s (%d) val %s (%d)\n", kcontrol->id.name, reg, proc_block_input_texts[value], value);
+       pr_debug("get input control %s (%d)  val %s\n", kcontrol->id.name,reg,
+                               proc_block_input_texts[value]);
 
        return 0;
 }
@@ -1545,26 +1820,19 @@ static int put_output_route_value(struct snd_kcontrol *kcontrol,
        int prev_mux;
        u8 algo_type;
 
+       mutex_lock(&codec->mutex);
        if (mux >= ARRAY_SIZE(proc_block_output_texts) || mux < 0) {
-               pr_err("%s(): Invalid output mux:%d Max valid value:%lu\n",
+               pr_err("%s(): Invalid output mux:%d Max valid value:%d\n",
                        __func__, mux, ARRAY_SIZE(proc_block_output_texts));
+               mutex_unlock(&codec->mutex);
                return -EINVAL;
        }
        /* VP CSOUT signals Tx init and VP FEOUT signals Rx init */
-       if (escore->algo_type == VP &&
-               strncmp(proc_block_output_texts[mux], "VP CSOUT", 8) == 0) {
-               es_vp_tx = ES_VP_TX_INIT;
-       } else if (escore->algo_type == VP &&
-               strncmp(proc_block_output_texts[mux], "VP FEOUT1", 9) == 0) {
-               es_vp_rx = ES_VP_RX_INIT;
-       } else if (escore->algo_type == AUDIOZOOM &&
-                       strncmp(proc_block_output_texts[mux],
-                               "AudioZoom CSOUT", 15) == 0) {
-               es_az_tx = ES_AZ_TX_INIT;
-       } else if (escore->algo_type == AUDIOZOOM &&
-                       strncmp(proc_block_output_texts[mux],
-                               "AudioZoom AOUT1", 15) == 0) {
-               es_az_rx = ES_AZ_RX_INIT;
+       if (escore->algo_type == VP) {
+               if (mux == VP_CSOUT1)
+                       es_vp_tx = ES_VP_TX_INIT;
+               else if (mux == VP_FEOUT1)
+                       es_vp_rx = ES_VP_RX_INIT;
        }
 
        algo_type = (mux) ? escore->algo_type : escore->algo_type_off;
@@ -1574,26 +1842,29 @@ static int put_output_route_value(struct snd_kcontrol *kcontrol,
 
        /* Request of clearing the VP output */
        if (!mux && prev_mux && algo_type == VP) {
-               if (!strncmp(proc_block_output_texts[prev_mux],
-                                       "VP CSOUT", sizeof("VP CSOUT") - 1))
+               if (prev_mux == VP_CSOUT1)
                        es_vp_tx = ES_VP_NONE;
-               else if (!strncmp(proc_block_output_texts[prev_mux],
-                                       "VP FEOUT1", sizeof("VP FEOUT1") - 1))
+               else if (prev_mux == VP_FEOUT1)
                        es_vp_rx = ES_VP_NONE;
        }
 
        if (!mux && atomic_read(&escore->active_streams))
                goto exit;
 
-#if (defined(CONFIG_ARCH_OMAP) || defined(CONFIG_ARCH_EXYNOS) || \
-       defined(CONFIG_X86_32) || defined(CONFIG_ARCH_TEGRA))
+#if (defined(KERNEL_VERSION_3_2_0) && defined(CONFIG_ARCH_OMAP))
+       rc = snd_soc_dapm_mux_update_power(widget, kcontrol, 1, mux, e);
+#elif (defined(CONFIG_ARCH_OMAP) || defined(CONFIG_ARCH_EXYNOS) || \
+               defined(CONFIG_X86_32) || defined(CONFIG_ARCH_TEGRA) || \
+               defined(CONFIG_ARCH_MSM8994))
        rc = snd_soc_dapm_mux_update_power(widget, kcontrol, mux, e);
 #else
        rc = snd_soc_dapm_mux_update_power(widget, kcontrol, 1, mux, e);
 #endif
 
 exit:
-       pr_debug("put output control %s (%d) val %s (%d)\n", kcontrol->id.name, reg, proc_block_output_texts[mux], mux);
+       pr_debug("put output control %s (%d) val %s\n", kcontrol->id.name,reg,
+                               proc_block_output_texts[mux]);
+       mutex_unlock(&codec->mutex);
        return rc;
 }
 
@@ -1612,7 +1883,8 @@ static int get_output_route_value(struct snd_kcontrol *kcontrol,
        /* TBD: translation */
        /* value = escore_read(NULL, reg); */
        ucontrol->value.enumerated.item[0] = value;
-       pr_debug("get output control %s (%d)  val %s (%d)\n", kcontrol->id.name, reg, proc_block_output_texts[value], value);
+       pr_debug("get output control %s (%d) val %s\n", kcontrol->id.name,reg,
+                               proc_block_output_texts[value]);
 
        return 0;
 }
@@ -1632,17 +1904,74 @@ static int put_write_route_cmds(struct snd_kcontrol *kcontrol,
        return 0;
 }
 
+static int put_dhwpt_sel(struct snd_kcontrol *kcontrol,
+                           struct snd_ctl_elem_value *ucontrol)
+{
+       struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+       struct escore_priv *escore = snd_soc_codec_get_drvdata(codec);
+
+       mutex_lock(&codec->mutex);
+       escore->dhwpt_enabled = ucontrol->value.enumerated.item[0];
+       pr_debug("put DHWPT enable control val %d\n", escore->dhwpt_enabled);
+
+       if (escore->dhwpt_enabled && !escore->dhwpt_mode) {
+               mutex_lock(&escore->access_lock);
+               _es_stop_route(escore, ES_TYPE_CAP);
+               mutex_unlock(&escore->access_lock);
+       }
+       mutex_unlock(&codec->mutex);
+       return 0;
+}
+
+static int get_dhwpt_sel(struct snd_kcontrol *kcontrol,
+               struct snd_ctl_elem_value *ucontrol)
+{
+       struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+       struct escore_priv *escore = snd_soc_codec_get_drvdata(codec);
+
+       pr_debug("get DHWPT enable control val %d\n", escore->dhwpt_enabled);
+       ucontrol->value.enumerated.item[0] = escore->dhwpt_enabled;
+       return 0;
+}
+
 static int put_asr_sel(struct snd_kcontrol *kcontrol,
                            struct snd_ctl_elem_value *ucontrol)
 {
        struct snd_soc_codec *codec = escore_priv.codec;
        struct escore_priv *escore = snd_soc_codec_get_drvdata(codec);
 
+       mutex_lock(&codec->mutex);
        escore->vp_asr = ucontrol->value.enumerated.item[0];
+       mutex_unlock(&codec->mutex);
 
        return 0;
 }
 
+static int get_ambient_noise(struct snd_kcontrol *kcontrol,
+               struct snd_ctl_elem_value *ucontrol)
+{
+       struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+       struct escore_priv *escore = snd_soc_codec_get_drvdata(codec);
+       int rc = 0;
+       u32 resp;
+
+       rc = escore_cmd_locked(escore, ES_QUERY_AMBIENT_NOISE, &resp);
+       if (rc < 0) {
+               pr_err("%s(): Error %d while reading ambient noise\n",
+                               __func__, rc);
+               return rc;
+       }
+
+       /* Ambient Noise query returns 16 bit value which is
+        * in form of 2's compliment. All the values except "max" value
+        * (i.e. 0 dB) will be negative. We need the typecasting to
+        * s16 of the value being reported to upper layers for the
+        * correctness.
+        */
+       ucontrol->value.enumerated.item[0] = (s16) (resp & 0xFFFF);
+       return rc;
+}
+
 static int get_asr_sel(struct snd_kcontrol *kcontrol,
                struct snd_ctl_elem_value *ucontrol)
 {
@@ -1659,7 +1988,10 @@ static int put_vp_aec(struct snd_kcontrol *kcontrol,
        struct snd_soc_codec *codec = escore_priv.codec;
        struct escore_priv *escore = snd_soc_codec_get_drvdata(codec);
 
+       mutex_lock(&codec->mutex);
        escore->vp_aec = ucontrol->value.enumerated.item[0];
+       mutex_unlock(&codec->mutex);
+
        return 0;
 }
 
@@ -1688,8 +2020,8 @@ static int put_reset(struct snd_kcontrol *kcontrol,
        es_d300_reset_cmdcache();
        es_vp_tx = ES_VP_NONE;
        es_vp_rx = ES_VP_NONE;
-       es_az_tx = ES_AZ_NONE;
-       es_az_rx = ES_AZ_NONE;
+       es_af_tx = ES_AF_NONE;
+       es_af_rx = ES_AF_NONE;
        return 0;
 }
 
@@ -1744,15 +2076,15 @@ static int get_pcm_port_param(struct snd_kcontrol *kcontrol,
        rc = escore_prepare_msg(escore, reg, value, (char *)msg, &msg_len,
                        ES_MSG_READ);
        if (rc) {
-               pr_err("%s(): Preparing write message failed\n", __func__);
+               pr_err("%s(): Prepare write message fail %d\n", __func__, rc);
                return rc;
        }
        /* Clear the Port info in read command */
        api_access->read_msg[0] &= ES_API_WORD(ES_GET_DEV_PARAM, 0x00ff);
 
-       rc = escore_cmd(escore, msg[0], &resp);
+       rc = escore_cmd_locked(escore, msg[0], &resp);
        if (rc < 0) {
-               pr_err("%s(): escore_cmd()", __func__);
+               pr_err("%s(): escore_cmd failed, rc = %d", __func__, rc);
                return rc;
        }
        msg[0] = escore->bus.last_response;
@@ -1795,9 +2127,9 @@ static int put_pcm_port_param(struct snd_kcontrol *kcontrol,
                        (pcm_port_id << 8));
 
        value = ucontrol->value.enumerated.item[0];
-       rc = escore_write(codec, reg, value);
+       rc = escore_write_locked(codec, reg, value);
        if (rc) {
-               pr_err("%s(): Preparing write message failed\n", __func__);
+               pr_err("%s(): Prepare write message fail %d\n", __func__, rc);
                return rc;
        }
 
@@ -1816,7 +2148,7 @@ static int get_mic_config(struct snd_kcontrol *kcontrol,
        unsigned int reg = e->reg;
        u16 value;
 
-       value = escore_read(codec, reg);
+       value = escore_read_locked(codec, reg);
 
        ucontrol->value.enumerated.item[0] = value;
 
@@ -1837,9 +2169,188 @@ static int put_mic_config(struct snd_kcontrol *kcontrol,
        pr_debug("%s: mic configuration value %u\n", __func__,
                value);
 
-       return escore_write(codec, reg, value);
+       return escore_write_locked(codec, reg, value);
+}
+
+static int get_pri_pb_mode(struct snd_kcontrol *kcontrol,
+               struct snd_ctl_elem_value *ucontrol)
+{
+       ucontrol->value.enumerated.item[0] = escore_priv.pri_pb_mode;
+       return 0;
+}
+
+static int _es_update_pt_vp_pri_switches(struct escore_priv *escore)
+{
+       int rc = 0;
+
+       switch (escore->pri_pb_mode) {
+       case PRI_PB_OFF:
+               es_d300_switch[SWOUT0].value = 0;
+               es_d300_switch[SWOUT1].value = 0;
+               break;
+       case PRI_PB_STEREO:
+               es_d300_switch[SWOUT0].value = 1;
+               es_d300_switch[SWOUT1].value = 1;
+               break;
+       }
+       /* Set the switches for if route is already active */
+       if (atomic_read(&escore->active_streams)) {
+               rc = _es_set_switch(SWOUT0);
+               if (!rc)
+                       rc = _es_set_switch(SWOUT1);
+       }
+
+       return rc;
+}
+
+static int _es_update_pt_vp_sec_switches(struct escore_priv *escore)
+{
+       int rc = 0;
+
+       switch (escore->sec_pb_mode) {
+       case SEC_PB_OFF:
+               es_d300_switch[SWIN2].value = 0;
+               es_d300_switch[SWOUT2].value = 0;
+               es_d300_switch[SWOUT3].value = 0;
+               break;
+       case SEC_PB_MIXED_MONO:
+               es_d300_switch[SWIN2].value = 0;
+               es_d300_switch[SWOUT2].value = 0;
+               es_d300_switch[SWOUT3].value = 1;
+               break;
+       case SEC_PB_STEREO:
+               es_d300_switch[SWIN2].value = 1;
+               es_d300_switch[SWOUT2].value = 1;
+               es_d300_switch[SWOUT3].value = 1;
+               break;
+       }
+       /* Set the switches for if route is already active */
+       if (atomic_read(&escore->active_streams)) {
+               rc = _es_set_switch(SWIN2);
+               if (!rc)
+                       rc = _es_set_switch(SWOUT2);
+               if (!rc)
+                       rc = _es_set_switch(SWOUT3);
+       }
+
+       return rc;
+}
+
+static int _es_update_bargein_pri_switches(struct escore_priv *escore)
+{
+       int rc = 0;
+
+       switch (escore->pri_pb_mode) {
+       case PRI_PB_OFF:
+               es_d300_switch[SWOUT0].value = 0;
+               es_d300_switch[SWOUT1].value = 0;
+               break;
+       case PRI_PB_STEREO:
+               es_d300_switch[SWOUT0].value = 1;
+               es_d300_switch[SWOUT1].value = 1;
+               break;
+       }
+       /* Set the switches for if route is already active */
+       if (atomic_read(&escore->active_streams)) {
+               rc = _es_set_switch(SWOUT0);
+               if (!rc)
+                       rc = _es_set_switch(SWOUT1);
+       }
+
+       return rc;
+}
+
+static int _es_update_bargein_sec_switches(struct escore_priv *escore)
+{
+       int rc = 0;
+
+       switch (escore->sec_pb_mode) {
+       case SEC_PB_OFF:
+               es_d300_switch[SWOUT2].value = 0;
+               break;
+       case SEC_PB_MIXED_MONO:
+               es_d300_switch[SWOUT2].value = 1;
+               break;
+       case SEC_PB_STEREO:
+               pr_warn("%s(): Secondary stereo output not supported\n",
+                               __func__);
+               break;
+       }
+       /* Set the switches for if route is already active */
+       if (atomic_read(&escore->active_streams))
+               rc = _es_set_switch(SWOUT2);
+
+       return rc;
+}
+
+static int put_pri_pb_mode(struct snd_kcontrol *kcontrol,
+               struct snd_ctl_elem_value *ucontrol)
+{
+       struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+       struct escore_priv *escore = snd_soc_codec_get_drvdata(codec);
+       int rc = 0;
+       int algo_type = escore->algo_type;
+
+       escore->pri_pb_mode = ucontrol->value.enumerated.item[0];
+
+       mutex_lock(&codec->mutex);
+       mutex_lock(&escore->access_lock);
+       switch (algo_type) {
+       case PASSTHRU_VP:
+               rc = _es_update_pt_vp_pri_switches(escore);
+               break;
+       case BARGE_IN:
+       case AUDIOFOCUS:
+               rc = _es_update_bargein_pri_switches(escore);
+               break;
+       default:
+               pr_err("%s(): Invalid algo type :%d\n", __func__, algo_type);
+               break;
+       }
+       mutex_unlock(&escore->access_lock);
+       mutex_unlock(&codec->mutex);
+
+       return rc;
+}
+
+static int get_sec_pb_mode(struct snd_kcontrol *kcontrol,
+               struct snd_ctl_elem_value *ucontrol)
+{
+       ucontrol->value.enumerated.item[0] = escore_priv.sec_pb_mode;
+       return 0;
+}
+
+static int put_sec_pb_mode(struct snd_kcontrol *kcontrol,
+               struct snd_ctl_elem_value *ucontrol)
+{
+       struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+       struct escore_priv *escore = snd_soc_codec_get_drvdata(codec);
+       int rc = 0;
+       int algo_type = escore->algo_type;
+
+       escore->sec_pb_mode = ucontrol->value.enumerated.item[0];
+
+       mutex_lock(&codec->mutex);
+       mutex_lock(&escore->access_lock);
+       switch (algo_type) {
+       case PASSTHRU_VP:
+               rc = _es_update_pt_vp_sec_switches(escore);
+               break;
+       case BARGE_IN:
+       case AUDIOFOCUS:
+               rc = _es_update_bargein_sec_switches(escore);
+               break;
+       default:
+               pr_err("%s(): Invalid algo type :%d\n", __func__, algo_type);
+               break;
+       }
+       mutex_unlock(&escore->access_lock);
+       mutex_unlock(&codec->mutex);
+
+       return rc;
 }
 
+
 static int get_lp_mode(struct snd_kcontrol *kcontrol,
                struct snd_ctl_elem_value *ucontrol)
 {
@@ -1873,13 +2384,15 @@ static int put_lp_route(struct snd_kcontrol *kcontrol,
                pr_debug("%s(): loopback mode is not enabled\n", __func__);
                return 0;
        }
+       mutex_lock(&escore->access_lock);
        if (!value) {
                pr_debug("%s(): discard cached list\n", __func__);
-               ret = es300_codec_stop_algo(escore);
+               ret = _es_stop_route(escore, ES_TYPE_NONE);
        } else {
                pr_debug("%s(): commit cached list\n", __func__);
-               ret = es_set_final_route(escore);
+               ret = _es_set_final_route(escore);
        }
+       mutex_unlock(&escore->access_lock);
        return ret;
 }
 
@@ -1893,28 +2406,31 @@ static int put_preset_value_one(struct snd_kcontrol *kcontrol,
 
        value = ucontrol->value.integer.value[0];
 
-       escore->algo_preset_one = value;
+       mutex_lock(&codec->mutex);
+       escore->algo_preset_one = (u16) value;
 
-       /* Ignore Preset ID 0 and don't send command to device,5
+       /* Ignore Preset ID 0 and don't send command to device,
         * but reset algo_preset value so that next preset value
         * can be set properly. */
-       if (!escore->algo_preset_one) {
+       if(!escore->algo_preset_one) {
                dev_dbg(escore_priv.dev,
-                       "%s(): Algo Preset %d is not supported, Skipped\n",
+                       "%s(): Preset ID %d is not supported\n",
                        __func__, value);
+               mutex_unlock(&codec->mutex);
                return rc;
        }
 
-       if (atomic_read(&escore->active_streams)) {
+       if (atomic_read(&escore->active_streams) && !escore->dhwpt_mode) {
                /* Set the preset immediately */
                usleep_range(5000, 5005);
                pr_debug("%s:add algo preset one: %d", __func__,
                                escore->algo_preset_one);
-               rc = escore_write(NULL, ES_PRESET, escore->algo_preset_one);
+               rc = escore_write_locked(NULL, ES_PRESET, escore->algo_preset_one);
                if (rc)
-                       pr_err("%s(): Set Algo Preset one failed:%d\n",
+                       dev_err(escore_priv.dev, "%s(): Set Preset one failed:%d\n",
                                __func__, rc);
        }
+       mutex_unlock(&codec->mutex);
 
        return rc;
 }
@@ -1939,29 +2455,31 @@ static int put_preset_value_two(struct snd_kcontrol *kcontrol,
 
        value = ucontrol->value.integer.value[0];
 
-       escore->algo_preset_two = value;
+       mutex_lock(&codec->mutex);
+       escore->algo_preset_two = (u16) value;
 
-       /* Ignore Preset ID 0 and don't send command to device,5
+       /* Ignore Preset ID 0 and don't send command to device,
         * but reset algo_preset value so that next preset value
         * can be set properly. */
-       if (!escore->algo_preset_two) {
+       if(!escore->algo_preset_two) {
                dev_dbg(escore_priv.dev,
-                       "%s(): Algo Preset %d is not supported, Skipped\n",
+                       "%s(): Preset ID %d is not supported\n",
                        __func__, value);
+               mutex_unlock(&codec->mutex);
                return rc;
        }
 
-       if (atomic_read(&escore->active_streams)) {
+       if (atomic_read(&escore->active_streams) && !escore->dhwpt_mode) {
                /* Set the preset immediately */
                usleep_range(5000, 5005);
                pr_debug("%s:add algo preset two: %d", __func__,
                                escore->algo_preset_two);
-               rc = escore_write(NULL, ES_PRESET, escore->algo_preset_two);
+               rc = escore_write_locked(NULL, ES_PRESET, escore->algo_preset_two);
                if (rc)
-                       pr_err("%s(): Set Algo Preset two failed:%d\n",
+                       dev_err(escore_priv.dev, "%s(): Set Preset two failed:%d\n",
                                __func__, rc);
        }
-
+       mutex_unlock(&codec->mutex);
        return rc;
 }
 
@@ -1975,7 +2493,75 @@ static int get_preset_value_two(struct snd_kcontrol *kcontrol,
        return 0;
 }
 
-static const char * const algorithm_texts[] = {
+
+static int get_vp_meters(struct snd_kcontrol *kcontrol,
+               struct snd_ctl_elem_value *ucontrol)
+{
+       struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+       struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
+       unsigned int reg = e->reg;
+       int rc;
+
+       rc = escore_read_locked(codec, reg);
+       if (rc < 0) {
+               pr_err("%s(): Failed to read VP Meters value :%d\n",
+                               __func__, rc);
+               return rc;
+       }
+
+       ucontrol->value.enumerated.item[0] = (unsigned int) rc;
+
+       return 0;
+}
+
+static int put_vp_meters(struct snd_kcontrol *kcontrol,
+               struct snd_ctl_elem_value *ucontrol)
+{
+       struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+       struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
+       unsigned int reg = e->reg, value;
+       int rc;
+
+       value = ucontrol->value.enumerated.item[0];
+
+       pr_debug("%s: %s VP Meters\n", __func__,
+                       (value) ? "Enable" : "Disable");
+
+       rc = escore_write_locked(codec, reg, value);
+
+       return rc;
+}
+
+static int get_hpf_mode(struct snd_kcontrol *kcontrol,
+                struct snd_ctl_elem_value *ucontrol)
+{
+       struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+       struct escore_priv *escore = snd_soc_codec_get_drvdata(codec);
+
+       ucontrol->value.enumerated.item[0] = escore->hpf_mode;
+
+       pr_debug("%s(): HPF mode Get:%d\n", __func__, escore->hpf_mode);
+       return 0;
+}
+
+static int put_hpf_mode(struct snd_kcontrol *kcontrol,
+                struct snd_ctl_elem_value *ucontrol)
+{
+       struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+       struct escore_priv *escore = snd_soc_codec_get_drvdata(codec);
+       int ret = 0;
+       int value = ucontrol->value.enumerated.item[0];
+
+       pr_debug("%s(): HPF mode Put:%d\n", __func__, value);
+
+       mutex_lock(&codec->mutex);
+       escore->hpf_mode = value;
+       mutex_unlock(&codec->mutex);
+
+       return ret;
+}
+
+static const char * const off_on_texts[] = {
        "Off", "On"
 };
 
@@ -1999,28 +2585,37 @@ static const struct soc_enum pcm_port_sel_enum =
 
 static const struct soc_enum vp_algorithm_enum =
        SOC_ENUM_SINGLE(ES_ALGORITHM_VP, 0,
-                       ARRAY_SIZE(algorithm_texts),
-                       algorithm_texts);
+                       ARRAY_SIZE(off_on_texts),
+                       off_on_texts);
 static const struct soc_enum mm_algorithm_enum =
        SOC_ENUM_SINGLE(ES_ALGORITHM_MM, 0,
-                       ARRAY_SIZE(algorithm_texts),
-                       algorithm_texts);
+                       ARRAY_SIZE(off_on_texts),
+                       off_on_texts);
 static const struct soc_enum pt_vp_algorithm_enum =
        SOC_ENUM_SINGLE(ES_ALGORITHM_PT_VP, 0,
-                       ARRAY_SIZE(algorithm_texts),
-                       algorithm_texts);
+                       ARRAY_SIZE(off_on_texts),
+                       off_on_texts);
 static const struct soc_enum pass_algorithm_enum =
        SOC_ENUM_SINGLE(ES_ALGORITHM_PT, 0,
-                       ARRAY_SIZE(algorithm_texts),
-                       algorithm_texts);
-static const struct soc_enum az_algorithm_enum =
-       SOC_ENUM_SINGLE(ES_ALGORITHM_AZ, 0,
-                       ARRAY_SIZE(algorithm_texts),
-                       algorithm_texts);
+                       ARRAY_SIZE(off_on_texts),
+                       off_on_texts);
+static const struct soc_enum af_algorithm_enum =
+       SOC_ENUM_SINGLE(ES_ALGORITHM_AF, 0,
+                       ARRAY_SIZE(off_on_texts),
+                       off_on_texts);
+static const struct soc_enum brg_algorithm_enum =
+       SOC_ENUM_SINGLE(ES_ALGORITHM_BRG, 0,
+                       ARRAY_SIZE(off_on_texts),
+                       off_on_texts);
+static const struct soc_enum kalaok_algorithm_enum =
+       SOC_ENUM_SINGLE(ES_ALGORITHM_KALAOK, 0,
+                       ARRAY_SIZE(off_on_texts),
+                       off_on_texts);
 static const struct soc_enum dhwpt_algorithm_enum =
        SOC_ENUM_SINGLE(ES_ALGORITHM_DHWPT, 0,
-                       ARRAY_SIZE(algorithm_texts),
-                       algorithm_texts);
+                       ARRAY_SIZE(off_on_texts),
+                       off_on_texts);
+
 
 static const char * const es755_algo_rates_text[] = {
        "None", "SR_8k", "SR_16k", "SR_24k", "SR_48k", "SR_96k", "SR_192k",
@@ -2031,14 +2626,10 @@ static const struct soc_enum algorithm_rate_enum =
                        ARRAY_SIZE(es755_algo_rates_text),
                        es755_algo_rates_text);
 
-static const char * const noise_suppression_texts[] = {
-       "Off", "On"
-};
-
 static const struct soc_enum noise_suppression_enum =
        SOC_ENUM_SINGLE(ES_SET_NS, 0,
-                       ARRAY_SIZE(noise_suppression_texts),
-                       noise_suppression_texts);
+                       ARRAY_SIZE(off_on_texts),
+                       off_on_texts);
 
 static const char * const mic_config_texts[] = {
        "CT Multi-mic", "FT Multi-mic", "DV 1-mic", "EXT 1-mic", "BT 1-mic",
@@ -2061,36 +2652,52 @@ static const struct soc_enum aec_mode_enum =
                ARRAY_SIZE(aec_mode_texts),
                aec_mode_texts);
 
+static const struct soc_enum vp_aec_enum =
+       SOC_ENUM_SINGLE(SND_SOC_NOPM, 0, ARRAY_SIZE(off_on_texts),
+                       off_on_texts);
+
 
-static const char * const es755_audio_zoom_texts[] = {
+static const char * const es755_audio_focus_texts[] = {
        "Narrator", "Scene", "Narration"
 };
 
-static const struct soc_enum es755_az_mode_enum =
-       SOC_ENUM_SINGLE(ES_AZ_MODE, 0, ARRAY_SIZE(es755_audio_zoom_texts),
-                       es755_audio_zoom_texts);
+static const struct soc_enum es755_af_mode_enum =
+       SOC_ENUM_SINGLE(ES_AF_MODE, 0, ARRAY_SIZE(es755_audio_focus_texts),
+                       es755_audio_focus_texts);
 
-static const char * const lp_mode_texts[] = {
-       "Off", "On"
-};
 static const struct soc_enum lp_mode_enum =
-       SOC_ENUM_SINGLE(SND_SOC_NOPM, 0, ARRAY_SIZE(lp_mode_texts),
-                       lp_mode_texts);
+       SOC_ENUM_SINGLE(SND_SOC_NOPM, 0, ARRAY_SIZE(off_on_texts),
+                       off_on_texts);
 
 static const char * const lp_commit_texts[] = {
        "Discard", "Commit"
 };
+
+static const char * const hpf_modes[] = {
+       "NONE", "FEOUT1", "FEOUT2", "FEOUT12", "AUDOUT1",
+       "AUDOUT2", "AUDOUT12", "PASSOUT1", "PASSOUT2",
+       "PASSOUT12", "PASSOUT3", "PASSOUT4", "PASSOUT34"
+};
+
 static const struct soc_enum lp_commit_enum =
        SOC_ENUM_SINGLE(SND_SOC_NOPM, 0, ARRAY_SIZE(lp_commit_texts),
                        lp_commit_texts);
 
-static const char * const vp_aec_texts[] = {
-       "Off", "On"
-};
-static const struct soc_enum vp_aec_enum =
-       SOC_ENUM_SINGLE(SND_SOC_NOPM, 0, ARRAY_SIZE(vp_aec_texts),
-                       vp_aec_texts);
+static const struct soc_enum pri_pb_mode_enum =
+       SOC_ENUM_SINGLE(SND_SOC_NOPM, 0, ARRAY_SIZE(pri_pb_mode_texts),
+                       pri_pb_mode_texts);
 
+static const struct soc_enum sec_pb_mode_enum =
+       SOC_ENUM_SINGLE(SND_SOC_NOPM, 0, ARRAY_SIZE(sec_pb_mode_texts),
+                       sec_pb_mode_texts);
+
+static const struct soc_enum vp_meters_enum =
+       SOC_ENUM_SINGLE(ES_VP_METERS, 0, ARRAY_SIZE(off_on_texts),
+                       off_on_texts);
+
+static const struct soc_enum hpf_modes_enum =
+       SOC_ENUM_SINGLE(SND_SOC_NOPM, 0, ARRAY_SIZE(hpf_modes),
+                       hpf_modes);
 
 static const struct snd_kcontrol_new es_d300_snd_controls[] = {
        SOC_ENUM_EXT("VP Algorithm", vp_algorithm_enum,
@@ -2101,13 +2708,19 @@ static const struct snd_kcontrol_new es_d300_snd_controls[] = {
                         es300_get_algo_state, es300_put_algo_state),
        SOC_ENUM_EXT("PT Algorithm", pass_algorithm_enum,
                         es300_get_algo_state, es300_put_algo_state),
-       SOC_ENUM_EXT("AZ Algorithm", az_algorithm_enum,
+       SOC_ENUM_EXT("AF Algorithm", af_algorithm_enum,
+                        es300_get_algo_state, es300_put_algo_state),
+       SOC_ENUM_EXT("BRG Algorithm", brg_algorithm_enum,
+                        es300_get_algo_state, es300_put_algo_state),
+       SOC_ENUM_EXT("KALAOK Algorithm", kalaok_algorithm_enum,
                         es300_get_algo_state, es300_put_algo_state),
        SOC_ENUM_EXT("DHWPT Algorithm", dhwpt_algorithm_enum,
                         es300_get_algo_state, es300_put_algo_state),
 
        SOC_ENUM_EXT("Algorithm Rate", algorithm_rate_enum,
                         get_control_enum, es300_put_algo_rate),
+       SOC_SINGLE_EXT("DHWPT Enable", SND_SOC_NOPM, 0, 1, 0,
+                       get_dhwpt_sel, put_dhwpt_sel),
        SOC_SINGLE_EXT("ASR", SND_SOC_NOPM, 0, 1, 0,
                         get_asr_sel, put_asr_sel),
        SOC_SINGLE_EXT("Write Route Cmds", SND_SOC_NOPM, 0, 1, 0,
@@ -2118,8 +2731,8 @@ static const struct snd_kcontrol_new es_d300_snd_controls[] = {
                        get_noise_suppression, put_noise_suppression),
        SOC_ENUM_EXT("Mic Config", mic_config_enum,
                        get_mic_config, put_mic_config),
-       SOC_ENUM_EXT("Audio Zoom", es755_az_mode_enum,
-                       get_az_mode, put_az_mode),
+       SOC_ENUM_EXT("Audio Focus Mode", es755_af_mode_enum,
+                       get_af_mode, put_af_mode),
        SOC_ENUM_EXT("PCM Port Selection", pcm_port_sel_enum,
                        get_control_enum, put_pcm_port_sel),
        SOC_ENUM_EXT("Command Mode Selection", cmd_compl_mode_sel_enum,
@@ -2167,8 +2780,26 @@ static const struct snd_kcontrol_new es_d300_snd_controls[] = {
        SOC_SINGLE_EXT("Algo Preset 2",
                        SND_SOC_NOPM, 0, 65535, 0, get_preset_value_two,
                        put_preset_value_two),
+       SOC_ENUM_EXT("PRI Playback Mode", pri_pb_mode_enum,
+                        get_pri_pb_mode, put_pri_pb_mode),
+       SOC_ENUM_EXT("SEC Playback Mode", sec_pb_mode_enum,
+                        get_sec_pb_mode, put_sec_pb_mode),
        SOC_ENUM_EXT("VP AEC", vp_aec_enum,
                         get_vp_aec, put_vp_aec),
+
+       /* The range of Ambient Noise starts from 0dB (Max) down to
+        * -96dB (Min). However, the kcontrol framework range start from
+        *  0 (Min) to XX (positive Max). We made this adjustment to use minimum
+        *  value of "Ambient Noise" value as the "max" field in kcontrol
+        *  declaration so that we get range of 0 to -96 (in dB).
+        */
+       SOC_SINGLE_EXT("Ambient Noise", SND_SOC_NOPM, 0, ES_MIN_NOISE_DB, 0,
+                        get_ambient_noise, NULL),
+       SOC_ENUM_EXT("VP Meters", vp_meters_enum,
+                        get_vp_meters, put_vp_meters),
+       SOC_ENUM_EXT("HPF Endpoint", hpf_modes_enum,
+                       get_hpf_mode, put_hpf_mode),
+
 };
 
 static const struct soc_enum vp_pri_enum =
@@ -2330,36 +2961,28 @@ static const struct soc_enum pass_audin4_enum =
 static const struct snd_kcontrol_new dapm_pass_audin4_control =
        SOC_DAPM_ENUM_EXT("Pass AUDIN4 MUX Mux", pass_audin4_enum,
                          get_input_route_value, put_input_route_value);
-static const struct soc_enum az_pri_enum =
-       SOC_ENUM_SINGLE(ES_AZ_PRI_MUX, 0,
-                    ARRAY_SIZE(proc_block_input_texts),
-                    proc_block_input_texts);
-static const struct snd_kcontrol_new dapm_az_pri_control =
-       SOC_DAPM_ENUM_EXT("AudioZoom Primary MUX Mux", az_pri_enum,
-                         get_input_route_value, put_input_route_value);
-
-static const struct soc_enum az_sec_enum =
-       SOC_ENUM_SINGLE(ES_AZ_SEC_MUX, 0,
+static const struct soc_enum af_pri_enum =
+       SOC_ENUM_SINGLE(ES_AF_PRI_MUX, 0,
                     ARRAY_SIZE(proc_block_input_texts),
                     proc_block_input_texts);
-static const struct snd_kcontrol_new dapm_az_sec_control =
-       SOC_DAPM_ENUM_EXT("AudioZoom Secondary MUX Mux", az_sec_enum,
+static const struct snd_kcontrol_new dapm_af_pri_control =
+       SOC_DAPM_ENUM_EXT("AudioFocus Primary MUX Mux", af_pri_enum,
                          get_input_route_value, put_input_route_value);
 
-static const struct soc_enum az_ter_enum =
-       SOC_ENUM_SINGLE(ES_AZ_TER_MUX, 0,
+static const struct soc_enum af_sec_enum =
+       SOC_ENUM_SINGLE(ES_AF_SEC_MUX, 0,
                     ARRAY_SIZE(proc_block_input_texts),
                     proc_block_input_texts);
-static const struct snd_kcontrol_new dapm_az_ter_control =
-       SOC_DAPM_ENUM_EXT("AudioZoom Tertiary MUX Mux", az_ter_enum,
+static const struct snd_kcontrol_new dapm_af_sec_control =
+       SOC_DAPM_ENUM_EXT("AudioFocus Secondary MUX Mux", af_sec_enum,
                          get_input_route_value, put_input_route_value);
 
-static const struct soc_enum az_ai1_enum =
-       SOC_ENUM_SINGLE(ES_AZ_AI1_MUX, 0,
+static const struct soc_enum af_ter_enum =
+       SOC_ENUM_SINGLE(ES_AF_TER_MUX, 0,
                     ARRAY_SIZE(proc_block_input_texts),
                     proc_block_input_texts);
-static const struct snd_kcontrol_new dapm_az_ai1_control =
-       SOC_DAPM_ENUM_EXT("AudioZoom AI1 MUX Mux", az_ai1_enum,
+static const struct snd_kcontrol_new dapm_af_ter_control =
+       SOC_DAPM_ENUM_EXT("AudioFocus Tertiary MUX Mux", af_ter_enum,
                          get_input_route_value, put_input_route_value);
 
 static const struct soc_enum pcm0_0_enum =
@@ -2710,15 +3333,13 @@ static const struct snd_soc_dapm_widget es_d300_dapm_widgets[] = {
                        &dapm_mm_passin2_control),
 
 
-       /* AudioZoom */
-       SND_SOC_DAPM_MUX("AudioZoom Primary MUX", SND_SOC_NOPM, 0, 0,
-                       &dapm_az_pri_control),
-       SND_SOC_DAPM_MUX("AudioZoom Secondary MUX", SND_SOC_NOPM, 0, 0,
-                       &dapm_az_sec_control),
-       SND_SOC_DAPM_MUX("AudioZoom Teritary MUX", SND_SOC_NOPM, 0, 0,
-                       &dapm_az_ter_control),
-       SND_SOC_DAPM_MUX("AudioZoom AI1 MUX", SND_SOC_NOPM, 0, 0,
-                       &dapm_az_ai1_control),
+       /* AudioFocus */
+       SND_SOC_DAPM_MUX("AudioFocus Primary MUX", SND_SOC_NOPM, 0, 0,
+                       &dapm_af_pri_control),
+       SND_SOC_DAPM_MUX("AudioFocus Secondary MUX", SND_SOC_NOPM, 0, 0,
+                       &dapm_af_sec_control),
+       SND_SOC_DAPM_MUX("AudioFocus Teritary MUX", SND_SOC_NOPM, 0, 0,
+                       &dapm_af_ter_control),
 
        SND_SOC_DAPM_MUX("PCM0.0 MUX", SND_SOC_NOPM, 0, 0,
                         &dapm_pcm0_0_control),
@@ -2785,10 +3406,10 @@ static const struct snd_soc_dapm_widget es_d300_dapm_widgets[] = {
        SND_SOC_DAPM_MIXER("Pass AUDOUT3 Mixer", SND_SOC_NOPM, 0, 0, NULL, 0),
        SND_SOC_DAPM_MIXER("Pass AUDOUT4 Mixer", SND_SOC_NOPM, 0, 0, NULL, 0),
        SND_SOC_DAPM_MIXER("Pass AO1 Mixer", SND_SOC_NOPM, 0, 0, NULL, 0),
-       SND_SOC_DAPM_MIXER("Pass MO2 Mixer", SND_SOC_NOPM, 0, 0, NULL, 0),
-       SND_SOC_DAPM_MIXER("AudioZoom CSOUT Mixer", SND_SOC_NOPM,
+       SND_SOC_DAPM_MIXER("Pass AO2 Mixer", SND_SOC_NOPM, 0, 0, NULL, 0),
+       SND_SOC_DAPM_MIXER("AudioFocus CSOUT1 Mixer", SND_SOC_NOPM,
                        0, 0, NULL, 0),
-       SND_SOC_DAPM_MIXER("AudioZoom AOUT1 Mixer", SND_SOC_NOPM,
+       SND_SOC_DAPM_MIXER("AudioFocus CSOUT2 Mixer", SND_SOC_NOPM,
                        0, 0, NULL, 0),
        SND_SOC_DAPM_OUTPUT("PCM PORT A.0"),
        SND_SOC_DAPM_OUTPUT("PCM PORT A.1"),
@@ -3062,6 +3683,7 @@ static const struct snd_soc_dapm_route intercon[] = {
        {"VP CSOUT2 Mixer", NULL, "VP Secondary MUX"},
        {"VP CSOUT2 Mixer", NULL, "VP Teritary MUX"},
        {"VP CSOUT2 Mixer", NULL, "VP AECREF MUX"},
+       {"VP CSOUT2 Mixer", NULL, "VP FEIN MUX"},
        {"VP FEOUT1 Mixer", NULL, "VP FEIN MUX"},
        {"VP FEOUT2 Mixer", NULL, "VP FEIN2 MUX"},
        {"VP FEOUT1 Mixer", NULL, "VP UITONE1 MUX"},
@@ -3375,144 +3997,116 @@ static const struct snd_soc_dapm_route intercon[] = {
        {"Pass AUDOUT4 Mixer", NULL, "Pass AUDIN4 MUX"},
        {"Pass AO1 Mixer", NULL, "Pass AUDIN1 MUX"},
        {"Pass AO1 Mixer", NULL, "Pass AUDIN2 MUX"},
-       {"Pass MO2 Mixer", NULL, "Pass AUDIN2 MUX"},
-
-       {"AudioZoom Primary MUX", "PCM0.0", "PCM0.0 RX"},
-       {"AudioZoom Primary MUX", "PCM0.1", "PCM0.1 RX"},
-       {"AudioZoom Primary MUX", "PCM0.2", "PCM0.2 RX"},
-       {"AudioZoom Primary MUX", "PCM0.3", "PCM0.3 RX"},
-       {"AudioZoom Primary MUX", "PCM1.0", "PCM1.0 RX"},
-       {"AudioZoom Primary MUX", "PCM1.1", "PCM1.1 RX"},
-       {"AudioZoom Primary MUX", "PCM1.2", "PCM1.2 RX"},
-       {"AudioZoom Primary MUX", "PCM1.3", "PCM1.3 RX"},
-       {"AudioZoom Primary MUX", "PCM2.0", "PCM2.0 RX"},
-       {"AudioZoom Primary MUX", "PCM2.1", "PCM2.1 RX"},
-       {"AudioZoom Primary MUX", "PCM2.2", "PCM2.2 RX"},
-       {"AudioZoom Primary MUX", "PCM2.3", "PCM2.3 RX"},
-       {"AudioZoom Primary MUX", "PDMI0", "PDMI0"},
-       {"AudioZoom Primary MUX", "PDMI1", "PDMI1"},
-       {"AudioZoom Primary MUX", "PDMI2", "PDMI2"},
-       {"AudioZoom Primary MUX", "PDMI3", "PDMI3"},
-       {"AudioZoom Primary MUX", "SBUS.RX0", "SBUS.RX0"},
-       {"AudioZoom Primary MUX", "SBUS.RX1", "SBUS.RX1"},
-       {"AudioZoom Primary MUX", "SBUS.RX2", "SBUS.RX2"},
-       {"AudioZoom Primary MUX", "SBUS.RX3", "SBUS.RX3"},
-       {"AudioZoom Primary MUX", "SBUS.RX4", "SBUS.RX4"},
-       {"AudioZoom Primary MUX", "SBUS.RX5", "SBUS.RX5"},
-       {"AudioZoom Primary MUX", "SBUS.RX6", "SBUS.RX6"},
-       {"AudioZoom Primary MUX", "SBUS.RX7", "SBUS.RX7"},
-       {"AudioZoom Primary MUX", "SBUS.RX8", "SBUS.RX8"},
-       {"AudioZoom Primary MUX", "SBUS.RX9", "SBUS.RX9"},
-       {"AudioZoom Primary MUX", "ADC0", "ADC0"},
-       {"AudioZoom Primary MUX", "ADC1", "ADC1"},
-       {"AudioZoom Primary MUX", "ADC2", "ADC2"},
-       {"AudioZoom Primary MUX", "ADC3", "ADC3"},
-
-       {"AudioZoom Secondary MUX", "PCM0.0", "PCM0.0 RX"},
-       {"AudioZoom Secondary MUX", "PCM0.1", "PCM0.1 RX"},
-       {"AudioZoom Secondary MUX", "PCM0.2", "PCM0.2 RX"},
-       {"AudioZoom Secondary MUX", "PCM0.3", "PCM0.3 RX"},
-       {"AudioZoom Secondary MUX", "PCM1.0", "PCM1.0 RX"},
-       {"AudioZoom Secondary MUX", "PCM1.1", "PCM1.1 RX"},
-       {"AudioZoom Secondary MUX", "PCM1.2", "PCM1.2 RX"},
-       {"AudioZoom Secondary MUX", "PCM1.3", "PCM1.3 RX"},
-       {"AudioZoom Secondary MUX", "PCM2.0", "PCM2.0 RX"},
-       {"AudioZoom Secondary MUX", "PCM2.1", "PCM2.1 RX"},
-       {"AudioZoom Secondary MUX", "PCM2.2", "PCM2.2 RX"},
-       {"AudioZoom Secondary MUX", "PCM2.3", "PCM2.3 RX"},
-       {"AudioZoom Secondary MUX", "PDMI0", "PDMI0"},
-       {"AudioZoom Secondary MUX", "PDMI1", "PDMI1"},
-       {"AudioZoom Secondary MUX", "PDMI2", "PDMI2"},
-       {"AudioZoom Secondary MUX", "PDMI3", "PDMI3"},
-       {"AudioZoom Secondary MUX", "SBUS.RX0", "SBUS.RX0"},
-       {"AudioZoom Secondary MUX", "SBUS.RX1", "SBUS.RX1"},
-       {"AudioZoom Secondary MUX", "SBUS.RX2", "SBUS.RX2"},
-       {"AudioZoom Secondary MUX", "SBUS.RX3", "SBUS.RX3"},
-       {"AudioZoom Secondary MUX", "SBUS.RX4", "SBUS.RX4"},
-       {"AudioZoom Secondary MUX", "SBUS.RX5", "SBUS.RX5"},
-       {"AudioZoom Secondary MUX", "SBUS.RX6", "SBUS.RX6"},
-       {"AudioZoom Secondary MUX", "SBUS.RX7", "SBUS.RX7"},
-       {"AudioZoom Secondary MUX", "SBUS.RX8", "SBUS.RX8"},
-       {"AudioZoom Secondary MUX", "SBUS.RX9", "SBUS.RX9"},
-       {"AudioZoom Secondary MUX", "ADC0", "ADC0"},
-       {"AudioZoom Secondary MUX", "ADC1", "ADC1"},
-       {"AudioZoom Secondary MUX", "ADC2", "ADC2"},
-       {"AudioZoom Secondary MUX", "ADC3", "ADC3"},
-
-       {"AudioZoom Teritary MUX", "PCM0.0", "PCM0.0 RX"},
-       {"AudioZoom Teritary MUX", "PCM0.1", "PCM0.1 RX"},
-       {"AudioZoom Teritary MUX", "PCM0.2", "PCM0.2 RX"},
-       {"AudioZoom Teritary MUX", "PCM0.3", "PCM0.3 RX"},
-       {"AudioZoom Teritary MUX", "PCM1.0", "PCM1.0 RX"},
-       {"AudioZoom Teritary MUX", "PCM1.1", "PCM1.1 RX"},
-       {"AudioZoom Teritary MUX", "PCM1.2", "PCM1.2 RX"},
-       {"AudioZoom Teritary MUX", "PCM1.3", "PCM1.3 RX"},
-       {"AudioZoom Teritary MUX", "PCM2.0", "PCM2.0 RX"},
-       {"AudioZoom Teritary MUX", "PCM2.1", "PCM2.1 RX"},
-       {"AudioZoom Teritary MUX", "PCM2.2", "PCM2.2 RX"},
-       {"AudioZoom Teritary MUX", "PCM2.3", "PCM2.3 RX"},
-       {"AudioZoom Teritary MUX", "PDMI0", "PDMI0"},
-       {"AudioZoom Teritary MUX", "PDMI1", "PDMI1"},
-       {"AudioZoom Teritary MUX", "PDMI2", "PDMI2"},
-       {"AudioZoom Teritary MUX", "PDMI3", "PDMI3"},
-       {"AudioZoom Teritary MUX", "SBUS.RX0", "SBUS.RX0"},
-       {"AudioZoom Teritary MUX", "SBUS.RX1", "SBUS.RX1"},
-       {"AudioZoom Teritary MUX", "SBUS.RX2", "SBUS.RX2"},
-       {"AudioZoom Teritary MUX", "SBUS.RX3", "SBUS.RX3"},
-       {"AudioZoom Teritary MUX", "SBUS.RX4", "SBUS.RX4"},
-       {"AudioZoom Teritary MUX", "SBUS.RX5", "SBUS.RX5"},
-       {"AudioZoom Teritary MUX", "SBUS.RX6", "SBUS.RX6"},
-       {"AudioZoom Teritary MUX", "SBUS.RX7", "SBUS.RX7"},
-       {"AudioZoom Teritary MUX", "SBUS.RX8", "SBUS.RX8"},
-       {"AudioZoom Teritary MUX", "SBUS.RX9", "SBUS.RX9"},
-       {"AudioZoom Teritary MUX", "ADC0", "ADC0"},
-       {"AudioZoom Teritary MUX", "ADC1", "ADC1"},
-       {"AudioZoom Teritary MUX", "ADC2", "ADC2"},
-       {"AudioZoom Teritary MUX", "ADC3", "ADC3"},
-
-       {"AudioZoom AI1 MUX", "PCM0.0", "PCM0.0 RX"},
-       {"AudioZoom AI1 MUX", "PCM0.1", "PCM0.1 RX"},
-       {"AudioZoom AI1 MUX", "PCM0.2", "PCM0.2 RX"},
-       {"AudioZoom AI1 MUX", "PCM0.3", "PCM0.3 RX"},
-       {"AudioZoom AI1 MUX", "PCM1.0", "PCM1.0 RX"},
-       {"AudioZoom AI1 MUX", "PCM1.1", "PCM1.1 RX"},
-       {"AudioZoom AI1 MUX", "PCM1.2", "PCM1.2 RX"},
-       {"AudioZoom AI1 MUX", "PCM1.3", "PCM1.3 RX"},
-       {"AudioZoom AI1 MUX", "PCM2.0", "PCM2.0 RX"},
-       {"AudioZoom AI1 MUX", "PCM2.1", "PCM2.1 RX"},
-       {"AudioZoom AI1 MUX", "PCM2.2", "PCM2.2 RX"},
-       {"AudioZoom AI1 MUX", "PCM2.3", "PCM2.3 RX"},
-       {"AudioZoom AI1 MUX", "PDMI0", "PDMI0"},
-       {"AudioZoom AI1 MUX", "PDMI1", "PDMI1"},
-       {"AudioZoom AI1 MUX", "PDMI2", "PDMI2"},
-       {"AudioZoom AI1 MUX", "PDMI3", "PDMI3"},
-       {"AudioZoom AI1 MUX", "SBUS.RX0", "SBUS.RX0"},
-       {"AudioZoom AI1 MUX", "SBUS.RX1", "SBUS.RX1"},
-       {"AudioZoom AI1 MUX", "SBUS.RX2", "SBUS.RX2"},
-       {"AudioZoom AI1 MUX", "SBUS.RX3", "SBUS.RX3"},
-       {"AudioZoom AI1 MUX", "SBUS.RX4", "SBUS.RX4"},
-       {"AudioZoom AI1 MUX", "SBUS.RX5", "SBUS.RX5"},
-       {"AudioZoom AI1 MUX", "SBUS.RX6", "SBUS.RX6"},
-       {"AudioZoom AI1 MUX", "SBUS.RX7", "SBUS.RX7"},
-       {"AudioZoom AI1 MUX", "SBUS.RX8", "SBUS.RX8"},
-       {"AudioZoom AI1 MUX", "SBUS.RX9", "SBUS.RX9"},
-       {"AudioZoom AI1 MUX", "ADC0", "ADC0"},
-       {"AudioZoom AI1 MUX", "ADC1", "ADC1"},
-       {"AudioZoom AI1 MUX", "ADC2", "ADC2"},
-       {"AudioZoom AI1 MUX", "ADC3", "ADC3"},
-
-       {"AudioZoom CSOUT Mixer", NULL, "AudioZoom Primary MUX"},
-       {"AudioZoom CSOUT Mixer", NULL, "AudioZoom Secondary MUX"},
-       {"AudioZoom CSOUT Mixer", NULL, "AudioZoom Teritary MUX"},
-       {"AudioZoom AOUT1 Mixer", NULL, "AudioZoom AI1 MUX"},
+       {"Pass AO2 Mixer", NULL, "Pass AUDIN1 MUX"},
+       {"Pass AO2 Mixer", NULL, "Pass AUDIN2 MUX"},
+
+       {"AudioFocus Primary MUX", "PCM0.0", "PCM0.0 RX"},
+       {"AudioFocus Primary MUX", "PCM0.1", "PCM0.1 RX"},
+       {"AudioFocus Primary MUX", "PCM0.2", "PCM0.2 RX"},
+       {"AudioFocus Primary MUX", "PCM0.3", "PCM0.3 RX"},
+       {"AudioFocus Primary MUX", "PCM1.0", "PCM1.0 RX"},
+       {"AudioFocus Primary MUX", "PCM1.1", "PCM1.1 RX"},
+       {"AudioFocus Primary MUX", "PCM1.2", "PCM1.2 RX"},
+       {"AudioFocus Primary MUX", "PCM1.3", "PCM1.3 RX"},
+       {"AudioFocus Primary MUX", "PCM2.0", "PCM2.0 RX"},
+       {"AudioFocus Primary MUX", "PCM2.1", "PCM2.1 RX"},
+       {"AudioFocus Primary MUX", "PCM2.2", "PCM2.2 RX"},
+       {"AudioFocus Primary MUX", "PCM2.3", "PCM2.3 RX"},
+       {"AudioFocus Primary MUX", "PDMI0", "PDMI0"},
+       {"AudioFocus Primary MUX", "PDMI1", "PDMI1"},
+       {"AudioFocus Primary MUX", "PDMI2", "PDMI2"},
+       {"AudioFocus Primary MUX", "PDMI3", "PDMI3"},
+       {"AudioFocus Primary MUX", "SBUS.RX0", "SBUS.RX0"},
+       {"AudioFocus Primary MUX", "SBUS.RX1", "SBUS.RX1"},
+       {"AudioFocus Primary MUX", "SBUS.RX2", "SBUS.RX2"},
+       {"AudioFocus Primary MUX", "SBUS.RX3", "SBUS.RX3"},
+       {"AudioFocus Primary MUX", "SBUS.RX4", "SBUS.RX4"},
+       {"AudioFocus Primary MUX", "SBUS.RX5", "SBUS.RX5"},
+       {"AudioFocus Primary MUX", "SBUS.RX6", "SBUS.RX6"},
+       {"AudioFocus Primary MUX", "SBUS.RX7", "SBUS.RX7"},
+       {"AudioFocus Primary MUX", "SBUS.RX8", "SBUS.RX8"},
+       {"AudioFocus Primary MUX", "SBUS.RX9", "SBUS.RX9"},
+       {"AudioFocus Primary MUX", "ADC0", "ADC0"},
+       {"AudioFocus Primary MUX", "ADC1", "ADC1"},
+       {"AudioFocus Primary MUX", "ADC2", "ADC2"},
+       {"AudioFocus Primary MUX", "ADC3", "ADC3"},
+
+       {"AudioFocus Secondary MUX", "PCM0.0", "PCM0.0 RX"},
+       {"AudioFocus Secondary MUX", "PCM0.1", "PCM0.1 RX"},
+       {"AudioFocus Secondary MUX", "PCM0.2", "PCM0.2 RX"},
+       {"AudioFocus Secondary MUX", "PCM0.3", "PCM0.3 RX"},
+       {"AudioFocus Secondary MUX", "PCM1.0", "PCM1.0 RX"},
+       {"AudioFocus Secondary MUX", "PCM1.1", "PCM1.1 RX"},
+       {"AudioFocus Secondary MUX", "PCM1.2", "PCM1.2 RX"},
+       {"AudioFocus Secondary MUX", "PCM1.3", "PCM1.3 RX"},
+       {"AudioFocus Secondary MUX", "PCM2.0", "PCM2.0 RX"},
+       {"AudioFocus Secondary MUX", "PCM2.1", "PCM2.1 RX"},
+       {"AudioFocus Secondary MUX", "PCM2.2", "PCM2.2 RX"},
+       {"AudioFocus Secondary MUX", "PCM2.3", "PCM2.3 RX"},
+       {"AudioFocus Secondary MUX", "PDMI0", "PDMI0"},
+       {"AudioFocus Secondary MUX", "PDMI1", "PDMI1"},
+       {"AudioFocus Secondary MUX", "PDMI2", "PDMI2"},
+       {"AudioFocus Secondary MUX", "PDMI3", "PDMI3"},
+       {"AudioFocus Secondary MUX", "SBUS.RX0", "SBUS.RX0"},
+       {"AudioFocus Secondary MUX", "SBUS.RX1", "SBUS.RX1"},
+       {"AudioFocus Secondary MUX", "SBUS.RX2", "SBUS.RX2"},
+       {"AudioFocus Secondary MUX", "SBUS.RX3", "SBUS.RX3"},
+       {"AudioFocus Secondary MUX", "SBUS.RX4", "SBUS.RX4"},
+       {"AudioFocus Secondary MUX", "SBUS.RX5", "SBUS.RX5"},
+       {"AudioFocus Secondary MUX", "SBUS.RX6", "SBUS.RX6"},
+       {"AudioFocus Secondary MUX", "SBUS.RX7", "SBUS.RX7"},
+       {"AudioFocus Secondary MUX", "SBUS.RX8", "SBUS.RX8"},
+       {"AudioFocus Secondary MUX", "SBUS.RX9", "SBUS.RX9"},
+       {"AudioFocus Secondary MUX", "ADC0", "ADC0"},
+       {"AudioFocus Secondary MUX", "ADC1", "ADC1"},
+       {"AudioFocus Secondary MUX", "ADC2", "ADC2"},
+       {"AudioFocus Secondary MUX", "ADC3", "ADC3"},
+
+       {"AudioFocus Teritary MUX", "PCM0.0", "PCM0.0 RX"},
+       {"AudioFocus Teritary MUX", "PCM0.1", "PCM0.1 RX"},
+       {"AudioFocus Teritary MUX", "PCM0.2", "PCM0.2 RX"},
+       {"AudioFocus Teritary MUX", "PCM0.3", "PCM0.3 RX"},
+       {"AudioFocus Teritary MUX", "PCM1.0", "PCM1.0 RX"},
+       {"AudioFocus Teritary MUX", "PCM1.1", "PCM1.1 RX"},
+       {"AudioFocus Teritary MUX", "PCM1.2", "PCM1.2 RX"},
+       {"AudioFocus Teritary MUX", "PCM1.3", "PCM1.3 RX"},
+       {"AudioFocus Teritary MUX", "PCM2.0", "PCM2.0 RX"},
+       {"AudioFocus Teritary MUX", "PCM2.1", "PCM2.1 RX"},
+       {"AudioFocus Teritary MUX", "PCM2.2", "PCM2.2 RX"},
+       {"AudioFocus Teritary MUX", "PCM2.3", "PCM2.3 RX"},
+       {"AudioFocus Teritary MUX", "PDMI0", "PDMI0"},
+       {"AudioFocus Teritary MUX", "PDMI1", "PDMI1"},
+       {"AudioFocus Teritary MUX", "PDMI2", "PDMI2"},
+       {"AudioFocus Teritary MUX", "PDMI3", "PDMI3"},
+       {"AudioFocus Teritary MUX", "SBUS.RX0", "SBUS.RX0"},
+       {"AudioFocus Teritary MUX", "SBUS.RX1", "SBUS.RX1"},
+       {"AudioFocus Teritary MUX", "SBUS.RX2", "SBUS.RX2"},
+       {"AudioFocus Teritary MUX", "SBUS.RX3", "SBUS.RX3"},
+       {"AudioFocus Teritary MUX", "SBUS.RX4", "SBUS.RX4"},
+       {"AudioFocus Teritary MUX", "SBUS.RX5", "SBUS.RX5"},
+       {"AudioFocus Teritary MUX", "SBUS.RX6", "SBUS.RX6"},
+       {"AudioFocus Teritary MUX", "SBUS.RX7", "SBUS.RX7"},
+       {"AudioFocus Teritary MUX", "SBUS.RX8", "SBUS.RX8"},
+       {"AudioFocus Teritary MUX", "SBUS.RX9", "SBUS.RX9"},
+       {"AudioFocus Teritary MUX", "ADC0", "ADC0"},
+       {"AudioFocus Teritary MUX", "ADC1", "ADC1"},
+       {"AudioFocus Teritary MUX", "ADC2", "ADC2"},
+       {"AudioFocus Teritary MUX", "ADC3", "ADC3"},
+
+       {"AudioFocus CSOUT1 Mixer", NULL, "AudioFocus Primary MUX"},
+       {"AudioFocus CSOUT1 Mixer", NULL, "AudioFocus Secondary MUX"},
+       {"AudioFocus CSOUT1 Mixer", NULL, "AudioFocus Teritary MUX"},
+       {"AudioFocus CSOUT2 Mixer", NULL, "AudioFocus Primary MUX"},
+       {"AudioFocus CSOUT2 Mixer", NULL, "AudioFocus Secondary MUX"},
+       {"AudioFocus CSOUT2 Mixer", NULL, "AudioFocus Teritary MUX"},
 
        {"PCM0.0 MUX", "VP CSOUT1", "VP CSOUT1 Mixer"},
        {"PCM0.0 MUX", "VP CSOUT2", "VP CSOUT2 Mixer"},
        {"PCM0.0 MUX", "VP FEOUT1", "VP FEOUT1 Mixer"},
        {"PCM0.0 MUX", "VP FEOUT1", "VP FEOUT_CSOUT Mixer"},
        {"PCM0.0 MUX", "VP FEOUT2", "VP FEOUT2 Mixer"},
-       {"PCM0.0 MUX", "AudioZoom CSOUT", "AudioZoom CSOUT Mixer"},
-       {"PCM0.0 MUX", "AudioZoom AOUT1", "AudioZoom AOUT1 Mixer"},
+       {"PCM0.0 MUX", "AudioFocus CSOUT1", "AudioFocus CSOUT1 Mixer"},
+       {"PCM0.0 MUX", "AudioFocus CSOUT2", "AudioFocus CSOUT2 Mixer"},
        {"PCM0.0 MUX", "MM PASSOUT1", "MM PASSOUT1 Mixer"},
        {"PCM0.0 MUX", "MM PASSOUT2", "MM PASSOUT2 Mixer"},
        {"PCM0.0 MUX", "MM AUDOUT1", "MM AUDOUT1 Mixer"},
@@ -3524,14 +4118,14 @@ static const struct snd_soc_dapm_route intercon[] = {
        {"PCM0.0 MUX", "Pass AUDOUT3", "Pass AUDOUT3 Mixer"},
        {"PCM0.0 MUX", "Pass AUDOUT4", "Pass AUDOUT4 Mixer"},
        {"PCM0.0 MUX", "Pass AO1", "Pass AO1 Mixer"},
-       {"PCM0.0 MUX", "Pass MO2", "Pass MO2 Mixer"},
+       {"PCM0.0 MUX", "Pass AO2", "Pass AO2 Mixer"},
        {"PCM0.1 MUX", "VP CSOUT1", "VP CSOUT1 Mixer"},
        {"PCM0.1 MUX", "VP CSOUT2", "VP CSOUT2 Mixer"},
        {"PCM0.1 MUX", "VP FEOUT1", "VP FEOUT1 Mixer"},
        {"PCM0.1 MUX", "VP FEOUT1", "VP FEOUT_CSOUT Mixer"},
        {"PCM0.1 MUX", "VP FEOUT2", "VP FEOUT2 Mixer"},
-       {"PCM0.1 MUX", "AudioZoom CSOUT", "AudioZoom CSOUT Mixer"},
-       {"PCM0.1 MUX", "AudioZoom AOUT1", "AudioZoom AOUT1 Mixer"},
+       {"PCM0.1 MUX", "AudioFocus CSOUT1", "AudioFocus CSOUT1 Mixer"},
+       {"PCM0.1 MUX", "AudioFocus CSOUT2", "AudioFocus CSOUT2 Mixer"},
        {"PCM0.1 MUX", "MM PASSOUT1", "MM PASSOUT1 Mixer"},
        {"PCM0.1 MUX", "MM PASSOUT2", "MM PASSOUT2 Mixer"},
        {"PCM0.1 MUX", "MM AUDOUT1", "MM AUDOUT1 Mixer"},
@@ -3543,14 +4137,14 @@ static const struct snd_soc_dapm_route intercon[] = {
        {"PCM0.1 MUX", "Pass AUDOUT3", "Pass AUDOUT3 Mixer"},
        {"PCM0.1 MUX", "Pass AUDOUT4", "Pass AUDOUT4 Mixer"},
        {"PCM0.1 MUX", "Pass AO1", "Pass AO1 Mixer"},
-       {"PCM0.1 MUX", "Pass MO2", "Pass MO2 Mixer"},
+       {"PCM0.1 MUX", "Pass AO2", "Pass AO2 Mixer"},
        {"PCM0.2 MUX", "VP CSOUT1", "VP CSOUT1 Mixer"},
        {"PCM0.2 MUX", "VP CSOUT2", "VP CSOUT2 Mixer"},
        {"PCM0.2 MUX", "VP FEOUT1", "VP FEOUT1 Mixer"},
        {"PCM0.2 MUX", "VP FEOUT1", "VP FEOUT_CSOUT Mixer"},
        {"PCM0.2 MUX", "VP FEOUT2", "VP FEOUT2 Mixer"},
-       {"PCM0.2 MUX", "AudioZoom CSOUT", "AudioZoom CSOUT Mixer"},
-       {"PCM0.2 MUX", "AudioZoom AOUT1", "AudioZoom AOUT1 Mixer"},
+       {"PCM0.2 MUX", "AudioFocus CSOUT1", "AudioFocus CSOUT1 Mixer"},
+       {"PCM0.2 MUX", "AudioFocus CSOUT2", "AudioFocus CSOUT2 Mixer"},
        {"PCM0.2 MUX", "MM PASSOUT1", "MM PASSOUT1 Mixer"},
        {"PCM0.2 MUX", "MM PASSOUT2", "MM PASSOUT2 Mixer"},
        {"PCM0.2 MUX", "MM AUDOUT1", "MM AUDOUT1 Mixer"},
@@ -3562,14 +4156,14 @@ static const struct snd_soc_dapm_route intercon[] = {
        {"PCM0.2 MUX", "Pass AUDOUT3", "Pass AUDOUT3 Mixer"},
        {"PCM0.2 MUX", "Pass AUDOUT4", "Pass AUDOUT4 Mixer"},
        {"PCM0.2 MUX", "Pass AO1", "Pass AO1 Mixer"},
-       {"PCM0.2 MUX", "Pass MO2", "Pass MO2 Mixer"},
+       {"PCM0.2 MUX", "Pass AO2", "Pass AO2 Mixer"},
        {"PCM0.3 MUX", "VP CSOUT1", "VP CSOUT1 Mixer"},
        {"PCM0.3 MUX", "VP CSOUT2", "VP CSOUT2 Mixer"},
        {"PCM0.3 MUX", "VP FEOUT1", "VP FEOUT1 Mixer"},
        {"PCM0.3 MUX", "VP FEOUT1", "VP FEOUT_CSOUT Mixer"},
        {"PCM0.3 MUX", "VP FEOUT2", "VP FEOUT2 Mixer"},
-       {"PCM0.3 MUX", "AudioZoom CSOUT", "AudioZoom CSOUT Mixer"},
-       {"PCM0.3 MUX", "AudioZoom AOUT1", "AudioZoom AOUT1 Mixer"},
+       {"PCM0.3 MUX", "AudioFocus CSOUT1", "AudioFocus CSOUT1 Mixer"},
+       {"PCM0.3 MUX", "AudioFocus CSOUT2", "AudioFocus CSOUT2 Mixer"},
        {"PCM0.3 MUX", "MM PASSOUT1", "MM PASSOUT1 Mixer"},
        {"PCM0.3 MUX", "MM PASSOUT2", "MM PASSOUT2 Mixer"},
        {"PCM0.3 MUX", "MM AUDOUT1", "MM AUDOUT1 Mixer"},
@@ -3581,15 +4175,15 @@ static const struct snd_soc_dapm_route intercon[] = {
        {"PCM0.3 MUX", "Pass AUDOUT3", "Pass AUDOUT3 Mixer"},
        {"PCM0.3 MUX", "Pass AUDOUT4", "Pass AUDOUT4 Mixer"},
        {"PCM0.3 MUX", "Pass AO1", "Pass AO1 Mixer"},
-       {"PCM0.3 MUX", "Pass MO2", "Pass MO2 Mixer"},
+       {"PCM0.3 MUX", "Pass AO2", "Pass AO2 Mixer"},
 
        {"PCM1.0 MUX", "VP CSOUT1", "VP CSOUT1 Mixer"},
        {"PCM1.0 MUX", "VP CSOUT2", "VP CSOUT2 Mixer"},
        {"PCM1.0 MUX", "VP FEOUT1", "VP FEOUT1 Mixer"},
        {"PCM1.0 MUX", "VP FEOUT1", "VP FEOUT_CSOUT Mixer"},
        {"PCM1.0 MUX", "VP FEOUT2", "VP FEOUT2 Mixer"},
-       {"PCM1.0 MUX", "AudioZoom CSOUT", "AudioZoom CSOUT Mixer"},
-       {"PCM1.0 MUX", "AudioZoom AOUT1", "AudioZoom AOUT1 Mixer"},
+       {"PCM1.0 MUX", "AudioFocus CSOUT1", "AudioFocus CSOUT1 Mixer"},
+       {"PCM1.0 MUX", "AudioFocus CSOUT2", "AudioFocus CSOUT2 Mixer"},
        {"PCM1.0 MUX", "MM PASSOUT1", "MM PASSOUT1 Mixer"},
        {"PCM1.0 MUX", "MM PASSOUT2", "MM PASSOUT2 Mixer"},
        {"PCM1.0 MUX", "MM AUDOUT1", "MM AUDOUT1 Mixer"},
@@ -3601,14 +4195,14 @@ static const struct snd_soc_dapm_route intercon[] = {
        {"PCM1.0 MUX", "Pass AUDOUT3", "Pass AUDOUT3 Mixer"},
        {"PCM1.0 MUX", "Pass AUDOUT4", "Pass AUDOUT4 Mixer"},
        {"PCM1.0 MUX", "Pass AO1", "Pass AO1 Mixer"},
-       {"PCM1.0 MUX", "Pass MO2", "Pass MO2 Mixer"},
+       {"PCM1.0 MUX", "Pass AO2", "Pass AO2 Mixer"},
        {"PCM1.1 MUX", "VP CSOUT1", "VP CSOUT1 Mixer"},
        {"PCM1.1 MUX", "VP CSOUT2", "VP CSOUT2 Mixer"},
        {"PCM1.1 MUX", "VP FEOUT1", "VP FEOUT1 Mixer"},
        {"PCM1.1 MUX", "VP FEOUT1", "VP FEOUT_CSOUT Mixer"},
        {"PCM1.1 MUX", "VP FEOUT2", "VP FEOUT2 Mixer"},
-       {"PCM1.1 MUX", "AudioZoom CSOUT", "AudioZoom CSOUT Mixer"},
-       {"PCM1.1 MUX", "AudioZoom AOUT1", "AudioZoom AOUT1 Mixer"},
+       {"PCM1.1 MUX", "AudioFocus CSOUT1", "AudioFocus CSOUT1 Mixer"},
+       {"PCM1.1 MUX", "AudioFocus CSOUT2", "AudioFocus CSOUT2 Mixer"},
        {"PCM1.1 MUX", "MM PASSOUT1", "MM PASSOUT1 Mixer"},
        {"PCM1.1 MUX", "MM PASSOUT2", "MM PASSOUT2 Mixer"},
        {"PCM1.1 MUX", "MM AUDOUT1", "MM AUDOUT1 Mixer"},
@@ -3620,14 +4214,14 @@ static const struct snd_soc_dapm_route intercon[] = {
        {"PCM1.1 MUX", "Pass AUDOUT3", "Pass AUDOUT3 Mixer"},
        {"PCM1.1 MUX", "Pass AUDOUT4", "Pass AUDOUT4 Mixer"},
        {"PCM1.1 MUX", "Pass AO1", "Pass AO1 Mixer"},
-       {"PCM1.1 MUX", "Pass MO2", "Pass MO2 Mixer"},
+       {"PCM1.1 MUX", "Pass AO2", "Pass AO2 Mixer"},
        {"PCM1.2 MUX", "VP CSOUT1", "VP CSOUT1 Mixer"},
        {"PCM1.2 MUX", "VP CSOUT2", "VP CSOUT2 Mixer"},
        {"PCM1.2 MUX", "VP FEOUT1", "VP FEOUT1 Mixer"},
        {"PCM1.2 MUX", "VP FEOUT1", "VP FEOUT_CSOUT Mixer"},
        {"PCM1.2 MUX", "VP FEOUT2", "VP FEOUT2 Mixer"},
-       {"PCM1.2 MUX", "AudioZoom CSOUT", "AudioZoom CSOUT Mixer"},
-       {"PCM1.2 MUX", "AudioZoom AOUT1", "AudioZoom AOUT1 Mixer"},
+       {"PCM1.2 MUX", "AudioFocus CSOUT1", "AudioFocus CSOUT1 Mixer"},
+       {"PCM1.2 MUX", "AudioFocus CSOUT2", "AudioFocus CSOUT2 Mixer"},
        {"PCM1.2 MUX", "MM PASSOUT1", "MM PASSOUT1 Mixer"},
        {"PCM1.2 MUX", "MM PASSOUT2", "MM PASSOUT2 Mixer"},
        {"PCM1.2 MUX", "MM AUDOUT1", "MM AUDOUT1 Mixer"},
@@ -3639,14 +4233,14 @@ static const struct snd_soc_dapm_route intercon[] = {
        {"PCM1.2 MUX", "Pass AUDOUT3", "Pass AUDOUT3 Mixer"},
        {"PCM1.2 MUX", "Pass AUDOUT4", "Pass AUDOUT4 Mixer"},
        {"PCM1.2 MUX", "Pass AO1", "Pass AO1 Mixer"},
-       {"PCM1.2 MUX", "Pass MO2", "Pass MO2 Mixer"},
+       {"PCM1.2 MUX", "Pass AO2", "Pass AO2 Mixer"},
        {"PCM1.3 MUX", "VP CSOUT1", "VP CSOUT1 Mixer"},
        {"PCM1.3 MUX", "VP CSOUT2", "VP CSOUT2 Mixer"},
        {"PCM1.3 MUX", "VP FEOUT1", "VP FEOUT1 Mixer"},
        {"PCM1.3 MUX", "VP FEOUT1", "VP FEOUT_CSOUT Mixer"},
        {"PCM1.3 MUX", "VP FEOUT2", "VP FEOUT2 Mixer"},
-       {"PCM1.3 MUX", "AudioZoom CSOUT", "AudioZoom CSOUT Mixer"},
-       {"PCM1.3 MUX", "AudioZoom AOUT1", "AudioZoom AOUT1 Mixer"},
+       {"PCM1.3 MUX", "AudioFocus CSOUT1", "AudioFocus CSOUT1 Mixer"},
+       {"PCM1.3 MUX", "AudioFocus CSOUT2", "AudioFocus CSOUT2 Mixer"},
        {"PCM1.3 MUX", "MM PASSOUT1", "MM PASSOUT1 Mixer"},
        {"PCM1.3 MUX", "MM PASSOUT2", "MM PASSOUT2 Mixer"},
        {"PCM1.3 MUX", "MM AUDOUT1", "MM AUDOUT1 Mixer"},
@@ -3658,15 +4252,15 @@ static const struct snd_soc_dapm_route intercon[] = {
        {"PCM1.3 MUX", "Pass AUDOUT3", "Pass AUDOUT3 Mixer"},
        {"PCM1.3 MUX", "Pass AUDOUT4", "Pass AUDOUT4 Mixer"},
        {"PCM1.3 MUX", "Pass AO1", "Pass AO1 Mixer"},
-       {"PCM1.3 MUX", "Pass MO2", "Pass MO2 Mixer"},
+       {"PCM1.3 MUX", "Pass AO2", "Pass AO2 Mixer"},
 
        {"PCM2.0 MUX", "VP CSOUT1", "VP CSOUT1 Mixer"},
        {"PCM2.0 MUX", "VP CSOUT2", "VP CSOUT2 Mixer"},
        {"PCM2.0 MUX", "VP FEOUT1", "VP FEOUT1 Mixer"},
        {"PCM2.0 MUX", "VP FEOUT1", "VP FEOUT_CSOUT Mixer"},
        {"PCM2.0 MUX", "VP FEOUT2", "VP FEOUT2 Mixer"},
-       {"PCM2.0 MUX", "AudioZoom CSOUT", "AudioZoom CSOUT Mixer"},
-       {"PCM2.0 MUX", "AudioZoom AOUT1", "AudioZoom AOUT1 Mixer"},
+       {"PCM2.0 MUX", "AudioFocus CSOUT1", "AudioFocus CSOUT1 Mixer"},
+       {"PCM2.0 MUX", "AudioFocus CSOUT2", "AudioFocus CSOUT2 Mixer"},
        {"PCM2.0 MUX", "MM PASSOUT1", "MM PASSOUT1 Mixer"},
        {"PCM2.0 MUX", "MM PASSOUT2", "MM PASSOUT2 Mixer"},
        {"PCM2.0 MUX", "MM AUDOUT1", "MM AUDOUT1 Mixer"},
@@ -3678,14 +4272,14 @@ static const struct snd_soc_dapm_route intercon[] = {
        {"PCM2.0 MUX", "Pass AUDOUT3", "Pass AUDOUT3 Mixer"},
        {"PCM2.0 MUX", "Pass AUDOUT4", "Pass AUDOUT4 Mixer"},
        {"PCM2.0 MUX", "Pass AO1", "Pass AO1 Mixer"},
-       {"PCM2.0 MUX", "Pass MO2", "Pass MO2 Mixer"},
+       {"PCM2.0 MUX", "Pass AO2", "Pass AO2 Mixer"},
        {"PCM2.1 MUX", "VP CSOUT1", "VP CSOUT1 Mixer"},
        {"PCM2.1 MUX", "VP CSOUT2", "VP CSOUT2 Mixer"},
        {"PCM2.1 MUX", "VP FEOUT1", "VP FEOUT1 Mixer"},
        {"PCM2.1 MUX", "VP FEOUT1", "VP FEOUT_CSOUT Mixer"},
        {"PCM2.1 MUX", "VP FEOUT2", "VP FEOUT2 Mixer"},
-       {"PCM2.1 MUX", "AudioZoom CSOUT", "AudioZoom CSOUT Mixer"},
-       {"PCM2.1 MUX", "AudioZoom AOUT1", "AudioZoom AOUT1 Mixer"},
+       {"PCM2.1 MUX", "AudioFocus CSOUT1", "AudioFocus CSOUT1 Mixer"},
+       {"PCM2.1 MUX", "AudioFocus CSOUT2", "AudioFocus CSOUT2 Mixer"},
        {"PCM2.1 MUX", "MM PASSOUT1", "MM PASSOUT1 Mixer"},
        {"PCM2.1 MUX", "MM PASSOUT2", "MM PASSOUT2 Mixer"},
        {"PCM2.1 MUX", "MM AUDOUT1", "MM AUDOUT1 Mixer"},
@@ -3697,14 +4291,14 @@ static const struct snd_soc_dapm_route intercon[] = {
        {"PCM2.1 MUX", "Pass AUDOUT3", "Pass AUDOUT3 Mixer"},
        {"PCM2.1 MUX", "Pass AUDOUT4", "Pass AUDOUT4 Mixer"},
        {"PCM2.1 MUX", "Pass AO1", "Pass AO1 Mixer"},
-       {"PCM2.1 MUX", "Pass MO2", "Pass MO2 Mixer"},
+       {"PCM2.1 MUX", "Pass AO2", "Pass AO2 Mixer"},
        {"PCM2.2 MUX", "VP CSOUT1", "VP CSOUT1 Mixer"},
        {"PCM2.2 MUX", "VP CSOUT2", "VP CSOUT2 Mixer"},
        {"PCM2.2 MUX", "VP FEOUT1", "VP FEOUT1 Mixer"},
        {"PCM2.2 MUX", "VP FEOUT1", "VP FEOUT_CSOUT Mixer"},
        {"PCM2.2 MUX", "VP FEOUT2", "VP FEOUT2 Mixer"},
-       {"PCM2.2 MUX", "AudioZoom CSOUT", "AudioZoom CSOUT Mixer"},
-       {"PCM2.2 MUX", "AudioZoom AOUT1", "AudioZoom AOUT1 Mixer"},
+       {"PCM2.2 MUX", "AudioFocus CSOUT1", "AudioFocus CSOUT1 Mixer"},
+       {"PCM2.2 MUX", "AudioFocus CSOUT2", "AudioFocus CSOUT2 Mixer"},
        {"PCM2.2 MUX", "MM PASSOUT1", "MM PASSOUT1 Mixer"},
        {"PCM2.2 MUX", "MM PASSOUT2", "MM PASSOUT2 Mixer"},
        {"PCM2.2 MUX", "MM AUDOUT1", "MM AUDOUT1 Mixer"},
@@ -3716,14 +4310,14 @@ static const struct snd_soc_dapm_route intercon[] = {
        {"PCM2.2 MUX", "Pass AUDOUT3", "Pass AUDOUT3 Mixer"},
        {"PCM2.2 MUX", "Pass AUDOUT4", "Pass AUDOUT4 Mixer"},
        {"PCM2.2 MUX", "Pass AO1", "Pass AO1 Mixer"},
-       {"PCM2.2 MUX", "Pass MO2", "Pass MO2 Mixer"},
+       {"PCM2.2 MUX", "Pass AO2", "Pass AO2 Mixer"},
        {"PCM2.3 MUX", "VP CSOUT1", "VP CSOUT1 Mixer"},
        {"PCM2.3 MUX", "VP CSOUT2", "VP CSOUT2 Mixer"},
        {"PCM2.3 MUX", "VP FEOUT1", "VP FEOUT1 Mixer"},
        {"PCM2.3 MUX", "VP FEOUT1", "VP FEOUT_CSOUT Mixer"},
        {"PCM2.3 MUX", "VP FEOUT2", "VP FEOUT2 Mixer"},
-       {"PCM2.3 MUX", "AudioZoom CSOUT", "AudioZoom CSOUT Mixer"},
-       {"PCM2.3 MUX", "AudioZoom AOUT1", "AudioZoom AOUT1 Mixer"},
+       {"PCM2.3 MUX", "AudioFocus CSOUT1", "AudioFocus CSOUT1 Mixer"},
+       {"PCM2.3 MUX", "AudioFocus CSOUT2", "AudioFocus CSOUT2 Mixer"},
        {"PCM2.3 MUX", "MM PASSOUT1", "MM PASSOUT1 Mixer"},
        {"PCM2.3 MUX", "MM PASSOUT2", "MM PASSOUT2 Mixer"},
        {"PCM2.3 MUX", "MM AUDOUT1", "MM AUDOUT1 Mixer"},
@@ -3735,7 +4329,7 @@ static const struct snd_soc_dapm_route intercon[] = {
        {"PCM2.3 MUX", "Pass AUDOUT3", "Pass AUDOUT3 Mixer"},
        {"PCM2.3 MUX", "Pass AUDOUT4", "Pass AUDOUT4 Mixer"},
        {"PCM2.3 MUX", "Pass AO1", "Pass AO1 Mixer"},
-       {"PCM2.3 MUX", "Pass MO2", "Pass MO2 Mixer"},
+       {"PCM2.3 MUX", "Pass AO2", "Pass AO2 Mixer"},
 
 
        {"SBUS.TX0 MUX", "VP CSOUT1", "VP CSOUT1 Mixer"},
@@ -3743,8 +4337,8 @@ static const struct snd_soc_dapm_route intercon[] = {
        {"SBUS.TX0 MUX", "VP FEOUT1", "VP FEOUT1 Mixer"},
        {"SBUS.TX0 MUX", "VP FEOUT1", "VP FEOUT_CSOUT Mixer"},
        {"SBUS.TX0 MUX", "VP FEOUT2", "VP FEOUT2 Mixer"},
-       {"SBUS.TX0 MUX", "AudioZoom CSOUT", "AudioZoom CSOUT Mixer"},
-       {"SBUS.TX0 MUX", "AudioZoom AOUT1", "AudioZoom AOUT1 Mixer"},
+       {"SBUS.TX0 MUX", "AudioFocus CSOUT1", "AudioFocus CSOUT1 Mixer"},
+       {"SBUS.TX0 MUX", "AudioFocus CSOUT2", "AudioFocus CSOUT2 Mixer"},
        {"SBUS.TX0 MUX", "MM PASSOUT1", "MM PASSOUT1 Mixer"},
        {"SBUS.TX0 MUX", "MM PASSOUT2", "MM PASSOUT2 Mixer"},
        {"SBUS.TX0 MUX", "MM AUDOUT1", "MM AUDOUT1 Mixer"},
@@ -3756,15 +4350,15 @@ static const struct snd_soc_dapm_route intercon[] = {
        {"SBUS.TX0 MUX", "Pass AUDOUT3", "Pass AUDOUT3 Mixer"},
        {"SBUS.TX0 MUX", "Pass AUDOUT4", "Pass AUDOUT4 Mixer"},
        {"SBUS.TX0 MUX", "Pass AO1", "Pass AO1 Mixer"},
-       {"SBUS.TX0 MUX", "Pass MO2", "Pass MO2 Mixer"},
+       {"SBUS.TX0 MUX", "Pass AO2", "Pass AO2 Mixer"},
 
        {"SBUS.TX1 MUX", "VP CSOUT1", "VP CSOUT1 Mixer"},
        {"SBUS.TX1 MUX", "VP CSOUT2", "VP CSOUT2 Mixer"},
        {"SBUS.TX1 MUX", "VP FEOUT1", "VP FEOUT1 Mixer"},
        {"SBUS.TX1 MUX", "VP FEOUT1", "VP FEOUT_CSOUT Mixer"},
        {"SBUS.TX1 MUX", "VP FEOUT2", "VP FEOUT2 Mixer"},
-       {"SBUS.TX1 MUX", "AudioZoom CSOUT", "AudioZoom CSOUT Mixer"},
-       {"SBUS.TX1 MUX", "AudioZoom AOUT1", "AudioZoom AOUT1 Mixer"},
+       {"SBUS.TX1 MUX", "AudioFocus CSOUT1", "AudioFocus CSOUT1 Mixer"},
+       {"SBUS.TX1 MUX", "AudioFocus CSOUT2", "AudioFocus CSOUT2 Mixer"},
        {"SBUS.TX1 MUX", "MM PASSOUT1", "MM PASSOUT1 Mixer"},
        {"SBUS.TX1 MUX", "MM PASSOUT2", "MM PASSOUT2 Mixer"},
        {"SBUS.TX1 MUX", "MM AUDOUT1", "MM AUDOUT1 Mixer"},
@@ -3776,15 +4370,15 @@ static const struct snd_soc_dapm_route intercon[] = {
        {"SBUS.TX1 MUX", "Pass AUDOUT3", "Pass AUDOUT3 Mixer"},
        {"SBUS.TX1 MUX", "Pass AUDOUT4", "Pass AUDOUT4 Mixer"},
        {"SBUS.TX1 MUX", "Pass AO1", "Pass AO1 Mixer"},
-       {"SBUS.TX1 MUX", "Pass MO2", "Pass MO2 Mixer"},
+       {"SBUS.TX1 MUX", "Pass AO2", "Pass AO2 Mixer"},
 
        {"SBUS.TX2 MUX", "VP CSOUT1", "VP CSOUT1 Mixer"},
        {"SBUS.TX2 MUX", "VP CSOUT2", "VP CSOUT2 Mixer"},
        {"SBUS.TX2 MUX", "VP FEOUT1", "VP FEOUT1 Mixer"},
        {"SBUS.TX2 MUX", "VP FEOUT1", "VP FEOUT_CSOUT Mixer"},
        {"SBUS.TX2 MUX", "VP FEOUT2", "VP FEOUT2 Mixer"},
-       {"SBUS.TX2 MUX", "AudioZoom CSOUT", "AudioZoom CSOUT Mixer"},
-       {"SBUS.TX2 MUX", "AudioZoom AOUT1", "AudioZoom AOUT1 Mixer"},
+       {"SBUS.TX2 MUX", "AudioFocus CSOUT1", "AudioFocus CSOUT1 Mixer"},
+       {"SBUS.TX2 MUX", "AudioFocus CSOUT2", "AudioFocus CSOUT2 Mixer"},
        {"SBUS.TX2 MUX", "MM PASSOUT1", "MM PASSOUT1 Mixer"},
        {"SBUS.TX2 MUX", "MM PASSOUT2", "MM PASSOUT2 Mixer"},
        {"SBUS.TX2 MUX", "MM AUDOUT1", "MM AUDOUT1 Mixer"},
@@ -3796,15 +4390,15 @@ static const struct snd_soc_dapm_route intercon[] = {
        {"SBUS.TX2 MUX", "Pass AUDOUT3", "Pass AUDOUT3 Mixer"},
        {"SBUS.TX2 MUX", "Pass AUDOUT4", "Pass AUDOUT4 Mixer"},
        {"SBUS.TX2 MUX", "Pass AO1", "Pass AO1 Mixer"},
-       {"SBUS.TX2 MUX", "Pass MO2", "Pass MO2 Mixer"},
+       {"SBUS.TX2 MUX", "Pass AO2", "Pass AO2 Mixer"},
 
        {"SBUS.TX3 MUX", "VP CSOUT1", "VP CSOUT1 Mixer"},
        {"SBUS.TX3 MUX", "VP CSOUT2", "VP CSOUT2 Mixer"},
        {"SBUS.TX3 MUX", "VP FEOUT1", "VP FEOUT1 Mixer"},
        {"SBUS.TX3 MUX", "VP FEOUT1", "VP FEOUT_CSOUT Mixer"},
        {"SBUS.TX3 MUX", "VP FEOUT2", "VP FEOUT2 Mixer"},
-       {"SBUS.TX3 MUX", "AudioZoom CSOUT", "AudioZoom CSOUT Mixer"},
-       {"SBUS.TX3 MUX", "AudioZoom AOUT1", "AudioZoom AOUT1 Mixer"},
+       {"SBUS.TX3 MUX", "AudioFocus CSOUT1", "AudioFocus CSOUT1 Mixer"},
+       {"SBUS.TX3 MUX", "AudioFocus CSOUT2", "AudioFocus CSOUT2 Mixer"},
        {"SBUS.TX3 MUX", "MM PASSOUT1", "MM PASSOUT1 Mixer"},
        {"SBUS.TX3 MUX", "MM PASSOUT2", "MM PASSOUT2 Mixer"},
        {"SBUS.TX3 MUX", "MM AUDOUT1", "MM AUDOUT1 Mixer"},
@@ -3816,15 +4410,15 @@ static const struct snd_soc_dapm_route intercon[] = {
        {"SBUS.TX3 MUX", "Pass AUDOUT3", "Pass AUDOUT3 Mixer"},
        {"SBUS.TX3 MUX", "Pass AUDOUT4", "Pass AUDOUT4 Mixer"},
        {"SBUS.TX3 MUX", "Pass AO1", "Pass AO1 Mixer"},
-       {"SBUS.TX3 MUX", "Pass MO2", "Pass MO2 Mixer"},
+       {"SBUS.TX3 MUX", "Pass AO2", "Pass AO2 Mixer"},
 
        {"SBUS.TX4 MUX", "VP CSOUT1", "VP CSOUT1 Mixer"},
        {"SBUS.TX4 MUX", "VP CSOUT2", "VP CSOUT2 Mixer"},
        {"SBUS.TX4 MUX", "VP FEOUT1", "VP FEOUT1 Mixer"},
        {"SBUS.TX4 MUX", "VP FEOUT1", "VP FEOUT_CSOUT Mixer"},
        {"SBUS.TX4 MUX", "VP FEOUT2", "VP FEOUT2 Mixer"},
-       {"SBUS.TX4 MUX", "AudioZoom CSOUT", "AudioZoom CSOUT Mixer"},
-       {"SBUS.TX4 MUX", "AudioZoom AOUT1", "AudioZoom AOUT1 Mixer"},
+       {"SBUS.TX4 MUX", "AudioFocus CSOUT1", "AudioFocus CSOUT1 Mixer"},
+       {"SBUS.TX4 MUX", "AudioFocus CSOUT2", "AudioFocus CSOUT2 Mixer"},
        {"SBUS.TX4 MUX", "MM PASSOUT1", "MM PASSOUT1 Mixer"},
        {"SBUS.TX4 MUX", "MM PASSOUT2", "MM PASSOUT2 Mixer"},
        {"SBUS.TX4 MUX", "MM AUDOUT1", "MM AUDOUT1 Mixer"},
@@ -3836,15 +4430,15 @@ static const struct snd_soc_dapm_route intercon[] = {
        {"SBUS.TX4 MUX", "Pass AUDOUT3", "Pass AUDOUT3 Mixer"},
        {"SBUS.TX4 MUX", "Pass AUDOUT4", "Pass AUDOUT4 Mixer"},
        {"SBUS.TX4 MUX", "Pass AO1", "Pass AO1 Mixer"},
-       {"SBUS.TX4 MUX", "Pass MO2", "Pass MO2 Mixer"},
+       {"SBUS.TX4 MUX", "Pass AO2", "Pass AO2 Mixer"},
 
        {"SBUS.TX5 MUX", "VP CSOUT1", "VP CSOUT1 Mixer"},
        {"SBUS.TX5 MUX", "VP CSOUT2", "VP CSOUT2 Mixer"},
        {"SBUS.TX5 MUX", "VP FEOUT1", "VP FEOUT1 Mixer"},
        {"SBUS.TX5 MUX", "VP FEOUT1", "VP FEOUT_CSOUT Mixer"},
        {"SBUS.TX5 MUX", "VP FEOUT2", "VP FEOUT2 Mixer"},
-       {"SBUS.TX5 MUX", "AudioZoom CSOUT", "AudioZoom CSOUT Mixer"},
-       {"SBUS.TX5 MUX", "AudioZoom AOUT1", "AudioZoom AOUT1 Mixer"},
+       {"SBUS.TX5 MUX", "AudioFocus CSOUT1", "AudioFocus CSOUT1 Mixer"},
+       {"SBUS.TX5 MUX", "AudioFocus CSOUT2", "AudioFocus CSOUT2 Mixer"},
        {"SBUS.TX5 MUX", "MM PASSOUT1", "MM PASSOUT1 Mixer"},
        {"SBUS.TX5 MUX", "MM PASSOUT2", "MM PASSOUT2 Mixer"},
        {"SBUS.TX5 MUX", "MM AUDOUT1", "MM AUDOUT1 Mixer"},
@@ -3856,15 +4450,15 @@ static const struct snd_soc_dapm_route intercon[] = {
        {"SBUS.TX5 MUX", "Pass AUDOUT3", "Pass AUDOUT3 Mixer"},
        {"SBUS.TX5 MUX", "Pass AUDOUT4", "Pass AUDOUT4 Mixer"},
        {"SBUS.TX5 MUX", "Pass AO1", "Pass AO1 Mixer"},
-       {"SBUS.TX5 MUX", "Pass MO2", "Pass MO2 Mixer"},
+       {"SBUS.TX5 MUX", "Pass AO2", "Pass AO2 Mixer"},
 
        {"DAC0.0 MUX", "VP CSOUT1", "VP CSOUT1 Mixer"},
        {"DAC0.0 MUX", "VP CSOUT2", "VP CSOUT2 Mixer"},
        {"DAC0.0 MUX", "VP FEOUT1", "VP FEOUT1 Mixer"},
        {"DAC0.0 MUX", "VP FEOUT1", "VP FEOUT_CSOUT Mixer"},
        {"DAC0.0 MUX", "VP FEOUT2", "VP FEOUT2 Mixer"},
-       {"DAC0.0 MUX", "AudioZoom CSOUT", "AudioZoom CSOUT Mixer"},
-       {"DAC0.0 MUX", "AudioZoom AOUT1", "AudioZoom AOUT1 Mixer"},
+       {"DAC0.0 MUX", "AudioFocus CSOUT1", "AudioFocus CSOUT1 Mixer"},
+       {"DAC0.0 MUX", "AudioFocus CSOUT2", "AudioFocus CSOUT2 Mixer"},
        {"DAC0.0 MUX", "MM PASSOUT1", "MM PASSOUT1 Mixer"},
        {"DAC0.0 MUX", "MM PASSOUT2", "MM PASSOUT2 Mixer"},
        {"DAC0.0 MUX", "MM AUDOUT1", "MM AUDOUT1 Mixer"},
@@ -3876,14 +4470,27 @@ static const struct snd_soc_dapm_route intercon[] = {
        {"DAC0.0 MUX", "Pass AUDOUT3", "Pass AUDOUT3 Mixer"},
        {"DAC0.0 MUX", "Pass AUDOUT4", "Pass AUDOUT4 Mixer"},
        {"DAC0.0 MUX", "Pass AO1", "Pass AO1 Mixer"},
-       {"DAC0.0 MUX", "Pass MO2", "Pass MO2 Mixer"},
+       {"DAC0.0 MUX", "Pass AO2", "Pass AO2 Mixer"},
+       {"DAC0.0 MUX", "PCM0.0", "PCM0.0 RX"},
+       {"DAC0.0 MUX", "PCM0.1", "PCM0.1 RX"},
+       {"DAC0.0 MUX", "PCM0.2", "PCM0.2 RX"},
+       {"DAC0.0 MUX", "PCM0.3", "PCM0.3 RX"},
+       {"DAC0.0 MUX", "PCM1.0", "PCM1.0 RX"},
+       {"DAC0.0 MUX", "PCM1.1", "PCM1.1 RX"},
+       {"DAC0.0 MUX", "PCM1.2", "PCM1.2 RX"},
+       {"DAC0.0 MUX", "PCM1.3", "PCM1.3 RX"},
+       {"DAC0.0 MUX", "PCM2.0", "PCM2.0 RX"},
+       {"DAC0.0 MUX", "PCM2.1", "PCM2.1 RX"},
+       {"DAC0.0 MUX", "PCM2.2", "PCM2.2 RX"},
+       {"DAC0.0 MUX", "PCM2.3", "PCM2.3 RX"},
+
        {"DAC0.1 MUX", "VP CSOUT1", "VP CSOUT1 Mixer"},
        {"DAC0.1 MUX", "VP CSOUT2", "VP CSOUT2 Mixer"},
        {"DAC0.1 MUX", "VP FEOUT1", "VP FEOUT1 Mixer"},
        {"DAC0.1 MUX", "VP FEOUT1", "VP FEOUT_CSOUT Mixer"},
        {"DAC0.1 MUX", "VP FEOUT2", "VP FEOUT2 Mixer"},
-       {"DAC0.1 MUX", "AudioZoom CSOUT", "AudioZoom CSOUT Mixer"},
-       {"DAC0.1 MUX", "AudioZoom AOUT1", "AudioZoom AOUT1 Mixer"},
+       {"DAC0.1 MUX", "AudioFocus CSOUT1", "AudioFocus CSOUT1 Mixer"},
+       {"DAC0.1 MUX", "AudioFocus CSOUT2", "AudioFocus CSOUT2 Mixer"},
        {"DAC0.1 MUX", "MM PASSOUT1", "MM PASSOUT1 Mixer"},
        {"DAC0.1 MUX", "MM PASSOUT2", "MM PASSOUT2 Mixer"},
        {"DAC0.1 MUX", "MM AUDOUT1", "MM AUDOUT1 Mixer"},
@@ -3895,15 +4502,27 @@ static const struct snd_soc_dapm_route intercon[] = {
        {"DAC0.1 MUX", "Pass AUDOUT3", "Pass AUDOUT3 Mixer"},
        {"DAC0.1 MUX", "Pass AUDOUT4", "Pass AUDOUT4 Mixer"},
        {"DAC0.1 MUX", "Pass AO1", "Pass AO1 Mixer"},
-       {"DAC0.1 MUX", "Pass MO2", "Pass MO2 Mixer"},
+       {"DAC0.1 MUX", "Pass AO2", "Pass AO2 Mixer"},
+       {"DAC0.1 MUX", "PCM0.0", "PCM0.0 RX"},
+       {"DAC0.1 MUX", "PCM0.1", "PCM0.1 RX"},
+       {"DAC0.1 MUX", "PCM0.2", "PCM0.2 RX"},
+       {"DAC0.1 MUX", "PCM0.3", "PCM0.3 RX"},
+       {"DAC0.1 MUX", "PCM1.0", "PCM1.0 RX"},
+       {"DAC0.1 MUX", "PCM1.1", "PCM1.1 RX"},
+       {"DAC0.1 MUX", "PCM1.2", "PCM1.2 RX"},
+       {"DAC0.1 MUX", "PCM1.3", "PCM1.3 RX"},
+       {"DAC0.1 MUX", "PCM2.0", "PCM2.0 RX"},
+       {"DAC0.1 MUX", "PCM2.1", "PCM2.1 RX"},
+       {"DAC0.1 MUX", "PCM2.2", "PCM2.2 RX"},
+       {"DAC0.1 MUX", "PCM2.3", "PCM2.3 RX"},
 
        {"DAC1.0 MUX", "VP CSOUT1", "VP CSOUT1 Mixer"},
        {"DAC1.0 MUX", "VP CSOUT2", "VP CSOUT2 Mixer"},
        {"DAC1.0 MUX", "VP FEOUT1", "VP FEOUT1 Mixer"},
        {"DAC1.0 MUX", "VP FEOUT1", "VP FEOUT_CSOUT Mixer"},
        {"DAC1.0 MUX", "VP FEOUT2", "VP FEOUT2 Mixer"},
-       {"DAC1.0 MUX", "AudioZoom CSOUT", "AudioZoom CSOUT Mixer"},
-       {"DAC1.0 MUX", "AudioZoom AOUT1", "AudioZoom AOUT1 Mixer"},
+       {"DAC1.0 MUX", "AudioFocus CSOUT1", "AudioFocus CSOUT1 Mixer"},
+       {"DAC1.0 MUX", "AudioFocus CSOUT2", "AudioFocus CSOUT2 Mixer"},
        {"DAC1.0 MUX", "MM PASSOUT1", "MM PASSOUT1 Mixer"},
        {"DAC1.0 MUX", "MM PASSOUT2", "MM PASSOUT2 Mixer"},
        {"DAC1.0 MUX", "MM AUDOUT1", "MM AUDOUT1 Mixer"},
@@ -3915,14 +4534,27 @@ static const struct snd_soc_dapm_route intercon[] = {
        {"DAC1.0 MUX", "Pass AUDOUT3", "Pass AUDOUT3 Mixer"},
        {"DAC1.0 MUX", "Pass AUDOUT4", "Pass AUDOUT4 Mixer"},
        {"DAC1.0 MUX", "Pass AO1", "Pass AO1 Mixer"},
-       {"DAC1.0 MUX", "Pass MO2", "Pass MO2 Mixer"},
+       {"DAC1.0 MUX", "Pass AO2", "Pass AO2 Mixer"},
+       {"DAC1.0 MUX", "PCM0.0", "PCM0.0 RX"},
+       {"DAC1.0 MUX", "PCM0.1", "PCM0.1 RX"},
+       {"DAC1.0 MUX", "PCM0.2", "PCM0.2 RX"},
+       {"DAC1.0 MUX", "PCM0.3", "PCM0.3 RX"},
+       {"DAC1.0 MUX", "PCM1.0", "PCM1.0 RX"},
+       {"DAC1.0 MUX", "PCM1.1", "PCM1.1 RX"},
+       {"DAC1.0 MUX", "PCM1.2", "PCM1.2 RX"},
+       {"DAC1.0 MUX", "PCM1.3", "PCM1.3 RX"},
+       {"DAC1.0 MUX", "PCM2.0", "PCM2.0 RX"},
+       {"DAC1.0 MUX", "PCM2.1", "PCM2.1 RX"},
+       {"DAC1.0 MUX", "PCM2.2", "PCM2.2 RX"},
+       {"DAC1.0 MUX", "PCM2.3", "PCM2.3 RX"},
+
        {"DAC1.1 MUX", "VP CSOUT1", "VP CSOUT1 Mixer"},
        {"DAC1.1 MUX", "VP CSOUT2", "VP CSOUT2 Mixer"},
        {"DAC1.1 MUX", "VP FEOUT1", "VP FEOUT1 Mixer"},
        {"DAC1.1 MUX", "VP FEOUT1", "VP FEOUT_CSOUT Mixer"},
        {"DAC1.1 MUX", "VP FEOUT2", "VP FEOUT2 Mixer"},
-       {"DAC1.1 MUX", "AudioZoom CSOUT", "AudioZoom CSOUT Mixer"},
-       {"DAC1.1 MUX", "AudioZoom AOUT1", "AudioZoom AOUT1 Mixer"},
+       {"DAC1.1 MUX", "AudioFocus CSOUT1", "AudioFocus CSOUT1 Mixer"},
+       {"DAC1.1 MUX", "AudioFocus CSOUT2", "AudioFocus CSOUT2 Mixer"},
        {"DAC1.1 MUX", "MM PASSOUT1", "MM PASSOUT1 Mixer"},
        {"DAC1.1 MUX", "MM PASSOUT2", "MM PASSOUT2 Mixer"},
        {"DAC1.1 MUX", "MM AUDOUT1", "MM AUDOUT1 Mixer"},
@@ -3934,7 +4566,19 @@ static const struct snd_soc_dapm_route intercon[] = {
        {"DAC1.1 MUX", "Pass AUDOUT3", "Pass AUDOUT3 Mixer"},
        {"DAC1.1 MUX", "Pass AUDOUT4", "Pass AUDOUT4 Mixer"},
        {"DAC1.1 MUX", "Pass AO1", "Pass AO1 Mixer"},
-       {"DAC1.1 MUX", "Pass MO2", "Pass MO2 Mixer"},
+       {"DAC1.1 MUX", "Pass AO2", "Pass AO2 Mixer"},
+       {"DAC1.1 MUX", "PCM0.0", "PCM0.0 RX"},
+       {"DAC1.1 MUX", "PCM0.1", "PCM0.1 RX"},
+       {"DAC1.1 MUX", "PCM0.2", "PCM0.2 RX"},
+       {"DAC1.1 MUX", "PCM0.3", "PCM0.3 RX"},
+       {"DAC1.1 MUX", "PCM1.0", "PCM1.0 RX"},
+       {"DAC1.1 MUX", "PCM1.1", "PCM1.1 RX"},
+       {"DAC1.1 MUX", "PCM1.2", "PCM1.2 RX"},
+       {"DAC1.1 MUX", "PCM1.3", "PCM1.3 RX"},
+       {"DAC1.1 MUX", "PCM2.0", "PCM2.0 RX"},
+       {"DAC1.1 MUX", "PCM2.1", "PCM2.1 RX"},
+       {"DAC1.1 MUX", "PCM2.2", "PCM2.2 RX"},
+       {"DAC1.1 MUX", "PCM2.3", "PCM2.3 RX"},
 
        /* AIF TX <--> PCM PORTA  */
 
@@ -4011,7 +4655,7 @@ int es_d300_fill_cmdcache(struct snd_soc_codec *codec)
        const char *algo_text[ALGO_MAX] = {
                [VP] = "VP",
                [MM] = "MM",
-               [AUDIOZOOM] = "AudioZoom",
+               [AUDIOFOCUS] = "AudioFocus",
                [PASSTHRU] = "Passthru",
        };
 
@@ -4041,8 +4685,13 @@ int es_d300_add_snd_soc_controls(struct snd_soc_codec *codec)
 {
        int rc;
 
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)
        rc = snd_soc_add_codec_controls(codec, es_d300_snd_controls,
                        ARRAY_SIZE(es_d300_snd_controls));
+#else
+       rc = snd_soc_add_controls(codec, es_d300_snd_controls,
+                       ARRAY_SIZE(es_d300_snd_controls));
+#endif
 
        return rc;
 }
index cfe4474b277e46762905d4a58ab2b848e47a79cf..520c7913329a4b34550a56f81d71fec14f6544f8 100644 (file)
@@ -60,37 +60,49 @@ enum {
 
 #define VP_RXCHMGR_MAX 9
 #define VP_TXCHMGR_MAX 6
+#define AUDIOFOCUS_TXCHMGR_MAX 6
 #define MM_RXCHMGR_MAX 6
 #define MM_TXCHMGR_MAX 6
 #define VP_MM_RXCHMGR_MAX 10
 #define VP_MM_TXCHMGR_MAX 5
 #define PT_VP_RXCHMGR_MAX 6
 #define PT_VP_TXCHMGR_MAX 6
-#define DHWPT_RXCHMGR_MAX 6
-#define DHWPT_TXCHMGR_MAX 6
+#define BARGE_IN_TXCHMGR_MAX 6
+#define KALA_OK_RXCHMGR_MAX 3
+#define KALA_OK_TXCHMGR_MAX 5
+
 enum {
        ES_VP_NONE,
        ES_VP_RX_INIT, /* VP RX Initialized */
        ES_VP_TX_INIT, /* VP TX Initialized */
-       ES_AZ_NONE,
-       ES_AZ_RX_INIT, /* AZ RX Initialized */
-       ES_AZ_TX_INIT, /* AZ TX Initialized */
+       ES_AF_NONE,
+       ES_AF_RX_INIT, /* AF RX Initialized */
+       ES_AF_TX_INIT, /* AF TX Initialized */
 };
 
+enum {
+       ES_TYPE_NONE,
+       ES_TYPE_PB,
+       ES_TYPE_CAP,
+};
+
+
 /* Algorithm */
 enum {
        VP,
        MM,
-       AUDIOZOOM,
+       AUDIOFOCUS,
        PASSTHRU,
        VP_MM,
        PASSTHRU_VP,
        PASSTHRU_MM,
        PASSTHRU_VP_MM,
-       PASSTHRU_AZ,
+       PASSTHRU_AF,
        VOICEQ,
+       BARGE_IN,
+       KALA_OK,
        DHWPT,
-       NONE,
+       ALGO_NONE,
        ALGO_MAX,
 };
 
@@ -117,7 +129,7 @@ enum {
        FILTER_TXCHANMGR5,
 
        FILTER_VP = 0x13,
-       FILTER_AZ,
+       FILTER_AF,
        FILTER_MM,
        FILTER_PASSTHRU,
        FILTER_BEEP,
@@ -210,10 +222,10 @@ enum {
        mm_o0 = 0x0,
        mm_o1,
 
-       az_i0 = 0x0,
-       az_i1,
-       az_i2,
-       az_o0 = 0x0,
+       af_i0 = 0x0,
+       af_i1,
+       af_i2,
+       af_o0 = 0x0,
 
        pass_i0 = 0x0,
        pass_i1,
@@ -260,16 +272,42 @@ struct es_ch_mgr_max {
 };
 
 /* Switch Settings used in PT+VP Algorithm */
-#define SWIN0_I0       0
-#define SWIN0_I1       1
-#define SWIN1_I0       2
-#define SWIN1_I1       3
-#define SWIN2_I0       4
-#define SWIN2_I1       5
-#define SWOUT0_O1      6
-#define SWOUT1_O1      7
-#define SWOUT2_O1      8
-#define SWOUT3_O1      9
+#define SW_VALUE_MAX 2
+struct switch_setting {
+       u32 value_cmd[SW_VALUE_MAX];
+       bool value;
+};
+
+enum {
+       SWIN1 = 0,
+       SWIN2,
+       SWOUT0,
+       SWOUT1,
+       SWOUT2,
+       SWOUT3,
+       SW_MAX,
+};
+
+/* Active IP */
+enum {
+       ACTIVE_IP_OFF = 0,
+       ACTIVE_IP_PRI,
+       ACTIVE_IP_WPIN,
+};
+
+/* Primary PB */
+enum {
+       PRI_PB_OFF = 0,
+       PRI_PB_STEREO,
+};
+
+/* Secondary PB */
+enum {
+       SEC_PB_OFF = 0,
+       SEC_PB_MIXED_MONO,
+       SEC_PB_STEREO,
+};
+
 
 /* TODO: Create a 2D array to map endpoint values
  * with path IDs. */
@@ -297,7 +335,9 @@ struct es_ch_mgr_max {
 extern int es_d300_add_snd_soc_dapm_controls(struct snd_soc_codec *codec);
 extern int es_d300_add_snd_soc_controls(struct snd_soc_codec *codec);
 extern int es_d300_add_snd_soc_route_map(struct snd_soc_codec *codec);
+extern int es_change_power_state_normal(struct escore_priv *escore);
 int es_d300_fill_cmdcache(struct snd_soc_codec *codec);
 void es_d300_reset_cmdcache(void);
+int _es_stop_route(struct escore_priv *escore, u8 stream_type);
 
 #endif /* _ES_D300_H */
index 344b6fc218131fe7eea0167240713e3f7de95144..0b208c14dd4e1b69c67ed15829e6f5efd4dd5743 100644 (file)
 
 
 #include "es-d300.h"
+#if defined(CONFIG_SND_SOC_ES854)
+#include "es-a350-reg.h"
+#elif defined(CONFIG_SND_SOC_ES857)
+#include "es-a375-reg.h"
+#else
 #include "es-a300-reg.h"
+#endif
 #include "es755.h"
 
 static struct escore_api_access es755_api_access[ES_API_ADDR_MAX] = {
@@ -51,7 +57,7 @@ static struct escore_api_access es755_api_access[ES_API_ADDR_MAX] = {
                .write_msg = { ES_API_WORD(0x9056, 0x0000) },
                .write_msg_len = 4,
                .val_shift = 0,
-               .val_max = 0xFF,
+               .val_max = 0x1FF,
        },
        [ES_GET_ACCDET_STATUS] = {
                .read_msg = { ES_API_WORD(0x8054, 0x0000) },
@@ -131,493 +137,16 @@ static struct escore_api_access es755_api_access[ES_API_ADDR_MAX] = {
                .val_shift = 0,
                .val_max = 65535,
        },
-       [ES_BUTTON_CTRL2] = {
-               .read_msg = { ES_API_WORD(ES_GET_DEV_PARAM, 0x1632) },
-               .read_msg_len = 4,
-               .write_msg = { ES_API_WORD(ES_SET_DEV_PARAM_ID, 0x1632),
-                              ES_API_WORD(ES_SET_DEV_PARAM, 0x0000) },
-               .write_msg_len = 8,
-               .val_shift = 0,
-               .val_max = 65535,
-       },
-       [ES_BUTTON_CTRL3] = {
-               .read_msg = { ES_API_WORD(ES_GET_DEV_PARAM, 0x1633) },
-               .read_msg_len = 4,
-               .write_msg = { ES_API_WORD(ES_SET_DEV_PARAM_ID, 0x1633),
-                              ES_API_WORD(ES_SET_DEV_PARAM, 0x0000) },
-               .write_msg_len = 8,
-               .val_shift = 0,
-               .val_max = 65535,
-       },
-       [ES_BUTTON_CTRL4] = {
-               .read_msg = { ES_API_WORD(ES_GET_DEV_PARAM, 0x1634) },
+       [ES_CODEC_VALUE] = {
+               .read_msg = { ES_API_WORD(0x8009, 0x0000) },
                .read_msg_len = 4,
-               .write_msg = { ES_API_WORD(ES_SET_DEV_PARAM_ID, 0x1634),
-                              ES_API_WORD(ES_SET_DEV_PARAM, 0x0000) },
-               .write_msg_len = 8,
+               .write_msg = { ES_API_WORD(0x900A, 0x0000) },
+               .write_msg_len = 4,
                .val_shift = 0,
                .val_max = 65535,
        },
-       [ES_PRIMARY_MUX] = {
-               .write_msg = {
-                       ES_API_WORD(ES_SET_MUX_CMD,
-                                       ES300_DATA_PATH(0, 0, RXCHMGR0)),
-                       ES_API_WORD(ES_SET_PATH_ID_CMD,
-                                       ES300_PATH_ID(RXCHMGR0, ES300_PRI)),
-               },
-               .write_msg_len = 8,
-               .val_shift = 0,
-               .val_max = MAX_INPUT_PORT,
-       },
-       [ES_SECONDARY_MUX] = {
-               .write_msg = {
-                       ES_API_WORD(ES_SET_MUX_CMD,
-                                       ES300_DATA_PATH(0, 0, RXCHMGR1)),
-                       ES_API_WORD(ES_SET_PATH_ID_CMD,
-                                       ES300_PATH_ID(RXCHMGR1, ES300_SEC)),
-                       ES_API_WORD(ES_CONNECT_CMD,
-                                       ES300_ENDPOINT(FILTER_RXCHANMGR1,
-                                               OUT, RxChMgr_o0)),
-                       ES_API_WORD(ES_CONNECT_CMD,
-                                       ES300_ENDPOINT(FILTER_VP, IN, vp_i2)),
-                       ES_API_WORD(ES_SET_RATE_CMD,
-                                       ES300_RATE(FILTER_RXCHANMGR1, 1)),
-                       ES_API_WORD(ES_SET_GROUP_CMD,
-                                       ES300_GROUP(FILTER_RXCHANMGR1, 0)),
-               },
-               .write_msg_len = 24,
-               .val_shift = 0,
-               .val_max = MAX_INPUT_PORT,
-
-       },
-       [ES_TERTIARY_MUX] = {
-               .write_msg = {
-                       ES_API_WORD(ES_SET_MUX_CMD,
-                                       ES300_DATA_PATH(0, 0, RXCHMGR2)),
-                       ES_API_WORD(ES_SET_PATH_ID_CMD,
-                                       ES300_PATH_ID(RXCHMGR2, ES300_TER)),
-                       ES_API_WORD(ES_CONNECT_CMD,
-                                       ES300_ENDPOINT(FILTER_RXCHANMGR2,
-                                               OUT, RxChMgr_o0)),
-                       ES_API_WORD(ES_CONNECT_CMD,
-                                       ES300_ENDPOINT(FILTER_VP, IN, vp_i3)),
-                       ES_API_WORD(ES_SET_RATE_CMD,
-                                       ES300_RATE(FILTER_RXCHANMGR2, 2)),
-                       ES_API_WORD(ES_SET_GROUP_CMD,
-                                       ES300_GROUP(FILTER_RXCHANMGR2, 0)),
-               },
-               .write_msg_len = 24,
-               .val_shift = 0,
-               .val_max = MAX_INPUT_PORT,
-       },
-       [ES_AECREF1_MUX] = {
-               .write_msg = {
-                       ES_API_WORD(ES_SET_MUX_CMD,
-                                       ES300_DATA_PATH(0, 0, RXCHMGR4)),
-                       ES_API_WORD(ES_SET_PATH_ID_CMD,
-                                       ES300_PATH_ID(RXCHMGR4, ES300_AECREF)),
-                       ES_API_WORD(ES_CONNECT_CMD,
-                                       ES300_ENDPOINT(FILTER_RXCHANMGR4,
-                                               OUT, RxChMgr_o0)),
-                       ES_API_WORD(ES_CONNECT_CMD,
-                                       ES300_ENDPOINT(FILTER_VP, IN, vp_i4)),
-                       ES_API_WORD(ES_SET_RATE_CMD,
-                                       ES300_RATE(FILTER_RXCHANMGR4, 2)),
-                       ES_API_WORD(ES_SET_GROUP_CMD,
-                                       ES300_GROUP(FILTER_RXCHANMGR4, 0)),
-               },
-               .write_msg_len = 24,
-               .val_shift = 0,
-               .val_max = MAX_INPUT_PORT,
-       },
-       [ES_FEIN_MUX] = {
-               .write_msg = {
-                       ES_API_WORD(ES_SET_MUX_CMD,
-                                       ES300_DATA_PATH(0, 0, RXCHMGR3)),
-                       ES_API_WORD(ES_SET_PATH_ID_CMD,
-                                       ES300_PATH_ID(RXCHMGR3, ES300_FEIN)),
-               },
-               .write_msg_len = 8,
-               .val_shift = 0,
-               .val_max = MAX_INPUT_PORT,
-       },
-
-       [ES_UITONE1_MUX] = {
-               .write_msg = {
-                       ES_API_WORD(ES_SET_MUX_CMD,
-                                       ES300_DATA_PATH(0, 0, RXCHMGR5)),
-                       ES_API_WORD(ES_SET_PATH_ID_CMD,
-                               ES300_PATH_ID(RXCHMGR5, ES300_UITONE1)),
-               },
-               .write_msg_len = 8,
-               .val_shift = 0,
-               .val_max = MAX_PATH_TYPE,
-       },
-
-       [ES_UITONE2_MUX] = {
-               .write_msg = {
-                       ES_API_WORD(ES_SET_MUX_CMD,
-                                       ES300_DATA_PATH(0, 0, RXCHMGR6)),
-                       ES_API_WORD(ES_SET_PATH_ID_CMD,
-                               ES300_PATH_ID(RXCHMGR6, ES300_UITONE1)),
-               },
-               .write_msg_len = 8,
-               .val_shift = 0,
-               .val_max = MAX_PATH_TYPE,
-       },
-
-       [ES_UITONE3_MUX] = {
-               .write_msg = {
-                       ES_API_WORD(ES_SET_MUX_CMD,
-                                       ES300_DATA_PATH(0, 0, RXCHMGR5)),
-                       ES_API_WORD(ES_SET_PATH_ID_CMD,
-                               ES300_PATH_ID(RXCHMGR5, ES300_UITONE3)),
-               },
-               .write_msg_len = 8,
-               .val_shift = 0,
-               .val_max = MAX_PATH_TYPE,
-       },
-
-       [ES_UITONE4_MUX] = {
-               .write_msg = {
-                       ES_API_WORD(ES_SET_MUX_CMD,
-                                       ES300_DATA_PATH(0, 0, RXCHMGR6)),
-                       ES_API_WORD(ES_SET_PATH_ID_CMD,
-                               ES300_PATH_ID(RXCHMGR6, ES300_UITONE4)),
-               },
-               .write_msg_len = 8,
-               .val_shift = 0,
-               .val_max = MAX_PATH_TYPE,
-       },
-
-       [ES_MMUITONE1_MUX] = {
-               .write_msg = {
-                       ES_API_WORD(ES_SET_MUX_CMD,
-                                       ES300_DATA_PATH(0, 0, RXCHMGR2)),
-                       ES_API_WORD(ES_SET_PATH_ID_CMD,
-                                       ES300_PATH_ID(RXCHMGR2, ES300_UITONE1)),
-               },
-               .write_msg_len = 8,
-               .val_shift = 0,
-               .val_max = MAX_PATH_TYPE,
-       },
-       [ES_MMUITONE2_MUX] = {
-               .write_msg = {
-                       ES_API_WORD(ES_SET_MUX_CMD,
-                                       ES300_DATA_PATH(0, 0, RXCHMGR3)),
-                       ES_API_WORD(ES_SET_PATH_ID_CMD,
-                                       ES300_PATH_ID(RXCHMGR3, ES300_UITONE2)),
-               },
-               .write_msg_len = 8,
-               .val_shift = 0,
-               .val_max = MAX_PATH_TYPE,
-       },
-       [ES_AUDIN1_MUX] = {
-               .write_msg = {
-                       ES_API_WORD(ES_SET_MUX_CMD,
-                                       ES300_DATA_PATH(0, 0, RXCHMGR0)),
-                       ES_API_WORD(ES_SET_PATH_ID_CMD,
-                                       ES300_PATH_ID(RXCHMGR0, ES300_AUDIN1)),
-               },
-               .write_msg_len = 8,
-               .val_shift = 0,
-               .val_max = MAX_PATH_TYPE,
-       },
-       [ES_AUDIN2_MUX] = {
-               .write_msg = {
-                       ES_API_WORD(ES_SET_MUX_CMD,
-                                       ES300_DATA_PATH(0, 0, RXCHMGR1)),
-                       ES_API_WORD(ES_SET_PATH_ID_CMD,
-                                       ES300_PATH_ID(RXCHMGR1, ES300_AUDIN2)),
-               },
-               .write_msg_len = 8,
-               .val_shift = 0,
-               .val_max = MAX_PATH_TYPE,
-       },
-       [ES_MM_PASSIN1_MUX] = {
-               .write_msg = {
-                       ES_API_WORD(ES_SET_MUX_CMD,
-                                       ES300_DATA_PATH(0, 0, RXCHMGR0)),
-                       ES_API_WORD(ES_SET_PATH_ID_CMD,
-                                       ES300_PATH_ID(RXCHMGR0, ES300_PASSIN1)),
-               },
-               .write_msg_len = 8,
-               .val_shift = 0,
-               .val_max = MAX_PATH_TYPE,
-       },
-       [ES_MM_PASSIN2_MUX] = {
-               .write_msg = {
-                       ES_API_WORD(ES_SET_MUX_CMD,
-                                       ES300_DATA_PATH(0, 0, RXCHMGR1)),
-                       ES_API_WORD(ES_SET_PATH_ID_CMD,
-                               ES300_PATH_ID(RXCHMGR1, ES300_PASSIN2)),
-                       ES_API_WORD(ES_CONNECT_CMD,
-                                       ES300_ENDPOINT(FILTER_RXCHANMGR1,
-                                               OUT, RxChMgr_o0)),
-                       ES_API_WORD(ES_CONNECT_CMD,
-                               ES300_ENDPOINT(FILTER_PASSTHRU, IN, pass_i1)),
-                       ES_API_WORD(ES_SET_RATE_CMD,
-                                       ES300_RATE(FILTER_RXCHANMGR1, 3)),
-                       ES_API_WORD(ES_SET_GROUP_CMD,
-                                       ES300_GROUP(FILTER_RXCHANMGR1, 0)),
-               },
-               .write_msg_len = 24,
-               .val_shift = 0,
-               .val_max = MAX_PATH_TYPE,
-       },
-
-       [ES_PASSIN1_MUX] = {
-               .write_msg = {
-                       ES_API_WORD(ES_SET_MUX_CMD,
-                                       ES300_DATA_PATH(0, 0, RXCHMGR0)),
-                       ES_API_WORD(ES_SET_PATH_ID_CMD,
-                                       ES300_PATH_ID(RXCHMGR0, ES300_PASSIN1)),
-               },
-               .write_msg_len = 8,
-               .val_shift = 0,
-               .val_max = MAX_PATH_TYPE,
-       },
-       [ES_PASSIN2_MUX] = {
-               .write_msg = {
-                       ES_API_WORD(ES_SET_MUX_CMD,
-                                       ES300_DATA_PATH(0, 0, RXCHMGR1)),
-                       ES_API_WORD(ES_SET_PATH_ID_CMD,
-                               ES300_PATH_ID(RXCHMGR1, ES300_PASSIN2)),
-                       ES_API_WORD(ES_CONNECT_CMD,
-                                       ES300_ENDPOINT(FILTER_RXCHANMGR1,
-                                               OUT, RxChMgr_o0)),
-                       ES_API_WORD(ES_CONNECT_CMD,
-                               ES300_ENDPOINT(FILTER_PASSTHRU, IN, pass_i1)),
-                       ES_API_WORD(ES_SET_RATE_CMD,
-                                       ES300_RATE(FILTER_RXCHANMGR1, 3)),
-                       ES_API_WORD(ES_SET_GROUP_CMD,
-                                       ES300_GROUP(FILTER_RXCHANMGR1, 0)),
-               },
-               .write_msg_len = 24,
-               .val_shift = 0,
-               .val_max = MAX_PATH_TYPE,
-       },
-       [ES_PASSIN3_MUX] = {
-               .write_msg = {
-                       ES_API_WORD(ES_SET_MUX_CMD,
-                                       ES300_DATA_PATH(0, 0, RXCHMGR2)),
-                       ES_API_WORD(ES_SET_PATH_ID_CMD,
-                               ES300_PATH_ID(RXCHMGR2, ES300_PASSIN3)),
-                       ES_API_WORD(ES_CONNECT_CMD,
-                                       ES300_ENDPOINT(FILTER_RXCHANMGR2,
-                                               OUT, RxChMgr_o0)),
-                       ES_API_WORD(ES_CONNECT_CMD,
-                               ES300_ENDPOINT(FILTER_PASSTHRU, IN, pass_i2)),
-                       ES_API_WORD(ES_SET_RATE_CMD,
-                                       ES300_RATE(FILTER_RXCHANMGR2, 4)),
-                       ES_API_WORD(ES_SET_GROUP_CMD,
-                                       ES300_GROUP(FILTER_RXCHANMGR2, 0)),
-               },
-               .write_msg_len = 24,
-               .val_shift = 0,
-               .val_max = MAX_PATH_TYPE,
-       },
-       [ES_PASSIN4_MUX] = {
-               .write_msg = {
-                       ES_API_WORD(ES_SET_MUX_CMD,
-                                       ES300_DATA_PATH(0, 0, RXCHMGR3)),
-                       ES_API_WORD(ES_SET_PATH_ID_CMD,
-                               ES300_PATH_ID(RXCHMGR3, ES300_PASSIN4)),
-                       ES_API_WORD(ES_CONNECT_CMD,
-                                       ES300_ENDPOINT(FILTER_RXCHANMGR3,
-                                               OUT, RxChMgr_o0)),
-                       ES_API_WORD(ES_CONNECT_CMD,
-                               ES300_ENDPOINT(FILTER_PASSTHRU, IN, pass_i3)),
-                       ES_API_WORD(ES_SET_RATE_CMD,
-                                       ES300_RATE(FILTER_RXCHANMGR3, 4)),
-                       ES_API_WORD(ES_SET_GROUP_CMD,
-                                       ES300_GROUP(FILTER_RXCHANMGR3, 0)),
-               },
-               .write_msg_len = 24,
-               .val_shift = 0,
-               .val_max = MAX_PATH_TYPE,
-       },
-       [ES_DAC0_0_MUX] = {
-               .write_msg = {
-                       ES_API_WORD(ES_SET_MUX_CMD,
-                                       ES300_DATA_PATH(DAC0, 0, 0)),
-                       ES_API_WORD(ES_SET_PATH_ID_CMD,
-                                       ES300_PATH_ID(0, 0)),
-               },
-               .write_msg_len = 8,
-               .val_shift = 0,
-               .val_max = MAX_PATH_TYPE,
-       },
-       [ES_DAC0_1_MUX] = {
-               .write_msg = {
-                       ES_API_WORD(ES_SET_MUX_CMD,
-                                       ES300_DATA_PATH(DAC0, 1, 0)),
-                       ES_API_WORD(ES_SET_PATH_ID_CMD,
-                                       ES300_PATH_ID(0, 0)),
-               },
-               .write_msg_len = 8,
-               .val_shift = 0,
-               .val_max = MAX_PATH_TYPE,
-       },
-       [ES_DAC1_0_MUX] = {
-               .write_msg = {
-                       ES_API_WORD(ES_SET_MUX_CMD,
-                                       ES300_DATA_PATH(DAC1, 0, 0)),
-                       ES_API_WORD(ES_SET_PATH_ID_CMD,
-                                       ES300_PATH_ID(0, 0)),
-               },
-               .write_msg_len = 8,
-               .val_shift = 0,
-               .val_max = MAX_PATH_TYPE,
-       },
-       [ES_DAC1_1_MUX] = {
-               .write_msg = {
-                       ES_API_WORD(ES_SET_MUX_CMD,
-                                       ES300_DATA_PATH(DAC1, 1, 0)),
-                       ES_API_WORD(ES_SET_PATH_ID_CMD,
-                                       ES300_PATH_ID(0, 0)),
-               },
-               .write_msg_len = 8,
-               .val_shift = 0,
-               .val_max = MAX_PATH_TYPE,
-       },
-
-       [ES_PCM0_0_MUX] = {
-               .write_msg = {
-                       ES_API_WORD(ES_SET_MUX_CMD,
-                                       ES300_DATA_PATH(PCM0, 0, 0)),
-                       ES_API_WORD(ES_SET_PATH_ID_CMD,
-                                       ES300_PATH_ID(0, 0)),
-               },
-               .write_msg_len = 8,
-               .val_shift = 0,
-               .val_max = MAX_PATH_TYPE,
-       },
-       [ES_PCM0_1_MUX] = {
-               .write_msg = {
-                       ES_API_WORD(ES_SET_MUX_CMD,
-                                       ES300_DATA_PATH(PCM0, 1, 0)),
-                       ES_API_WORD(ES_SET_PATH_ID_CMD,
-                                       ES300_PATH_ID(0, 0)),
-               },
-               .write_msg_len = 8,
-               .val_shift = 0,
-               .val_max = MAX_PATH_TYPE,
-       },
-       [ES_PCM0_2_MUX] = {
-               .write_msg = {
-                       ES_API_WORD(ES_SET_MUX_CMD,
-                                       ES300_DATA_PATH(PCM0, 2, 0)),
-                       ES_API_WORD(ES_SET_PATH_ID_CMD,
-                                       ES300_PATH_ID(0, 0)),
-               },
-               .write_msg_len = 8,
-               .val_shift = 0,
-               .val_max = MAX_PATH_TYPE,
-       },
-       [ES_PCM0_3_MUX] = {
-               .write_msg = {
-                       ES_API_WORD(ES_SET_MUX_CMD,
-                                       ES300_DATA_PATH(PCM0, 3, 0)),
-                       ES_API_WORD(ES_SET_PATH_ID_CMD,
-                                       ES300_PATH_ID(0, 0)),
-               },
-               .write_msg_len = 8,
-               .val_shift = 0,
-               .val_max = MAX_PATH_TYPE,
-       },
-       [ES_PCM1_0_MUX] = {
-               .write_msg = {
-                       ES_API_WORD(ES_SET_MUX_CMD,
-                                       ES300_DATA_PATH(PCM1, 0, 0)),
-                       ES_API_WORD(ES_SET_PATH_ID_CMD,
-                                       ES300_PATH_ID(0, 0)),
-               },
-               .write_msg_len = 8,
-               .val_shift = 0,
-               .val_max = MAX_PATH_TYPE,
-       },
-       [ES_PCM1_1_MUX] = {
-               .write_msg = {
-                       ES_API_WORD(ES_SET_MUX_CMD,
-                                       ES300_DATA_PATH(PCM1, 1, 0)),
-                       ES_API_WORD(ES_SET_PATH_ID_CMD,
-                                       ES300_PATH_ID(0, 0)),
-               },
-               .write_msg_len = 8,
-               .val_shift = 0,
-               .val_max = MAX_PATH_TYPE,
-       },
-       [ES_PCM1_2_MUX] = {
-               .write_msg = {
-                       ES_API_WORD(ES_SET_MUX_CMD,
-                                       ES300_DATA_PATH(PCM1, 2, 0)),
-                       ES_API_WORD(ES_SET_PATH_ID_CMD,
-                                       ES300_PATH_ID(0, 0)),
-               },
-               .write_msg_len = 8,
-               .val_shift = 0,
-               .val_max = MAX_PATH_TYPE,
-       },
-       [ES_PCM1_3_MUX] = {
-               .write_msg = {
-                       ES_API_WORD(ES_SET_MUX_CMD,
-                                       ES300_DATA_PATH(PCM1, 3, 0)),
-                       ES_API_WORD(ES_SET_PATH_ID_CMD,
-                                       ES300_PATH_ID(0, 0)),
-               },
-               .write_msg_len = 8,
-               .val_shift = 0,
-               .val_max = MAX_PATH_TYPE,
-       },
-       [ES_PCM2_0_MUX] = {
-               .write_msg = {
-                       ES_API_WORD(ES_SET_MUX_CMD,
-                                       ES300_DATA_PATH(PCM2, 0, 0)),
-                       ES_API_WORD(ES_SET_PATH_ID_CMD,
-                                       ES300_PATH_ID(0, 0)),
-               },
-               .write_msg_len = 8,
-               .val_shift = 0,
-               .val_max = MAX_PATH_TYPE,
-       },
-       [ES_PCM2_1_MUX] = {
-               .write_msg = {
-                       ES_API_WORD(ES_SET_MUX_CMD,
-                                       ES300_DATA_PATH(PCM2, 1, 0)),
-                       ES_API_WORD(ES_SET_PATH_ID_CMD,
-                                       ES300_PATH_ID(0, 0)),
-               },
-               .write_msg_len = 8,
-               .val_shift = 0,
-               .val_max = MAX_PATH_TYPE,
-       },
-       [ES_PCM2_2_MUX] = {
-               .write_msg = {
-                       ES_API_WORD(ES_SET_MUX_CMD,
-                                       ES300_DATA_PATH(PCM2, 2, 0)),
-                       ES_API_WORD(ES_SET_PATH_ID_CMD,
-                                       ES300_PATH_ID(0, 0)),
-               },
-               .write_msg_len = 8,
-               .val_shift = 0,
-               .val_max = MAX_PATH_TYPE,
-       },
-       [ES_PCM2_3_MUX] = {
-               .write_msg = {
-                       ES_API_WORD(ES_SET_MUX_CMD,
-                                       ES300_DATA_PATH(PCM2, 3, 0)),
-                       ES_API_WORD(ES_SET_PATH_ID_CMD,
-                                       ES300_PATH_ID(0, 0)),
-               },
-               .write_msg_len = 8,
-               .val_shift = 0,
-               .val_max = MAX_PATH_TYPE,
-       },
-       [ES_CODEC_VALUE] = {
-               .read_msg = { ES_API_WORD(0x807B, 0x0000) },
-               .read_msg_len = 4,
-               .write_msg = { ES_API_WORD(0x907C, 0x0000) },
+       [ES_CODEC_ADDR] = {
+               .write_msg = { ES_API_WORD(0x9008, 0x0000) },
                .write_msg_len = 4,
                .val_shift = 0,
                .val_max = 65535,
@@ -712,7 +241,7 @@ static struct escore_api_access es755_api_access[ES_API_ADDR_MAX] = {
                               ES_API_WORD(ES_SET_ALGO_PARAM, 0x0000) },
                .write_msg_len = 8,
                .val_shift = 0,
-               .val_max = 5,
+               .val_max = 2,
        },
        [ES_VOICE_SENSE_TRAINING_STATUS] = {
                .read_msg = { ES_API_WORD(ES_GET_ALGO_PARAM, 0x5007) },
@@ -721,7 +250,7 @@ static struct escore_api_access es755_api_access[ES_API_ADDR_MAX] = {
                               ES_API_WORD(ES_SET_ALGO_PARAM, 0x0000) },
                .write_msg_len = 8,
                .val_shift = 0,
-               .val_max = 4,
+               .val_max = 7,
        },
        [ES_VOICE_SENSE_TRAINING_MODEL_LENGTH] = {
                .read_msg = { ES_API_WORD(ES_GET_ALGO_PARAM, 0x500A) },
@@ -756,77 +285,6 @@ static struct escore_api_access es755_api_access[ES_API_ADDR_MAX] = {
                .val_shift = 0,
                .val_max = 65535,
        },
-       [ES_SBUSTX0_MUX] = {
-               .write_msg = {
-                       ES_API_WORD(ES_SET_MUX_CMD,
-                                       ES300_DATA_PATH(SBUS, 0, 0)),
-                       ES_API_WORD(ES_SET_PATH_ID_CMD,
-                                       ES300_PATH_ID(0, 0)),
-               },
-               .write_msg_len = 8,
-               .val_shift = 0,
-               .val_max = MAX_PATH_TYPE,
-       },
-       [ES_SBUSTX1_MUX] = {
-               .write_msg = {
-                       ES_API_WORD(ES_SET_MUX_CMD,
-                                       ES300_DATA_PATH(SBUS, 1, 0)),
-                       ES_API_WORD(ES_SET_PATH_ID_CMD,
-                                       ES300_PATH_ID(0, 0)),
-               },
-               .write_msg_len = 8,
-               .val_shift = 0,
-               .val_max = MAX_PATH_TYPE,
-       },
-
-       [ES_SBUSTX2_MUX] = {
-               .write_msg = {
-                       ES_API_WORD(ES_SET_MUX_CMD,
-                                       ES300_DATA_PATH(SBUS, 2, 0)),
-                       ES_API_WORD(ES_SET_PATH_ID_CMD,
-                                       ES300_PATH_ID(0, 0)),
-               },
-               .write_msg_len = 8,
-               .val_shift = 0,
-               .val_max = MAX_PATH_TYPE,
-       },
-
-       [ES_SBUSTX3_MUX] = {
-               .write_msg = {
-                       ES_API_WORD(ES_SET_MUX_CMD,
-                                       ES300_DATA_PATH(SBUS, 3, 0)),
-                       ES_API_WORD(ES_SET_PATH_ID_CMD,
-                                       ES300_PATH_ID(0, 0)),
-               },
-               .write_msg_len = 8,
-               .val_shift = 0,
-               .val_max = MAX_PATH_TYPE,
-       },
-
-       [ES_SBUSTX4_MUX] = {
-               .write_msg = {
-                       ES_API_WORD(ES_SET_MUX_CMD,
-                                       ES300_DATA_PATH(SBUS, 4, 0)),
-                       ES_API_WORD(ES_SET_PATH_ID_CMD,
-                                       ES300_PATH_ID(0, 0)),
-               },
-               .write_msg_len = 8,
-               .val_shift = 0,
-               .val_max = MAX_PATH_TYPE,
-       },
-
-       [ES_SBUSTX5_MUX] = {
-               .write_msg = {
-                       ES_API_WORD(ES_SET_MUX_CMD,
-                                       ES300_DATA_PATH(SBUS, 5, 0)),
-                       ES_API_WORD(ES_SET_PATH_ID_CMD,
-                                       ES300_PATH_ID(0, 0)),
-               },
-               .write_msg_len = 8,
-               .val_shift = 0,
-               .val_max = MAX_PATH_TYPE,
-       },
-
        [ES_STEREO_WIDTH] = {
                .read_msg = {ES_API_WORD(ES_GET_ALGO_PARAM, 0x1006)},
                .read_msg_len = 4,
@@ -863,7 +321,7 @@ static struct escore_api_access es755_api_access[ES_API_ADDR_MAX] = {
                .val_max = 65535,
        },
 
-       [ES_AZ_MODE] = {
+       [ES_AF_MODE] = {
                .read_msg = {ES_API_WORD(ES_GET_ALGO_PARAM, 0x2002)},
                .read_msg_len = 4,
                .write_msg = {
@@ -875,6 +333,18 @@ static struct escore_api_access es755_api_access[ES_API_ADDR_MAX] = {
                .val_max = 65535,
        },
 
+       [ES_VP_METERS] = {
+               .read_msg = {ES_API_WORD(ES_GET_ALGO_PARAM, 0x003A)},
+               .read_msg_len = 4,
+               .write_msg = {
+                       ES_API_WORD(ES_SET_ALGO_PARAM_ID, 0x003A),
+                       ES_API_WORD(ES_SET_ALGO_PARAM, 0x0000),
+               },
+               .write_msg_len = 8,
+               .val_shift = 0,
+               .val_max = 1,
+       },
+
        [ES_PORT_WORD_LEN] = {
                .read_msg = { ES_API_WORD(ES_GET_DEV_PARAM, 0x0000) },
                .read_msg_len = 4,
@@ -983,61 +453,6 @@ static struct escore_api_access es755_api_access[ES_API_ADDR_MAX] = {
                .val_shift = 0,
                .val_max = 65535,
        },
-       [ES_AZ_PRI_MUX] = {
-               .write_msg = {
-                       ES_API_WORD(ES_SET_MUX_CMD,
-                                       ES300_DATA_PATH(0, 0, RXCHMGR0)),
-                       ES_API_WORD(ES_SET_PATH_ID_CMD,
-                                       ES300_PATH_ID(RXCHMGR0, ES300_PRI)),
-               },
-               .write_msg_len = 8,
-               .val_shift = 0,
-               .val_max = MAX_INPUT_PORT,
-       },
-       [ES_AZ_SEC_MUX] = {
-               .write_msg = {
-                       ES_API_WORD(ES_SET_MUX_CMD,
-                                       ES300_DATA_PATH(0, 0, RXCHMGR1)),
-                       ES_API_WORD(ES_SET_PATH_ID_CMD,
-                                       ES300_PATH_ID(RXCHMGR1, ES300_SEC)),
-               },
-               .write_msg_len = 8,
-               .val_shift = 0,
-               .val_max = MAX_INPUT_PORT,
-
-       },
-       [ES_AZ_TER_MUX] = {
-               .write_msg = {
-                       ES_API_WORD(ES_SET_MUX_CMD,
-                                       ES300_DATA_PATH(0, 0, RXCHMGR2)),
-                       ES_API_WORD(ES_SET_PATH_ID_CMD,
-                                       ES300_PATH_ID(RXCHMGR2, ES300_TER)),
-                       ES_API_WORD(ES_CONNECT_CMD,
-                                       ES300_ENDPOINT(FILTER_RXCHANMGR2,
-                                               OUT, RxChMgr_o0)),
-                       ES_API_WORD(ES_CONNECT_CMD,
-                                       ES300_ENDPOINT(FILTER_AZ, IN, az_i2)),
-                       ES_API_WORD(ES_SET_RATE_CMD,
-                                       ES300_RATE(FILTER_RXCHANMGR2, 3)),
-                       ES_API_WORD(ES_SET_GROUP_CMD,
-                                       ES300_GROUP(FILTER_RXCHANMGR2, 0)),
-               },
-               .write_msg_len = 24,
-               .val_shift = 0,
-               .val_max = MAX_INPUT_PORT,
-
-       },
-       [ES_AZ_AI1_MUX] = {
-               .write_msg = {
-                       ES_API_WORD(ES_SET_MUX_CMD,
-                                       ES300_DATA_PATH(0, 0, RXCHMGR3)),
-                       ES_API_WORD(ES_SET_PATH_ID_CMD,
-                                       ES300_PATH_ID(RXCHMGR3, ES300_AUDIN1)),
-               },
-               .write_msg_len = 8,
-               .val_shift = 0,
-               .val_max = MAX_INPUT_PORT,
-       },
        [ES_FE_STREAMING] = {
                .read_msg = { ES_API_WORD(0x8028, 0x0000) },
                .read_msg_len = 4,
@@ -1056,89 +471,9 @@ static struct escore_api_access es755_api_access[ES_API_ADDR_MAX] = {
                .val_max = 65535,
        },
 
-
 };
 
-static struct escore_reg_cache a300_reg_cache[ES_MAX_REGISTER] = {
-       { 0x01, 0 },
-       { 0x60, 0 },
-       { 0x00, 0 },
-       { 0x00, 0 },
-       { 0x00, 0 },
-       { 0x00, 0 },
-       { 0xA0, 0 },
-       { 0x00, 0 },
-       { 0x00, 0 },
-       { 0x00, 0 },
-       { 0x00, 0 },
-       { 0x00, 0 },
-       { 0x28, 0 },
-       { 0x00, 0 },
-       { 0x00, 0 },
-       { 0x00, 0 },
-       { 0x00, 0 },
-       { 0x00, 0 },
-       { 0x00, 0 },
-       { 0x00, 0 },
-       { 0x00, 0 },
-       { 0x00, 0 },
-       { 0x00, 0 },
-       { 0x00, 0 },
-       { 0x00, 0 },
-       { 0x00, 0 },
-       { 0x00, 0 },
-       { 0x00, 0 },
-       { 0x00, 0 },
-       { 0x08, 0 },
-       { 0x00, 0 },
-       { 0x00, 1 },
-       { 0xFF, 1 },
-       { 0x00, 1 },
-       { 0xFF, 1 },
-       { 0x00, 1 },
-       { 0x00, 1 },
-       { 0x00, 1 },
-       { 0xC7, 1 },
-       { 0x00, 0 },
-       { 0x52, 0 },
-       { 0x70, 0 },
-       { 0x00, 0 },
-       { 0x00, 0 },
-       { 0x66, 0 },
-       { 0x03, 0 },
-       { 0x00, 0 },
-       { 0x00, 0 },
-       { 0x00, 0 },
-       { 0x00, 0 },
-       { 0x1F, 0 },
-       { 0x0C, 1 },
-       { 0x00, 0 },
-       { 0x00, 0 },
-       { 0x00, 0 },
-       { 0x00, 0 },
-       { 0x00, 0 },
-       { 0x00, 0 },
-       { 0x00, 0 },
-       { 0x00, 1 },
-       { 0x00, 0 },
-       { 0xFF, 0 },
-       { 0x00, 0 },
-       { 0xFF, 0 },
-       { 0x00, 0 },
-       { 0x00, 0 },
-       { 0x00, 0 },
-       { 0x00, 0 },
-       { 0x00, 0 },
-       { 0x00, 0 },
-       { 0x40, 0 },
-       { 0x0F, 0 },
-       { 0x41, 0 },
-       { 0xFF, 0 },
-       { 0x6B, 0 },
-       { 0x14, 0 },
-       { 0x50, 0 },
-       { 0x1D, 0 },
-};
+static struct escore_reg_cache a300_reg_cache[ES_MAX_REGISTER] = { {0} };
 
 
 #endif /* _ES_ACCESS_H */
old mode 100755 (executable)
new mode 100644 (file)
index b194acc..8364fc8
 #include "escore-uart-common.h"
 #include "es755-access.h"
 #include "es-d300.h"
+#if defined(CONFIG_SND_SOC_ES854)
+#include "es-a350-reg.h"
+#elif defined(CONFIG_SND_SOC_ES857)
+#include "es-a375-reg.h"
+#else
 #include "es-a300-reg.h"
+#endif
 #include "escore-version.h"
 #include <linux/sort.h>
 #ifdef CONFIG_QPNP_CLKDIV
@@ -40,19 +46,36 @@ union es755_accdet_reg {
                u16 res2:1;
                u16 mic_det_fsm:1;
                u16 mg_sel_force:1;
-               u16 mg_select:1;
+               u16 mg_select:2;
        } fields;
 };
+
+static const u16 es755_vs_presets[] = {
+       [ES755_DMIC0] = ES755_DMIC0_VS_ROUTE_PRESET,
+       [ES755_MIC0]  = ES755_MIC0_VS_ROUTE_PRESET,
+       [ES755_MICHS] = ES755_MICHS_VS_ROUTE_PRESET,
+};
+
+static const u16 es755_cvs_presets[] = {
+       [ES755_DMIC0] = ES755_DMIC0_CVS_PRESET,
+       [ES755_MIC0]  = ES755_MIC0_CVS_PRESET,
+       [ES755_MICHS] = ES755_MICHS_CVS_PRESET,
+};
+
 /* codec private data TODO: move to runtime init */
 struct escore_priv escore_priv = {
-       .pm_state = ES_PM_ACTIVE,
        .probe = es755_core_probe,
        .set_streaming = es755_set_streaming,
        .set_datalogging = es755_set_datalogging,
        .streamdev.no_more_bit = 0,
-       .es_vs_route_preset = ES755_MIC0_VS_ROUTE_PREST,
-       .es_cvs_preset = ES755_MIC0_CVS_PREST,
-       .system_suspend = 0,
+       .default_cvq_mic = ES755_MIC0,
+       .es_vs_route_preset = ES755_MIC0_VS_ROUTE_PRESET,
+       .es_cvs_preset = ES755_MIC0_CVS_PRESET,
+       .es_wdb_max_size = ES755_WDB_MAX_SIZE,
+       .delay.wakeup_to_normal = ES755_DELAY_WAKEUP_TO_NORMAL,
+       .delay.wakeup_to_vs = ES755_DELAY_WAKEUP_TO_VS,
+       .delay.vs_to_normal = ES755_DELAY_VS_TO_NORMAL,
+       .delay.mpsleep_to_normal = ES755_DELAY_MPSLEEP_TO_NORMAL,
 };
 
 struct snd_soc_dai_driver es755_dai[];
@@ -95,6 +118,14 @@ static const u32 es755_streaming_cmds[] = {
 };
 
 #ifdef CONFIG_ARCH_MSM
+#if defined(CONFIG_SND_SOC_ES854)
+const struct slim_device_id escore_slim_id[] = {
+       { "earSmart-codec", ESCORE_DEVICE_NONE }, /* for portability */
+       { "earSmart-codec-intf", ESCORE_INTERFACE_DEVICE },
+       { "earSmart-codec-gen0", ESCORE_GENERIC_DEVICE },
+       {  }
+};
+#else
 const struct slim_device_id escore_slim_id[] = {
        { "earSmart-codec", ESCORE_DEVICE_NONE }, /* for portability */
        { "eS755A0-codec-intf", ESCORE_INTERFACE_DEVICE },
@@ -105,17 +136,21 @@ const struct slim_device_id escore_slim_id[] = {
        { "eS755A2-codec-gen0", ESCORE_GENERIC_DEVICE },
        {  }
 };
+#endif
 MODULE_DEVICE_TABLE(slim, escore_slim_id);
 #endif
 
 static int es755_clk_ctl(int enable)
 {
        int ret = 0;
+       bool clk_en;
+
+       clk_en = enable? true: false;
 
-       if (enable == escore_priv.codec_clk_en)
+       if (clk_en == escore_priv.codec_clk_en)
                return 0;
 
-       if (enable)
+       if (clk_en)
 #ifdef CONFIG_QPNP_CLKDIV
                ret = qpnp_clkdiv_enable(codec_clk);
 #else
@@ -128,11 +163,11 @@ static int es755_clk_ctl(int enable)
                clk_disable(codec_clk);
 #endif
 
-       if (EINVAL != ret) {
-               escore_priv.codec_clk_en = !!enable;
+       if ( -EINVAL != ret)
+       {
+               escore_priv.codec_clk_en = clk_en;
                ret = 0;
        }
-
        return ret;
 }
 static int es755_channel_dir(int dai_id)
@@ -151,21 +186,53 @@ static int es755_channel_dir(int dai_id)
 
        return dir;
 }
+
+static int es755_get_route_status(struct escore_priv *escore, int algo_id)
+{
+       int ret = 0, value = 0;
+       u32 api_word = 0;
+       unsigned int msg_len;
+
+       ret = escore_prepare_msg(escore, ES_CHANGE_STATUS, value,
+                       (char *)&api_word, &msg_len, ES_MSG_READ);
+       if (ret) {
+               pr_err("%s: Prepare message fail %d\n", __func__, ret);
+               goto out;
+       }
+
+       /* Set the algo type in message */
+       api_word |= algo_id;
+       ret = escore_cmd_locked(escore, api_word, &value);
+       if (ret < 0) {
+               pr_err("%s(): escore_cmd() ret:%d", __func__, ret);
+               goto out;
+       }
+       ret = (value & 0xFF);
+
+out:
+       return ret;
+}
+
 static ssize_t es755_route_status_show(struct device *dev,
                                       struct device_attribute *attr,
                                       char *buf)
 {
        int ret = 0;
-       unsigned int value = 0;
+       int value = 0;
        char *status_name = "Route Status";
        struct escore_priv *escore = &escore_priv;
-       unsigned int msg_len;
-       u32 api_word = 0;
        const char *algo_text[ALGO_MAX] = {
                [VP] = "VP",
                [MM] = "MM",
-               [AUDIOZOOM] = "AudioZoom",
+               [AUDIOFOCUS] = "AudioFocus",
                [PASSTHRU] = "Passthru",
+               [VP_MM] = "VP_MM",
+               [PASSTHRU_VP] = "Passthru VP",
+               [PASSTHRU_MM] = "Passthru MM",
+               [PASSTHRU_VP_MM] = "Passthru VP MM",
+               [PASSTHRU_AF] = "Passthru AF",
+               [VOICEQ] = "VoiceQ",
+               [KALA_OK] = "KalaOK",
        };
 
        const char *status_text[] = {
@@ -179,34 +246,69 @@ static ssize_t es755_route_status_show(struct device *dev,
        const u8 algo_id[ALGO_MAX] = {
                [VP] = 0,
                [MM] = 1,
-               [AUDIOZOOM] = 2,
+               [AUDIOFOCUS] = 2,
                [PASSTHRU] = 3,
+               [VOICEQ] = 4,
+               [KALA_OK] = 3, /* KalaOK is same as PASSTHRU */
        };
 
-       if (escore->algo_type != NONE) {
-               ret = escore_prepare_msg(escore, ES_CHANGE_STATUS, value,
-                               (char *)&api_word, &msg_len, ES_MSG_READ);
-               if (ret) {
-                       pr_err("%s(): Failed to prepare message\n", __func__);
+       if (escore->algo_type == ALGO_NONE) {
+               pr_err("Algo type not set\n");
+               ret = -EINVAL;
+               goto out;
+       }
+
+       switch (escore->algo_type) {
+       case VP:
+       case MM:
+       case AUDIOFOCUS:
+       case PASSTHRU:
+       case VOICEQ:
+       case KALA_OK:
+               value = es755_get_route_status(escore,
+                               algo_id[escore->algo_type]);
+               if (value < 0) {
+                       pr_err("%s(): GetRouteChangeStatus Failed: %d\n",
+                                       __func__, value);
+                       ret = value;
                        goto out;
                }
 
-               /* Set the algo type in message */
-               api_word |= algo_id[escore->algo_type];
-               ret = escore_cmd(escore, api_word, &value);
-               if (ret < 0) {
-                       pr_err("%s(): escore_cmd()", __func__);
+               ret = snprintf(buf, PAGE_SIZE, "%s for %s Algo (%d) is %s\n",
+                               status_name, algo_text[escore->algo_type],
+                               escore->algo_type, status_text[value]);
+               break;
+       case PASSTHRU_VP:
+       case BARGE_IN:
+               {
+               int ret1, ret2;
+               value = es755_get_route_status(escore, algo_id[VP]);
+               if (value < 0) {
+                       pr_err("%s(): GetRouteChangeStatus Failed: %d\n",
+                                       __func__, value);
+                       ret = value;
                        goto out;
                }
-               value &= 0xFF;
 
-               ret = snprintf(buf, PAGE_SIZE, "%s for %s Algo is %s\n",
-                               status_name, algo_text[escore->algo_type],
-                               status_text[value]);
+               ret1 = snprintf(buf, PAGE_SIZE, "%s for %s Algo (%d) is %s\n",
+                               status_name, algo_text[VP],
+                               VP, status_text[value]);
 
-       } else {
-               pr_err("Algo type not set\n");
-               ret = -EINVAL;
+               value = es755_get_route_status(escore, algo_id[PASSTHRU]);
+               if (value < 0) {
+                       pr_err("%s(): GetRouteChangeStatus Failed: %d\n",
+                                       __func__, value);
+                       ret = value;
+                       goto out;
+               }
+
+               ret2 = snprintf(buf+ret1, PAGE_SIZE,
+                               "%s for %s Algo (%d) is %s\n",
+                               status_name, algo_text[PASSTHRU],
+                               PASSTHRU, status_text[value]);
+               ret = ret1 + ret2;
+               break;
+               }
        }
 out:
        return ret;
@@ -219,7 +321,7 @@ static ssize_t es755_get_pm_enable(struct device *dev,
                                     struct device_attribute *attr,
                                     char *buf)
 {
-       return snprintf(buf, PAGE_SIZE, "%s\n", escore_priv.pm_enable ?
+       return snprintf(buf, PAGE_SIZE, "%s\n", escore_priv.pm_status ?
                        "on" : "off");
 }
 static ssize_t es755_set_pm_enable(struct device *dev,
@@ -228,9 +330,9 @@ static ssize_t es755_set_pm_enable(struct device *dev,
 {
        pr_info("%s(): requested - %s\n", __func__, buf);
        if (!strncmp(buf, "on", 2))
-               escore_pm_enable();
+               escore_pm_status_update(ES_PM_ON);
        else if (!strncmp(buf, "off", 3))
-               escore_pm_disable();
+               escore_pm_status_update(ES_PM_OFF);
        return count;
 
 }
@@ -246,9 +348,11 @@ static ssize_t es755_fw_version_show(struct device *dev,
        unsigned int value;
        char versionbuffer[SIZE_OF_VERBUF];
        char *verbuf = versionbuffer;
+       struct escore_priv *escore = &escore_priv;
 
        memset(verbuf, 0, SIZE_OF_VERBUF);
 
+       mutex_lock(&escore->access_lock);
        value = escore_read(NULL, ES_FW_FIRST_CHAR);
        *verbuf++ = (value & 0x00ff);
        for (idx = 0; idx < (SIZE_OF_VERBUF-2); idx++) {
@@ -257,6 +361,7 @@ static ssize_t es755_fw_version_show(struct device *dev,
                if (!value)
                        break;
        }
+       mutex_unlock(&escore->access_lock);
        /* Null terminate the string*/
        *verbuf = '\0';
        pr_debug("Audience fw ver %s\n", versionbuffer);
@@ -298,10 +403,10 @@ static ssize_t es755_ping_status_show(struct device *dev,
        u32 sync_ack;
        char *status_name = "Ping";
 
-       rc = escore_cmd(es755, sync_cmd, &sync_ack);
+       rc = escore_cmd_locked(es755, sync_cmd, &sync_ack);
        if (rc < 0) {
-               pr_err("%s(): firmware load failed sync write\n",
-                               __func__);
+               pr_err("%s(): firmware load failed sync write %d\n",
+                      __func__, rc);
                goto cmd_err;
        }
        pr_debug("%s(): sync_ack = 0x%08x\n", __func__, sync_ack);
@@ -323,6 +428,135 @@ static ssize_t escore_version_show(struct device *dev,
 }
 static DEVICE_ATTR(escore_version, 0444, escore_version_show, NULL);
 
+static const char * const es755_power_state_texts[] = {
+       "None", "Sleep", "MP_Sleep", "MP_Cmd", "Normal", "Overlay", "Low_Power",
+       "Codec Deep Sleep"
+};
+
+static ssize_t es755_power_state_show(struct device *dev,
+               struct device_attribute *attr,
+               char *buf)
+{
+       struct escore_priv *es755 = &escore_priv;
+
+       dev_dbg(es755->dev, "%s(): power state = %s\n", __func__,
+                       es755_power_state_texts[es755->escore_power_state]);
+       return snprintf(buf, PAGE_SIZE, "power state = %s\n",
+                       es755_power_state_texts[es755->escore_power_state]);
+}
+
+static DEVICE_ATTR(power_state, 0444, es755_power_state_show, NULL);
+
+
+/* Display Data format of Codec Control Registers dump */
+#define ES_CODEC_REG_DISP_FMT          "Reg = 0x%02X , Value = 0x%02X\n"
+
+/* Store register addresses of 1 byte */
+static u8 reg_addr[ES_MAX_CODEC_CONTROL_REG];
+/* Store read count of registers to be displayed */
+static u8 reg_read_cnt = ES_MAX_CODEC_CONTROL_REG;
+
+/* Device Attribute to dump Codec Control Registers */
+static ssize_t codec_reg_dump_show(struct device *dev,
+                                    struct device_attribute *attr,
+                                    char *buf)
+{
+       struct escore_priv *es755 = &escore_priv;
+       int rc = 0;
+       int j = 0;
+       u32 cmd, resp;
+       u8 i, val;
+       u8 addr;
+       int reg_max = reg_read_cnt;
+       u32 max_size_disp_op;
+
+       /* Dump all the registers */
+       if (reg_read_cnt == ES_MAX_CODEC_CONTROL_REG)
+               reg_max += 1;
+
+       pr_debug("%s(): reg_max = 0x%02x\n", __func__, reg_max);
+
+       /* Error if Display Data exceeds PAGE_SIZE */
+       max_size_disp_op  = reg_max * sizeof(ES_CODEC_REG_DISP_FMT);
+       if (max_size_disp_op > PAGE_SIZE) {
+               pr_err("%s(): Display Data exceeds PAGE_SIZE", __func__);
+               return -EINVAL;
+       }
+
+       mutex_lock(&es755->access_lock);
+       for (i = 0; i < reg_max; i++) {
+               if (reg_read_cnt == ES_MAX_CODEC_CONTROL_REG)
+                       addr = i;
+               else
+                       addr = reg_addr[i];
+
+               cmd = (ES_GET_CODEC_VAL << 16) | (addr << 8);
+               rc = escore_cmd(es755, cmd, &resp);
+               if (rc < 0) {
+                       pr_err("%s(): escore_cmd() rc:%d", __func__, rc);
+                       goto cmd_err;
+               }
+               pr_debug("%s(): cmd = 0x%08x, resp = 0x%08x\n",
+                               __func__, cmd, resp);
+
+               val = resp & ES_CODEC_VAL_MASK;
+
+               j += snprintf(buf + j, PAGE_SIZE,
+                              ES_CODEC_REG_DISP_FMT,
+                              addr, val);
+               rc = j;
+       }
+
+cmd_err:
+       mutex_unlock(&es755->access_lock);
+       /* Assign max value for next read operation */
+       reg_read_cnt = ES_MAX_CODEC_CONTROL_REG;
+
+       return rc;
+}
+
+/* Device Attribute to store address of Codec Control Registers into array */
+static ssize_t codec_reg_dump_store(struct device *dev,
+                                       struct device_attribute *attr,
+                                       const char *buf, size_t count)
+{
+       int arg_read = 0;
+       int pos = 0;
+       int bytes_read = 0;
+       int in_addr;
+
+       pr_debug("%s(): requested - %s, count=%d\n", __func__, buf, count);
+
+       /* Return Error for Invalid argument */
+       if (strncmp(buf, "0x", 2) || !count) {
+               pr_err("%s(): Invalid Argument\n", __func__);
+               return -EINVAL;
+       }
+
+       /* Reset total for new operation */
+       reg_read_cnt = 0;
+
+       while ((bytes_read <= count) &&
+                       (reg_read_cnt <= ES_MAX_CODEC_CONTROL_REG)) {
+               arg_read = sscanf(buf + bytes_read, "%x%n", &in_addr, &pos);
+               bytes_read += pos;
+
+               pr_debug("%s(): in_addr = %02x, arg_read=%d, bytes_read=%d\n",
+                               __func__, in_addr, arg_read, bytes_read);
+
+               /* Skip Invalid characters and register address */
+               if (!arg_read || (in_addr > ES_MAX_CODEC_CONTROL_REG))
+                       continue;
+
+               reg_addr[reg_read_cnt] = in_addr;
+               reg_read_cnt++;
+       };
+
+       return count;
+}
+static DEVICE_ATTR(codec_reg_dump, 0666, codec_reg_dump_show,
+                       codec_reg_dump_store);
+
 static struct attribute *core_sysfs_attrs[] = {
        &dev_attr_route_status.attr,
        &dev_attr_reset_control.attr,
@@ -331,6 +565,8 @@ static struct attribute *core_sysfs_attrs[] = {
        &dev_attr_ping_status.attr,
        &dev_attr_pm_enable.attr,
        &dev_attr_escore_version.attr,
+       &dev_attr_power_state.attr,
+       &dev_attr_codec_reg_dump.attr,
        NULL
 };
 
@@ -341,11 +577,9 @@ static struct attribute_group core_sysfs = {
 static int es755_fw_download(struct escore_priv *es755)
 {
        int rc;
-       u32 cmd;
 
        pr_debug("%s()\n", __func__);
 
-       BUG_ON(es755->standard->size == 0);
        /* Reset Mode to Polling */
        es755->cmd_compl_mode = ES_CMD_COMP_POLL;
 
@@ -362,49 +596,49 @@ static int es755_fw_download(struct escore_priv *es755)
                pr_debug("%s(): calling bus specific boot setup\n", __func__);
                rc = es755->boot_ops.setup(es755);
                if (rc != 0) {
-                       pr_err("%s() bus specific boot setup error\n",
-                               __func__);
+                       pr_err("%s() bus specific boot setup error %d\n",
+                              __func__, rc);
                        goto es755_bootup_failed;
                }
        }
        es755->mode = SBL;
 
+       /* Set flag to Wait for API Interrupt */
+       escore_set_api_intr_wait(es755);
+
        rc = es755->bus.ops.high_bw_write(es755, (char *)es755->standard->data,
                              es755->standard->size);
        if (rc < 0) {
-               pr_err("%s(): firmware download failed\n", __func__);
+               pr_err("%s(): firmware download failed %d\n",
+                      __func__, rc);
                rc = -EIO;
                goto es755_bootup_failed;
        }
 
-       /* Give the chip some time to become ready after firmware
-        * download. */
-       msleep(20);
-
-       if (es755->boot_ops.finish) {
+       /* Wait for API Interrupt to confirm that firmware is
+        * ready to accept command */
+       if (es755->pdata->gpioa_gpio != -1) {
+               rc = escore_api_intr_wait_completion(es755);
+               if (rc)
+                       goto es755_bootup_failed;
+       } else if (es755->boot_ops.finish) {
+               /* Give the chip some time to become ready after firmware
+                * download. */
+               msleep(20);
                pr_debug("%s(): calling bus specific boot finish\n", __func__);
                rc = es755->boot_ops.finish(es755);
                if (rc != 0) {
-                       pr_err("%s() bus specific boot finish error\n",
-                               __func__);
+                       pr_err("%s() bus specific boot finish error %d\n",
+                              __func__, rc);
                        goto es755_bootup_failed;
                }
        }
        es755->mode = STANDARD;
 
-       if (es755->pdata->gpioa_gpio != -1) {
-               cmd = ((ES_SYNC_CMD | ES_SUPRESS_RESPONSE) << 16) |
-                                       es755->pdata->gpio_a_irq_type;
-               rc = escore_cmd(es755, cmd, NULL);
-               if (rc < 0) {
-                       pr_err("%s(): API interrupt config failed:%d\n",
-                                       __func__, rc);
-
-                       goto es755_bootup_failed;
-               }
-               /* Set Interrupt Mode */
-               es755->cmd_compl_mode = ES_CMD_COMP_INTR;
-       }
+       /* Reconfig API Interrupt mode */
+       rc = escore_reconfig_api_intr(es755);
+       if (rc)
+               goto es755_bootup_failed;
 
 es755_bootup_failed:
        if (es755->bus.ops.high_bw_close) {
@@ -421,6 +655,7 @@ es755_high_bw_open_failed:
        return rc;
 }
 
+/* This function must be called with access_lock acquired */
 int es755_bootup(struct escore_priv *es755)
 {
        u8 retry = ES755_FW_DOWNLOAD_MAX_RETRY;
@@ -444,6 +679,7 @@ int es755_bootup(struct escore_priv *es755)
        return rc;
 }
 
+
 static int es755_slim_set_channel_map(struct snd_soc_dai *dai,
                                      unsigned int tx_num,
                                      unsigned int *tx_slot,
@@ -528,25 +764,6 @@ static int es755_slim_get_channel_map(struct snd_soc_dai *dai,
 }
 #endif
 
-int es755_digital_mute(struct snd_soc_dai *dai, int mute)
-{
-       struct snd_soc_codec *codec = dai->codec;
-       unsigned int val;
-
-       dev_dbg(codec->dev, "%s() mute %d\n", __func__, mute);
-
-       if (mute) {
-               val = 0;
-       } else {
-               /* find which DACs are ON */
-               val = snd_soc_read(codec, ES_DAC_CTRL);
-       }
-
-       return snd_soc_update_bits(codec, ES_DAC_DIG_EN, ES_DAC0_LEFT_EN_MASK |
-               ES_DAC0_RIGHT_EN_MASK | ES_DAC1_LEFT_EN_MASK |
-               ES_DAC1_RIGHT_EN_MASK, val);
-}
-
 #if defined(CONFIG_SND_SOC_ES_I2S)
 static void es755_shutdown(struct snd_pcm_substream *substream,
                               struct snd_soc_dai *dai)
@@ -570,19 +787,11 @@ static void es755_shutdown(struct snd_pcm_substream *substream,
 static int es755_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
 {
        struct snd_soc_codec *codec = dai->codec;
-       struct escore_priv *escore = snd_soc_codec_get_drvdata(codec);
-       struct escore_api_access *api_access;
-       int data_justification;
        int id = DAI_INDEX(dai->id);
-       u8 pcm_port[] = { ES755_PCM_PORT_A,
-               ES755_PCM_PORT_B,
-               ES755_PCM_PORT_C };
-       int rc;
 
        dev_dbg(codec->dev, "%s(): dai->name = %s, dai->id = %d, fmt = %x\n",
                __func__, dai->name, dai->id, fmt);
 
-
        /* set master/slave audio interface */
        switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
        case SND_SOC_DAIFMT_CBM_CFM:
@@ -616,9 +825,9 @@ static int es755_hw_params(struct snd_pcm_substream *substream,
        int bps = 0;
        int rate = 0;
        int id = DAI_INDEX(dai->id);
-       int port_map = 0;
        u16 clock_control = 0;
        u16 codec_output_rate = 0;
+       int port_map = 0;
        u8 pcm_port[] = { ES755_PCM_PORT_A,
                ES755_PCM_PORT_B,
                ES755_PCM_PORT_C };
@@ -626,6 +835,16 @@ static int es755_hw_params(struct snd_pcm_substream *substream,
        dev_dbg(codec->dev, "%s(): dai->name = %s, dai->id = %d\n", __func__,
                dai->name, dai->id);
 
+       mutex_lock(&escore->access_lock);
+       rc =  es_change_power_state_normal(escore);
+       mutex_unlock(&escore->access_lock);
+
+       if (rc) {
+               dev_err(codec->dev, "%s(): Power state transition failed %d\n",
+                               __func__, rc);
+               return rc;
+       }
+
        channels = params_channels(params);
        switch (channels) {
        case 1:
@@ -647,7 +866,12 @@ static int es755_hw_params(struct snd_pcm_substream *substream,
                return -EINVAL;
        }
 
-       switch (params_format(params)) {
+
+       escore->pcm_format = params_format(params);
+       /* ######## HACK : Set PCM format as 32bit ####### */
+       escore->pcm_format = SNDRV_PCM_FORMAT_S32_LE;
+
+       switch (escore->pcm_format) {
        case SNDRV_PCM_FORMAT_A_LAW:
                bps = 0x0207;
                break;
@@ -683,10 +907,10 @@ static int es755_hw_params(struct snd_pcm_substream *substream,
                api_access->write_msg[0] |=  ES_API_WORD(ES_SET_DEV_PARAM_ID,
                                (pcm_port[id] << 8));
 
-               rc = escore_write(codec, ES_PORT_WORD_LEN, bps);
+               rc = escore_write_locked(codec, ES_PORT_WORD_LEN, bps);
                if (rc) {
-                       pr_err("%s(): Preparing write message failed\n",
-                                       __func__);
+                       pr_err("%s(): Preparing write message failed %d\n",
+                              __func__, rc);
                        return rc;
                }
                /* Clear the Port info in write command */
@@ -742,25 +966,38 @@ static int es755_hw_params(struct snd_pcm_substream *substream,
        api_access->write_msg[0] |=  ES_API_WORD(ES_SET_DEV_PARAM_ID,
                        (pcm_port[id] << 8));
 
-       clock_control = rate | (i2s_dai_data[id].port_mode << 8);
+       clock_control  = rate | (i2s_dai_data[id].port_mode << 8);
 
-       rc = escore_write(codec, ES_PORT_CLOCK_CONTROL, clock_control);
+       rc = escore_write_locked(codec, ES_PORT_CLOCK_CONTROL, clock_control);
        if (rc) {
-               pr_err("%s(): Preparing write message failed\n",
-                               __func__);
+               pr_err("%s(): Preparing write message failed %d\n",
+                      __func__, rc);
                return rc;
        }
 
        /* Clear the Port info in write command */
        api_access->write_msg[0] &= ES_API_WORD(ES_SET_DEV_PARAM_ID, 0x00ff);
 
-       /* Set codec output rate 96Khz(0x2) for 192K and 48Khz(0x0) for rest */
-       /* required for droop filter settings */
-       if (params_rate(params) == 192000 || params_rate(params) == 96000)
-               codec_output_rate = 0x2;
-
-       rc = escore_write(codec, ES_CODEC_OUTPUT_RATE,
-                       codec_output_rate);
+       /* Set codec output rate  */
+       if (escore->dhwpt_enabled || escore->algo_type == DHWPT) {
+               switch (params_rate(params)) {
+               case 44100:
+                       codec_output_rate = 0x7;
+                       break;
+               case 48000:
+                       codec_output_rate = 0x6;
+                       break;
+               case 96000:
+               case 192000:
+                       codec_output_rate = 0x2;
+                       break;
+               default:
+                       pr_err("%s: Unsupported sampling rate %d for DHWPT\n",
+                               __func__, params_rate(params));
+                       return -EINVAL;
+               }
+       }
+       rc = escore_write_locked(codec, ES_CODEC_OUTPUT_RATE, codec_output_rate);
        if (rc) {
                pr_err("%s(): Preparing write message failed %d\n",
                                __func__, rc);
@@ -772,7 +1009,10 @@ static int es755_hw_params(struct snd_pcm_substream *substream,
         * is required. For that, minimum 48Khz sample rate, 32 bit word length
         * and 2 channels are required.
         */
-       escore->can_mpsleep = (rate == 48) && (bps == 0x1F) && (channels == 2);
+       escore->can_mpsleep = (rate >= 48) && (bps >= 0x1F) && (channels >= 2);
+
+       dev_dbg(codec->dev, "%s(): ############# Rate %d BPS %d channels %d #############n", __func__,
+               rate, bps, channels);
 
        switch (dai->id) {
        case ES_I2S_PORTA:
@@ -786,10 +1026,33 @@ static int es755_hw_params(struct snd_pcm_substream *substream,
                break;
        }
 
-       if (escore->can_mpsleep || escore->algo_type == DHWPT)
+       if (escore->algo_type == DHWPT || escore->dhwpt_enabled)
                escore->dhwpt_cmd = (ES_DHWPT_CMD << 16) | port_map;
-       else
-               escore->dhwpt_cmd = 0;
+
+
+       /* BAS-3205, if frame size is 64 bits and word length is 16 bits, set
+        * TDM Timeslots Per Frame of PortA to 3  */
+
+
+       if (escore->algo_type != DHWPT && !escore->dhwpt_enabled) {
+               if (64 == (bps + 1)*channels && 0x1F == bps) {
+                       api_access = &escore->api_access[ES_PORT_TDM_SLOTS_PER_FRAME];
+                       api_access->write_msg[0] |=  ES_API_WORD(ES_SET_DEV_PARAM_ID,
+                                       (ES755_PCM_PORT_A << 8));
+
+                       rc = escore_write_locked(escore,
+                                       ES_PORT_TDM_SLOTS_PER_FRAME,
+                                       3);
+                       if (rc) {
+                               pr_err("%s(): Set TDM slots per frame fail %d\n",
+                                               __func__, rc);
+                               return rc;
+                       }
+
+                       api_access->write_msg[0] &= ES_API_WORD(ES_SET_DEV_PARAM_ID,
+                                       0x00ff);
+               }
+       }
 
        dev_dbg(codec->dev, "%s(): params_channels(params) = %d\n", __func__,
                channels);
@@ -954,7 +1217,7 @@ static const struct soc_enum es755_vs_training_mode_enum =
 
 static const char * const es755_vs_training_status_texts[] = {
        "busy", "Success", "Utterance Long", "Utterance Short",
-       "Verification Failed", "Failed Bad length",
+       "Verification Failed", "Failed Bad length", "Noise", "Level too low",
 };
 static const struct soc_enum es755_vs_training_status_enum =
        SOC_ENUM_SINGLE(ES_VOICE_SENSE_TRAINING_STATUS, 0,
@@ -962,8 +1225,7 @@ static const struct soc_enum es755_vs_training_status_enum =
                        es755_vs_training_status_texts);
 
 static const char * const es755_vs_training_record_texts[] = {
-       "Previous Keyword", "Keyword_1", "Keyword_2",
-       "Keyword_3", "Keyword_4", "Keyword_5",
+       "Start_0", "Start_1", "Start_2",
 };
 static const struct soc_enum es755_vs_training_record_enum =
        SOC_ENUM_SINGLE(ES_VOICE_SENSE_TRAINING_RECORD, 0,
@@ -978,6 +1240,15 @@ static const struct soc_enum es755_vs_stored_keyword_enum =
                        ARRAY_SIZE(es755_vs_stored_keyword_texts),
                        es755_vs_stored_keyword_texts);
 
+static const char * const es755_default_cvq_mic_texts[] = {
+       "MIC0", "DMIC0",
+};
+
+static const struct soc_enum es755_default_cvq_mic_enum =
+       SOC_ENUM_SINGLE(SND_SOC_NOPM, 0,
+                       ARRAY_SIZE(es755_default_cvq_mic_texts),
+                       es755_default_cvq_mic_texts);
+
 /* Use for NULL "get" handler */
 static int es755_get_null_control_enum(struct snd_kcontrol *kcontrol,
                                        struct snd_ctl_elem_value *ucontrol)
@@ -986,6 +1257,53 @@ static int es755_get_null_control_enum(struct snd_kcontrol *kcontrol,
        return 0;
 }
 
+static int es755_get_power_saving_mode(struct snd_kcontrol *kcontrol,
+                            struct snd_ctl_elem_value *ucontrol)
+{
+        struct snd_soc_codec *codec = escore_priv.codec;
+        struct escore_priv *escore = snd_soc_codec_get_drvdata(codec);
+
+        ucontrol->value.enumerated.item[0] = escore->power_saving_mode;
+
+       return 0;
+}
+
+static int es755_set_power_saving_mode(struct snd_kcontrol *kcontrol,
+                            struct snd_ctl_elem_value *ucontrol)
+{
+       struct snd_soc_codec *codec = escore_priv.codec;
+       struct escore_priv *escore = snd_soc_codec_get_drvdata(codec);
+
+       mutex_lock(&codec->mutex);
+       /* Value 0 is used to disable Power Level support */
+       escore->power_saving_mode = ucontrol->value.enumerated.item[0];
+       mutex_unlock(&codec->mutex);
+
+       return 0;
+}
+
+static int es755_get_default_cvq_mic_enum(struct snd_kcontrol *kcontrol,
+               struct snd_ctl_elem_value *ucontrol)
+{
+       struct escore_priv *escore = &escore_priv;
+
+       ucontrol->value.enumerated.item[0] = escore->default_cvq_mic;
+
+       return 0;
+}
+
+static int es755_put_default_cvq_mic_enum(struct snd_kcontrol *kcontrol,
+               struct snd_ctl_elem_value *ucontrol)
+{
+       struct escore_priv *escore = &escore_priv;
+
+       escore->default_cvq_mic = ucontrol->value.enumerated.item[0];
+       escore->es_vs_route_preset = es755_vs_presets[escore->default_cvq_mic];
+       escore->es_cvs_preset = es755_cvs_presets[escore->default_cvq_mic];
+
+       return 0;
+}
+
 static struct snd_kcontrol_new es755_voice_sense_snd_controls[] = {
        SOC_ENUM_EXT("Voice Sense Status",
                     es755_vs_event_enum,
@@ -1031,8 +1349,25 @@ static struct snd_kcontrol_new es755_voice_sense_snd_controls[] = {
                       SND_SOC_NOPM, 0, 1, 0,
                       escore_get_vs_sleep,
                       escore_put_vs_sleep),
+       SOC_SINGLE_EXT("VS keyword length",
+                      SND_SOC_NOPM, 0, 65535, 0,
+                      escore_get_vs_keyword_length,
+                      escore_put_vs_keyword_length),
+       SOC_SINGLE_EXT("KW Overrun Error",
+                      0, 0, 65535, 0, escore_get_keyword_overrun,
+                      NULL),
+       SOC_ENUM_EXT("CVQ Default MIC", es755_default_cvq_mic_enum,
+                       es755_get_default_cvq_mic_enum,
+                       es755_put_default_cvq_mic_enum),
+       SOC_SINGLE_EXT("Power Saving Level",
+                       SND_SOC_NOPM, 0, 6, 0,
+                       es755_get_power_saving_mode,
+                       es755_set_power_saving_mode),
+       SOC_SINGLE_EXT("Audio Focus Enable", SND_SOC_NOPM, 0, 1, 0,
+                       escore_get_af_status, escore_put_af_status),
 };
 
+/* This function must be called with access_lock acquired */
 int es755_start_int_osc(void)
 {
        int rc = 0;
@@ -1044,8 +1379,8 @@ int es755_start_int_osc(void)
        rc = escore_write(NULL, ES_VS_INT_OSC_MEASURE_START, 0);
        if (rc) {
                dev_err(escore_priv.dev,
-                       "%s(): OSC Measure Start fail\n",
-                       __func__);
+                       "%s(): OSC Measure Start fail %d\n",
+                       __func__, rc);
                return rc;
        }
 
@@ -1060,8 +1395,8 @@ int es755_start_int_osc(void)
 
                if (rc < 0) {
                        dev_err(escore_priv.dev,
-                               "%s(): OSC Measure Read Status fail\n",
-                               __func__);
+                               "%s(): OSC Measure Read Status fail %d\n",
+                               __func__, rc);
                        break;
                }
                dev_dbg(escore_priv.dev,
@@ -1092,50 +1427,29 @@ int es755_wakeup(void)
        return rc;
 }
 
-int escore_enter_dhwpt(struct escore_priv *escore)
-{
-       int resp;
-       int rc = 0;
-
-       if (!atomic_read(&escore->active_streams)) {
-               pr_debug("%s(): No active streams.\n", __func__);
-               goto out;
-       }
-
-       if (!escore->can_mpsleep) {
-               pr_debug("%s(): Insufficient Clock to enable DHWPT\n",
-                               __func__);
-               rc = -EINVAL;
-               goto out;
-       }
-
-       rc = escore_cmd(escore, escore->dhwpt_cmd, &resp);
-       if (rc < 0)
-               pr_err("%s(): Error %d in sending DHWPT command\n",
-                               __func__, rc);
-out:
-       return rc;
-}
-
-/* Power state transition */
+/* Power state transition:
+ * This function must be called with access_lock acquired */
 int es755_power_transition(int next_power_state,
                                unsigned int set_power_state_cmd)
 {
        int rc = 0;
-       int reconfig_intr = 0;
-
-       dev_info(escore_priv.dev, "%s()\n", __func__);
+       dev_dbg(escore_priv.dev,
+                       "%s(): **** Current state = %d, Next state = %d\n",
+                       __func__, escore_priv.escore_power_state,
+                       next_power_state);
 
        /* Power state transition */
        while (next_power_state != escore_priv.escore_power_state) {
                switch (escore_priv.escore_power_state) {
                case ES_SET_POWER_STATE_SLEEP:
+               case ES_SET_POWER_STATE_DEEP_SLEEP:
+               case ES_SET_POWER_STATE_MP_SLEEP:
                        /* Wakeup Chip */
                        rc = es755_wakeup();
                        if (rc) {
                                dev_err(escore_priv.dev,
-                                       "%s(): es755 wakeup failed\n",
-                                       __func__);
+                                       "%s(): es755 wakeup failed %d\n",
+                                       __func__, rc);
                                goto es755_power_transition_exit;
                        }
                        escore_priv.escore_power_state =
@@ -1146,13 +1460,6 @@ int es755_power_transition(int next_power_state,
                        /* Either switch to Sleep or VS Overlay mode */
                        switch (next_power_state) {
                        case ES_SET_POWER_STATE_MP_SLEEP:
-                               rc = escore_enter_dhwpt(&escore_priv);
-                               if (rc) {
-                                       dev_err(escore_priv.dev,
-                                               "%s(): Failed to enter DHWPT\n",
-                                               __func__);
-                                       goto es755_power_transition_exit;
-                               }
                                escore_priv.escore_power_state =
                                        next_power_state;
                                break;
@@ -1166,36 +1473,52 @@ int es755_power_transition(int next_power_state,
                                        next_power_state;
                                break;
                        }
+                       /* Set flag to Wait for API Interrupt */
+                       escore_set_api_intr_wait(&escore_priv);
+
                        rc = escore_write(NULL, set_power_state_cmd,
                                        escore_priv.escore_power_state);
                        if (rc) {
                                dev_err(escore_priv.dev,
-                                       "%s(): Power state cmd write failed\n",
-                                       __func__);
+                                       "%s(): Power state cmd write fail %d\n",
+                                       __func__, rc);
                                escore_priv.escore_power_state =
                                        ES_SET_POWER_STATE_NORMAL;
                                goto es755_power_transition_exit;
                        }
 
+                       /* Wait for API Interrupt to confirm
+                        * the power transition */
+                       if (escore_priv.pdata->gpioa_gpio != -1) {
+                               rc =
+                               escore_api_intr_wait_completion(&escore_priv);
+                               if (rc)
+                                       goto es755_power_transition_exit;
+                       }
+
                        /* VS fw download */
                        if (escore_priv.escore_power_state ==
                                ES_SET_POWER_STATE_VS_OVERLAY) {
-                               /* wait es755 SBL mode */
-                               msleep(50);
+                               /* wait es755 SBL mode for polling method */
+                               if (escore_priv.pdata->gpioa_gpio == -1)
+                                       msleep(50);
                                rc = escore_vs_load(&escore_priv);
                                if (rc) {
                                        dev_err(escore_priv.dev,
-                                               "%s(): vs fw downlaod failed\n",
-                                               __func__);
+                                               "%s(): vs fw download fail %d\n",
+                                               __func__, rc);
                                        goto es755_power_transition_exit;
                                }
-                       } else {
-                               /* Reset Interrupt mode for sleep */
-                               if (escore_priv.pdata->gpioa_gpio != -1)
-                                       escore_priv.cmd_compl_mode =
-                                                       ES_CMD_COMP_POLL;
                        }
-                       break;
+
+                       if (escore_priv.escore_power_state ==
+                               ES_SET_POWER_STATE_MP_SLEEP) {
+                               /* Diable reference clock in MP_Sleep */
+                               if (escore_priv.pdata->esxxx_clk_cb)
+                                       escore_priv.pdata->esxxx_clk_cb(0);
+                       }
+
+                       break;
 
                case ES_SET_POWER_STATE_VS_OVERLAY:
                        /* Either switch to VS low power or Normal mode */
@@ -1209,47 +1532,51 @@ int es755_power_transition(int next_power_state,
                                        ES_SET_POWER_STATE_VS_LOWPWR;
 
                        } else {
+                               /* Set flag to Wait for API Interrupt */
+                               escore_set_api_intr_wait(&escore_priv);
+
                                escore_priv.escore_power_state =
                                        ES_SET_POWER_STATE_NORMAL;
                                escore_priv.mode = STANDARD;
-                               reconfig_intr = 1;
                        }
 
                        rc = escore_write(NULL, set_power_state_cmd,
                                        escore_priv.escore_power_state);
                        if (rc) {
                                dev_err(escore_priv.dev,
-                                       "%s(): Power state cmd write failed\n",
-                                       __func__);
+                                       "%s(): Power state cmd write fail %d\n",
+                                       __func__, rc);
                                escore_priv.escore_power_state =
                                        ES_SET_POWER_STATE_VS_OVERLAY;
                                goto es755_power_transition_exit;
                        }
 
                        if (escore_priv.escore_power_state ==
-                                       ES_SET_POWER_STATE_VS_LOWPWR)
+                                       ES_SET_POWER_STATE_VS_LOWPWR) {
                                /* Disable the clocks */
                                if (escore_priv.pdata->esxxx_clk_cb)
                                        escore_priv.pdata->esxxx_clk_cb(0);
-
-                       escore_priv.pm_state = ES_PM_ASLEEP;
-
-                       if (reconfig_intr) {
-                               msleep(20);
-                               rc = escore_reconfig_intr(&escore_priv);
-                               if (rc < 0) {
-                                       dev_err(escore_priv.dev,
-                                       "%s(): Interrupt config failed :%d\n",
-                                               __func__, rc);
-                                       goto es755_power_transition_exit;
-                               }
-                       } else {
-                               /* Reset Interrupt mode for low power */
                                if (escore_priv.pdata->gpioa_gpio != -1)
                                        escore_priv.cmd_compl_mode =
                                                        ES_CMD_COMP_POLL;
+                       } else if ((escore_priv.pdata->gpioa_gpio != -1) &&
+                               (escore_priv.escore_power_state ==
+                               ES_SET_POWER_STATE_NORMAL)) {
+                               /* Wait for API Interrupt to confirm
+                                * the power transition */
+                               rc =
+                               escore_api_intr_wait_completion(&escore_priv);
+                               if (rc)
+                                       goto es755_power_transition_exit;
+                               /* Reconfig API Interrupt mode */
+                               rc = escore_reconfig_api_intr(&escore_priv);
+                               if (rc)
+                                       goto es755_power_transition_exit;
+                       } else if (escore_priv.escore_power_state ==
+                               ES_SET_POWER_STATE_NORMAL) {
+                               /* Add delay before power transition */
+                               msleep(escore_priv.delay.vs_to_normal);
                        }
-
                        break;
 
                case ES_SET_POWER_STATE_VS_LOWPWR:
@@ -1257,36 +1584,13 @@ int es755_power_transition(int next_power_state,
                        rc = es755_wakeup();
                        if (rc) {
                                dev_err(escore_priv.dev,
-                                       "%s(): es755 wakeup failed\n",
-                                       __func__);
+                                       "%s(): es755 wakeup fail %d\n",
+                                       __func__, rc);
                                goto es755_power_transition_exit;
                        }
                        escore_priv.escore_power_state =
                                ES_SET_POWER_STATE_VS_OVERLAY;
                        break;
-               case ES_SET_POWER_STATE_MP_SLEEP:
-                       rc = es755_wakeup();
-                       if (rc) {
-                               dev_err(escore_priv.dev,
-                                               "%s(): es755 wakeup failed\n",
-                                               __func__);
-                               goto es755_power_transition_exit;
-                       }
-                       escore_priv.escore_power_state =
-                               ES_SET_POWER_STATE_MP_CMD;
-                       break;
-               case ES_SET_POWER_STATE_MP_CMD:
-                       rc = escore_write(NULL, set_power_state_cmd,
-                                       ES_SET_POWER_STATE_NORMAL);
-                       if (rc) {
-                               dev_err(escore_priv.dev,
-                                       "%s(): Power state cmd write failed\n",
-                                               __func__);
-                               goto es755_power_transition_exit;
-                       }
-                       escore_priv.escore_power_state =
-                               ES_SET_POWER_STATE_NORMAL;
-                       break;
                default:
                        dev_err(escore_priv.dev,
                                "%s(): Unsupported state in es755\n",
@@ -1294,14 +1598,15 @@ int es755_power_transition(int next_power_state,
                        rc = -EINVAL;
                        goto es755_power_transition_exit;
                }
+/*
                dev_dbg(escore_priv.dev,
                        "%s(): Current state = %d, val=%d\n",
                        __func__, escore_priv.escore_power_state,
                        next_power_state);
+*/
        }
 
-       dev_dbg(escore_priv.dev, "%s(): Power state change successful\n",
-               __func__);
+       dev_dbg(escore_priv.dev, "%s(): Power state changed to %d\n", __func__,escore_priv.escore_power_state);
 es755_power_transition_exit:
        return rc;
 }
@@ -1321,8 +1626,10 @@ static int es755_put_power_control_enum(struct snd_kcontrol *kcontrol,
        unsigned int reg = e->reg;
        unsigned int value;
        int rc = 0;
+       struct escore_priv *escore = &escore_priv;
 
        value = ucontrol->value.enumerated.item[0];
+       dev_dbg(escore_priv.dev, "%s(): ***** Put Power state call %d *** \n", __func__,value);
 
        /* Not supported */
        if (!value) {
@@ -1330,21 +1637,52 @@ static int es755_put_power_control_enum(struct snd_kcontrol *kcontrol,
                return -EINVAL;
        }
 
+       mutex_lock(&escore->access_lock);
        rc = escore_pm_get_sync();
        if (rc < 0) {
                dev_err(escore_priv.dev, "%s(): pm_get_sync failed :%d\n",
                                                                __func__, rc);
-               return rc;
+               goto exit;
        }
 
-       rc = es755_power_transition(value, reg);
-       if (rc) {
-               dev_err(escore_priv.dev,
-                               "%s(): es755_power_transition() failed\n",
-                               __func__);
+       if (ES_SET_POWER_STATE_MP_SLEEP == value) {
+               /* If already in DHWPT mode, directly switch to MP_Sleep,
+                * otherwise buffer the MP_Sleep switching to
+                * _es_set_final_route() */
+
+               escore->mp_sleep_requested = 1;
+
+               dev_dbg(escore_priv.dev, "%s(): ***** Can_mpsleep %d MP_sleep requested %d DHWPT mode %d dhwpt_capture_on %d *****\n",
+                                               __func__,escore->can_mpsleep,escore->mp_sleep_requested,escore->dhwpt_mode,escore->dhwpt_capture_on);
+               if (escore->mp_sleep_requested && escore->dhwpt_mode && !escore->dhwpt_capture_on) {
+                       rc = es755_enter_mp_sleep();
+                       if (rc) {
+                               dev_dbg(escore_priv.dev,
+                                               "%s() es755_enter_mp_sleep fail :%d\n",
+                                               __func__, rc);
+                       }
+               } else {
+                       dev_dbg(escore_priv.dev, "%s(): ***** Seem capture is present or no playback started yet, Skip putting in MP_sleep *****\n", __func__);
+               }
+       } else {
+
+               escore->mp_sleep_requested = 0;
+               rc = cancel_delayed_work_sync(&escore->mp_sleep_work);
+               dev_dbg(escore_priv.dev,
+                       "%s() cancel_delayed_work_sync() rc = %d\n",
+                       __func__, rc);
+
+               rc = es755_power_transition(value, reg);
+               if (rc) {
+                       dev_err(escore_priv.dev,
+                               "%s(): es755_power_transition() fail %d\n",
+                               __func__, rc);
+               }
        }
 
        escore_pm_put_autosuspend();
+exit:
+       mutex_unlock(&escore->access_lock);
 
        return rc;
 }
@@ -1360,10 +1698,10 @@ static int es755_put_preset_value(struct snd_kcontrol *kcontrol,
 
        value = ucontrol->value.integer.value[0];
 
-       rc = escore_write(NULL, reg, value);
+       rc = escore_write_locked(NULL, reg, value);
        if (rc) {
-               dev_err(escore_priv.dev, "%s(): Set Preset failed\n",
-                       __func__);
+               dev_err(escore_priv.dev, "%s(): Set Preset fail %d\n",
+                       __func__, rc);
                return rc;
        }
 
@@ -1403,6 +1741,7 @@ static int es755_get_event_status(struct snd_kcontrol *kcontrol,
 
        return 0;
 }
+
 static int es755_put_hs_delay_value(struct snd_kcontrol *kcontrol,
                                        struct snd_ctl_elem_value *ucontrol)
 {
@@ -1424,15 +1763,149 @@ static int es755_get_hs_delay_value(struct snd_kcontrol *kcontrol,
        return 0;
 }
 
-static const char * const es755_vs_power_state_texts[] = {
-       "None", "Sleep", "MP_Sleep", "MP_Cmd", "Normal", "Overlay", "Low_Power",
-       "Codec Deep Sleep"
+static int es755_put_select_endpoint(struct snd_kcontrol *kcontrol,
+                                       struct snd_ctl_elem_value *ucontrol)
+{
+       struct escore_priv *escore = &escore_priv;
+       u32 value = ucontrol->value.enumerated.item[0];
+
+       pr_debug("%s: Select path ID %d.\n", __func__, value);
+
+       /* Only support path ID, endpoint ID is not supported */
+       if (value > ES300_PASSOUT4) {
+               dev_err(escore_priv.dev, "%s(): Incorrect Path ID.\n",
+                       __func__);
+               return -EINVAL;
+       }
+
+       escore->selected_endpoint = value;
+
+       return 0;
+}
+
+static int es755_get_digital_gain(struct snd_kcontrol *kcontrol,
+                                       struct snd_ctl_elem_value *ucontrol)
+{
+       struct escore_priv *escore = &escore_priv;
+
+       ucontrol->value.integer.value[0] = escore->digital_gain[0];
+       return 0;
+}
+
+static int es755_put_digital_gain(struct snd_kcontrol *kcontrol,
+                                       struct snd_ctl_elem_value *ucontrol)
+{
+       struct escore_priv *escore = &escore_priv;
+       struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
+       unsigned int val   = e->values[ucontrol->value.enumerated.item[0]];
+       unsigned int mask  = e->mask;
+
+       pr_debug("%s: Set digital gain 0x%x.\n", __func__, val);
+
+       if ( ucontrol->value.enumerated.item[0] > (e->max - 1) ) {
+               dev_err(escore_priv.dev, "%s(): Enum exceed the maximum!\n",
+                       __func__);
+               return -EINVAL;
+       }
+
+       if (escore->selected_endpoint < ES300_PRI ||
+           escore->selected_endpoint > ES300_PASSOUT4) {
+               dev_err(escore_priv.dev, "%s(): Invalid selected endpoint/pathID!\n",
+                       __func__);
+               return -EINVAL;
+       }
+
+       escore->digital_gain[escore->selected_endpoint] = (u32)val&mask;
+       escore->selected_endpoint = -1;
+
+       return 0;
+}
+
+
+static const char * const es755_path_id_texts[] = {
+       [ES300_PRI] = "PRI", "SEC", "TER", "FEIN", "AECREF", "AUDIN1", "AUDIN2",
+       "RESERVED", "RESERVED",
+       [ES300_UITONE1] = "UITONE1", "UITONE2", "UITONE3", "UITONE4", "PASSIN1",
+       "PASSIN2", "PASSIN3", "PASSIN4", "FEIN2", "RESERVED", "RESERVED", "RESERVED",
+       "RESERVED", "RESERVED", "RESERVED", "RESERVED", "RESERVED", "RESERVED",
+       "RESERVED", "RESERVED", "RESERVED", "RESERVED", "RESERVED",
+       [ES300_CSOUT1] = "CSOUT1", "CSOUT2", "FEOUT1", "FEOUT2", "AUDOUT1", "AUDOUT2",
+       "RESERVED", "RESERVED",
+       [ES300_MONOUT1] = "MONOUT1", "MONOUT2", "MONOUT3", "MONOUT4", "PASSOUT1",
+       "PASSOUT2", "PASSOUT3", "PASSOUT4",
+};
+
+static const struct soc_enum es755_path_id_enum =
+       SOC_ENUM_SINGLE(SND_SOC_NOPM, 0,
+                       ARRAY_SIZE(es755_path_id_texts),
+                       es755_path_id_texts);
+
+static const char * const digital_gain_text[] = {
+       "-90dB", "-89dB", "-88dB", "-87dB", "-86dB",
+       "-85dB", "-84dB", "-83dB", "-82dB", "-81dB",
+       "-80dB", "-79dB", "-78dB", "-77dB", "-76dB",
+       "-75dB", "-74dB", "-73dB", "-72dB", "-71dB",
+       "-70dB", "-69dB", "-68dB", "-67dB", "-66dB",
+       "-65dB", "-64dB", "-63dB", "-62dB", "-61dB",
+       "-60dB", "-59dB", "-58dB", "-57dB", "-56dB",
+       "-55dB", "-54dB", "-53dB", "-52dB", "-51dB",
+       "-50dB", "-49dB", "-48dB", "-47dB", "-46dB",
+       "-45dB", "-44dB", "-43dB", "-42dB", "-41dB",
+       "-40dB", "-39dB", "-38dB", "-37dB", "-36dB",
+       "-35dB", "-34dB", "-33dB", "-32dB", "-31dB",
+       "-30dB", "-29dB", "-28dB", "-27dB", "-26dB",
+       "-25dB", "-24dB", "-23dB", "-22dB", "-21dB",
+       "-20dB", "-19dB", "-18dB", "-17dB", "-16dB",
+       "-15dB", "-14dB", "-13dB", "-12dB", "-11dB",
+       "-10dB", "-9dB", "-8dB", "-7dB", "-6dB",
+       "-5dB", "-4dB", "-3dB", "-2dB", "-1dB",
+       "0dB", "1dB", "2dB", "3dB", "4dB",
+       "5dB", "6dB", "7dB", "8dB", "9dB",
+       "10dB", "11dB", "12dB", "13dB", "14dB",
+       "15dB", "16dB", "17dB", "18dB", "19dB",
+       "20dB", "21dB", "22dB", "23dB", "24dB",
+       "25dB", "26dB", "27dB", "28dB", "29dB",
+       "30dB",
+};
+
+static const unsigned int digital_gain_value[] = {
+       0xA6, 0xA7, 0xA8, 0xA9, 0xAA,
+       0xAB, 0xAC, 0xAD, 0xAE, 0xAF,
+       0xB0, 0xB1, 0xB2, 0xB3, 0xB4,
+       0xB5, 0xB6, 0xB7, 0xB8, 0xB9,
+       0xBA, 0xBB, 0xBC, 0xBD, 0xBE,
+       0xBF, 0xC0, 0xC1, 0xC2, 0xC3,
+       0xC4, 0xC5, 0xC6, 0xC7, 0xC8,
+       0xC9, 0xCA, 0xCB, 0xCC, 0xCD,
+       0xCE, 0xCF, 0xD0, 0xD1, 0xD2,
+       0xD3, 0xD4, 0xD5, 0xD6, 0xD7,
+       0xD8, 0xD9, 0xDA, 0xDB, 0xDC,
+       0xDD, 0xDE, 0xDF, 0xE0, 0xE1,
+       0xE2, 0xE3, 0xE4, 0xE5, 0xE6,
+       0xE7, 0xE8, 0xE9, 0xEA, 0xEB,
+       0xEC, 0xED, 0xEE, 0xEF, 0xF0,
+       0xF1, 0xF2, 0xF3, 0xF4, 0xF5,
+       0xF6, 0xF7, 0xF8, 0xF9, 0xFA,
+       0xFB, 0xFC, 0xFD, 0xFE, 0xFF,
+       0x00, 0x01, 0x02, 0x03, 0x04,
+       0x05, 0x06, 0x07, 0x08, 0x09,
+       0x0A, 0x0B, 0x0C, 0x0D, 0x0E,
+       0x0F, 0x10, 0x11, 0x12, 0x13,
+       0x14, 0x15, 0x16, 0x17, 0x18,
+       0x19, 0x1A, 0x1B, 0x1C, 0x1D,
+       0x1E,
 };
 
-static const struct soc_enum es755_vs_power_state_enum =
+static const struct soc_enum digital_gain_enum =
+       SOC_VALUE_ENUM_SINGLE(SND_SOC_NOPM, 0,
+               ES_DIGITAL_GAIN_MASK, ARRAY_SIZE(digital_gain_text),
+               digital_gain_text,
+               digital_gain_value);
+
+static const struct soc_enum es755_power_state_enum =
        SOC_ENUM_SINGLE(ES_POWER_STATE, 0,
-                       ARRAY_SIZE(es755_vs_power_state_texts),
-                       es755_vs_power_state_texts);
+                       ARRAY_SIZE(es755_power_state_texts),
+                       es755_power_state_texts);
 
 static const char * const es755_runtime_pm_texts[] = {
        "Disable", "Enable"
@@ -1452,7 +1925,7 @@ static const struct soc_enum es755_streaming_mode_enum =
                        es755_streaming_mode_texts);
 
 static struct snd_kcontrol_new es755_snd_controls[] = {
-       SOC_ENUM_EXT("ES755 Power State", es755_vs_power_state_enum,
+       SOC_ENUM_EXT("ES755 Power State", es755_power_state_enum,
                     es755_get_power_control_enum,
                     es755_put_power_control_enum),
        SOC_ENUM_EXT("Runtime PM", es755_runtime_pm_enum,
@@ -1469,21 +1942,92 @@ static struct snd_kcontrol_new es755_snd_controls[] = {
        SOC_ENUM_EXT("Streaming Mode", es755_streaming_mode_enum,
                           escore_get_streaming_mode,
                           escore_put_streaming_mode),
+       SOC_ENUM_EXT("Select Endpoint", es755_path_id_enum,
+                          NULL,
+                          es755_put_select_endpoint),
+       SOC_ENUM_EXT("Set Digital Gain", digital_gain_enum,
+                          es755_get_digital_gain,
+                          es755_put_digital_gain),
        SOC_SINGLE_EXT("HS Delay",
-                      ES_HS_DELAY, 0, 2000, 0, es755_get_hs_delay_value,
+                      SND_SOC_NOPM, 0, 2000, 0, es755_get_hs_delay_value,
                       es755_put_hs_delay_value),
 };
 
 static int es_voice_sense_add_snd_soc_controls(struct snd_soc_codec *codec)
 {
        int ret;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)
        ret = snd_soc_add_codec_controls(codec, es755_voice_sense_snd_controls,
                        ARRAY_SIZE(es755_voice_sense_snd_controls));
+#else
+       ret = snd_soc_add_controls(codec, es755_voice_sense_snd_controls,
+                       ARRAY_SIZE(es755_voice_sense_snd_controls));
+#endif
        return ret;
 }
 
 #endif /* CONFIG_SND_SOC_ES_VS */
 
+static void es755_mp_sleep_work(struct work_struct *work)
+{
+       int rc;
+
+       rc = es755_power_transition(ES_SET_POWER_STATE_MP_SLEEP,
+                                   ES_POWER_STATE);
+       if (rc) {
+               dev_err(escore_priv.dev,
+                       "%s(): es755_power_transition() failed %d\n",
+                       __func__, rc);
+       }
+
+}
+
+int es755_enter_mp_sleep()
+{
+       struct escore_priv *escore = &escore_priv;
+       int ret = 0;
+       int rc  = 0;
+
+       ret = queue_delayed_work(escore->power_transition_wq,
+                                &(escore->mp_sleep_work),
+                                msecs_to_jiffies(ES755_MP_SLEEP_DELAY));
+               dev_dbg(escore->dev, "%s() queue_delayed_work() ret = %d\n",
+                       __func__, ret);
+
+       dev_dbg(escore->dev, "%s() queue_delayed_work() ret = %d\n",
+               __func__, ret);
+       return rc;
+}
+
+int es755_exit_mp_sleep()
+{
+       struct escore_priv *escore = &escore_priv;
+       int rc = 0;
+       int ret = 0;
+
+       rc = cancel_delayed_work_sync(&escore->mp_sleep_work);
+       dev_dbg(escore->dev, "%s() cancel_delayed_work_sync() rc = %d\n",
+               __func__, rc);
+
+       if (escore->escore_power_state == ES_SET_POWER_STATE_MP_SLEEP) {
+
+               dev_dbg(escore->dev,
+                       "%s(): Bring chip from MP Sleep to Normal mode\n",
+                       __func__);
+
+               ret = es755_power_transition(ES_SET_POWER_STATE_NORMAL,
+                                            ES_POWER_STATE);
+               if (ret) {
+                       dev_err(escore->dev,
+                               "%s(): es755_power_transition() failed %d\n",
+                               __func__, ret);
+
+                       return ret;
+               }
+       }
+
+       return ret;
+}
 
 static int es755_set_bias_level(struct snd_soc_codec *codec,
                                      enum snd_soc_bias_level level)
@@ -1493,6 +2037,17 @@ static int es755_set_bias_level(struct snd_soc_codec *codec,
        return 0;
 }
 
+
+static void es755_init_regs(struct escore_priv *es755)
+{
+       int reg_index;
+
+       for (reg_index = 0; reg_index < ES_MAX_REGISTER; reg_index++) {
+               /* Initialize values with invalid values */
+               es755->reg_cache[reg_index].value = ES_INVALID_REG_VALUE;
+       }
+}
+
 static int es755_codec_probe(struct snd_soc_codec *codec)
 {
        int ret;
@@ -1502,40 +2057,49 @@ static int es755_codec_probe(struct snd_soc_codec *codec)
        es755->codec = codec;
 
        codec->control_data = snd_soc_codec_get_drvdata(codec);
+
+       es755_init_regs(es755);
+
        ret = es_d300_add_snd_soc_controls(codec);
        if (ret) {
                dev_err(codec->dev,
-                       "%s(): es_d300_snd_controls failed\n", __func__);
+                       "%s(): es_d300_snd_controls fail %d\n",
+                       __func__, ret);
                return ret;
        }
        ret = es_analog_add_snd_soc_controls(codec);
        if (ret) {
                dev_err(codec->dev,
-                       "%s(): es_analog_snd_controls failed\n", __func__);
+                       "%s(): es_analog_snd_controls fail %d\n",
+                       __func__, ret);
                return ret;
        }
        ret = es_d300_add_snd_soc_dapm_controls(codec);
        if (ret) {
                dev_err(codec->dev,
-                       "%s(): es_d300_dapm_widgets failed\n", __func__);
+                       "%s(): es_d300_dapm_widgets fail %d\n",
+                       __func__, ret);
                return ret;
        }
        ret = es_analog_add_snd_soc_dapm_controls(codec);
        if (ret) {
                dev_err(codec->dev,
-                       "%s(): es_analog_dapm_widgets failed\n", __func__);
+                       "%s(): es_analog_dapm_widgets fail %d\n",
+                       __func__, ret);
                return ret;
        }
        ret = es_d300_add_snd_soc_route_map(codec);
        if (ret) {
                dev_err(codec->dev,
-                       "%s(): es_d300_add_routes failed\n", __func__);
+                       "%s(): es_d300_add_routes fail %d\n",
+                       __func__, ret);
                return ret;
        }
        ret = es_analog_add_snd_soc_route_map(codec);
        if (ret) {
                dev_err(codec->dev,
-                       "%s(): es_analog_add_routes failed\n", __func__);
+                       "%s(): es_analog_add_routes fail %d\n",
+                       __func__, ret);
                return ret;
        }
 
@@ -1543,24 +2107,28 @@ static int es755_codec_probe(struct snd_soc_codec *codec)
        ret = es_voice_sense_add_snd_soc_controls(codec);
        if (ret) {
                dev_err(codec->dev,
-                       "%s(): es755 VS snd control failed\n", __func__);
+                       "%s(): es755 VS snd control fail %d\n",
+                       __func__, ret);
                return ret;
        }
 
        device_set_wakeup_capable(codec->dev, true);
 
-       /* TBD - Need to move this to a ALSA control function */
-       escore_pm_vs_enable(&escore_priv, true);
-
 #endif
 
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)
        ret = snd_soc_add_codec_controls(codec, es755_snd_controls,
                        ARRAY_SIZE(es755_snd_controls));
+#else
+       ret = snd_soc_add_controls(codec, es755_snd_controls,
+                       ARRAY_SIZE(es755_snd_controls));
+#endif
 
        ret = es_d300_fill_cmdcache(escore_priv.codec);
        if (ret) {
                dev_err(codec->dev,
-                       "%s(): Cache initialization failed\n", __func__);
+                       "%s(): Cache initialization fail %d\n",
+                       __func__, ret);
                return ret;
        }
 
@@ -1579,164 +2147,129 @@ static unsigned int es755_codec_read(struct snd_soc_codec *codec,
                                unsigned int reg)
 {
        struct escore_priv *escore = &escore_priv;
-       struct escore_api_access *api_access;
-       u32 cmd;
-       u32 resp;
-       unsigned int msg_len;
+       u32 value = 0;
        int rc;
-       u8 state_changed = 0;
+       int ret = 0;
 
+       pr_debug("%s()\n", __func__);
        if (reg > ES_MAX_REGISTER) {
                /*dev_err(codec->dev, "read out of range reg %d", reg);*/
                return 0;
        }
 
-       if (!escore->reg_cache[reg].is_volatile)
-               return escore->reg_cache[reg].value & 0xff;
+       if (escore->reg_cache[reg].value != ES_INVALID_REG_VALUE) {
+               value = escore->reg_cache[reg].value;
+               return value;
+       }
 
-       if (escore->can_mpsleep &&
-               escore->escore_power_state == ES_SET_POWER_STATE_MP_SLEEP) {
+       mutex_lock(&escore->access_lock);
 
-               /* Bring the chip to normal state before sending any analog
-                * commands*/
-               pr_debug("%s(): Bring chip into normal mode\n", __func__);
-               rc = es755_power_transition(ES_SET_POWER_STATE_NORMAL,
-                               ES_POWER_STATE);
+       if (escore->dhwpt_mode) {
+               /* Bring the chip from MP Sleep to normal state before
+                * sending any analog commands*/
+               rc = es755_exit_mp_sleep();
                if (rc) {
-                       dev_err(escore_priv.dev,
-                               "%s(): es755_power_transition() failed\n",
-                               __func__);
+                       dev_err(codec->dev,
+                       "%s(): es755_exit_mp_sleep() fail %d\n",
+                       __func__, rc);
                        goto out;
                }
-
-               state_changed = 1;
-               msleep(20);
        }
 
-       api_access = &escore->api_access[ES_CODEC_VALUE];
-       msg_len = api_access->read_msg_len;
-       memcpy((char *)&cmd, (char *)api_access->read_msg, msg_len);
+       ret = escore_write(codec, ES_CODEC_ADDR, reg);
+       if (ret < 0) {
+               dev_err(codec->dev, "codec reg %x write err %d\n",
+                       reg, ret);
+               goto out;
+       }
 
-       rc = escore_cmd(escore, cmd | reg<<8, &resp);
-       if (rc < 0) {
-               dev_err(codec->dev, "codec reg read err %d()", rc);
+       value = escore_read(NULL, ES_CODEC_VALUE);
+       rc = value;
+       if (value < 0) {
+               pr_err("%s(): ES_CODEC_VALUE read fail %d\n", __func__, rc);
                goto out;
        }
-       cmd = escore->bus.last_response;
+       escore->reg_cache[reg].value = value;
 
-       if (state_changed) {
-               msleep(20);
+       dev_dbg(escore_priv.dev, "%s(): ***** Can_mpsleep %d MP_sleep requested %d DHWPT mode %d dhwpt_capture_on %d *****\n",
+                       __func__,escore->can_mpsleep,escore->mp_sleep_requested,escore->dhwpt_mode,escore->dhwpt_capture_on);
+       if (escore->mp_sleep_requested && escore->dhwpt_mode && !escore->dhwpt_capture_on && escore->acc_det_status != ES_ACC_BUTTON_PRESSED) {
                pr_debug("%s(): Put chip back into mp_sleep\n", __func__);
-               rc = es755_power_transition(ES_SET_POWER_STATE_MP_SLEEP,
-                               ES_POWER_STATE);
-               if (rc) {
-                       dev_err(escore_priv.dev,
-                               "%s(): es755_power_transition() failed\n",
-                               __func__);
-               }
+               es755_enter_mp_sleep();
        }
 out:
-       return (rc < 0) ? rc : (cmd & 0xff);
+       mutex_unlock(&escore->access_lock);
+       return (rc < 0) ? rc : value;
 
 }
 
 static int es755_codec_write(struct snd_soc_codec *codec, unsigned int reg,
        unsigned int value)
 {
-       u32 resp;
-       u32 cmd;
        struct escore_priv *escore = &escore_priv;
+       u32 resp;
        int ret = 0;
-       u8 state_changed = 0;
-       u32 sync_cmd = (ES_SYNC_CMD << 16) | ES_SYNC_POLLING;
-       u32 sync_ack;
+       pr_debug("%s()\n", __func__);
 
        if (reg > ES_MAX_REGISTER) {
                /*dev_err(codec->dev, "write out of range reg %d", reg);*/
                return 0;
        }
 
-       if (escore->can_mpsleep &&
-               escore->escore_power_state == ES_SET_POWER_STATE_MP_SLEEP) {
+       mutex_lock(&escore->access_lock);
 
-               /* Bring the chip to normal state before sending any analog
-                * commands*/
-               pr_debug("%s(): Bring chip into normal mode\n", __func__);
-               ret = es755_power_transition(ES_SET_POWER_STATE_NORMAL,
-                               ES_POWER_STATE);
+       if (escore->dhwpt_mode) {
+               /* Bring the chip from MP Sleep to normal state before
+                * sending any analog commands*/
+               ret = es755_exit_mp_sleep();
                if (ret) {
-                       dev_err(escore_priv.dev,
-                               "%s(): es755_power_transition() failed\n",
-                               __func__);
+                       dev_err(codec->dev,
+                               "%s(): es755_exit_mp_sleep() fail %d\n",
+                               __func__, ret);
                        goto out;
                }
-
-               state_changed = 1;
-
-               /* Sleep is added after some observations where chip was
-                * failing to response some command sent quickly.
-                * For example, bringing chip to normal state from mp_sleep
-                * and set the gains very quickly results in failure of
-                * response.
-                */
-               msleep(20);
        }
 
        if (atomic_read(&escore->active_streams) > 0)
+       {
                usleep_range(1000, 1005);
+       }
 
-       ret = escore_write(codec, ES_CODEC_VALUE, reg<<8 | value);
+       ret = escore_write(codec, ES_CODEC_ADDR, reg);
        if (ret < 0) {
-               dev_err(codec->dev, "codec reg %x write err %d\n",
+               dev_err(codec->dev, "codec ES_CODEC_ADDR, %x write err %d\n",
                        reg, ret);
                goto out;
        }
 
-       if (reg == ES_HP_L_GAIN) {
-               ret = escore_cmd(escore, sync_cmd, &sync_ack);
-               if (ret < 0) {
-                       pr_err("%s(): firmware load failed sync write\n",
-                               __func__);
-                       goto out;
-               }
-       }
-       if (reg == ES_HP_R_GAIN) {
-               ret = escore_cmd(escore, sync_cmd, &sync_ack);
-               if (ret < 0) {
-                       pr_err("%s(): firmware load failed sync write\n",
-                               __func__);
-                       goto out;
-               }
+       ret = escore_write(codec, ES_CODEC_VALUE, value);
+       if (ret < 0) {
+               dev_err(codec->dev, "codec ES_CODEC_VALUE, %x write err %d\n",
+                       reg, ret);
+               goto out;
        }
        escore->reg_cache[reg].value = value;
 
-       if (escore->algo_type == DHWPT && reg == ES_HP_L_CTRL) {
-               if (value & 1) {
-                       cmd = escore->dhwpt_cmd;
-                       ret = escore->bus.ops.cmd(escore, cmd, &resp);
-                       if (ret < 0) {
-                               pr_err("%s(): Error %d in setting event response\n",
-                                               __func__, ret);
-                               goto out;
-                       }
-               }
-       }
-
-       if (state_changed) {
-               msleep(20);
+       dev_dbg(escore_priv.dev, "%s(): ***** Can_mpsleep %d MP_sleep requested %d DHWPT mode %d dhwpt_capture_on %d *****\n",
+                       __func__,escore->can_mpsleep,escore->mp_sleep_requested,escore->dhwpt_mode,escore->dhwpt_capture_on);
+       if (escore->mp_sleep_requested && escore->dhwpt_mode && !escore->dhwpt_capture_on && escore->acc_det_status != ES_ACC_BUTTON_PRESSED) {
                pr_debug("%s(): Put chip back into mp_sleep\n", __func__);
-               ret = es755_power_transition(ES_SET_POWER_STATE_MP_SLEEP,
-                               ES_POWER_STATE);
-               if (ret) {
-                       dev_err(escore_priv.dev,
-                               "%s(): es755_power_transition() failed\n",
-                               __func__);
-               }
+               es755_enter_mp_sleep();
        }
 out:
+       mutex_unlock(&escore->access_lock);
        return ret;
 }
 
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)
+struct snd_soc_codec_driver soc_codec_dev_es755 = {
+       .probe =        es755_codec_probe,
+       .remove =       es755_codec_remove,
+       .read =         es755_codec_read,
+       .write =        es755_codec_write,
+       .set_bias_level =       es755_set_bias_level,
+};
+#else
 struct snd_soc_codec_driver soc_codec_dev_es755 = {
        .probe =        es755_codec_probe,
        .remove =       es755_codec_remove,
@@ -1744,18 +2277,19 @@ struct snd_soc_codec_driver soc_codec_dev_es755 = {
        .write =        es755_codec_write,
        .set_bias_level =       es755_set_bias_level,
 };
+#endif
 
 int es755_set_streaming(struct escore_priv *escore, int value)
 {
        u32 resp;
-       return escore_cmd(escore,
+       return escore_cmd_locked(escore,
                es755_streaming_cmds[escore->streamdev.intf] | value, &resp);
 }
 
 int es755_set_datalogging(struct escore_priv *escore, int value)
 {
        u32 resp;
-       return escore_cmd(escore, value, &resp);
+       return escore_cmd_locked(escore, value, &resp);
 }
 
 void es755_slim_setup(struct escore_priv *escore_priv)
@@ -1804,6 +2338,42 @@ void es755_slim_setup(struct escore_priv *escore_priv)
        escore_priv->slim_dai_data[DAI_INDEX(ES_SLIM_3_CAP)].ch_num[1] = 144;
 }
 
+static int es755_disable_codec_irq(struct escore_priv *escore)
+{
+       u32 cmd;
+       u32 resp;
+       int rc;
+
+       /* Disable interrupt Mask */
+       cmd = (ES_SET_INT_MASK << 16) | ES_DISABLE_CODEC_INT;
+       rc = escore_cmd_locked(escore, cmd, &resp);
+       if (rc < 0)
+               dev_err(escore->dev,
+                       "%s(): Error %d in setting interrupt mask\n",
+                       __func__, rc);
+       else
+               disable_irq_nosync(gpio_to_irq(escore_priv.pdata->gpiob_gpio));
+       return rc;
+}
+
+static int es755_enable_codec_irq(struct escore_priv *escore)
+{
+       u32 cmd;
+       u32 resp;
+       int rc;
+
+       enable_irq(gpio_to_irq(escore_priv.pdata->gpiob_gpio));
+
+       /* Enable interrupt Mask */
+       cmd = (ES_SET_INT_MASK << 16) | ES_ENABLE_CODEC_INT;
+       rc = escore_cmd_locked(escore, cmd, &resp);
+       if (rc < 0)
+               dev_err(escore->dev,
+                       "%s(): Error %d in setting interrupt mask\n",
+                       __func__, rc);
+       return rc;
+}
+
 static int es755_config_jack(struct escore_priv *escore)
 {
        struct esxxx_accdet_config *accdet_cfg = &escore->pdata->accdet_cfg;
@@ -1814,7 +2384,7 @@ static int es755_config_jack(struct escore_priv *escore)
 
        /* Setup the Event response */
        cmd = (ES_SET_EVENT_RESP << 16) | escore->pdata->gpio_b_irq_type;
-       rc = escore->bus.ops.cmd(escore, cmd, &resp);
+       rc = escore_cmd_nopm(escore, cmd, &resp);
        if (rc < 0) {
                pr_err("%s(): Error %d in setting event response\n",
                                __func__, rc);
@@ -1827,7 +2397,7 @@ static int es755_config_jack(struct escore_priv *escore)
 
        /* Setup the debounce timer for plug event */
        cmd = (ES_ACCDET_CONFIG_CMD << 16) | (accdet_reg.value);
-       rc = escore->bus.ops.cmd(escore, cmd, &resp);
+       rc = escore_cmd_nopm(escore, cmd, &resp);
        if (rc < 0)
                pr_err("%s(): Error %d in setting debounce timer\n",
                                __func__, rc);
@@ -1841,13 +2411,13 @@ int es755_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack)
        struct escore_priv *escore = snd_soc_codec_get_drvdata(codec);
        int rc;
 
+       mutex_lock(&escore->access_lock);
        rc = escore_pm_get_sync();
        if (rc > -1) {
-               mutex_lock(&escore->api_mutex);
                rc = es755_config_jack(escore);
-               mutex_unlock(&escore->api_mutex);
                escore_pm_put_autosuspend();
        }
+       mutex_unlock(&escore->access_lock);
 
        if (rc >= 0)
                escore->jack = jack;
@@ -1856,26 +2426,19 @@ int es755_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack)
 }
 EXPORT_SYMBOL_GPL(es755_detect);
 
+
 static struct esxxx_platform_data *es755_populate_dt_pdata(struct device *dev)
 {
        struct esxxx_platform_data *pdata;
        struct property *prop;
-       struct es755_btn_cfg  *es755_btn_cfg;
-
        u8 *temp;
+
        pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
        if (!pdata) {
                dev_err(dev, "could not allocate memory for platform data\n");
                return NULL;
        }
 
-       es755_btn_cfg = devm_kzalloc(dev, sizeof(*es755_btn_cfg), GFP_KERNEL);
-       if (!es755_btn_cfg) {
-               dev_err(dev, "could not allocate memory for es755_btn_cfg\n");
-               return NULL;
-       }
-
-       pdata->priv = (struct es755_btn_cfg *)es755_btn_cfg;
        pdata->reset_gpio = of_get_named_gpio(dev->of_node,
                        "adnc,reset-gpio", 0);
        if (pdata->reset_gpio < 0) {
@@ -1898,7 +2461,7 @@ static struct esxxx_platform_data *es755_populate_dt_pdata(struct device *dev)
        pdata->uart_gpio = of_get_named_gpio(dev->of_node,
                        "adnc,int-gpio", 0);
        if (pdata->uart_gpio < 0) {
-               dev_dbg(dev, "Looking up %s property in node %s failed %d\n",
+               dev_err(dev, "Looking up %s property in node %s failed %d\n",
                                "adnc,uart-gpio", dev->of_node->full_name,
                                pdata->uart_gpio);
                pdata->uart_gpio = -1;
@@ -1946,72 +2509,6 @@ static struct esxxx_platform_data *es755_populate_dt_pdata(struct device *dev)
                        pdata->ext_clk_rate = temp[3];
        }
 
-       prop = of_find_property(dev->of_node, "adnc,btn_press_settling_time",
-                       NULL);
-       if (prop != NULL) {
-               temp = (u8 *)prop->value;
-               if (temp[3] != 0)
-                       es755_btn_cfg->btn_press_settling_time = temp[3];
-       }
-
-       prop = of_find_property(dev->of_node, "adnc,btn_press_polling_rate",
-                       NULL);
-       if (prop != NULL) {
-               temp = (u8 *)prop->value;
-               if (temp[3] != 0)
-                       es755_btn_cfg->btn_press_polling_rate = temp[3];
-       }
-
-       prop = of_find_property(dev->of_node, "adnc,btn_press_det_act", NULL);
-       if (prop != NULL) {
-               temp = (u8 *)prop->value;
-               if (temp[3] != 0)
-                       es755_btn_cfg->btn_press_det_act = temp[3];
-       }
-
-       prop = of_find_property(dev->of_node, "adnc,double_btn_timer", NULL);
-       if (prop != NULL) {
-               temp = (u8 *)prop->value;
-               if (temp[3] != 0)
-                       es755_btn_cfg->double_btn_timer = temp[3];
-       }
-
-       prop = of_find_property(dev->of_node, "adnc,mic_det_settling_timer",
-                       NULL);
-       if (prop != NULL) {
-               temp = (u8 *)prop->value;
-               if (temp[3] != 0)
-                       es755_btn_cfg->mic_det_settling_timer = temp[3];
-       }
-
-       prop = of_find_property(dev->of_node, "adnc,long_btn_timer", NULL);
-       if (prop != NULL) {
-               temp = (u8 *)prop->value;
-               if (temp[3] != 0)
-                       es755_btn_cfg->long_btn_timer = temp[3];
-       }
-
-       prop = of_find_property(dev->of_node, "adnc,adc_btn_mute", NULL);
-       if (prop != NULL) {
-               temp = (u8 *)prop->value;
-               if (temp[3] != 0)
-                       es755_btn_cfg->adc_btn_mute = temp[3];
-       }
-
-       prop = of_find_property(dev->of_node, "adnc,valid_levels", NULL);
-       if (prop != NULL) {
-               temp =  (u8 *)prop->value;
-               if (temp[3] != 0)
-                       es755_btn_cfg->valid_levels = temp[3];
-       }
-
-       prop = of_find_property(dev->of_node, "adnc,impd_det_timer", NULL);
-       if (prop != NULL) {
-               temp = (u8 *)prop->value;
-               if (temp[3] != 0)
-                       es755_btn_cfg->impd_det_timer = temp[3];
-       }
-
        prop = of_find_property(dev->of_node, "adnc,gpio_b_irq_type", NULL);
        if (prop != NULL) {
                temp = (u8 *)prop->value;
@@ -2040,12 +2537,24 @@ static struct esxxx_platform_data *es755_populate_dt_pdata(struct device *dev)
                        pdata->accdet_cfg.mic_det_enabled = temp[3];
        }
 
+/*
+       prop = of_find_property(dev->of_node, "adnc,hs_mg_select", NULL);
+       if (prop != NULL) {
+               temp = (u8 *)prop->value;
+               if (temp[3] != 0)
+                       pdata->accdet_cfg.hs_mg_select = temp[3];
+       }
+*/
+       pdata->accdet_cfg.hs_mg_select = 2;
+
+
        prop = of_find_property(dev->of_node, "adnc,cmd_comp_mode", NULL);
        if (prop != NULL) {
                temp = (u8 *)prop->value;
                if (temp[3] != 0)
                        pdata->cmd_comp_mode = temp[3];
        }
+
 /*TODO:Acce detect GPIO*/
        /*
 pdata->gpiob_gpio = of_get_named_gpio(dev->of_node,
@@ -2064,7 +2573,7 @@ pdata->gpiob_gpio = of_get_named_gpio(dev->of_node,
        codec_clk = clk_get(dev, "es755-mclk");
 #endif
        if (IS_ERR(codec_clk)) {
-               dev_dbg(dev, "%s: Failed to request es755 mclk from pmic %ld\n",
+               dev_err(dev, "%s: Failed to request es755 mclk from pmic %ld\n",
                                __func__, PTR_ERR(codec_clk));
                pdata->esxxx_clk_cb = NULL;
        } else {
@@ -2087,194 +2596,215 @@ static int es755_mic_config(struct escore_priv *escore)
        accdet_reg.fields.mic_det_fsm = 1;
        accdet_reg.fields.plug_det_fsm = accdet_cfg.plug_det_enabled & (0x1);
        accdet_reg.fields.debounce_timer = accdet_cfg.debounce_timer & (0x3);
-
-       /* This allows detection of both type of headsets: LRGM and LRMG */
-       /*accdet_reg.fields.mg_sel_force = accdet_cfg.mic_det_enabled & (0x1);*/
-       /* No need to set mg_sel_force bit for LRGM/LRMG detection*/
+       /*
+        * BAS-3584: As per updated accessory detection logic, always set
+        * mg_sel_force bit to 1 and mg_select bits as per required
+        * configuration - LRGM: 0, LRMG: 1, Both: 2
+        * */
+       accdet_reg.fields.mg_sel_force = 1;
+       accdet_reg.fields.mg_select = accdet_cfg.hs_mg_select;
 
        pr_debug("%s()\n", __func__);
 
-       return escore_write(codec, ES_ACCDET_CONFIG, accdet_reg.value);
+       return escore_write_locked(codec, ES_ACCDET_CONFIG, accdet_reg.value);
 }
 
-static int es755_button_config(struct escore_priv *escore)
-{
-       struct esxxx_platform_data *pdata = escore->pdata;
-       struct es755_btn_cfg *btn_cfg;
-       union es755_btn_ctl1 btn_ctl1;
-       union es755_btn_ctl2 btn_ctl2;
-       union es755_btn_ctl3 btn_ctl3;
-       union es755_btn_ctl4 btn_ctl4;
-       u8 invalid = (u8) -1;
-       u8 update = 0;
-       int rc = 0;
+static int es755_button_config(struct escore_priv *escore)
+{
+       union es755_btn_ctl1 btn_ctl1;
+       int rc = 0;
+
+       btn_ctl1.value = 0;
+       /* Enable Button Press Detection */
+       btn_ctl1.fields.btn_press_det = ES_BTN_DET_EN;
+       mutex_lock(&escore->access_lock);
+
+       /* Read default value */
+       rc = escore_read(NULL, ES_BUTTON_CTRL1);
+       if (rc < 0) {
+               dev_err(escore_priv.dev,
+                       "%s(): ES_BUTTON_CTRL Read fail %d\n",
+                       __func__, rc);
+               goto btn_cfg_exit;
+       }
+
+       /* Enable btn_press_det bit */
+       btn_ctl1.value |= rc;
+
+       /* Write updated value with Button Press Detection enabled */
+       rc = escore_write(NULL, ES_BUTTON_CTRL1, btn_ctl1.value);
+       if (rc < 0)
+               pr_err("%s(): Error setting button control 1 %d\n",
+                      __func__, rc);
+btn_cfg_exit:
+       mutex_unlock(&escore->access_lock);
+       return rc;
+
+}
+
+static int chk_btn_press_event(
+       struct escore_priv *escore, int sys_intr_resp)
+{
+       int rc = 0, value;
+       union es755_accdet_status_reg accdet_status_reg;
+
+       if (ES_BUTTON_PRESS_EVENT(sys_intr_resp)) {
+               pr_debug("%s(): Button press event\n", __func__);
+
+               /*
+                * Due to FW constraint, wait for 65ms before Button
+                * Detection
+                */
+               msleep(65);
+
+               value = escore_read_locked(NULL, ES_GET_ACCDET_STATUS);
+               if (value < 0) {
+                       pr_err("%s(): Accessory detect status fail %d\n",
+                              __func__, value);
+                       rc = value;
+                       goto err_exit;
+               }
 
-       btn_cfg = (struct es755_btn_cfg *)pdata->priv;
+               accdet_status_reg.value = value;
 
-       btn_ctl1.value = 0;
-       btn_ctl2.value = 0;
-       btn_ctl3.value = 0;
-       btn_ctl4.value = 0;
+               pr_debug("Impd:%d\n", accdet_status_reg.fields.impd_level);
 
-       /* Config for Button Control 1 */
+               switch (accdet_status_reg.fields.impd_level) {
+#if defined(CONFIG_SND_SOC_ES854) || defined(CONFIG_SND_SOC_ES857)
+               case 0:
+                       snd_soc_jack_report(escore->jack,
+                                           SND_JACK_BTN_0, SND_JACK_BTN_0);
+                       escore->acc_btn_pressed = SND_JACK_BTN_0;
+                       pr_info("%s(): Button-0 Press event\n", __func__);
+                       break;
 
-       rc = escore_read(NULL, ES_BUTTON_CTRL1);
-       if (rc < 0) {
-               pr_err("%s(): Error reading button control 1\n",
-                               __func__);
-               goto btn_cfg_exit;
-       }
-       btn_ctl1.value = rc;
+               case 1:
+                       /* BTN_3 is mapped with IMPD_LEVEL 1 to support
+                        * Google Voice Search trigger functionality */
+                       snd_soc_jack_report(escore->jack,
+                                           SND_JACK_BTN_3, SND_JACK_BTN_3);
+                       escore->acc_btn_pressed = SND_JACK_BTN_3;
+                       pr_info("%s(): Button-3 Press event\n", __func__);
+                       break;
+#else
+               case 0:
+               case 1:
+                       snd_soc_jack_report(escore->jack,
+                                           SND_JACK_BTN_0, SND_JACK_BTN_0);
+                       escore->acc_btn_pressed = SND_JACK_BTN_0;
+                       pr_info("%s(): Button-0 Press event\n", __func__);
+                       break;
+#endif
 
-       if (btn_cfg->btn_press_settling_time != invalid) {
-               btn_ctl1.fields.btn_press_settling_time =
-                       (btn_cfg->btn_press_settling_time & 0x7);
-               update = 1;
-       }
-       if (btn_cfg->btn_press_polling_rate != invalid) {
-               btn_ctl1.fields.btn_press_polling_rate =
-                       (btn_cfg->btn_press_polling_rate & 0x3);
-               update = 1;
-       }
-       if (btn_cfg->btn_press_det_act != invalid) {
-               btn_ctl1.fields.btn_press_det =
-                       (btn_cfg->btn_press_det_act & 0x1);
-               update = 1;
-       }
+               case 2:
+                       snd_soc_jack_report(escore->jack,
+                                           SND_JACK_BTN_1, SND_JACK_BTN_1);
+                       escore->acc_btn_pressed = SND_JACK_BTN_1;
+                       pr_info("%s(): Button-1 Press event\n", __func__);
+                       break;
 
-       pr_debug("%s() button value: %x", __func__, btn_ctl1.value);
+               case 3:
+                       snd_soc_jack_report(escore->jack,
+                                           SND_JACK_BTN_2, SND_JACK_BTN_2);
+                       escore->acc_btn_pressed = SND_JACK_BTN_2;
+                       pr_info("%s(): Button-2 Press event\n", __func__);
+                       break;
 
-       if (update) {
-               rc = escore_write(NULL, ES_BUTTON_CTRL1, btn_ctl1.value);
-               if (rc < 0) {
-                       pr_err("%s(): Error setting button control 1\n",
-                                       __func__);
-                       goto btn_cfg_exit;
-               }
-               update = 0;
-       }
-       /* Leave Button Ctrl2, 3 and 4 as default value in firwmare */
-       /* Config for Button Control 2 */
-       /*if (btn_cfg->double_btn_timer != invalid) {
-               btn_ctl2.fields.double_btn_timer =
-                       (btn_cfg->double_btn_timer & 0xf);
-               update = 1;
-       }
-       if (btn_cfg->mic_det_settling_timer != invalid) {
-               btn_ctl2.fields.mic_det_settling_timer =
-                       (btn_cfg->mic_det_settling_timer & 0x3);
-               update = 1;
-       }
-       if (update) {
-               rc = escore_write(NULL, ES_BUTTON_CTRL2, btn_ctl2.value);
-               if (rc < 0) {
-                       pr_err("%s(): Error setting button control 2\n",
-                                       __func__);
-                       goto btn_cfg_exit;
-               }
-               update = 0;
-       }*/
-
-       /* Config for Button Control 3 */
-       /*if (btn_cfg->long_btn_timer != invalid) {
-               btn_ctl3.fields.long_btn_timer =
-                       (btn_cfg->long_btn_timer & 0xf);
-               update = 1;
-       }
-       if (btn_cfg->adc_btn_mute != invalid) {
-               btn_ctl3.fields.adc_btn_mute =
-                       (btn_cfg->adc_btn_mute & 0x1);
-               update = 1;
-       }
-       if (update) {
-               rc = escore_write(NULL, ES_BUTTON_CTRL3, btn_ctl3.value);
-               if (rc < 0) {
-                       pr_err("%s(): Error setting button control 3\n",
-                                       __func__);
-                       goto btn_cfg_exit;
+               default:
+                       escore->acc_btn_pressed = ES_ACC_BTN_INVALID;
+                       pr_err("Invalid button type : %d\n",
+                              accdet_status_reg.fields.impd_level);
+                       break;
                }
-               update = 0;
-       }*/
-
-       /* Config for Button Control 4 */
-       /*if (btn_cfg->valid_levels != invalid) {
-               btn_ctl4.fields.valid_levels =
-                       (btn_cfg->valid_levels & 0x3f);
-               update = 1;
-       }
-       if (btn_cfg->impd_det_timer != invalid) {
-               btn_ctl4.fields.impd_det_timer =
-                       (btn_cfg->impd_det_timer & 0x3);
-               update = 1;
-       }
-       if (update) {
-               rc = escore_write(NULL, ES_BUTTON_CTRL4, btn_ctl4.value);
-               if (rc < 0) {
-                       pr_err("%s(): Error setting button control 4\n",
-                                       __func__);
-                       goto btn_cfg_exit;
+
+               /* Avoid chip suspend when button is still pressed */
+               if (escore->acc_det_status != ES_ACC_BUTTON_PRESSED) {
+                       rc = escore_pm_get_sync();
+                       if (rc < 0) {
+                               pr_err("%s(): pm_get_sync failed :%d\n",
+                                               __func__, rc);
+                               goto err_exit;
+                       }
+                       escore->acc_det_status = ES_ACC_BUTTON_PRESSED;
                }
-               update = 0;
-       }*/
+       }
 
-btn_cfg_exit:
+err_exit:
        return rc;
-
 }
 
-static int es755_recover_wakeup_failure(struct escore_priv *es755)
+static int chk_btn_release_event(
+       struct escore_priv *escore, int sys_intr_resp)
 {
-       int rc;
+       int rc = 0;
 
-       rc = es755_config_jack(es755);
-       if (rc)
-               pr_err("%s Failed to configure jack detection\n", __func__);
-       return rc;
-}
+       if (ES_BUTTON_RELEASE_EVENT(sys_intr_resp)) {
+               pr_debug("%s(): Button release event\n", __func__);
 
-/* Notifier callback to configure the Interrupts:
- * It gets called in two conditions,
- * 1) Any interrupt arrived when the chip was suspended
- * 2) Chip woke up as a part of system resume.
- */
-static int es755_codec_reconfig_intr(struct notifier_block *self,
-               unsigned long action, void *dev)
-{
-       struct escore_priv *escore = (struct escore_priv *)dev;
-       int rc;
+               /*
+                * If user presses button for more than autosuspend
+                * time, firmware should not be put into suspend mode
+                * until button is released OR it is unplugged.
+                * Put the chip back to autosuspend when user releases
+                * the button.
+                */
+               if (escore->acc_det_status == ES_ACC_BUTTON_PRESSED) {
+                       escore_pm_put_autosuspend();
+                       if (escore->mp_sleep_requested && escore->dhwpt_mode && !escore->dhwpt_capture_on) {
+                               pr_debug("%s(): Put chip back into mp_sleep\n", __func__);
+                               es755_enter_mp_sleep();
+                       }
+               }
 
-       pr_debug("%s(): Event: 0x%04x\n", __func__, (u32)action);
+               pr_debug("button type : %d\n", escore->acc_btn_pressed);
 
-       if (((action & 0xFF) == ES_RECONFIG_INTR_EVENT) ||
-               (escore->escore_power_state == ES_SET_POWER_STATE_NORMAL
-               && escore->defer_intr_config)) {
+               switch (escore->acc_btn_pressed) {
+               case SND_JACK_BTN_0:
+                       /* Button release event must be sent */
+                       snd_soc_jack_report(escore->jack, 0, SND_JACK_BTN_0);
 
-               escore->defer_intr_config = 0;
+                       pr_info("%s(): Button-0 release event\n", __func__);
+                       break;
 
-               mutex_lock(&escore->api_mutex);
-               rc = escore_reconfig_intr(escore);
-               if (rc < 0) {
-                       pr_err("%s(): Reconfig interrupt failed: %d\n",
-                                       __func__, rc);
-                       mutex_unlock(&escore->api_mutex);
-                       goto out;
+               case SND_JACK_BTN_1:
+                       /* Button release event must be sent */
+                       snd_soc_jack_report(escore->jack, 0, SND_JACK_BTN_1);
+                       pr_info("%s(): Button-1 release event\n", __func__);
+                       break;
+
+               case SND_JACK_BTN_2:
+                       /* Button release event must be sent */
+                       snd_soc_jack_report(escore->jack, 0, SND_JACK_BTN_2);
+                       pr_info("%s(): Button-2 release event\n", __func__);
+                       break;
+
+               case SND_JACK_BTN_3:
+                       /* Button release event must be sent */
+                       snd_soc_jack_report(escore->jack, 0, SND_JACK_BTN_3);
+                       pr_info("%s(): Button-3 release event\n", __func__);
+                       break;
+
+               case ES_ACC_BTN_INVALID:
+               default:
+                       pr_err("Invalid button type : %d\n",
+                              escore->acc_btn_pressed);
+                       break;
                }
-               mutex_unlock(&escore->api_mutex);
 
-               if (escore->button_config_required)
-                       es755_button_config(escore);
+               escore->acc_det_status = ES_ACC_BUTTON_RELEASED;
+
        }
-out:
-       return NOTIFY_OK;
-}
+
+       return rc;
+};
 
 static int es755_codec_intr(struct notifier_block *self, unsigned long action,
                void *dev)
 {
        struct escore_priv *escore = (struct escore_priv *)dev;
        union es755_accdet_status_reg accdet_status_reg;
-       union es755_accdet_reg accdet_reg;
-       int value;
+       struct esxxx_accdet_config accdet_cfg = escore->pdata->accdet_cfg;
+       int sys_intr_resp, value;
        int rc = 0;
        static int redetect_hs=1;
        u8 impd_level;
@@ -2284,35 +2814,70 @@ static int es755_codec_intr(struct notifier_block *self, unsigned long action,
 
        pr_debug("%s(): Event: 0x%04x\n", __func__, (u32)action);
 
+       if (escore->dhwpt_mode) {
+               /* Cancel delayed work of MP Sleep, and bring chip to Normal mode
+                * if it is in MP Sleep mode */
+               pr_debug("%s(): Bring chip from MP Sleep to Normal mode\n",
+                               __func__);
+               rc = es755_exit_mp_sleep();
+               if (rc) {
+                       dev_err(escore_priv.dev,
+                                       "%s(): es755_exit_mp_sleep() fail %d\n",
+                                       __func__, rc);
+                       goto intr_exit;
+               }
+       }
+
        if (action & ES_CODEC_INTR_EVENT) {
-               value = escore_read(NULL, ES_GET_SYS_INTERRUPT);
-               if (value < 0) {
-                       pr_err("%s(): Get System Event failed\n", __func__);
+               sys_intr_resp = escore_read_locked(NULL, ES_GET_SYS_INTERRUPT);
+               if (sys_intr_resp < 0) {
+                       pr_err("%s(): Get System Event failed %d\n",
+                              __func__, sys_intr_resp);
                        goto intr_exit;
                }
 
-               if (ES_PLUG_EVENT(value)) {
+               if (ES_PLUG_EVENT(sys_intr_resp)) {
 
+                       /*
+                        * Due to Quick insertion, FW might give more
+                        * than 1 interrupt for single Plug event. if
+                        * MIC Config is already sent, ignore
+                        * subsequent Plug events.
+                        */
+                       /*
+                        * However, in case of Slow insertions, FW
+                        * will send 2 Plug-in events which is valid and
+                        * should not be ignored.
+                        *
+                        * Since the events are actually coming from the
+                        * FW, HSW should display it as is. So, accept
+                        * plug-in events even if it is a Duplicate.
+                       */
                        pr_info("%s(): Plug event\n", __func__);
+
                        /* Enable MIC Detection */
-redetect_HS:
                        rc = es755_mic_config(escore);
                        if (rc < 0) {
-                               pr_err("%s(): MIC config failed\n", __func__);
+                               pr_err("%s(): MIC config fail %d\n",
+                                      __func__, rc);
                                goto intr_exit;
                        }
-               } else if (ES_MICDET_EVENT(value)) {
 
-                       value = escore_read(NULL, ES_GET_ACCDET_STATUS);
+                       escore->acc_det_status = ES_ACC_PLUGGED;
+               }
+
+               if (ES_MICDET_EVENT(sys_intr_resp)) {
+
+                       value = escore_read_locked(NULL, ES_GET_ACCDET_STATUS);
                        if (value < 0) {
-                               pr_err("%s(): Accessory detect status failed\n",
-                                               __func__);
+                               pr_err("%s(): Accessory detect status fail %d\n",
+                                      __func__, value);
                                goto intr_exit;
                        }
 
                        accdet_status_reg.value = value;
 
-                       /* Ignore interurpt if
+                       /* Ignore interrupt if
                         * plugdet_fsm2 = 1 and plugdet_fsm1 = 0
                         */
                        if (accdet_status_reg.fields.plug_det_fsm2 &&
@@ -2323,79 +2888,77 @@ redetect_HS:
                        }
 
                        impd_level = accdet_status_reg.fields.impd_level;
+                       pr_info("%s(): ******* Impd level ****** %d\n",__func__,impd_level);
+
+                       mg_select = accdet_status_reg.fields.mg_select;
+                       mg_sel_force = accdet_cfg.mic_det_enabled & (0x1);
+
+                       /* Updated Headphone Type Decode Table as per BAS_3584
+                        *  ------------------------------
+                        * | MG_SEL | IMP_LEVEL | HS_TYPE |
+                        * |   X    |    0      |  LRG HP |
+                        * |   0    |   1-5     |  Inval  |
+                        * |   0    |    6      |  LRGM   |
+                        * |   1    |   1-5     |  Inval  |
+                        * |   1    |    6      |  LRMG   |
+                        *  ------------------------------
+                        */
 
-                       value = escore_read(NULL, ES_ACCDET_CONFIG);
-                       if (value < 0) {
-                               pr_err("%s(): Accessory detect config failed\n",
+                       /* Open mic detected then according to es854 API guide
+                        * HS_TYPE is assume to LRGG */
+                       if (ES_OPEN_MICDET_EVENT(sys_intr_resp)) {
+                               pr_info("%s(): LRGG Headset detected, Reporting as Headphone\n",
                                                __func__);
-                               goto intr_exit;
-                       }
+                               snd_soc_jack_report(escore->jack,
+                                       SND_JACK_HEADPHONE,
+                                       SND_JACK_HEADPHONE);
+                               escore->acc_det_status = ES_ACC_DETECTED;
 
-                       accdet_reg.value = value;
-                       mg_sel_force = accdet_reg.fields.mg_sel_force;
-                       mg_select = accdet_reg.fields.mg_select;
-
-                       /* Headphone Type Decode Table
-                        *  ---------------------------------------------
-                        * | IMP_LEVEL | MG_SEL_FORCE | MG_SEL | HS_TYPE |
-                        * |   1-5     |       1      |   1    |  LRGM   |
-                        * |   1-5     |       1      |   0    |  LRMG   |
-                        * |   1-5     |       0      |  0/1   |  Inval  |
-                        * |    6      |       1      |   1    |  LRMG   |
-                        * |    6      |       1      |   0    |  LRGM   |
-                        * |    6      |       0      |   1    |  LRMG   |
-                        * |    6      |       0      |   0    |  LRGM   |
-                        * |  > 6      |       X      |   X    |  Inval  |
-                        * |    0      |       X      |   X    |  LRG    |
-                        *  ---------------------------------------------
-                        */
-                       if (impd_level) {
+                       } else if (impd_level) {
                                pr_info("%s(): Headset detected\n", __func__);
 
                                if (redetect_hs) {
                                        redetect_hs=0;
                                        msleep(escore_priv.hs_delay);
-                                       pr_debug("%s(): Redetect HS MIC with Delay %d\n",
+                                       pr_debug("%s(): ***Redetect HS MIC with Delay %d\n",
                                                __func__,escore_priv.hs_delay);
-                                       goto redetect_HS;
+                                       // redetect_HS
+                                       rc = es755_mic_config(escore);
+                                       if (rc < 0) {
+                                               pr_err("%s(): MIC config fail %d\n",
+                                                          __func__, rc);
+                                       }
+                                       goto intr_exit;
                                } else
                                        redetect_hs=1;
 
-                               is_invalid_type = false;
-                               /* MIC Impedence - 1 to 5 */
-                               if (impd_level < MIC_IMPEDANCE_LEVEL) {
-                                       if ((mg_sel_force) && (mg_select))
-                                               pr_info("LRGM Headset\n");
-                                       else if ((mg_sel_force) &&
-                                                       (mg_select == false))
-                                               pr_info("LRMG Headset\n");
-                                       else
-                                               is_invalid_type = true;
-                               }
                                /* Mic Impedence - 6 */
-                               else if (impd_level == MIC_IMPEDANCE_LEVEL) {
-                                       if ((mg_sel_force) && (mg_select))
-                                               pr_info("LRMG Headset\n");
-                                       else if ((mg_sel_force) &&
-                                                       (mg_select == false))
-                                               pr_info("LRGM Headset\n");
-                                       else if ((mg_sel_force == false) &&
-                                                       (mg_select))
+                               if (impd_level == MIC_IMPEDANCE_LEVEL) {
+                                       if (mg_select)
                                                pr_info("LRMG Headset\n");
                                        else
                                                pr_info("LRGM Headset\n");
-                               } else
+                                       is_invalid_type = false;
+                               } else {
+                                       /* MIC Impedence - 1 to 5 or > 6 */
                                        is_invalid_type = true;
+                               }
 
                                if (is_invalid_type) {
                                        pr_err("Invalid type:%d\n", impd_level);
                                        rc = -EINVAL;
                                        goto intr_exit;
                                }
+                               escore->es_vs_route_preset =
+                                               es755_vs_presets[ES755_MICHS];
+                               escore->es_cvs_preset =
+                                               es755_cvs_presets[ES755_MICHS];
 
                                escore->button_config_required = 1;
                                snd_soc_jack_report(escore->jack,
-                                       SND_JACK_HEADSET, JACK_DET_MASK);
+                                       SND_JACK_HEADSET, SND_JACK_HEADSET);
+
+                               escore->acc_det_status = ES_ACC_DETECTED;
 
                                rc = es755_button_config(escore);
                                if (rc < 0)
@@ -2408,61 +2971,34 @@ redetect_HS:
 
                                snd_soc_jack_report(escore->jack,
                                        SND_JACK_HEADPHONE,
-                                       JACK_DET_MASK);
+                                       SND_JACK_HEADPHONE);
+
+                               escore->acc_det_status = ES_ACC_DETECTED;
                        }
 
                        pr_debug("%s(): AccDet status 0x%04x\n", __func__,
                                        accdet_status_reg.value);
-               } else if (ES_BUTTON_PRESS_EVENT(value)) {
-                       pr_info("%s(): Button press event\n", __func__);
+               }
 
-               } else if (ES_BUTTON_RELEASE_EVENT(value)) {
-                       pr_info("%s(): Button release event\n", __func__);
-                       value = escore_read(NULL, ES_GET_ACCDET_STATUS);
-                       if (value < 0) {
-                               pr_err("%s(): Accessory detect status failed\n",
-                                               __func__);
+               /*
+                * Note: Un-Plug event should have higher priority compared to
+                * button press & release Event Checks.
+                */
+               if (ES_UNPLUG_EVENT(sys_intr_resp)) {
+
+                       /*
+                        * Due to Quick removal, FW might give more
+                        * than 1 interrupt for single Unplug event.
+                        * If Unplug Event is already detected, ignore
+                        * subsequent Unplug events.
+                        */
+                       if (escore->acc_det_status == ES_ACC_UNPLUGGED) {
+                               pr_debug("%s(): Ignoring Duplicate Unplug Event\n",
+                                        __func__);
                                goto intr_exit;
                        }
 
-                       accdet_status_reg.value = value;
-
-                       pr_info("Impd:%d\n",
-                                       accdet_status_reg.fields.impd_level);
-
-                       switch (accdet_status_reg.fields.impd_level) {
-                       case 0:
-                       case 1:
-                               snd_soc_jack_report(escore->jack,
-                                               SND_JACK_BTN_0,
-                                               JACK_DET_MASK);
-                               /* Button release event must be sent */
-                               snd_soc_jack_report(escore->jack,
-                                               0, SND_JACK_BTN_0);
-
-                               break;
-                       case 2:
-                               snd_soc_jack_report(escore->jack,
-                                               SND_JACK_BTN_1,
-                                               JACK_DET_MASK);
-                               /* Button release event must be sent */
-                               snd_soc_jack_report(escore->jack,
-                                               0, SND_JACK_BTN_1);
-                               break;
-                       case 3:
-                               snd_soc_jack_report(escore->jack,
-                                               SND_JACK_BTN_2,
-                                               JACK_DET_MASK);
-                               /* Button release event must be sent */
-                               snd_soc_jack_report(escore->jack,
-                                               0, SND_JACK_BTN_2);
-                               break;
-                       default:
-                               pr_info("Release event but impedance not in range\n");
-                               break;
-                       }
-               } else if (ES_UNPLUG_EVENT(value)) {
-                       value = escore_read(NULL, ES_GET_ACCDET_STATUS);
+                       value = escore_read_locked(NULL, ES_GET_ACCDET_STATUS);
                        if (value < 0) {
                                pr_err("%s(): Accessory detect status fail %d",
                                       __func__, value);
@@ -2471,22 +3007,98 @@ redetect_HS:
                        accdet_status_reg.value = value;
                        redetect_hs = 1; /* initialize the counter */
 
-                       /* Ignore interurpt if
+                       /* Ignore interrupt if
                         * plugdet_fsm2 = 1 and plugdet_fsm1 = 1
                         */
                        if (accdet_status_reg.fields.plug_det_fsm2 &&
-                               accdet_status_reg.fields.plug_det_fsm1) {
+                           accdet_status_reg.fields.plug_det_fsm1) {
                                pr_info("%s(): Found UNPLUG_LOCK, ignore it\n",
-                                      __func__);
+                                       __func__);
                                goto intr_exit;
                        }
 
                        pr_info("%s(): Unplug detected\n", __func__);
+                       escore->es_vs_route_preset =
+                               es755_vs_presets[escore->default_cvq_mic];
+                       escore->es_cvs_preset =
+                               es755_cvs_presets[escore->default_cvq_mic];
 
                        escore->button_config_required = 0;
                        snd_soc_jack_report(escore->jack, 0, JACK_DET_MASK);
+
+                       /*
+                        * If user presses button for more than autosuspend
+                        * time, firmware should not be put into suspend mode
+                        * until button is released OR it is unplugged.
+                        * Put the chip back to autosuspend when user unplugs.
+                        */
+                       if (escore->acc_det_status == ES_ACC_BUTTON_PRESSED) {
+
+                               escore_pm_put_autosuspend();
+
+                               if (escore->mp_sleep_requested && escore->dhwpt_mode && !escore->dhwpt_capture_on) {
+                                       pr_debug("%s(): Put chip back into mp_sleep\n", __func__);
+                                       es755_enter_mp_sleep();
+                               }
+                       }
+
+                       escore->acc_det_status = ES_ACC_UNPLUGGED;
+
+                       /*
+                        * Since Headphone/set is removed, Mask the Button
+                        * Press/Release event as well. This way, duplicate or
+                        * invalid Button event is avoided.
+                        */
+                       sys_intr_resp &= ~(ES_BUTTON_RELEASE_EVENT_MASK |
+                                               ES_BUTTON_PRESS_EVENT_MASK);
+
                }
 
+               if (ES_THERMAL_SHUTDOWN_EVENT(sys_intr_resp))
+                       pr_err("%s(): Thermal shut down detected\n",
+                               __func__);
+
+               if (ES_LINEOUT_SHORT_CIRCUIT_EVENT(sys_intr_resp))
+                       pr_err("%s(): Lineout short circuit detected\n",
+                               __func__);
+
+               if (ES_SPKR_LEFT_SHORT_CIRCUIT_EVENT(sys_intr_resp))
+                       pr_err("%s(): Speaker left short circuit detected\n",
+                               __func__);
+
+               if (ES_SPKR_RIGHT_SHORT_CIRCUIT_EVENT(sys_intr_resp))
+                       pr_err("%s(): Speaker right short circuit detected\n",
+                               __func__);
+
+               if (ES_HP_SHORT_CIRCUIT_EVENT(sys_intr_resp))
+                       pr_err("%s(): Headphone short circuit detected\n",
+                               __func__);
+
+               if (ES_EP_SHORT_CIRCUIT_EVENT(sys_intr_resp))
+                       pr_err("%s(): Earphone short circuit detected\n",
+                               __func__);
+
+
+               /*
+                * If previous Event is not Button Press, Test Button Press 1st
+                * & then Button Release.
+                */
+               if (escore->acc_det_status != ES_ACC_BUTTON_PRESSED) {
+                       rc = chk_btn_press_event(escore, sys_intr_resp);
+                       if (rc < 0)
+                               goto intr_exit;
+
+                       chk_btn_release_event(escore, sys_intr_resp);
+
+               }  else {
+
+                       /* Test Button Release 1st  & then Button Press */
+                       rc = chk_btn_release_event(escore, sys_intr_resp);
+                       if (rc < 0)
+                               goto intr_exit;
+
+                       chk_btn_press_event(escore, sys_intr_resp);
+               }
        }
 
 intr_exit:
@@ -2499,14 +3111,12 @@ irqreturn_t es755_cmd_completion_isr(int irq, void *data)
 
        BUG_ON(!escore);
 
-       pr_debug("%s(): API Rising edge received\n",
-                       __func__);
+       pr_debug("%s(): API Interrupt received\n", __func__);
        /* Complete if expected */
        if (escore->wait_api_intr) {
-               pr_debug("%s(): API Rising edge completion.\n",
-                               __func__);
-               complete(&escore->cmd_compl);
+               pr_debug("%s(): API Interrupt completion.\n", __func__);
                escore->wait_api_intr = 0;
+               complete(&escore->cmd_compl);
        }
        return IRQ_HANDLED;
 }
@@ -2515,15 +3125,33 @@ irqreturn_t es755_irq_work(int irq, void *data)
 {
        struct escore_priv *escore = (struct escore_priv *)data;
        int retry = ES_EVENT_STATUS_RETRY_COUNT;
-       int rc = 0;
-       int ret = 0;
+       int rc, ret;
        u32 cmd = 0;
        u32 event_type = 0;
-
+       pr_info("%s(): @@@@@@ Entry #####\n", __func__);
        pr_debug("%s() Interrupt received\n", __func__);
        if (!escore) {
                pr_err("%s(): Invalid IRQ data\n", __func__);
-               goto irq_exit;
+               return IRQ_HANDLED;
+       }
+
+       escore->intr_recvd = 1;
+
+repeat:
+       rc = wait_event_interruptible(escore->irq_waitq,
+                       (escore->dev->power.is_suspended != true));
+       if (unlikely(rc == -ERESTARTSYS)) {
+               pr_err("%s(): Signal received, try again\n", __func__);
+               goto repeat;
+       }
+
+       mutex_lock(&escore->access_lock);
+       rc = escore_pm_get_sync();
+       if (rc < 0) {
+               dev_err(escore_priv.dev, "%s(): pm_get_sync() failed :%d\n",
+                                                               __func__, rc);
+               mutex_unlock(&escore->access_lock);
+               goto err_pm_get_sync;
        }
 
        /* Enable the clocks. This is required for codec interrupts. If chip
@@ -2537,8 +3165,33 @@ irqreturn_t es755_irq_work(int irq, void *data)
                msleep(ES_PM_CLOCK_STABILIZATION);
        }
 
-       /* Delay required for firmware to be ready in case of CVQ mode */
-       msleep(50);
+
+       if (escore->dhwpt_mode) {
+               /* Cancel delayed work of MP Sleep, and bring chip to Normal mode
+                * if it is in MP Sleep mode */
+               pr_debug("%s(): Bring chip from MP Sleep to Normal mode\n",
+                               __func__);
+               rc = es755_exit_mp_sleep();
+               if (rc) {
+                       dev_err(escore_priv.dev,
+                       "%s(): es755_exit_mp_sleep() fail %d\n",
+                       __func__, rc);
+                       goto irq_exit;
+               }
+       }
+
+       /* BAS-2402: When pm usage count is non-zero and device is in
+        * VS Low Power mode, following delay is required for firmware
+        * to be ready after keyword detection interrupt is received.
+        * Runtime PM status value is set to ES_PM_OFF only by CVQ
+        * from application and increments pm usage count, otherwise
+        * setting Runtime PM status value to ES_PM_OFF is not advisable
+        * for actual usecases.
+        */
+       if (escore->escore_power_state == ES_SET_POWER_STATE_VS_LOWPWR)
+               msleep(escore_priv.delay.vs_to_normal);
+       else if (escore->escore_power_state == ES_SET_POWER_STATE_MP_SLEEP)
+               msleep(escore_priv.delay.mpsleep_to_normal);
 
        /* Power state change:
         * Interrupt will put the chip into Normal State
@@ -2546,52 +3199,42 @@ irqreturn_t es755_irq_work(int irq, void *data)
 
        cmd = ES_GET_EVENT << 16;
 
-       mutex_lock(&escore->api_mutex);
        while (retry) {
-               /* Check power state before sending command */
-               if ((escore->escore_power_state == ES_SET_POWER_STATE_NORMAL)
-                       || escore->escore_power_state ==
-                               ES_SET_POWER_STATE_VS_OVERLAY) {
-                       rc = escore->bus.ops.cmd(escore, cmd, &event_type);
-                       if (!rc || !--retry)
-                               break;
-               } else {
-                       pr_info("%s(): wakeup and retry\n", __func__);
-                       ret = escore_wakeup(escore);
-                       if (ret) {
-                               dev_err(escore->dev,
-                                       "%s() wakeup failed ret = %d\n",
-                                       __func__, ret);
-                               break;
-                       }
-
-                       if (escore->escore_power_state ==
-                                       escore->non_vs_sleep_state) {
-                               escore->escore_power_state = ES_SET_POWER_STATE_NORMAL;
-                       } else if (escore->escore_power_state ==
-                                       ES_SET_POWER_STATE_VS_LOWPWR) {
-                               escore->escore_power_state =
-                                       ES_SET_POWER_STATE_VS_OVERLAY;
-
-                       /* If the chip is not awake,the reading of event will wakeup
-                        * the chip which will result in interrupt reconfiguration
-                        * from device resume. Reconfiguration is deferred till the
-                        * time interrupt is processed from the notifier callback.
-                        *
-                        * The interrupt reconfiguration in this case will be taken
-                        * care of by a low priority notifier callback
-                        */
-                               escore->defer_intr_config = 1;
-                       }
+               rc = escore_cmd_nopm(escore, cmd, &event_type);
+               if (!rc || !--retry)
+                       break;
+               pr_info("%s(): wakeup and retry\n", __func__);
+               ret = escore_wakeup(escore);
+               if (ret) {
+                       dev_err(escore->dev, "%s() wakeup failed ret = %d\n",
+                                                               __func__, ret);
+                       break;
                }
        }
        if (rc < 0) {
                pr_err("%s(): Error reading IRQ event: %d\n", __func__, rc);
-               mutex_unlock(&escore->api_mutex);
+               mutex_unlock(&escore->access_lock);
                goto irq_exit;
        }
 
-       mutex_unlock(&escore->api_mutex);
+       mutex_unlock(&escore->access_lock);
+
+       if (escore->escore_power_state == escore->non_vs_sleep_state ||
+               escore->escore_power_state == ES_SET_POWER_STATE_MP_SLEEP) {
+               escore->escore_power_state = ES_SET_POWER_STATE_NORMAL;
+       } else if (escore->escore_power_state == ES_SET_POWER_STATE_VS_LOWPWR) {
+               escore->escore_power_state = ES_SET_POWER_STATE_VS_OVERLAY;
+
+               /* If the chip is not awake, the reading of event will wakeup
+                * the chip which will result in interrupt reconfiguration
+                * from device resume. Reconfiguration is deferred till the
+                * time interrupt is processed from the notifier callback.
+                *
+                * The interrupt reconfiguration in this case will be taken
+                * care of by a low priority notifier callback
+                */
+               escore->defer_intr_config = 1;
+       }
 
        event_type &= ES_MASK_INTR_EVENT;
        mutex_lock(&escore->escore_event_type_mutex);
@@ -2606,6 +3249,10 @@ irqreturn_t es755_irq_work(int irq, void *data)
        }
 
 irq_exit:
+       escore_pm_put_autosuspend();
+err_pm_get_sync:
+       escore->intr_recvd = 0;
+       pr_info("%s(): @@@@@@ Exit #####\n", __func__);
        return IRQ_HANDLED;
 }
 
@@ -2616,21 +3263,35 @@ static struct notifier_block es755_codec_intr_cb = {
        .priority = ES_NORMAL,
 };
 
-static struct notifier_block es755_codec_reconfig_intr_cb = {
-       .notifier_call = es755_codec_reconfig_intr,
-       .priority = ES_LOW,
-};
-
 int es755_core_probe(struct device *dev)
 {
        struct esxxx_platform_data *pdata;
        int rc = 0;
        unsigned long irq_flags = IRQF_DISABLED;
+#if defined(CONFIG_SND_SOC_ES854)
+       const char *fw_filename = "audience/es854/audience-es854-fw.bin";
+       const char *fw_af_filename = "audience/es854/audience-es755-af.bin";
+#if defined(CONFIG_SND_SOC_ES_VS)
+       const char *vs_filename = "audience/es854/audience-es854-vs.bin";
+       const char *bkg_filename =
+               "audience/cvqmodels/adnc_cvq_detection_bkg_w_hdrs.bin";
+#endif
+#elif defined(CONFIG_SND_SOC_ES857)
+       const char *fw_filename = "audience/es857/audience-es857-fw.bin";
+       const char *fw_af_filename = "audience/es857/audience-es857-af.bin";
+#if defined(CONFIG_SND_SOC_ES_VS)
+       const char *vs_filename = "audience/es857/audience-es857-vs.bin";
+       const char *bkg_filename =
+               "audience/cvqmodels/adnc_cvq_detection_bkg_w_hdrs.bin";
+#endif
+#else
        const char *fw_filename = "audience/es755/audience-es755-fw.bin";
+       const char *fw_af_filename = "audience/es755/audience-es755-af.bin";
 #if defined(CONFIG_SND_SOC_ES_VS)
        const char *vs_filename = "audience/es755/audience-es755-vs.bin";
        const char *bkg_filename =
                "audience/cvqmodels/adnc_cvq_detection_bkg_w_hdrs.bin";
+#endif
 #endif
 
        /**/
@@ -2667,10 +3328,19 @@ int es755_core_probe(struct device *dev)
 
        init_completion(&escore_priv.cmd_compl);
        init_waitqueue_head(&escore_priv.stream_in_q);
+       init_waitqueue_head(&escore_priv.irq_waitq);
        INIT_LIST_HEAD(&escore_priv.msg_list);
        escore_priv.irq_notifier_list = &es755_irq_notifier_list;
        escore_priv.cmd_compl_mode = ES_CMD_COMP_POLL;
        escore_priv.wait_api_intr = 0;
+       escore_priv.fw_af_filename = fw_af_filename;
+
+       escore_priv.selected_endpoint = -1;
+       memset( escore_priv.digital_gain, 0, sizeof(escore_priv.digital_gain) );
+
+       escore_priv.power_transition_wq =
+               create_singlethread_workqueue("escore_power_transition_wq");
+       INIT_DELAYED_WORK(&escore_priv.mp_sleep_work, es755_mp_sleep_work);
 
 #if defined(CONFIG_SND_SOC_ES_VS)
        rc = escore_vs_init(&escore_priv);
@@ -2686,18 +3356,19 @@ int es755_core_probe(struct device *dev)
                pdata->wakeup_gpio);
 
        if (pdata->wakeup_gpio != -1) {
-               rc = gpio_request(pdata->wakeup_gpio, "es755_wakeup");
+               rc = devm_gpio_request(dev, pdata->wakeup_gpio, "es755_wakeup");
                if (rc < 0) {
                        dev_err(escore_priv.dev,
-                               "%s(): es755_wakeup request failed", __func__);
-                       goto wakeup_gpio_request_error;
+                               "%s(): es755_wakeup request fail %d\n",
+                               __func__, rc);
+                       goto exit;
                }
                rc = gpio_direction_output(pdata->wakeup_gpio, 1);
                if (rc < 0) {
                        dev_err(escore_priv.dev,
-                               "%s(): es755_wakeup direction failed",
-                               __func__);
-                       goto wakeup_gpio_direction_error;
+                               "%s(): es755_wakeup direction fail %d\n",
+                               __func__, rc);
+                       goto exit;
                }
        } else {
                dev_warn(escore_priv.dev, "%s(): es755_wakeup undefined\n",
@@ -2711,22 +3382,24 @@ int es755_core_probe(struct device *dev)
        dev_dbg(escore_priv.dev, "%s(): gpioa_gpio = %d\n", __func__,
                pdata->gpioa_gpio);
        if (pdata->gpioa_gpio != -1) {
-               rc = gpio_request(pdata->gpioa_gpio, "es755_gpioa");
+               rc = devm_gpio_request(dev, pdata->gpioa_gpio, "es755_gpioa");
                if (rc < 0) {
                        dev_err(escore_priv.dev,
-                               "%s(): es755_gpioa request failed", __func__);
-                       goto gpioa_gpio_request_error;
+                               "%s(): es755_gpioa request fail %d\n",
+                               __func__, rc);
+                       goto exit;
                }
                rc = gpio_direction_input(pdata->gpioa_gpio);
                if (rc < 0) {
                        dev_err(escore_priv.dev,
-                               "%s(): es755_gpioa direction failed", __func__);
-                       goto gpioa_gpio_direction_error;
+                               "%s(): es755_gpioa direction fail %d\n",
+                               __func__, rc);
+                       goto exit;
                }
                /* Fix value for IRQ Type */
                pdata->gpio_a_irq_type = ES_FALLING_EDGE;
        } else {
-               dev_dbg(escore_priv.dev, "%s(): es755_gpioa undefined\n",
+               dev_warn(escore_priv.dev, "%s(): es755_gpioa undefined\n",
                         __func__);
        }
 
@@ -2734,17 +3407,19 @@ int es755_core_probe(struct device *dev)
                pdata->gpiob_gpio);
 
        if (pdata->gpiob_gpio != -1) {
-               rc = gpio_request(pdata->gpiob_gpio, "es755_gpiob");
+               rc = devm_gpio_request(dev, pdata->gpiob_gpio, "es755_gpiob");
                if (rc < 0) {
                        dev_err(escore_priv.dev,
-                               "%s(): es755_gpiob request failed", __func__);
-                       goto gpiob_gpio_request_error;
+                               "%s(): es755_gpiob request fail %d\n",
+                               __func__, rc);
+                       goto exit;
                }
                rc = gpio_direction_input(pdata->gpiob_gpio);
                if (rc < 0) {
                        dev_err(escore_priv.dev,
-                               "%s(): es755_gpiob direction failed", __func__);
-                       goto gpiob_gpio_direction_error;
+                               "%s(): es755_gpiob direction fail %d\n",
+                               __func__, rc);
+                       goto exit;
                }
        } else {
                dev_warn(escore_priv.dev, "%s(): es755_gpiob undefined\n",
@@ -2754,18 +3429,19 @@ int es755_core_probe(struct device *dev)
        dev_dbg(escore_priv.dev, "%s(): reset_gpio = %d\n", __func__,
                pdata->reset_gpio);
        if (pdata->reset_gpio != -1) {
-               rc = gpio_request(pdata->reset_gpio, "es755_reset");
+               rc = devm_gpio_request(dev, pdata->reset_gpio, "es755_reset");
                if (rc < 0) {
                        dev_err(escore_priv.dev,
-                               "%s(): es755_reset request failed :%d",
-                               __func__, pdata->reset_gpio);
-                       goto reset_gpio_request_error;
+                               "%s(): es755_reset (%d) request failed :%d",
+                               __func__, pdata->reset_gpio, rc);
+                       goto exit;
                }
                rc = gpio_direction_output(pdata->reset_gpio, 1);
                if (rc < 0) {
                        dev_err(escore_priv.dev,
-                               "%s(): es755_reset direction failed", __func__);
-                       goto reset_gpio_direction_error;
+                               "%s(): es755_reset direction fail %d\n",
+                               __func__, rc);
+                       goto exit;
                }
                if (!escore_priv.flag.reset_done)
                        escore_gpio_reset(&escore_priv);
@@ -2782,6 +3458,7 @@ int es755_core_probe(struct device *dev)
                        __func__, fw_filename, rc);
                goto request_firmware_error;
        }
+
 #if defined(CONFIG_SND_SOC_ES_VS)
        rc = escore_vs_request_firmware(&escore_priv, vs_filename);
        if (rc) {
@@ -2799,18 +3476,8 @@ int es755_core_probe(struct device *dev)
                goto vs_request_bkg_err;
        }
 #endif
-       /* Enable accessory detection for ES755 */
-       escore_priv.process_analog = 1;
-       escore_priv.regs = kmalloc(sizeof(struct escore_intr_regs), GFP_KERNEL);
-       if (escore_priv.regs == NULL) {
-               dev_err(escore_priv.dev, "%s(): memory alloc failed for regs\n",
-                               __func__);
-               rc = -ENOMEM;
-               goto regs_memalloc_error;
-       }
 
        escore_priv.boot_ops.bootup = es755_bootup;
-       escore_priv.recover_wkup_failure = es755_recover_wakeup_failure;
        escore_priv.soc_codec_dev_escore = &soc_codec_dev_es755;
        escore_priv.dai = es755_dai;
        escore_priv.dai_nr = ES_NUM_CODEC_DAIS;
@@ -2822,6 +3489,8 @@ int es755_core_probe(struct device *dev)
        escore_priv.escore_event_type = ES_NO_EVENT;
        escore_priv.i2s_dai_data = i2s_dai_data;
        escore_priv.config_jack = es755_config_jack;
+       escore_priv.disable_codec_irq = es755_disable_codec_irq;
+       escore_priv.enable_codec_irq = es755_enable_codec_irq;
        escore_priv.non_vs_sleep_state = ES_SET_POWER_STATE_DEEP_SLEEP;
        if (escore_priv.pri_intf == ES_SLIM_INTF) {
 
@@ -2858,20 +3527,21 @@ int es755_core_probe(struct device *dev)
                escore_priv.slim_setup(&escore_priv);
        }
 #if defined(CONFIG_SND_SOC_ES_I2S)
-       escore_priv.i2s_dai_ops.digital_mute = es755_digital_mute;
        escore_priv.i2s_dai_ops.hw_params = es755_hw_params;
        escore_priv.i2s_dai_ops.set_fmt = es755_set_fmt;
        escore_priv.i2s_dai_ops.shutdown = es755_shutdown;
 #endif
-#if defined(CONFIG_SND_SOC_ES_SLIM)
-       escore_priv.slim_dai_ops.digital_mute = es755_digital_mute;
-#endif
+
+       /* Setup Default Accessory Detect Parameters */
+       escore_priv.acc_det_status = ES_ACC_INVALID;
+       escore_priv.acc_btn_pressed = ES_ACC_BTN_INVALID;
        escore_priv.hs_delay = DEFAULT_HS_REDETECTION_DELAY;
 
        /* API Interrupt registration */
        if (pdata->gpioa_gpio != -1) {
                rc = request_threaded_irq(gpio_to_irq(pdata->gpioa_gpio), NULL,
-                               es755_cmd_completion_isr, IRQF_TRIGGER_FALLING,
+                               es755_cmd_completion_isr,
+                               IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
                                "es755-cmd-completion-isr", &escore_priv);
                if (rc < 0) {
                        pr_err("%s() API interrupt registration failed :%d",
@@ -2896,15 +3566,10 @@ int es755_core_probe(struct device *dev)
                        irq_flags = IRQF_TRIGGER_RISING;
                        break;
                }
-#if defined(CONFIG_ARCH_TEGRA)
+
                rc = request_threaded_irq(gpio_to_irq(pdata->gpiob_gpio), NULL,
                                es755_irq_work, irq_flags | IRQF_ONESHOT,
                                "escore-irq-work", &escore_priv);
-#else
-               rc = request_threaded_irq(gpio_to_irq(pdata->gpiob_gpio), NULL,
-                               es755_irq_work, irq_flags,
-                               "escore-irq-work", &escore_priv);
-#endif
                if (rc < 0) {
                        pr_err("Error in registering interrupt :%d", rc);
                        goto event_intr_error;
@@ -2913,14 +3578,14 @@ int es755_core_probe(struct device *dev)
                }
 
                /* Disable the interrupt till needed */
-               if (escore_priv.pdata->gpiob_gpio != -1)
+               if (escore_priv.pdata->gpiob_gpio != -1) {
                        disable_irq(gpio_to_irq(pdata->gpiob_gpio));
+                       /* Disable IRQ Wakeup capability */
+                       disable_irq_wake(gpio_to_irq(pdata->gpiob_gpio));
+               }
 
                escore_register_notify(escore_priv.irq_notifier_list,
                                &es755_codec_intr_cb);
-
-               escore_register_notify(escore_priv.irq_notifier_list,
-                               &es755_codec_reconfig_intr_cb);
        }
 
 #if defined(CONFIG_SND_SOC_ES_UART_STREAMDEV)
@@ -2930,7 +3595,6 @@ int es755_core_probe(struct device *dev)
 #endif
        return rc;
 
-regs_memalloc_error:
 event_intr_error:
        if (pdata->gpioa_gpio != -1)
                free_irq(gpio_to_irq(pdata->gpioa_gpio), NULL);
@@ -2943,20 +3607,7 @@ request_vs_firmware_error:
 #endif
        release_firmware(escore_priv.standard);
 request_firmware_error:
-reset_gpio_direction_error:
-       gpio_free(pdata->reset_gpio);
-reset_gpio_request_error:
-gpiob_gpio_direction_error:
-       gpio_free(pdata->gpiob_gpio);
-gpiob_gpio_request_error:
-gpioa_gpio_direction_error:
-       gpio_free(pdata->gpioa_gpio);
-gpioa_gpio_request_error:
-wakeup_gpio_direction_error:
-       gpio_free(pdata->wakeup_gpio);
-wakeup_gpio_request_error:
-       dev_dbg(escore_priv.dev, "%s(): exit with error\n", __func__);
-
+exit:
        return rc;
 }
 EXPORT_SYMBOL_GPL(es755_core_probe);
@@ -2967,14 +3618,15 @@ static __init int es755_init(void)
 
        pr_debug("%s()", __func__);
 
-       escore_pm_init();
-
        escore_priv.codec_clk_en = false;
+       /* Initially power level support is disabled */
+       escore_priv.power_saving_mode = ES_POWER_LEVEL_DISABLE;
        escore_priv.device_name  = "elemental-addr";
        escore_priv.interface_device_name  = "slim-ifd";
        escore_priv.interface_device_elem_addr_name  =
                                        "slim-ifd-elemental-addr";
-       mutex_init(&escore_priv.api_mutex);
+       mutex_init(&escore_priv.access_lock);
+       mutex_init(&escore_priv.intf_probed_mutex);
        init_completion(&escore_priv.fw_download);
        escore_platform_init();
 #if defined(CONFIG_SND_SOC_ES_I2C)
@@ -3040,6 +3692,12 @@ module_init(es755_init);
 static __exit void es755_exit(void)
 {
        pr_debug("%s()\n", __func__);
+       if (escore_priv.flag.af)
+               release_firmware(escore_priv.af);
+
+       if (escore_priv.power_transition_wq)
+               destroy_workqueue(escore_priv.power_transition_wq);
+
 #if defined(CONFIG_SND_SOC_ES_VS)
        escore_vs_release_firmware(&escore_priv);
        escore_vs_exit(&escore_priv);
@@ -3058,4 +3716,10 @@ MODULE_DESCRIPTION("ASoC ES755 driver");
 MODULE_AUTHOR("Greg Clemson <gclemson@audience.com>");
 MODULE_LICENSE("GPL");
 MODULE_ALIAS("platform:es755-codec");
+#if defined(CONFIG_SND_SOC_ES854)
+MODULE_FIRMWARE("audience-es854-fw.bin");
+#elif defined(CONFIG_SND_SOC_ES857)
+MODULE_FIRMWARE("audience-es857-fw.bin");
+#else
 MODULE_FIRMWARE("audience-es755-fw.bin");
+#endif
old mode 100755 (executable)
new mode 100644 (file)
index ffd5e9c..b262ccb
 #include <sound/soc.h>
 #include <linux/time.h>
 #include "escore.h"
+#if defined(CONFIG_SND_SOC_ES854)
+#include "es-a350-reg.h"
+#elif defined(CONFIG_SND_SOC_ES857)
+#include "es-a375-reg.h"
+#else
 #include "es-a300-reg.h"
+#endif
 
+#define ES_INVALID_REG_VALUE           -1
 #define ES_SYNC_CMD                    0x8000
 #define ES_SYNC_POLLING                0x0000
 #define ES_SYNC_ACK                    0x80000000
@@ -45,7 +52,8 @@
 #define ES_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |\
                        SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 |\
                        SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000 |\
-                       SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_192000)
+                       SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_192000 |\
+                       SNDRV_PCM_RATE_44100)
 #define ES_SLIMBUS_RATES (SNDRV_PCM_RATE_48000)
 
 #define ES_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S16_BE |\
 #define ES_VP                          0x0001
 #define ES_MM                          0x0002
 #define ES_VP_MM                       0x0003
-#define ES_AZ                          0x0004
+#define ES_AF                          0x0004
 #define ES_PASSTHRU                    0x0008
 #define ES_PASSTHRU_VP         0x0009
 #define ES_PASSTHRU_MM         0x000A
 #define ES_PASSTHRU_VP_MM      0x000B
-#define ES_PASSTHRU_AZ         0x000C
+#define ES_PASSTHRU_AF         0x000C
 #define ES_VOICESENSE          0x0010
 
 /*
 #define ES_SET_EVENT_RESP              0x901A
 #define ES_ACCDET_CONFIG_CMD           0x9056
 #define ES_SMOOTH_RATE                 0x804E
+#define ES_SET_INT_MASK                        0x807F
+#define ES_DISABLE_CODEC_INT           0x0000
+/* bits 15:14 are reserved, bit 3 is to enable event for
+ * button released and should be enabled only after button
+ * press event is found */
+#define ES_ENABLE_CODEC_INT            0x3FF7
 #define ES755_FW_DOWNLOAD_MAX_RETRY    5
 #define ES_EVENT_STATUS_RETRY_COUNT    2
 
+/*
+ * Audio path commands codes
+ */
+#define ES_SELECT_ENDPOINT             0x8069
+#define ES_SET_DIGITAL_GAIN            0x8015
+#define ES_GET_DIGITAL_GAIN            0x801D
+#define ES_DIGITAL_GAIN_MASK           0xFF
+#define ES_SELECT_HPF_MODE              0x806E
+
+/*
+ * Codec Control Register Access
+ * */
+#define ES_GET_CODEC_VAL               0x807B
+#define ES_CODEC_VAL_MASK              0xFF
+
+#if defined(CONFIG_SND_SOC_ES854) || defined(CONFIG_SND_SOC_ES857)
+#define ES_MAX_CODEC_CONTROL_REG       0x77
+#else
+#define ES_MAX_CODEC_CONTROL_REG       0x55
+#endif
+
 /*
  * Stereo widening presets for headphone playback and MM audio algo rate 48K
  */
 #define ES_FULL_WIDENING               0x000A
 #define ES_DEF_ST_WIDE_SETTING         0x8000
 
-#define ES_MAX_AZ_MODE                 2
+#define ES_MAX_AF_MODE                 2
 #define ES_MAX_AEC_MODE                        7
 /* Impedance level for MIC detection */
 #define MIC_IMPEDANCE_LEVEL            0x6
 
+/* Ambient Noise Query API */
+#define ES_QUERY_AMBIENT_NOISE         0x80420002
+#define ES_MIN_NOISE_DB                        (-96)
+
 /* Jack detection mask */
+#if defined(CONFIG_SND_SOC_ES854) || defined(CONFIG_SND_SOC_ES857)
+/* BTN_3 is mapped with IMPD_LEVEL 1 to support
+ * Google Voice Search trigger functionality */
+#define JACK_DET_MASK  (SND_JACK_HEADSET | SND_JACK_BTN_0 | SND_JACK_BTN_1 |\
+               SND_JACK_BTN_2 | SND_JACK_BTN_3)
+#else
 #define JACK_DET_MASK  (SND_JACK_HEADSET | SND_JACK_BTN_0 | SND_JACK_BTN_1 |\
                SND_JACK_BTN_2)
+#endif
 
 #define MAX_RETRY_TO_SWITCH_TO_LOW_POWER_MODE  5
 
-#define ES755_DMIC0_VS_ROUTE_PREST             0x056A
-#define ES755_MIC0_VS_ROUTE_PREST              0x0568
-#define ES755_MICHS_VS_ROUTE_PREST             0x056B
-#define ES755_DMIC0_CVS_PREST                  0x1B59
-#define ES755_MIC0_CVS_PREST                   0x1B8A
-#define ES755_MICHS_CVS_PREST                  0x1B8B
+#define ES755_DMIC0_VS_ROUTE_PRESET            0x056A
+#define ES755_MIC0_VS_ROUTE_PRESET             0x0568
+#define ES755_MICHS_VS_ROUTE_PRESET            0x056B
+#define ES755_DMIC0_CVS_PRESET                 0x1B59
+#define ES755_MIC0_CVS_PRESET                  0x1B8A
+#define ES755_MICHS_CVS_PRESET                 0x1B8B
+
+#if defined(CONFIG_SND_SOC_ES854) || defined(CONFIG_SND_SOC_ES857)
+#define ES755_WDB_MAX_SIZE     4096
+#else
+#define ES755_WDB_MAX_SIZE     512
+#endif
 
 /* PCM Port IDs */
 #define ES755_PCM_PORT_A               0xA
 #define MIN_HS_REDETECTION_DELAY 50
 #define DEFAULT_HS_REDETECTION_DELAY 250
 
+/* Delay values required for different stages */
+#define ES755_DELAY_WAKEUP_TO_NORMAL   20 /* ms */
+#define ES755_DELAY_WAKEUP_TO_VS       20 /* ms */
+#define ES755_DELAY_VS_TO_NORMAL       90 /* ms */
+#define ES755_DELAY_MPSLEEP_TO_NORMAL  30 /* ms */
+#define ES755_DELAY_VS_STREAMING_TO_VS 10 /* ms */
+
+/* Value to disable Master clock */
+#define ES755_DISABLE_MASTER_CLK       8
+
+/* Delay value to put chip into MP Sleep mode */
+#define ES755_MP_SLEEP_DELAY   2000 /* 2 sec */
+
+enum {
+       ES755_MIC0,
+       ES755_DMIC0,
+       ES755_MICHS,
+};
+
 union es755_accdet_status_reg {
        u16 value;
        struct {
@@ -151,7 +222,8 @@ union es755_accdet_status_reg {
                u16 hp_out:1;
                u16 thermal_shutdown:1;
                u16 impd_level:3;
-               u16 res:3;
+               u16 res:2;
+               u16 mg_select:1;
                u16 i2c_ctl_ready:1;
                u16 glb_enable_status:1;
        } fields;
@@ -180,7 +252,9 @@ enum {
        ES_ALGORITHM_MM,
        ES_ALGORITHM_PT,
        ES_ALGORITHM_PT_VP,
-       ES_ALGORITHM_AZ,
+       ES_ALGORITHM_AF,
+       ES_ALGORITHM_BRG,
+       ES_ALGORITHM_KALAOK,
        ES_ALGORITHM_DHWPT,
 
        /* PCM Port Parameters*/
@@ -199,9 +273,6 @@ enum {
        ES_PORT_FS_DURATION,
 
        ES_BUTTON_CTRL1,
-       ES_BUTTON_CTRL2,
-       ES_BUTTON_CTRL3,
-       ES_BUTTON_CTRL4,
 
        ES_PRIMARY_MUX,
        ES_SECONDARY_MUX,
@@ -218,10 +289,10 @@ enum {
        ES_MMUITONE1_MUX,
        ES_MMUITONE2_MUX,
 
-       ES_AZ_PRI_MUX,
-       ES_AZ_SEC_MUX,
-       ES_AZ_TER_MUX,
-       ES_AZ_AI1_MUX,
+       ES_AF_PRI_MUX,
+       ES_AF_SEC_MUX,
+       ES_AF_TER_MUX,
+       ES_AF_AI1_MUX,
 
        ES_MM_PASSIN1_MUX,
        ES_MM_PASSIN2_MUX,
@@ -256,6 +327,7 @@ enum {
        ES_SBUSTX5_MUX,
 
        ES_CODEC_VALUE,
+       ES_CODEC_ADDR,
        ES_POWER_STATE,
        ES_RUNTIME_PM,
        ES_VS_INT_OSC_MEASURE_START,
@@ -276,13 +348,13 @@ enum {
        ES_STEREO_WIDTH,
        ES_MIC_CONFIG,
        ES_AEC_MODE,
-       ES_AZ_MODE,
+       ES_AF_MODE,
+       ES_VP_METERS,
        ES_CMD_COMPL_MODE,
        ES_FE_STREAMING,
-       ES_FEIN2_MUX,
        ES_CODEC_OUTPUT_RATE,
+       ES_FEIN2_MUX,
        ES_API_ADDR_MAX,
-       ES_HS_DELAY,
 };
 
 #define ES_SLIM_1_PB_MAX_CHANS 2
@@ -327,13 +399,23 @@ enum {
 /*
  * Codec Events
  */
+#define ES_EP_SHORT_CIRCUIT_EVENT(value)               ((1<<13) & value)
+#define ES_HP_SHORT_CIRCUIT_EVENT(value)               ((1<<12) & value)
+#define ES_SPKR_RIGHT_SHORT_CIRCUIT_EVENT(value)       ((1<<11) & value)
+#define ES_SPKR_LEFT_SHORT_CIRCUIT_EVENT(value)                ((1<<10) & value)
+#define ES_LINEOUT_SHORT_CIRCUIT_EVENT(value)          ((1<<9) & value)
+#define ES_THERMAL_SHUTDOWN_EVENT(value)               ((1<<8) & value)
 
 #define ES_PLUG_EVENT(value)           ((1<<6) & value)
 #define ES_UNPLUG_EVENT(value)         ((1<<5) & value)
 #define ES_MICDET_EVENT(value)         ((1<<4) & value)
 #define ES_BUTTON_RELEASE_EVENT(value) ((1<<3) & value)
+#define ES_BUTTON_RELEASE_EVENT_MASK           (1<<3)
+
 #define ES_BUTTON_PRESS_EVENT(value)   ((1<<2) & value)
+#define ES_BUTTON_PRESS_EVENT_MASK             (1<<2)
 
+#define ES_OPEN_MICDET_EVENT(value)    ((1<<0) & value)
 enum {
        ES_SLIM_1_PB = ES_DAI_ID_BASE,
        ES_SLIM_1_CAP,
@@ -343,13 +425,6 @@ enum {
        ES_SLIM_3_CAP,
 };
 
-enum {
-       ES_PM_SLEEP = 0x1,
-       ES_PM_MP_SLEEP,
-       ES_PM_MP_CMD,
-       ES_PM_ACTIVE,
-};
-
 /* Base name used by character devices. */
 #define ES_CDEV_NAME "adnc"
 
@@ -374,5 +449,7 @@ void es755_slim_setup(struct escore_priv *escore_priv);
 int es755_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack);
 int es755_power_transition(int next_power_state,
                                unsigned int set_power_state_cmd);
+int es755_enter_mp_sleep(void);
+int es755_exit_mp_sleep(void);
 
 #endif /* _ES_H */
index ca213743ac684e323ef2350a397aae64c63259c9..202da3c4d6ecacff6e92aadd5887188b78280c23 100644 (file)
@@ -55,7 +55,6 @@
  * data in the circular buffer first.
  */
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
 #include <linux/delay.h>
 #include <linux/string.h>
 #include <linux/kthread.h>
@@ -67,7 +66,6 @@
 
 #include "escore.h"
 #include "escore-uart-common.h"
-#include "mq100-sensorhub.h"
 /* Index offset for the 3 character devices types. */
 enum {
        CDEV_COMMAND,
@@ -136,8 +134,6 @@ static int parse_have;              /* Bytes currently in buffer. */
 static int last_token;         /* Used to control parser state. */
 static int (*parse_cb_preset)(void *, int);
 static int (*parse_cb_cmd)(void *, u32);
-static bool is_nomore_databit_found(int clear, unsigned char *buf, int len,
-                                       int *nbytes_to_read);
 
 int macro_preset_id(void *ctx, int id)
 {
@@ -150,7 +146,7 @@ int macro_cmd(void *ctx, u32 cmd)
        struct escore_priv *escore = (struct escore_priv *)ctx;
        u32 resp;
        int rc;
-       rc = escore_cmd(escore, cmd, &resp);
+       rc = escore_cmd_locked(escore, cmd, &resp);
        if (!(cmd & BIT(28))) {
                pr_debug("escore: cmd=0x%08x Response:0x%08x\n", cmd,
                                escore->bus.last_response);
@@ -323,7 +319,7 @@ static ssize_t command_read(struct file *filp, char __user *buf,
 
        slen -= *f_pos;
        cnt = min(count, slen);
-       err = copy_to_user(buf, readbuf + *f_pos, slen);
+       err = copy_to_user(buf, readbuf + *f_pos, cnt);
        if (err) {
                dev_dbg(escore->dev, "%s copy_to_user = %d\n", __func__, err);
                goto OUT;
@@ -458,15 +454,6 @@ static int firmware_open(struct inode *inode, struct file *filp)
                                ret);
                return ret;
        }
-/* This is not the right place for indicating state change
- * However since firmware download functionality is closely tied to
- * escore-(interface) files this is one of the common places to have
- * less or no impact on escore's working. This will be removed later
- * while refactoring
- */
-#ifdef CONFIG_MQ100_SENSOR_HUB
-       mq100_indicate_state_change(MQ100_STATE_RESET);
-#endif
        pr_debug("firmware download setup ok\n");
 
 escore_high_bw_open_failed:
@@ -494,15 +481,6 @@ static int firmware_release(struct inode *inode, struct file *filp)
                                ret);
                        goto firmware_release_exit;
                }
-/* This is not the right place for indicating state change
- * However since firmware download functionality is closely tied to
- * escore-(interface) files this is one of the common places to have
- * less or no impact on escore's working. This will be removed later
- * while refactoring
- */
-#ifdef CONFIG_MQ100_SENSOR_HUB
-               mq100_indicate_state_change(MQ100_STATE_NORMAL);
-#endif
        }
 
        /* Previous interrupt configuration would have been lost after
@@ -543,13 +521,13 @@ static ssize_t firmware_write(struct file *filp, const char __user *buf,
        escore = filp->private_data;
        BUG_ON(!escore);
 
-       pr_debug("firmware write count=%zu bytes\n", count);
+       pr_debug("firmware write count=%zd bytes\n", count);
 
        wr = bs = 0;
        while (wr < count) {
                bs = min(count - wr, FW_BUF_SIZE);
                BUG_ON(bs == 0);
-               pr_debug("wr=%zu bs=%zu buf+wr=%p\n", wr, bs, buf + wr);
+               pr_debug("wr=%zd bs=%zd buf+wr=%p\n", wr, bs, buf + wr);
                ret = copy_from_user(fw_buf, buf + wr, bs);
                if (ret) {
                        dev_err(escore->dev,
@@ -648,10 +626,8 @@ static int stream_datalog_open(struct escore_priv *escore, struct inode *inode,
                        goto streamdev_open_err;
                }
                /* Set NS baud rate after VS to NS switching */
-               /*
                if (escore->streamdev.config)
                        escore->streamdev.config(escore);
-               */
        }
 
        /* initialize stream buffer */
@@ -746,7 +722,10 @@ static int stream_datalog_release(struct escore_priv *escore,
 
        /* ignore threadfn return value */
        pr_debug("%s(): stopping stream kthread\n", __func__);
-       kthread_stop(escore->stream_thread);
+
+       /* stop streaming thread if running */
+       if (atomic_read(&escore->stream_thread->usage) > 0)
+               kthread_stop(escore->stream_thread);
 
        /* free any pages on the circular buffer */
        while ((page = streaming_consume_page(&length)))
@@ -778,13 +757,17 @@ static int streaming_open(struct inode *inode, struct file *filp)
 
        pr_debug("called: %s\n", __func__);
 
+       escore = container_of((inode)->i_cdev, struct escore_priv,
+                       cdev_streaming);
+
+       mutex_lock(&escore->access_lock);
        err = escore_pm_get_sync();
+       mutex_unlock(&escore->access_lock);
+
        if (err < 0) {
                pr_err("%s(): pm_get_sync failed :%d\n", __func__, err);
                return err;
        }
-       escore = container_of((inode)->i_cdev, struct escore_priv,
-                       cdev_streaming);
 
        err = stream_datalog_open(escore, inode, filp);
        if (err)
@@ -805,7 +788,9 @@ static int streaming_release(struct inode *inode, struct file *filp)
                dev_err(escore->dev, "%s(): stream_datalog_release error = %d\n",
                        __func__, err);
 
+       mutex_lock(&escore->access_lock);
        escore_pm_put_autosuspend();
+       mutex_unlock(&escore->access_lock);
        return err;
 }
 
@@ -958,90 +943,6 @@ ERR_OUT:
        return err;
 }
 
-static bool is_nomore_databit_found(int clear, unsigned char *buf, int len,
-                                       int *nbytes_to_read)
-{
-       bool rc = false;
-       int i = 0, j = 0;
-       static int sync1, sync2, byteoff, skip_bytes;
-       u32 plen = 0;
-
-       if (clear) {
-               sync1 = sync2 = byteoff = skip_bytes = 0;
-               return 0;
-       }
-
-       /* skip data part. Only decode header */
-       if (skip_bytes) {
-               i += skip_bytes;
-               skip_bytes -= skip_bytes >= len ? len : skip_bytes;
-       }
-
-       while (i < len) {
-               if (buf[i] == 0x12 && sync1 == 0)
-                       sync1 = 1;
-               else if (sync1 && !sync2 && buf[i] == 0x34) {
-                       sync2 = 1;
-                       byteoff = 1;
-               } else if (sync2 && byteoff <= 6) {
-                       switch (byteoff) {
-                       case 3:
-                               plen = buf[i];
-                               break;
-                       case 4:
-                               plen |= buf[i] << 8;
-                               break;
-                       case 5:
-                               plen |= buf[i] << 16;
-                               break;
-                       case 6:
-                               plen |= buf[i] << 24;
-                               if (plen & 0x80000000) {
-                                       pr_info("%s()Nomore bit found\n",
-                                       __func__);
-                                       rc = true;
-                               }
-                               plen &= 0x3FFFFFFF;
-                               skip_bytes = plen;
-                               sync1 = 0;
-                               sync2 = 0;
-                               byteoff = 0;
-                               break;
-                       default:
-                               break;
-                       }
-                       byteoff++;
-                       if (rc)
-                               break;
-               } else {
-                       sync1 = 0;
-                       sync2 = 0;
-                       byteoff = 0;
-               }
-               i++;
-               j = i;
-               i += skip_bytes;
-               skip_bytes -= skip_bytes >= (len - j) ? (len - j) : skip_bytes;
-       }
-
-       /*If no more bit was found then get the number of bytes yet to be read*/
-       if (true == rc) {
-               *nbytes_to_read = i + plen - len + 1;
-
-               /* Ideally nbytes_to_read should be positive. But in case of
-                * synchronous interfaces like SPI, when data are read after
-                * buffer data are over (after last packet is read, data are
-                * filled with zero. Thus in these cases, there are data
-                * (zeros) after buffer data is over which can cause negative
-                * value.
-                */
-               if (*nbytes_to_read < 0)
-                       *nbytes_to_read = 0;
-       }
-
-       return rc;
-}
-
 static int streaming_producer(void *ptr)
 {
        struct escore_priv *escore;
@@ -1051,17 +952,14 @@ static int streaming_producer(void *ptr)
        int rlen_last = 0;      /* bytes read on last read call */
        int length;
        int chead, ctail;
-       int data_ready = 0;
+       int data_ready = 1;
        unsigned long bytes_read = 0;
-       int nbytes_to_read = 0;
-       bool no_more_bit = 0;
 
        buf = streaming_page_alloc();
        if (!buf)
                return -ENOMEM;
 
        pr_debug("called: %s\n", __func__);
-       is_nomore_databit_found(1, 0, 0, 0);
        escore = (struct escore_priv *) ptr;
 
        /*
@@ -1070,8 +968,7 @@ static int streaming_producer(void *ptr)
         * that may be in the UART receive buffer
         */
        do {
-               if (rlen == PAGE_SIZE ||
-                               (no_more_bit && !nbytes_to_read)) {
+               if (rlen == PAGE_SIZE) {
                        chead = stream_circ.head;
                        ctail = ACCESS_ONCE(stream_circ.tail);
 
@@ -1102,15 +999,12 @@ static int streaming_producer(void *ptr)
                                return -ENOMEM;
                        rlen = 0;
                }
+               if (escore->streamdev.wait)
+                       data_ready = escore->streamdev.wait(escore);
 
-               data_ready = escore->streamdev.wait(escore);
                if (data_ready > 0) {
-
-                       if (!no_more_bit)
-                               nbytes_to_read = PAGE_SIZE - rlen;
-
                        rlen_last = escore->streamdev.read(escore, buf + rlen,
-                                       nbytes_to_read);
+                                       PAGE_SIZE - rlen);
                        if (rlen_last < 0) {
                                dev_err(escore->dev, "%s(): read error on streamdev: %d\n",
                                                __func__, rlen_last);
@@ -1118,20 +1012,6 @@ static int streaming_producer(void *ptr)
                                rlen += rlen_last;
                        }
                }
-               if (!no_more_bit) {
-                       no_more_bit = is_nomore_databit_found(
-                                       0,
-                                       buf + rlen - rlen_last,
-                                       rlen_last,
-                                       &nbytes_to_read);
-                       if (no_more_bit)
-                               dev_info(escore->dev,
-                                               "%s() Data to be read = %d",
-                                               __func__, nbytes_to_read);
-               } else {
-                       pr_debug("%s() read %d\n", __func__, rlen_last);
-                       nbytes_to_read -= rlen_last;
-               }
        } while (!kthread_should_stop());
 
        dev_dbg(escore->dev, "%s(): end capture streaming data\n", __func__);
@@ -1187,22 +1067,37 @@ static ssize_t datablock_read(struct file *filp, char __user *buf,
                                = (struct escore_priv *)filp->private_data;
        ssize_t rcnt = count < escore->datablock_dev.rdb_read_count ?
                                count : escore->datablock_dev.rdb_read_count;
-       int rc = 0;
+       int rc;
 
        BUG_ON(!escore);
+
+       if (escore->datablock_dev.rdb_read_buffer == NULL)
+               return 0;
+
        /* Mutex required against simultaneous read/writes on the RDB buffer */
        rc = mutex_lock_killable(&escore->datablock_dev.datablock_read_mutex);
        if (rc) {
-               rcnt = -EIO;
-               goto read_err;
+               pr_err("%s() failed to get datablock read lock: %d\n",
+                               __func__, rc);
+               return rc;
        }
-       rc = copy_to_user(buf, escore->datablock_dev.rdb_read_buffer, rcnt);
+
+       rc = copy_to_user(buf, escore->datablock_dev.rdb_read_buffer + *f_pos,
+                       rcnt);
        mutex_unlock(&escore->datablock_dev.datablock_read_mutex);
-       if (rc)
-               rcnt -= rc;
-read_err:
-       /* Reset the read count */
-       escore->datablock_dev.rdb_read_count = 0;
+       if (rc) {
+               pr_err("%s() copy to user failed: %d\n", __func__, rc);
+               return rc;
+       }
+
+       /* update position & count to support multiple reads in chunks smaller
+        * than the buffer */
+       *f_pos += rcnt;
+       escore->datablock_dev.rdb_read_count -= rcnt;
+       if (!escore->datablock_dev.rdb_read_count) {
+               kfree(escore->datablock_dev.rdb_read_buffer);
+               escore->datablock_dev.rdb_read_buffer = NULL;
+       }
 
        return rcnt;
 }
@@ -1210,11 +1105,12 @@ read_err:
 static int datablock_write_dispatch(struct escore_priv * const escore,
                                u32 cmd, size_t count)
 {
-       char *data = data_buf += sizeof(cmd);
+       char *data = data_buf + sizeof(cmd);
        int remains = (int)count - sizeof(cmd);
        int err = 0;
        u32 cmd_id = cmd >> 16;
        u32 rspn;
+       struct es_datablock_device *datablock_dev = &escore->datablock_dev;
 
        if (cmd_id == ES_WDB_CMD) {
                err = escore_datablock_write(escore, data, remains);
@@ -1227,17 +1123,47 @@ static int datablock_write_dispatch(struct escore_priv * const escore,
                if (err > 0)
                        err += 4;
        } else if (cmd_id == ES_RDB_CMD) {
-               err = mutex_lock_killable(
-                       &escore->datablock_dev.datablock_read_mutex);
+               int size;
+               err = mutex_lock_killable(&datablock_dev->datablock_read_mutex);
+               if (unlikely(err)) {
+                       dev_err(escore->dev,
+                               "%s(): lock failed for datablock read: %d\n",
+                               __func__, err);
+                       return err;
+               }
+
+               /* Reset read data block size */
+               datablock_dev->rdb_read_count = 0;
+
+               size = escore_get_rdb_size(escore, (cmd & 0xFFFF));
+               if (size < 0) {
+                       mutex_unlock(&datablock_dev->datablock_read_mutex);
+                       return size;
+               }
+
+               /* free previously malloced data (if any) & malloc with new
+                * size */
+               kfree(datablock_dev->rdb_read_buffer);
+               datablock_dev->rdb_read_buffer = kmalloc(size, GFP_KERNEL);
+               if (datablock_dev->rdb_read_buffer == NULL) {
+                       dev_err(escore->dev,
+                               "%s(): Not enough memory to read RDB data\n",
+                               __func__);
+                       mutex_unlock(&datablock_dev->datablock_read_mutex);
+                       return -ENOMEM;
+               }
+
                /* include the ID of the ES block to be read */
                err = escore_datablock_read(escore,
-                                       escore->datablock_dev.rdb_read_buffer,
-                                       PARSE_BUFFER_SIZE, (cmd & 0xFFFF));
+                                       datablock_dev->rdb_read_buffer, size);
                /* If there is no error, this function should return 0 */
-               if (err > 0)
+               if (err > 0) {
                        err = 0;
+                       /* Store read data block size */
+                       datablock_dev->rdb_read_count = size;
+               }
 
-               mutex_unlock(&escore->datablock_dev.datablock_read_mutex);
+               mutex_unlock(&datablock_dev->datablock_read_mutex);
        } else {
                err = escore_cmd(escore, cmd, &rspn);
                if (err) {
@@ -1261,7 +1187,13 @@ static ssize_t datablock_write(struct file *filp, const char __user *buf,
        int err = 0;
 
        BUG_ON(!escore);
-       dev_dbg(escore->dev, "%s() entry: count: %zu\n", __func__, count);
+       dev_dbg(escore->dev, "%s() entry: count: %zd\n", __func__, count);
+
+       if (count > sizeof(parse_buffer)) {
+               dev_err(escore->dev, "%s() invalid counter size\n", __func__);
+               err = -EINVAL;
+               goto OUT;
+       }
 
        err = copy_from_user(data_buf, buf, count);
        if (err) {
@@ -1273,7 +1205,9 @@ static ssize_t datablock_write(struct file *filp, const char __user *buf,
 
        dev_dbg(escore->dev, "%s(): cmd: 0x%08x\n", __func__, cmd);
 
+       mutex_lock(&escore->access_lock);
        err = datablock_write_dispatch(escore, cmd, count);
+       mutex_unlock(&escore->access_lock);
 OUT:
        return (err) ? err : count;
 }
@@ -1309,7 +1243,9 @@ static int datablock_open(struct inode *inode, struct file *filp)
                goto OPEN_ERR;
        }
 
+       mutex_lock(&escore->access_lock);
        err = escore_pm_get_sync();
+       mutex_unlock(&escore->access_lock);
        if (err < 0) {
                pr_err("%s(): pm_get_sync failed :%d\n", __func__, err);
                return err;
@@ -1343,7 +1279,11 @@ static int datablock_release(struct inode *inode, struct file *filp)
                        = (struct escore_priv *)filp->private_data;
        BUG_ON(!escore);
        mutex_unlock(&escore->datablock_dev.datablock_mutex);
+
+       mutex_lock(&escore->access_lock);
        escore_pm_put_autosuspend();
+       mutex_unlock(&escore->access_lock);
+
        escore_datablock_close(escore);
        dev_dbg(escore->dev, "%s(): release complete\n", __func__);
        return 0;
@@ -1487,7 +1427,6 @@ static int cmd_history_release(struct inode *inode, struct file *filp)
        escore->cmd_history_size = 0;
        return 0;
 }
-
 static const struct file_operations datablock_fops = {
        .owner = THIS_MODULE,
        .read = datablock_read,
@@ -1496,6 +1435,7 @@ static const struct file_operations datablock_fops = {
        .release = datablock_release,
 };
 
+
 static const struct file_operations cmd_history_fops = {
        .owner = THIS_MODULE,
        .read = cmd_history_read,
@@ -1523,7 +1463,7 @@ static int create_cdev(struct escore_priv *escore, struct cdev *cdev,
 
        dev = device_create(cdev_class, NULL, devno, NULL,
                            ESCORE_CDEV_NAME "%d", cdev_minor + index);
-       if (IS_ERR(cdev)) {
+       if (IS_ERR(dev)) {
                err = PTR_ERR(dev);
                dev_err(escore->dev, "device_create cdev=%d failed: %d\n",
                        index, err);
@@ -1600,15 +1540,6 @@ int escore_cdev_init(struct escore_priv *escore)
                goto err_datablock;
        dev_dbg(escore->dev, "datablock cdev initialized.\n");
 
-       escore->datablock_dev.rdb_read_buffer = kmalloc(PARSE_BUFFER_SIZE,
-                                                       GFP_KERNEL);
-       if (!escore->datablock_dev.rdb_read_buffer) {
-               dev_err(escore->dev, "%s(): rdb_read_buffer alloc failed\n",
-                       __func__);
-               err = -ENOMEM;
-               goto err_datablock;
-       }
-
        err = create_cdev(escore, &escore->cdev_datalogging, &datalogging_fops,
                          CDEV_DATALOGGING);
        if (err)
index 244c4ea74bfee7ee50c835ed96987ba9265e7ecc..f4bca0c085d722b0d7b4098b16e27ef78d534de8 100644 (file)
@@ -39,6 +39,7 @@ int escore_i2c_read(struct escore_priv *escore, void *buf, int len)
        int rc = 0;
 
        rc = i2c_transfer(escore_i2c->adapter, msg, 1);
+
        /*
         * i2c_transfer returns number of messages executed. Since we
         * are always sending only 1 msg, return value should be 1 for
@@ -47,10 +48,12 @@ int escore_i2c_read(struct escore_priv *escore, void *buf, int len)
        if (rc != 1) {
                pr_err("%s(): i2c_transfer() failed, rc = %d, msg_len = %d\n",
                        __func__, rc, len);
-               return -EIO;
-       } else {
-               return 0;
+
+               ESCORE_FW_RECOVERY_FORCED_OFF(escore);
+               return rc;
        }
+
+       return 0;
 }
 
 int escore_i2c_write(struct escore_priv *escore, const void *buf, int len)
@@ -78,9 +81,24 @@ int escore_i2c_write(struct escore_priv *escore, const void *buf, int len)
                        usleep_range(10000, 10050);
                        --retry;
                } while (retry != 0);
+
+               /*
+                * i2c_transfer returns number of messages executed. Since we
+                * are always sending only 1 msg, return value should be 1 for
+                * success case
+                */
+               if (rc != 1) {
+                       pr_err("%s:i2c_transfer() failed, rc=%d, msg_len=%d\n",
+                                        __func__, rc, xfer_len);
+
+                       ESCORE_FW_RECOVERY_FORCED_OFF(escore);
+                       return rc;
+               }
+
                retry = ES_MAX_RETRIES;
                written += xfer_len;
        }
+
        return 0;
 }
 
@@ -93,28 +111,24 @@ int escore_i2c_cmd(struct escore_priv *escore, u32 cmd, u32 *resp)
 
        dev_dbg(escore->dev,
                        "%s: cmd=0x%08x  sr=0x%08x\n", __func__, cmd, sr);
+       INC_DISABLE_FW_RECOVERY_USE_CNT(escore);
 
        if ((escore->cmd_compl_mode == ES_CMD_COMP_INTR) && !sr)
-               escore->wait_api_intr = 1;
+               escore_set_api_intr_wait(escore);
 
+       *resp = 0;
        cmd = cpu_to_be32(cmd);
        err = escore_i2c_write(escore, &cmd, sizeof(cmd));
        if (err || sr)
-               return err;
+               goto cmd_exit;
 
        do {
                if (escore->cmd_compl_mode == ES_CMD_COMP_INTR) {
                        pr_debug("%s(): Waiting for API interrupt. Jiffies:%lu",
                                        __func__, jiffies);
-                       err = wait_for_completion_timeout(&escore->cmd_compl,
-                                       msecs_to_jiffies(ES_RESP_TOUT_MSEC));
-                       if (!err) {
-                               pr_debug("%s(): API Interrupt wait timeout\n",
-                                               __func__);
-                               escore->wait_api_intr = 0;
-                               err = -ETIMEDOUT;
+                       err = escore_api_intr_wait_completion(escore);
+                       if (err)
                                break;
-                       }
                } else {
                        usleep_range(ES_RESP_POLL_TOUT,
                                        ES_RESP_POLL_TOUT + 500);
@@ -125,16 +139,16 @@ int escore_i2c_cmd(struct escore_priv *escore, u32 cmd, u32 *resp)
                dev_dbg(escore->dev, "%s: *resp=0x%08x\n", __func__, *resp);
                if (err) {
                        dev_dbg(escore->dev,
-                               "%s: escore_i2c_read() failure\n", __func__);
+                               "%s: I2C Read() failed %d\n", __func__, err);
                } else if ((*resp & ES_ILLEGAL_CMD) == ES_ILLEGAL_CMD) {
                        dev_err(escore->dev, "%s: illegal command 0x%08x\n",
-                               __func__, cmd);
+                               __func__, be32_to_cpu(cmd));
                        err = -EINVAL;
                        goto cmd_exit;
                } else if (*resp == ES_NOT_READY) {
                        dev_dbg(escore->dev,
                                "%s: escore_i2c_read() not ready\n", __func__);
-                       err = -ETIMEDOUT;
+                       err = -EBUSY;
                } else {
                        goto cmd_exit;
                }
@@ -143,6 +157,11 @@ int escore_i2c_cmd(struct escore_priv *escore, u32 cmd, u32 *resp)
        } while (retry != 0 && escore->cmd_compl_mode != ES_CMD_COMP_INTR);
 
 cmd_exit:
+       update_cmd_history(be32_to_cpu(cmd), *resp);
+       DEC_DISABLE_FW_RECOVERY_USE_CNT(escore);
+       if (err && ((*resp & ES_ILLEGAL_CMD) != ES_ILLEGAL_CMD))
+               ESCORE_FW_RECOVERY_FORCED_OFF(escore);
+
        return err;
 }
 
@@ -155,27 +174,27 @@ int escore_i2c_boot_setup(struct escore_priv *escore)
 
        pr_info("%s()\n", __func__);
        pr_info("%s(): write ES_BOOT_CMD = 0x%04x\n", __func__, boot_cmd);
-#ifdef CONFIG_MQ100_SENSOR_HUB
-       mq100_indicate_state_change(MQ100_STATE_RESET);
-#endif
        cpu_to_be16s(&boot_cmd);
        memcpy(msg, (char *)&boot_cmd, 2);
        rc = escore_i2c_write(escore, msg, 2);
        if (rc < 0) {
-               pr_err("%s(): firmware load failed boot write\n", __func__);
+               pr_err("%s(): firmware load failed boot write %d\n",
+                      __func__, rc);
                goto escore_bootup_failed;
        }
        usleep_range(1000, 1005);
        memset(msg, 0, 2);
        rc = escore_i2c_read(escore, msg, 2);
        if (rc < 0) {
-               pr_err("%s(): firmware load failed boot ack\n", __func__);
+               pr_err("%s(): firmware load failed boot ack %d\n",
+                      __func__, rc);
                goto escore_bootup_failed;
        }
        memcpy((char *)&boot_ack, msg, 2);
        pr_info("%s(): boot_ack = 0x%04x\n", __func__, boot_ack);
        if (boot_ack != ES_I2C_BOOT_ACK) {
-               pr_err("%s(): firmware load failed boot ack pattern", __func__);
+               pr_err("%s(): firmware load failed boot ack pattern (0x%x)",
+                      __func__, boot_ack);
                rc = -EIO;
                goto escore_bootup_failed;
        }
@@ -197,8 +216,8 @@ int escore_i2c_boot_finish(struct escore_priv *escore)
                                __func__, sync_cmd);
                rc = escore_i2c_cmd(escore, sync_cmd, &sync_ack);
                if (rc < 0) {
-                       pr_err("%s(): firmware load failed sync write\n",
-                                       __func__);
+                       pr_err("%s(): firmware load failed sync write %d\n",
+                              __func__, rc);
                        continue;
                }
                pr_debug("%s(): sync_ack = 0x%08x\n", __func__, sync_ack);
@@ -207,9 +226,6 @@ int escore_i2c_boot_finish(struct escore_priv *escore)
                                        __func__);
                        rc = -EIO;
                } else {
-#ifdef CONFIG_MQ100_SENSOR_HUB
-                       mq100_indicate_state_change(MQ100_STATE_NORMAL);
-#endif
                        pr_info("%s(): firmware load success", __func__);
                        break;
                }
@@ -224,6 +240,8 @@ static void escore_i2c_setup_pri_intf(struct escore_priv *escore)
        escore->bus.ops.write = escore_i2c_write;
        escore->bus.ops.cmd = escore_i2c_cmd;
        escore->streamdev = es_i2c_streamdev;
+       escore->bus.ops.cpu_to_bus = escore_cpu_to_i2c;
+       escore->bus.ops.bus_to_cpu = escore_i2c_to_cpu;
 }
 
 static int escore_i2c_setup_high_bw_intf(struct escore_priv *escore)
@@ -235,15 +253,15 @@ static int escore_i2c_setup_high_bw_intf(struct escore_priv *escore)
        escore->bus.ops.high_bw_cmd = escore_i2c_cmd;
        escore->boot_ops.setup = escore_i2c_boot_setup;
        escore->boot_ops.finish = escore_i2c_boot_finish;
-       escore->bus.ops.cpu_to_bus = escore_cpu_to_i2c;
-       escore->bus.ops.bus_to_cpu = escore_i2c_to_cpu;
+       escore->bus.ops.cpu_to_high_bw_bus = escore_cpu_to_i2c;
+       escore->bus.ops.high_bw_bus_to_cpu = escore_i2c_to_cpu;
        rc = escore->probe(escore->dev);
        if (rc)
                goto out;
 
+       mutex_lock(&escore->access_lock);
        rc = escore->boot_ops.bootup(escore);
-       if (rc)
-               goto out;
+       mutex_unlock(&escore->access_lock);
 
 out:
        return rc;
@@ -376,12 +394,14 @@ static int escore_i2c_probe(struct i2c_client *i2c,
 
                rc = escore_i2c_regulator_configure(escore);
                if (rc) {
-                       dev_err(escore->dev, "Failed to intialize hardware\n");
+                       dev_err(escore->dev, "%s: initialize hw fail %d\n",
+                               __func__, rc);
                        goto continue_init;
                }
                rc = escore_i2c_power_on(escore);
                if (rc)
-                       dev_err(escore->dev, "Failed to power on hardware\n");
+                       dev_err(escore->dev, "%s: Power On hardware Fail %d\n",
+                               __func__, rc);
        }
 
 continue_init:
@@ -392,11 +412,6 @@ continue_init:
 
 static int escore_i2c_remove(struct i2c_client *i2c)
 {
-       struct esxxx_platform_data *pdata = i2c->dev.platform_data;
-       if (pdata->reset_gpio != -1)
-               gpio_free(pdata->reset_gpio);
-       gpio_free(pdata->wakeup_gpio);
-       gpio_free(pdata->gpioa_gpio);
 #ifdef CONFIG_ARCH_MSM8974
        escore_i2c_power_off(&escore_priv);
        escore_i2c_regulator_disable(&escore_priv);
@@ -406,8 +421,30 @@ static int escore_i2c_remove(struct i2c_client *i2c)
        return 0;
 }
 
+
+
+/* streamdev read function should return length.
+ * In case of I2C as streaming device,I2C read returns
+ * 0 in case of success  otherwise error.
+ * So implement this wrapper function to support
+ * streaming over I2C.
+ * This function return length on success and 0 in case of failure
+ * so that streaming thread exit gracefully.
+ */
+static int escore_i2c_stream_read(struct escore_priv *escore, void *buf,
+               int len)
+{
+       int rc = escore_i2c_read(escore, buf, len);
+
+       if (rc != 0) {
+               pr_err("%s: i2c stream read fail\n", __func__);
+               return 0;
+       }
+       return len;
+}
+
 struct es_stream_device es_i2c_streamdev = {
-       .read = escore_i2c_read,
+       .read = escore_i2c_stream_read,
        .intf = ES_I2C_INTF,
 };
 
index 9820010a4a089b928a5c93e00675351f4164937a..86a26e148fc12fda06684f5c4de09eeea4934664 100644 (file)
@@ -15,7 +15,6 @@
 #define _ESCORE_I2C_H
 
 #include "escore.h"
-#include "mq100-sensorhub.h"
 #define ES_I2C_BOOT_CMD                        0x0001
 #define ES_I2C_BOOT_ACK                        0x0101
 
index 385b1fe0b2916bcaf4dd584a7c7af4922a2e026c..e7bf7d7a55219f0b99a9b5c7b442f91cddc61340 100644 (file)
@@ -29,7 +29,6 @@
 #include <sound/initval.h>
 #include <sound/tlv.h>
 #include <linux/kthread.h>
-#include <linux/esxxx.h>
 #include "escore.h"
 #include "escore-list.h"
 
index 442c11c7ac68f3efd882dfbdfc9fe16f0aa6de2b..92afd0f6370844aa0d2968f15ce9023019d212cd 100644 (file)
@@ -30,6 +30,7 @@ int escore_queue_msg_to_list(struct escore_priv *escore,
 }
 EXPORT_SYMBOL_GPL(escore_queue_msg_to_list);
 
+/* This function must be called with access_lock acquired */
 int escore_write_msg_list(struct escore_priv *escore)
 {
        struct msg_list_entry *entry;
@@ -38,7 +39,6 @@ int escore_write_msg_list(struct escore_priv *escore)
        u32 resp;
 
        pr_debug("%s()\n", __func__);
-
        if (!escore)
                escore = &escore_priv;
 
@@ -49,24 +49,22 @@ int escore_write_msg_list(struct escore_priv *escore)
        }
 
        mutex_lock(&escore->msg_list_mutex);
-       mutex_lock(&escore->api_mutex);
        list_for_each_entry(entry, &escore->msg_list, list) {
                memcpy((char *)api_word, entry->msg, entry->msg_len);
                for (i = 0; i < entry->msg_len / 4; i++) {
                        resp = 0;
-                       rc = escore->bus.ops.cmd(escore, api_word[i],
-                                       &resp);
+                       rc = escore_cmd_nopm(escore, api_word[i], &resp);
                        if (rc < 0) {
-                               pr_err("%s(): failed", __func__);
+                               pr_err("%s(): Write Msg fail %d\n",
+                                      __func__, rc);
                                goto exit;
                        }
                }
        }
-
 exit:
-       mutex_unlock(&escore->api_mutex);
        mutex_unlock(&escore->msg_list_mutex);
        escore_pm_put_autosuspend();
+
        return rc;
 }
 EXPORT_SYMBOL_GPL(escore_write_msg_list);
index c3dd0c7ab42d86dc05b7b8df976cc50b47923aa9..0e4167579ee19f0d4d2e9a84c7eabb0bde66dd47 100644 (file)
  * For the time being, the default actions are those required for the
  * ES755 as decibed in "ES755 ENgineering API Guide" version 0.31
  */
+
+/*
+ * Locking notes: This file should take no access_lock.
+ * The caller of functions defined in this file must make sure the
+ * access_lock is taken before using the functions.
+ * With system wide suspend and resume implementation, it is required to take
+ * access_lock in system suspend/resume routines.
+ */
 #include <linux/kernel.h>
 #include <linux/jiffies.h>
 #include "escore.h"
@@ -18,9 +26,8 @@
 #include "escore-uart-common.h"
 #include "escore-slim.h"
 
-#define ES_PM_SLEEP_DELAY              30 /* 30 ms */
-#define ES_PM_RESUME_TIME              30 /* 30ms */
 #define ES_PM_AUTOSUSPEND_DELAY                3000 /* 3 sec */
+#define ES_PM_SLEEP_DELAY              30 /* 30 ms */
 
 static inline bool es_ready_to_suspend(struct escore_priv *escore)
 {
@@ -34,350 +41,278 @@ static inline bool es_ready_to_suspend(struct escore_priv *escore)
        return !is_active;
 }
 
-static int escore_non_vs_suspend(struct device *dev);
-static int escore_non_vs_resume(struct device *dev);
-
-static int escore_vs_suspend(struct device *dev)
+static int escore_non_vs_suspend(struct device *dev)
 {
        struct escore_priv *escore = &escore_priv;
-       int ret;
-
+       u32 cmd, resp;
+       int ret = 0;
        dev_dbg(dev, "%s()\n", __func__);
 
-       /* Already in low power mode because of runtime CVQ suspend.
-        */
-       if (escore_priv.escore_power_state == ES_SET_POWER_STATE_VS_LOWPWR) {
-               dev_dbg(dev, "%s() Already in VS low power mode\n", __func__);
-               return 0;
+       /* Set flag to Wait for API Interrupt */
+       escore_set_api_intr_wait(escore);
+
+       /* Send a SetPowerState command - no respnse */
+       cmd = (ES_SET_POWER_STATE << 16) | escore->non_vs_sleep_state;
+
+       ret = escore_cmd_nopm(escore, cmd, &resp);
+       if (ret < 0) {
+               dev_err(dev, "%s() - Chip dead.....\n", __func__);
+               goto escore_non_vs_suspend_exit;
        }
 
+#ifdef CONFIG_SND_SOC_ES_AVOID_REPEAT_FW_DOWNLOAD
        /*
-        * Do not suspend in runtime if CVQ training is going on.
-        * For System suspend, application onPause() have already
-        * put chip in normal mode.
+        * If chip is successfully moved to sleep, VS firmware has
+        * to be redownloaded.
         */
-       if (escore_priv.mode == VOICESENSE_PENDING || \
-                               escore_priv.mode == VOICESENSE) {
-               dev_dbg(dev, "%s() Suspend Deferred\n", __func__);
-               return -EBUSY;
-       }
+       escore_set_vs_download_req(escore, true);
+#endif
 
-       ret = escore->vs_ops.escore_voicesense_sleep(escore);
+       if (escore->pdata->gpioa_gpio != -1) {
+               /* Wait for API Interrupt to confirm
+                * that device is ready to accept commands */
+               ret = escore_api_intr_wait_completion(escore);
+               if (ret)
+                       goto escore_non_vs_suspend_exit;
+       } else
+               /* Set delay time */
+               msleep(ES_PM_SLEEP_DELAY);
 
+       escore->escore_power_state = escore->non_vs_sleep_state;
+
+escore_non_vs_suspend_exit:
+       dev_dbg(dev, "%s() complete %d\n", __func__, ret);
        return ret;
 }
 
-static int escore_vs_resume(struct device *dev)
+static int escore_non_vs_resume(struct device *dev)
 {
        struct escore_priv *escore = &escore_priv;
-       int ret;
+       int ret = 0;
 
        dev_dbg(dev, "%s()\n", __func__);
 
-       ret = escore->vs_ops.escore_voicesense_wakeup(escore);
+       ret = escore_wakeup(escore);
+       if (ret) {
+               dev_err(dev, "%s() wakeup failed ret = %d\n", __func__, ret);
+               goto escore_non_vs_resume_exit;
+       }
+       escore->escore_power_state = ES_SET_POWER_STATE_NORMAL;
 
-       if (!escore_priv.defer_intr_config)
-               blocking_notifier_call_chain(escore->irq_notifier_list,
-                               ES_RECONFIG_INTR_EVENT, escore);
+escore_non_vs_resume_exit:
+       dev_dbg(dev, "%s() complete %d\n", __func__, ret);
 
        return ret;
 }
 
-static int escore_non_vs_suspend(struct device *dev)
+static int escore_vs_suspend(struct device *dev)
 {
+       struct escore_priv *escore = &escore_priv;
        int ret = 0;
-       int rsp;
-       u32 cmd;
 
        dev_dbg(dev, "%s()\n", __func__);
 
-       /*
-        * Do not suspend in runtime if CVQ training is going on.
-        * For System suspend, application onPause() have already
-        * put chip in normal mode.
-        */
-       if (escore_priv.escore_power_state != ES_SET_POWER_STATE_NORMAL
-               || escore_priv.mode == VOICESENSE_PENDING) {
-               dev_dbg(dev, "%s() Suspend Deferred\n", __func__);
-               return -EBUSY;
-       }
-
-       mutex_lock(&escore_priv.api_mutex);
-       /* It is assumed that a channels have already been muted */
-       /* Send a SetPowerState command - no respnse */
-       cmd = (ES_SET_POWER_STATE << 16) |
-               escore_priv.non_vs_sleep_state;
-       ret = escore_priv.bus.ops.cmd(&escore_priv, cmd,
-                       &rsp);
-       if (ret < 0) {
-               dev_err(dev, "%s() - Chip dead.....\n", __func__);
-               goto suspend_out;
-       }
-
-       if (escore_priv.pdata->gpioa_gpio != -1)
-               escore_priv.cmd_compl_mode = ES_CMD_COMP_POLL;
-
-       /* Set delay time time */
-       msleep(ES_PM_SLEEP_DELAY);
-
-       escore_priv.escore_power_state = escore_priv.non_vs_sleep_state;
+       ret = escore->vs_ops.escore_voicesense_sleep(escore);
 
-suspend_out:
-       mutex_unlock(&escore_priv.api_mutex);
+       dev_dbg(dev, "%s() complete %d\n", __func__, ret);
 
        return ret;
 }
 
-static int escore_non_vs_resume(struct device *dev)
+static int escore_vs_resume(struct device *dev)
 {
        struct escore_priv *escore = &escore_priv;
        int ret = 0;
-       dev_dbg(dev, "%s()\n", __func__);
-
-       mutex_lock(&escore->api_mutex);
-       ret = escore_wakeup(escore);
-       if (ret) {
-               dev_err(dev, "%s() wakeup failed ret = %d\n", __func__, ret);
-               goto escore_wakeup_fail_recovery;
-       }
 
-       escore->escore_power_state = ES_SET_POWER_STATE_NORMAL;
-       mutex_unlock(&escore->api_mutex);
+       dev_dbg(dev, "%s()\n", __func__);
 
-       dev_dbg(dev, "%s() - out rc =%d\n", __func__, ret);
+       ret = escore->vs_ops.escore_voicesense_wakeup(escore);
 
-       return ret;
+       dev_dbg(dev, "%s() complete %d\n", __func__, ret);
 
-escore_wakeup_fail_recovery:
-       mutex_unlock(&escore->api_mutex);
        return ret;
 }
 
 static int escore_runtime_suspend(struct device *dev)
 {
-       int ret = 0;
-       unsigned long time_left;
        struct escore_priv *escore = &escore_priv;
-
+       int ret = 0;
+       pr_info("%s(): @@@@@@ Entry #####\n", __func__);
        dev_dbg(dev, "%s()\n", __func__);
-
-       if (!es_ready_to_suspend(escore)) {
-               dev_dbg(dev, "%s() - Not ready for suspend\n", __func__);
+       if (escore->dev != dev) {
+               dev_dbg(dev, "%s() Invalid device\n", __func__);
                return 0;
        }
-
-       time_left = pm_runtime_autosuspend_expiration(escore->dev);
-       if (time_left) {
-               /*
-                * If pm_runtime_suspend() is called without RPM_AUTO flag,
-                * this condition may be hit. This condition may happen if
-                * the suspend() is initiated outside of this driver, e.g.
-                * ASoC subsystem which calls pm_runtime_put() which internally
-                * calls pm_runtime_idle() which does not call suspend() with
-                * RPM_AUTO flag.
-                *
-                * Ideally, the function should check for the autosuspend
-                * timer expiration, and if the timer is not expiring, -EBUSY
-                * should be returned. But kernel does not handle this
-                * error code if suspend() was called without RPM_AUTO flag,
-                * so here this condition is ignored and chip would enter into
-                * suspend mode.
-                */
-
-               pm_runtime_mark_last_busy(escore->dev);
-               dev_dbg(escore->dev, "%s() Autosuspend timer not expired yet\n",
-                               __func__);
+       if (!es_ready_to_suspend(escore)) {
+               dev_dbg(dev, "%s() - Not ready for suspend\n", __func__);
                return -EBUSY;
        }
 
+       INC_DISABLE_FW_RECOVERY_USE_CNT(escore);
        /*
         * If the user has selected MP_SLEEP playback mode, the chip will not
         * enter into normal mode once the stream is shutdown. We need to
         * bring chip into normal mode to enter into desired runtime suspend
         * state.
         */
-       mutex_lock(&escore->api_mutex);
        if (escore->escore_power_state == ES_SET_POWER_STATE_MP_SLEEP) {
                ret = escore_wakeup(escore);
                if (ret) {
                        dev_err(dev, "%s() wakeup failed ret = %d\n",
                                        __func__, ret);
-                       mutex_unlock(&escore_priv.api_mutex);
                        goto out;
                }
                escore->escore_power_state = ES_SET_POWER_STATE_NORMAL;
        }
-       mutex_unlock(&escore->api_mutex);
-#ifdef CONFIG_SND_SOC_ES_RUNTIME_SUSPEND_MODE_SLEEP
-       ret = escore_non_vs_suspend(dev);
-#elif defined(CONFIG_SND_SOC_ES_RUNTIME_SUSPEND_MODE_CVQ)
+
        if (escore->voice_sense &&
                escore->vs_ops.escore_is_voicesense_sleep_enable(escore))
                ret = escore_vs_suspend(dev);
        else
                ret = escore_non_vs_suspend(dev);
-#endif
 
        if (ret)
                goto out;
 
-       escore->pm_state = ES_PM_RUNTIME_SLEEP;
-
        /* Disable the clocks */
-       if (escore_priv.pdata->esxxx_clk_cb)
-               escore_priv.pdata->esxxx_clk_cb(0);
+       if (escore->pdata->esxxx_clk_cb)
+               escore->pdata->esxxx_clk_cb(0);
 
-       if (escore_priv.dev && device_may_wakeup(escore_priv.dev))
-               enable_irq_wake(gpio_to_irq(escore_priv.pdata->gpiob_gpio));
+       dev_dbg(dev, "%s() complete %d\n", __func__, ret);
+       DEC_DISABLE_FW_RECOVERY_USE_CNT(escore);
+       pr_info("%s(): @@@@@@ EXIT #####\n", __func__);
+       return ret;
 
 out:
-       return ret;
+       DEC_DISABLE_FW_RECOVERY_USE_CNT(escore);
+       ret = escore_fw_recovery(escore, FORCED_FW_RECOVERY_ON);
+       if (ret < 0) {
+               dev_err(dev, "%s() Firmware recovery failed %d\n",
+                                                       __func__, ret);
+       }
+
+       return -EAGAIN;
 }
 
 static int escore_runtime_resume(struct device *dev)
 {
-       int ret = 0;
        struct escore_priv *escore = &escore_priv;
        struct device *p = dev->parent;
-
+       int ret = 0;
+       pr_info("%s(): @@@@@@ Entry #####\n", __func__);
        dev_dbg(dev, "%s()\n", __func__);
+
        if (p && pm_runtime_status_suspended(p)) {
                dev_err(dev, "%s() - parent is suspended\n", __func__);
                pm_runtime_resume(p);
        }
 
-       if (escore->pm_state == ES_PM_NORMAL) {
-               dev_dbg(dev, "%s() - already awake\n", __func__);
-               return 0;
-       }
-#ifdef CONFIG_SND_SOC_ES_RUNTIME_SUSPEND_MODE_SLEEP
-       ret = escore_non_vs_resume(dev);
-#elif defined(CONFIG_SND_SOC_ES_RUNTIME_SUSPEND_MODE_CVQ)
+       INC_DISABLE_FW_RECOVERY_USE_CNT(escore);
+       /* Resume functions will take care of enabling clock */
        if (escore->voice_sense &&
                escore->vs_ops.escore_is_voicesense_sleep_enable(escore))
                ret = escore_vs_resume(dev);
        else
                ret = escore_non_vs_resume(dev);
-#endif
-       if (!ret)
-               escore->pm_state = ES_PM_NORMAL;
 
-       pm_runtime_mark_last_busy(escore->dev);
+       if (ret)
+               goto escore_wakeup_fail_recovery;
 
-       if (escore_priv.dev && device_may_wakeup(escore_priv.dev))
-               disable_irq_wake(gpio_to_irq(escore_priv.pdata->gpiob_gpio));
+       pm_runtime_mark_last_busy(escore->dev);
 
        dev_dbg(dev, "%s() complete %d\n", __func__, ret);
+       DEC_DISABLE_FW_RECOVERY_USE_CNT(escore);
+       pr_info("%s(): @@@@@@ EXIT #####\n", __func__);
+       return ret;
+
+escore_wakeup_fail_recovery:
+       DEC_DISABLE_FW_RECOVERY_USE_CNT(escore);
+       ret = escore_fw_recovery(escore, FORCED_FW_RECOVERY_ON);
+       if (ret < 0) {
+               dev_err(dev, "%s() Firmware recovery failed %d\n",
+                                                       __func__, ret);
+       }
 
        return ret;
 }
 
-int escore_system_suspend(struct device *dev)
+static int escore_system_suspend(struct device *dev)
 {
-       int ret = 0;
        struct escore_priv *escore = &escore_priv;
-
+       int ret = 0;
+       pr_info("%s(): @@@@@@ Entry #####\n", __func__);
        dev_dbg(dev, "%s()\n", __func__);
 
-       if (escore->pm_state == ES_PM_ASLEEP) {
-               dev_dbg(dev, "%s() - already suspended\n", __func__);
+       if (escore->dev != dev) {
+               dev_dbg(dev, "%s() Invalid device\n", __func__);
                return 0;
        }
 
-       if (!es_ready_to_suspend(escore)) {
+/*     if (!es_ready_to_suspend(escore)) {
                dev_dbg(dev, "%s() - Not ready for suspend\n", __func__);
-               return 0;
+               return -EBUSY;
        }
 
-       if (escore->voice_sense &&
-               escore->vs_ops.escore_is_voicesense_sleep_enable(escore)) {
-               if (escore->escore_power_state == escore->non_vs_sleep_state) {
-                       ret = escore_non_vs_resume(dev);
-                       if (ret) {
-                               dev_err(escore->dev,
-                                       "%s() non VS resume failed ret = %d\n",
-                                       __func__, ret);
-                                       goto out;
-                       }
+       if (escore->disable_codec_irq) {
+               ret = escore->disable_codec_irq(escore);
+               if (ret < 0) {
+                       dev_err(dev, "%s(): Disable irq failed\n",
+                               __func__);
+                       return -EBUSY;
                }
-               ret = escore_vs_suspend(dev);
-       } else {
-               if (escore->escore_power_state == escore->non_vs_sleep_state) {
-                       dev_dbg(dev, "%s() - already suspended in runtime\n",
-                                       __func__);
-                       ret = 0;
-                       escore->pm_state = ES_PM_ASLEEP;
-                       goto out;
-               } else if (escore->escore_power_state ==
-                               ES_SET_POWER_STATE_MP_SLEEP) {
-                       /*
-                        * Case where playback was happening into MP_SLEEP mode
-                        * and stream is shutdown now. But system suspend
-                        * initiated before runtime suspend got a chance.
-                        * Need to bring chip into normal mode before putting
-                        * into suspend state.
-                        */
-                       mutex_lock(&escore_priv.api_mutex);
-                       ret = escore_wakeup(escore);
-                       if (ret) {
-                               dev_err(dev, "%s() wakeup failed ret = %d\n",
-                                               __func__, ret);
-                               mutex_unlock(&escore_priv.api_mutex);
-                               goto out;
-                       }
-                       escore->escore_power_state = ES_SET_POWER_STATE_NORMAL;
-                       mutex_unlock(&escore_priv.api_mutex);
+               pr_info("%s(): @@@@@@ disable_codec_irq #####\n", __func__);
+       }*/
+
+       if (!pm_runtime_suspended(dev)) {
+               dev_dbg(dev, "%s() system suspend\n", __func__);
+               mutex_lock(&escore->access_lock);
+               ret = escore_runtime_suspend(dev);
+               /*
+                * If runtime-PM still thinks it's active, then make sure its
+                * status is in sync with HW status.
+                * If runtime suspend is not executed yet, RPM status is
+                * RPM_ACTIVE. System suspend changes chip status to suspend
+                * and hence RPM status needs to be updated manually to match
+                * actual chip status. This can be done by disabling RPM,
+                * changing RPM status and enabling RPM again.
+                */
+               if (!ret) {
+                       pm_runtime_disable(dev);
+                       pm_runtime_set_suspended(dev);
+                       pm_runtime_enable(dev);
                }
-               ret = escore_non_vs_suspend(dev);
+               mutex_unlock(&escore->access_lock);
        }
 
-       if (ret)
-               goto out;
-
-       escore->pm_state = ES_PM_ASLEEP;
-
-       /* Disable the clocks */
-       if (escore_priv.pdata->esxxx_clk_cb)
-               escore_priv.pdata->esxxx_clk_cb(0);
-
-       if (escore_priv.dev && device_may_wakeup(escore_priv.dev))
-               enable_irq_wake(gpio_to_irq(escore_priv.pdata->gpiob_gpio));
-out:
+       dev_dbg(dev, "%s() complete %d\n", __func__, ret);
+       pr_info("%s(): @@@@@@ Exit #####\n", __func__);
        return ret;
 }
-int escore_system_resume(struct device *dev)
+static int escore_system_resume(struct device *dev)
 {
-       int ret = 0;
        struct escore_priv *escore = &escore_priv;
-
+       int ret = 0;
+       pr_info("%s(): @@@@@@ Entry #####\n", __func__);
        dev_dbg(dev, "%s()\n", __func__);
 
-       /* Voice Wakeup case */
-       if (escore->pm_state == ES_PM_NORMAL) {
-               dev_dbg(dev, "%s() - already awake\n", __func__);
+       if (escore->dev != dev) {
+               dev_dbg(dev, "%s() Invalid device\n", __func__);
                return 0;
        }
 
-       if (escore->voice_sense &&
-               escore->vs_ops.escore_is_voicesense_sleep_enable(escore))
-               ret = escore_vs_resume(dev);
-       else
-               ret = escore_non_vs_resume(dev);
-
-       if (!ret)
-               escore->pm_state = ES_PM_NORMAL;
-
-       if (escore_priv.dev && device_may_wakeup(escore_priv.dev))
-               disable_irq_wake(gpio_to_irq(escore_priv.pdata->gpiob_gpio));
-
-       /* Bring the device to full powered state upon system resume */
-       pm_runtime_disable(dev);
-       pm_runtime_mark_last_busy(escore_priv.dev);
-       pm_runtime_set_active(dev);
-       pm_runtime_enable(dev);
+       /* If keyword is detected, chip will be in full power mode but
+        * RPM status will be RPM_SUSPENDED and hence it should be set
+        * to RPM_ACTIVE manually.
+        */
+       if (escore->escore_power_state == ES_SET_POWER_STATE_NORMAL) {
+               pm_runtime_disable(dev);
+               pm_runtime_mark_last_busy(escore->dev);
+               ret = pm_runtime_set_active(dev);
+               pm_runtime_enable(dev);
 
+       }
        dev_dbg(dev, "%s() complete %d\n", __func__, ret);
-
+       pr_info("%s(): @@@@@@ Exit #####\n", __func__);
        return ret;
 }
 
@@ -388,10 +323,10 @@ static int escore_runtime_idle(struct device *dev)
        return -EAGAIN;
 }
 
-int escore_generic_suspend(struct device *dev)
+static int escore_generic_suspend(struct device *dev)
 {
-       int ret = 0;
        struct escore_priv *escore = &escore_priv;
+       int ret = 0;
 
        dev_dbg(dev, "%s()\n", __func__);
 
@@ -400,15 +335,25 @@ int escore_generic_suspend(struct device *dev)
                return 0;
        }
 
-       if (escore->system_suspend)
-               escore_system_suspend(dev);
+       /* SLIMbus stack registers system PM ops instead of runtime PM ops
+        * in its driver. Because of this, when runtime suspend of SLIMbus
+        * is called, it calls sysetm suspend ops function of escore driver.
+        * Thus it is required to identify runtime suspend and separate it.
+        * escore driver does it by using system PM dev->pm.is_prepared and
+        * dev->pm.is_suspended flags.
+        * Based on type of suspend, appropriate suspend function is called.
+        */
+       if (escore->dev->power.is_prepared)
+               ret = escore_system_suspend(dev);
        else
-               escore_runtime_suspend(dev);
+               ret = escore_runtime_suspend(dev);
+
+       dev_dbg(dev, "%s() complete %d\n", __func__, ret);
 
        return ret;
 }
 
-int escore_generic_resume(struct device *dev)
+static int escore_generic_resume(struct device *dev)
 {
        int ret = 0;
        struct escore_priv *escore = &escore_priv;
@@ -420,137 +365,156 @@ int escore_generic_resume(struct device *dev)
                return 0;
        }
 
-       if (escore->system_suspend)
-               escore_system_resume(dev);
+       /* SLIMbus stack registers system PM ops instead of runtime PM ops
+        * in its driver. Because of this, when runtime resume of SLIMbus
+        * is called, it calls sysetm resume ops function of escore driver.
+        * Thus it is required to identify runtime resume and separate it.
+        * escore driver does it by using system PM dev->pm.is_prepared and
+        * dev->pm.is_suspended flags.
+        * Based on type of resume, appropriate resume function is called.
+        */
+       if (escore->dev->power.is_suspended)
+               ret = escore_system_resume(dev);
        else
-               escore_runtime_resume(dev);
+               ret = escore_runtime_resume(dev);
+
+       dev_dbg(dev, "%s() complete %d\n", __func__, ret);
 
        return ret;
 }
 
-int escore_prepare(struct device *dev)
+static int escore_prepare(struct device *dev)
 {
        struct escore_priv *escore = &escore_priv;
+       int ret = 0;
 
        dev_dbg(dev, "%s()\n", __func__);
-
-       if (escore->dev != dev)
+       pr_info("%s(): @@@@@@ Enter #####\n", __func__);
+       if (escore->dev != dev) {
                dev_dbg(dev, "%s() Invalid device\n", __func__);
-       else
-               escore->system_suspend = 1;
+               return 0;
+       }
+
+       if (!es_ready_to_suspend(escore)) {
+               dev_err(dev, "%s() - Not ready for suspend\n", __func__);
+               msleep(10);
+               return -EAGAIN;
+       }
+
+       if (escore->intr_recvd) {
+               dev_err(dev, "%s() - ISR in process\n", __func__);
+               pr_info("%s(): @@@@@@ ISR in process #####\n", __func__);
+               msleep(100);
+               return -EAGAIN;
+       }
 
-       return 0;
+       if (escore->disable_codec_irq) {
+               ret = escore->disable_codec_irq(escore);
+               if (ret < 0) {
+                       msleep(10);
+                       return -EAGAIN;
+               }
+       }
+
+       dev_dbg(dev, "%s() complete %d\n", __func__, ret);
+       pr_info("%s(): @@@@@@ Exit #####\n", __func__);
+       return ret;
 }
 
-void escore_complete(struct device *dev)
+static void escore_complete(struct device *dev)
 {
        struct escore_priv *escore = &escore_priv;
 
        dev_dbg(dev, "%s()\n", __func__);
-
-       if (escore->dev != dev)
+       pr_info("%s(): @@@@@@ Enter #####\n", __func__);
+       if (escore->dev != dev) {
                dev_dbg(dev, "%s() Invalid device\n", __func__);
-       else
-               escore->system_suspend = 0;
+               return;
+       }
+
+       wake_up_interruptible(&escore->irq_waitq);
+       if (escore->enable_codec_irq)
+               escore->enable_codec_irq(escore);
+       pr_info("%s(): @@@@@@ Exit #####\n", __func__);
 }
 
+
 const struct dev_pm_ops escore_pm_ops = {
        .suspend = escore_generic_suspend,
        .resume = escore_generic_resume,
-       .prepare = escore_prepare,
        .complete = escore_complete,
+       .prepare = escore_prepare,
        .runtime_suspend = escore_runtime_suspend,
        .runtime_resume = escore_runtime_resume,
        .runtime_idle = escore_runtime_idle,
 };
 
-void escore_pm_init(void)
-{
-
-       if (escore_priv.voice_sense) {
-               escore_priv.vs_pm_ops.suspend = escore_vs_suspend;
-               escore_priv.vs_pm_ops.resume = escore_vs_resume;
-       }
-       escore_priv.non_vs_pm_ops.suspend = escore_non_vs_suspend;
-       escore_priv.non_vs_pm_ops.resume = escore_non_vs_resume;
-
-       return;
-}
-
 void escore_pm_enable(void)
-{
-       dev_dbg(escore_priv.dev, "%s()\n", __func__);
-       escore_priv.pm_enable = 1;
-       pm_runtime_set_active(escore_priv.dev);
-       pm_runtime_enable(escore_priv.dev);
-       pm_runtime_set_autosuspend_delay(escore_priv.dev,
-                                       ES_PM_AUTOSUSPEND_DELAY);
-       pm_runtime_use_autosuspend(escore_priv.dev);
-       device_init_wakeup(escore_priv.dev, true);
-       return;
-}
-
-void escore_pm_disable(void)
 {
        struct escore_priv *escore = &escore_priv;
-       struct device *xdev = escore->dev;
-
-       escore->pm_enable = 0;
-       if (escore->pm_state == ES_PM_RUNTIME_SLEEP ||
-                       escore->pm_state == ES_PM_ASLEEP) {
-               dev_dbg(xdev, "%s(): Wakeup chip before Runtime PM disable\n",
-                               __func__);
-               escore_runtime_resume(xdev);
-       }
-       pm_runtime_disable(xdev);
-       return;
-}
+       int ret = 0;
 
-void escore_pm_vs_enable(struct escore_priv *escore, bool value)
-{
-       struct device *xdev = escore->dev;
        dev_dbg(escore->dev, "%s()\n", __func__);
-       if (xdev) {
-               if (value == true)
-                       device_wakeup_enable(xdev);
-               else
-                       device_wakeup_disable(xdev);
+
+       if(escore->pm_enable) {
+               pr_err("%s(): Already Enabled\n", __func__);
+               return;
        }
+
+       escore->pm_enable = ES_PM_ON;
+       escore->pm_status = ES_PM_ON;
+       pm_runtime_set_active(escore->dev);
+       pm_runtime_mark_last_busy(escore->dev);
+       pm_runtime_set_autosuspend_delay(escore->dev, ES_PM_AUTOSUSPEND_DELAY);
+       pm_runtime_use_autosuspend(escore->dev);
+       pm_runtime_enable(escore->dev);
+       device_init_wakeup(escore->dev, true);
+       if(pm_runtime_get_sync(escore->dev) >= 0) {
+               ret = pm_runtime_put_sync_autosuspend(escore->dev);
+               if (ret < 0){
+                       dev_err(escore->dev,
+                               "%s() escore PM put failed ret = %d\n",
+                               __func__, ret);
+               }
+       } else
+               dev_err(escore->dev,
+                       "%s() escore PM get failed ret = %d\n", __func__, ret);
        return;
 }
 
 int escore_pm_get_sync(void)
 {
+       struct escore_priv *escore = &escore_priv;
        int ret = 0;
-       dev_dbg(escore_priv.dev, "%s()\n", __func__);
-       if (mutex_trylock(&escore_priv.pm_mutex)) {
-               if (escore_priv.pm_enable == 1) {
-                       if (!escore_priv.system_suspend)
-                               ret = pm_runtime_get_sync(escore_priv.dev);
-               }
-               mutex_unlock(&escore_priv.pm_mutex);
-       }
+
+       dev_dbg(escore->dev, "%s()\n", __func__);
+
+       if (!escore->pm_enable)
+               return 0;
+
+       escore->sleep_abort = 1;
+       ret = pm_runtime_get_sync(escore->dev);
+       escore->sleep_abort = 0;
+
        return ret;
 }
 
 void escore_pm_put_autosuspend(void)
 {
+       struct escore_priv *escore = &escore_priv;
        int ret = 0;
-       dev_dbg(escore_priv.dev, "%s()\n", __func__);
-       if (mutex_trylock(&escore_priv.pm_mutex)) {
-               if (escore_priv.pm_enable == 1 && !escore_priv.system_suspend) {
-                       pm_runtime_mark_last_busy(escore_priv.dev);
-                       ret = pm_runtime_put_sync_autosuspend(escore_priv.dev);
-                       if (ret)
-                               dev_err(escore_priv.dev, "%s() - failed\n",
-                                               __func__);
-               }
-               mutex_unlock(&escore_priv.pm_mutex);
-       }
 
-       return;
-}
+       dev_dbg(escore->dev, "%s()\n", __func__);
+
+       if (!escore->pm_enable)
+               return;
+
+       pm_runtime_mark_last_busy(escore->dev);
 
+       ret = pm_runtime_put_sync_autosuspend(escore->dev);
+       if (ret)
+               dev_err(escore->dev, "%s(): fail %d\n", __func__, ret);
+}
 
 bool escore_is_probe_error(void)
 {
index 3c2696ab1d1d2c10e75f4ecc2273a20e090ca4e9..d0badf6af921ac761bbc1a9f1a421e0fa63284f4 100644 (file)
@@ -574,6 +574,7 @@ int escore_slim_read(struct escore_priv *escore, void *buf, int len)
                .comp = NULL,
        };
 
+
        rc = slim_get_logical_addr(sbdev, escore->gen0_client->e_addr,
                        6, &(escore->gen0_client->laddr));
        if (rc)
@@ -591,11 +592,14 @@ int escore_slim_read(struct escore_priv *escore, void *buf, int len)
                usleep_range(SMB_DELAY, SMB_DELAY + 5);
        } while (--retry);
 
-       if (rc != 0)
+       if (rc != 0) {
                dev_err(&sbdev->dev,
                        "%s: Error read failed rc=%d after %d retries\n",
                        __func__, rc, MAX_SMB_TRIALS);
 
+               ESCORE_FW_RECOVERY_FORCED_OFF(escore);
+       }
+
        return rc;
 }
 
@@ -653,6 +657,9 @@ int escore_slim_write(struct escore_priv *escore, const void *buf, int len)
                wr += sz;
        }
 
+       if (rc)
+               ESCORE_FW_RECOVERY_FORCED_OFF(escore);
+
        return rc;
 }
 
@@ -666,26 +673,26 @@ int escore_slim_cmd(struct escore_priv *escore, u32 cmd, u32 *resp)
 
        dev_dbg(&sbdev->dev,
                        "%s: cmd=0x%08x  sr=0x%08x\n", __func__, cmd, sr);
+       INC_DISABLE_FW_RECOVERY_USE_CNT(escore);
 
+       if ((escore->cmd_compl_mode == ES_CMD_COMP_INTR) && !sr)
+               escore_set_api_intr_wait(escore);
+
+       *resp = 0;
        cmd = cpu_to_le32(cmd);
        err = escore_slim_write(escore, &cmd, sizeof(cmd));
        dev_dbg(&sbdev->dev, "%s: err=%d, cmd_cmpl_mode=%d\n",
                 __func__, err, escore->cmd_compl_mode);
        if (err || sr)
-               return err;
+               goto cmd_exit;
 
        do {
                if (escore->cmd_compl_mode == ES_CMD_COMP_INTR) {
                        pr_debug("%s(): Waiting for API interrupt. Jiffies:%lu",
                                        __func__, jiffies);
-                       err = wait_for_completion_timeout(&escore->cmd_compl,
-                                       msecs_to_jiffies(ES_RESP_TOUT_MSEC));
-                       if (!err) {
-                               pr_debug("%s(): API Interrupt wait timeout\n",
-                                               __func__);
-                               err = -ETIMEDOUT;
+                       err = escore_api_intr_wait_completion(escore);
+                       if (err)
                                break;
-                       }
                } else {
                        pr_debug("%s(): Polling method\n", __func__);
                        usleep_range(ES_RESP_POLL_TOUT,
@@ -697,16 +704,16 @@ int escore_slim_cmd(struct escore_priv *escore, u32 cmd, u32 *resp)
                dev_dbg(&sbdev->dev, "%s: *resp=0x%08x\n", __func__, *resp);
                if (err) {
                        dev_dbg(&sbdev->dev,
-                               "%s: escore_slim_read() failure\n", __func__);
+                               "%s: slim_read() fail %d\n", __func__, err);
                } else if ((*resp & ES_ILLEGAL_CMD) == ES_ILLEGAL_CMD) {
                        dev_err(&sbdev->dev, "%s: illegal command 0x%08x\n",
-                               __func__, cmd);
+                               __func__, le32_to_cpu(cmd));
                        err = -EINVAL;
                        goto cmd_exit;
                } else if (*resp == ES_NOT_READY) {
                        dev_dbg(&sbdev->dev,
                                "%s: escore_slim_read() not ready\n", __func__);
-                       err = -ETIMEDOUT;
+                       err = -EBUSY;
                } else {
                        goto cmd_exit;
                }
@@ -715,6 +722,11 @@ int escore_slim_cmd(struct escore_priv *escore, u32 cmd, u32 *resp)
        } while (retry != 0 && escore->cmd_compl_mode != ES_CMD_COMP_INTR);
 
 cmd_exit:
+       update_cmd_history(le32_to_cpu(cmd), *resp);
+       DEC_DISABLE_FW_RECOVERY_USE_CNT(escore);
+       if (err && ((*resp & ES_ILLEGAL_CMD) != ES_ILLEGAL_CMD))
+               ESCORE_FW_RECOVERY_FORCED_OFF(escore);
+
        return err;
 }
 
@@ -1006,12 +1018,14 @@ int escore_slim_boot_setup(struct escore_priv *escore)
 
        rc = escore_slim_cmd(escore, boot_cmd, &boot_ack);
        if (rc < 0) {
-               pr_err("%s(): firmware load failed boot slim cmd\n", __func__);
+               pr_err("%s(): firmware load failed boot slim cmd %d\n",
+                      __func__, rc);
                goto escore_bootup_failed;
        }
        pr_debug("%s(): boot_ack = 0x%08x\n", __func__, boot_ack);
        if (boot_ack != ES_SLIM_BOOT_ACK) {
-               pr_err("%s(): firmware load failed boot ack pattern", __func__);
+               pr_err("%s(): firmware load failed boot ack pattern (0x%x)",
+                      __func__, boot_ack);
                rc = -EIO;
                goto escore_bootup_failed;
        }
@@ -1044,8 +1058,8 @@ int escore_slim_boot_finish(struct escore_priv *escore)
                                __func__, sync_cmd);
                rc = escore_slim_cmd(escore, sync_cmd, &sync_ack);
                if (rc < 0) {
-                       pr_err("%s(): firmware load failed sync write\n",
-                                       __func__);
+                       pr_err("%s(): firmware load failed sync write %d\n",
+                              __func__, rc);
                        continue;
                }
                pr_debug("%s(): sync_ack = 0x%08x\n", __func__, sync_ack);
@@ -1121,8 +1135,8 @@ static int escore_dt_parse_slim_dev_info(struct slim_device *slim_gen,
                                 escore_priv.interface_device_name,
                                 &slim_ifd->name);
        if (rc < 0) {
-               dev_err(dev, "%s(): %s fail for %s", __func__,
-                       dev->of_node->full_name, slim_ifd->name);
+               dev_err(dev, "%s(): %s fail (%d) for %s", __func__,
+                       dev->of_node->full_name, rc, slim_ifd->name);
                return rc;
        }
 
@@ -1150,6 +1164,8 @@ static void escore_slim_setup_pri_intf(struct escore_priv *escore)
        escore->bus.ops.read = escore_slim_read;
        escore->bus.ops.write = escore_slim_write;
        escore->bus.ops.cmd = escore_slim_cmd;
+       escore->bus.ops.cpu_to_bus = escore_cpu_to_slim;
+       escore->bus.ops.bus_to_cpu = escore_slim_to_cpu;
 
 #ifndef CONFIG_SLIMBUS_MSM_NGD
        /* Fix-Me: Board may not be ready by now. so this may fail */
@@ -1168,17 +1184,17 @@ static int escore_slim_setup_high_bw_intf(struct escore_priv *escore)
        escore->bus.ops.high_bw_cmd = escore_slim_cmd;
        escore->boot_ops.setup = escore_slim_boot_setup;
        escore->boot_ops.finish = escore_slim_boot_finish;
-       escore->bus.ops.cpu_to_bus = escore_cpu_to_slim;
-       escore->bus.ops.bus_to_cpu = escore_slim_to_cpu;
+       escore->bus.ops.cpu_to_high_bw_bus = escore_cpu_to_slim;
+       escore->bus.ops.high_bw_bus_to_cpu = escore_slim_to_cpu;
 
 
        rc = escore->probe(&escore->gen0_client->dev);
        if (rc)
                goto out;
 
+       mutex_lock(&escore->access_lock);
        rc = escore->boot_ops.bootup(escore);
-       if (rc)
-               goto out;
+       mutex_unlock(&escore->access_lock);
 
 out:
 
@@ -1231,7 +1247,8 @@ static int populate_and_trigger_reset(struct device *dev)
                rc = gpio_direction_output(reset_gpio, 0);
                if (rc < 0) {
                        dev_err(escore_priv.dev,
-                               "%s(): es705_reset direction failed", __func__);
+                               "%s(): es705_reset direction fail %d\n",
+                               __func__, rc);
                        return rc;
                }
                gpio_set_value(reset_gpio, 0);
@@ -1337,14 +1354,8 @@ out:
 
 static int escore_slim_remove(struct slim_device *sbdev)
 {
-       struct esxxx_platform_data *pdata = sbdev->dev.platform_data;
-
        dev_dbg(&sbdev->dev, "%s(): sbdev->name = %s\n", __func__, sbdev->name);
 
-       gpio_free(pdata->reset_gpio);
-       gpio_free(pdata->wakeup_gpio);
-       gpio_free(pdata->gpioa_gpio);
-
        snd_soc_unregister_codec(&sbdev->dev);
 
        return 0;
index 5500eff038382ee3e6f34934519973f6ad66f692..111c72976bcfab36cceb403777cbd02429204633 100644 (file)
@@ -35,8 +35,9 @@ static int escore_spi_read(struct escore_priv *escore, void *buf, int len)
        if (rc < 0) {
                dev_err(&escore_spi->dev, "%s(): error %d reading SR\n",
                        __func__, rc);
-               return rc;
+               ESCORE_FW_RECOVERY_FORCED_OFF(escore);
        }
+
        return rc;
 }
 
@@ -109,6 +110,161 @@ static int escore_spi_write(struct escore_priv *escore,
 
        if (rem != 0)
                rc = spi_write(escore_spi, align, 4 - rem);
+       if (rc < 0)
+               ESCORE_FW_RECOVERY_FORCED_OFF(escore);
+
+       return rc;
+}
+
+static int escore_spi_high_bw_write(struct escore_priv *escore,
+                           const void *buf, int len)
+{
+       int rc = 0;
+       int rem = 0;
+       char align[4] = {0};
+
+#ifdef CONFIG_SND_SOC_ES_SPI_WRITE_DMA_MODE
+       int dma_bytes = 0;
+       int non_dma_bytes = 0, room = 0, bytes = 0;
+       unsigned long pfn = 0;
+       const void *current_vaddr =  NULL;
+       void *kaddr = NULL;
+       int offset = 0;
+#endif
+       /* Check if length is 4 byte aligned or not
+          If not aligned send extra bytes after write */
+       if ((len > 4) && (len % 4 != 0)) {
+               rem = len % 4;
+               dev_info(escore->dev,
+                       "Alignment required 0x%x bytes\n", rem);
+       }
+
+/* Buffer data can be transmitted by the SPI controller
+ * using either DMA mode or polling mode.
+ * In DMA mode the SPI controller directly takes data from memory without
+ * any interference from processor whereas in polling mode processor is
+ * utilized for transferring buffer data from memory to SPI controller.
+ * As per the implementation of SPI controller a threshold limit is
+ * defined which decides the mode of transfer.
+ * So when number of bytes to be transferred exceeds threshold limit
+ * DMA mode is utilized, otherwise polling mode is utilized.
+ */
+#ifdef CONFIG_SND_SOC_ES_SPI_WRITE_DMA_MODE
+       if (is_vmalloc_or_module_addr(buf)) {
+
+               /* If the buffer is not page aligned,
+                * transfer the number of bytes from the page offset of buffer
+                * using DMA mode if number of bytes are greater than
+                * ES_SPI_DMA_MIN_BYTES otherwise use non dma mode.
+                * Go to next page if still remaining bytes of data exist.
+                */
+               if (((unsigned long)buf & (~PAGE_MASK))) {
+                       current_vaddr = buf;
+                       offset = (unsigned long)current_vaddr & (~PAGE_MASK);
+                       bytes = len;
+                       room = PAGE_SIZE - offset;
+                       bytes = ((bytes < room) ? bytes : room);
+
+                       /* DMA mode requires buffer address which has
+                        * a direct mapping with physical address,So
+                        * deduce the physical page frame number from vmalloc
+                        * address and from that deduce the virtual address.
+                        */
+                       if (bytes >= ES_SPI_DMA_MIN_BYTES) {
+                               pfn = vmalloc_to_pfn(current_vaddr);
+                               kaddr = pfn_to_kaddr(pfn);
+                               kaddr += offset;
+                       } else {
+
+                       /* Since ES_SPI_DMA_MIN_BYTES
+                        * may vary across different platforms,
+                        * For number of bytes < ES_SPI_DMA_MIN_BYTES
+                        * the SPI controller may use either DMA mode
+                        * or polling mode.
+                        * So copy the buffer from vmalloc address
+                        * to a kernel logical address so that it can be
+                        * utilized for both DMA and polling mode.
+                        */
+                               kaddr = kzalloc(bytes, GFP_KERNEL | GFP_DMA);
+                               memcpy(kaddr, current_vaddr, bytes);
+                       }
+                       rc = spi_write(escore_spi, kaddr, bytes);
+
+                       if (bytes < ES_SPI_DMA_MIN_BYTES)
+                               kfree(kaddr);
+
+                       if (rc < 0) {
+                               dev_err(escore->dev,
+                                       "%s(): SPI Write failed rc = %d\n",
+                                       __func__, rc);
+                               goto spi_write_err;
+                       }
+
+                       len -= bytes;
+
+                       if (len == 0) {
+                               if (rem)
+                                       rc = spi_write(escore_spi,
+                                                       align, 4 - rem);
+                               goto spi_write_err;
+                       }
+
+                       current_vaddr += bytes;
+                       buf = current_vaddr;
+               }
+
+               non_dma_bytes = ((len % PAGE_SIZE < ES_SPI_DMA_MIN_BYTES) ?
+                               len % PAGE_SIZE : 0);
+               dma_bytes = len - non_dma_bytes;
+               current_vaddr = buf;
+
+               while  (dma_bytes > 0) {
+                       pfn = vmalloc_to_pfn(current_vaddr);
+                       kaddr = pfn_to_kaddr(pfn);
+                       rc = spi_write(escore_spi, kaddr,
+                                       (dma_bytes > PAGE_SIZE) ?
+                                       PAGE_SIZE : dma_bytes);
+                       if (rc < 0) {
+                               dev_err(escore->dev,
+                                       "%s(): SPI Write failed rc = %d\n",
+                                       __func__, rc);
+                               goto spi_write_err;
+                       }
+                       current_vaddr += PAGE_SIZE;
+                       dma_bytes -= PAGE_SIZE;
+               }
+
+               if (non_dma_bytes) {
+                       kaddr = kzalloc(non_dma_bytes, GFP_KERNEL | GFP_DMA);
+                       memcpy(kaddr, current_vaddr, non_dma_bytes);
+                       rc = spi_write(escore_spi, kaddr, non_dma_bytes);
+                       kfree(kaddr);
+                       if (rc < 0) {
+                               dev_err(escore->dev,
+                                       "%s(): SPI Write failed rc = %d\n",
+                                       __func__, rc);
+                               goto spi_write_err;
+
+                       }
+               }
+               len = 0;
+       }
+#endif
+       if (len) {
+               rc = spi_write(escore_spi, buf, len);
+               if (rc < 0) {
+                       dev_err(escore->dev,
+                               "%s(): SPI Write failed rc = %d\n",
+                               __func__, rc);
+                       goto spi_write_err;
+               }
+       }
+
+       if (rem != 0)
+               rc = spi_write(escore_spi, align, 4 - rem);
+spi_write_err:
+       if (rc < 0)
+               ESCORE_FW_RECOVERY_FORCED_OFF(escore);
 
        return rc;
 }
@@ -119,16 +275,15 @@ static int escore_spi_cmd(struct escore_priv *escore,
        int err = 0;
        int sr = cmd & BIT(28);
        int retry = ES_SPI_MAX_RETRIES;
-       u16 resp16;
+       u32 resp32;
 
        dev_dbg(escore->dev,
                        "%s: cmd=0x%08x  sr=0x%08x\n", __func__, cmd, sr);
+       INC_DISABLE_FW_RECOVERY_USE_CNT(escore);
 
        if ((escore->cmd_compl_mode == ES_CMD_COMP_INTR) && !sr)
-               escore->wait_api_intr = 1;
-
+               escore_set_api_intr_wait(escore);
        *resp = 0;
-
        cmd = cpu_to_be32(cmd);
        err = escore_spi_write(escore, &cmd, sizeof(cmd));
        if (err || sr)
@@ -137,15 +292,9 @@ static int escore_spi_cmd(struct escore_priv *escore,
        if (escore->cmd_compl_mode == ES_CMD_COMP_INTR) {
                pr_debug("%s(): Waiting for API interrupt. Jiffies:%lu",
                                __func__, jiffies);
-               err = wait_for_completion_timeout(&escore->cmd_compl,
-                               msecs_to_jiffies(ES_RESP_TOUT_MSEC));
-               if (!err) {
-                       pr_err("%s(): API Interrupt wait timeout\n",
-                                       __func__);
-                       escore->wait_api_intr = 0;
-                       err = -ETIMEDOUT;
+               err = escore_api_intr_wait_completion(escore);
+               if (err)
                        goto cmd_exit;
-               }
        }
 
        usleep_range(ES_SPI_RETRY_DELAY, ES_SPI_RETRY_DELAY + 50);
@@ -153,31 +302,20 @@ static int escore_spi_cmd(struct escore_priv *escore,
        do {
                --retry;
                if (escore->cmd_compl_mode != ES_CMD_COMP_INTR) {
-
-                               usleep_range(ES_SPI_1MS_DELAY,
+                       usleep_range(ES_SPI_1MS_DELAY,
                                        ES_SPI_1MS_DELAY + 50);
                }
 
-               err = escore_spi_read(escore, &resp16, sizeof(resp16));
+               err = escore_spi_read(escore, &resp32, sizeof(resp32));
                dev_dbg(escore->dev, "%s: err=%d\n", __func__, err);
-               *resp = (be16_to_cpu(resp16) << 16);
+               *resp = (be32_to_cpu(resp32));
                dev_dbg(escore->dev, "%s: *resp=0x%08x\n", __func__, *resp);
                if (err) {
                        dev_dbg(escore->dev,
                                "%s: escore_spi_read() failure, err=%d\n",
                                __func__, err);
                }
-               if (resp16 != 0) {
-                       err = escore_spi_read(escore, &resp16, sizeof(resp16));
-                       (*resp) |= be16_to_cpu(resp16);
-                       dev_dbg(escore->dev, "%s: *resp=0x%08x\n",
-                                       __func__, *resp);
-                       if (err) {
-                               dev_dbg(escore->dev,
-                                       "%s: escore_spi_read() failure, err=%d\n",
-                                       __func__, err);
-                       }
-               } else {
+               if (*resp == 0) {
                        if (retry == 0) {
                                err = -ETIMEDOUT;
                                dev_err(escore->dev,
@@ -187,11 +325,27 @@ static int escore_spi_cmd(struct escore_priv *escore,
                        } else {
                                continue;
                        }
+               } else if ((*resp >> 16) == 0) {
+                       /* Fw SPI interface is 16bit. So in the 32bit
+                        * read of command's response, sometimes fw
+                        * sends first 16bit in first 32bit read and
+                        * second 16bit in second 32bit. So this is
+                        * special condition handling to make response.
+                        */
+                       err = escore_spi_read(escore, &resp32, sizeof(resp32));
+                       if (err) {
+                               dev_dbg(escore->dev,
+                                       "%s: escore_spi_read() failure, err=%d\n",
+                                       __func__, err);
+                       } else {
+                               *resp = *resp << 16;
+                               *resp |= (be32_to_cpu(resp32) >> 16);
+                       }
                }
 
                if ((*resp & ES_ILLEGAL_CMD) == ES_ILLEGAL_CMD) {
                        dev_err(escore->dev, "%s: illegal command 0x%08x\n",
-                               __func__, cmd);
+                               __func__, be32_to_cpu(cmd));
                        err = -EINVAL;
                        goto cmd_exit;
                } else {
@@ -199,10 +353,13 @@ static int escore_spi_cmd(struct escore_priv *escore,
                }
 
        } while (retry != 0);
-       dev_dbg(escore->dev, "%s: err=%d  *resp=0x%08x\n", __func__, err, *resp);
 
 cmd_exit:
        update_cmd_history(be32_to_cpu(cmd), *resp);
+       DEC_DISABLE_FW_RECOVERY_USE_CNT(escore);
+       if (err && ((*resp & ES_ILLEGAL_CMD) != ES_ILLEGAL_CMD))
+               ESCORE_FW_RECOVERY_FORCED_OFF(escore);
+
        return err;
 }
 
@@ -226,168 +383,138 @@ static int escore_spi_setup(u32 speed)
        return status;
 }
 
+static int escore_spi_set_bits_per_word(u8 bits)
+{
+       int status;
+
+       /* set SPI bits per word to
+        *      - 16 bits per word for before fw download
+        *      - 32 bits per word for rest operations */
+       switch (bits) {
+       case ES_SPI_8BITS_PER_WORD:
+       case ES_SPI_16BITS_PER_WORD:
+       case ES_SPI_32BITS_PER_WORD:
+               break;
+       default:
+               pr_err("%s : Unsupported SPI bits per word %d\n",
+                               __func__, bits);
+               return -EINVAL;
+       }
+       escore_spi->bits_per_word = bits;
+       status = spi_setup(escore_spi);
+       if (status < 0) {
+               pr_err("%s : can't setup %s, status %d\n", __func__,
+                               (char *)dev_name(&escore_spi->dev), status);
+       } else {
+               pr_debug("%s(): SPI bits per word changed to %d\n",
+                               __func__, escore_spi->bits_per_word);
+       }
+       return status;
+}
+
 static int escore_spi_datablock_read(struct escore_priv *escore, void *buf,
-               size_t len, int id)
+               size_t len)
 {
        int rc;
-       int size;
-       u32 cmd;
        int rdcnt = 0;
-       u32 resp;
-       u8 flush_extra_blk = 0;
-       u32 flush_buf;
        u16 temp;
 
-       /* Reset read data block size */
-       escore->datablock_dev.rdb_read_count = 0;
-
-       cmd = (ES_READ_DATA_BLOCK << 16) | (id & 0xFFFF);
-
-       rc = escore_spi_cmd(escore, cmd, &resp);
+       rc = escore_spi_read(escore, (char *)buf, len);
        if (rc < 0) {
-               dev_err(escore->dev, "%s(): escore_spi_cmd() failed rc = %d\n",
-                        __func__, rc);
-               goto out;
-       }
-       if ((resp >> 16) != ES_READ_DATA_BLOCK) {
-               dev_err(escore->dev, "%s(): Invalid respn received: 0x%08x\n",
-                               __func__, resp);
-               rc = -EINVAL;
-               goto out;
-       }
-
-       size = resp & 0xFFFF;
-       dev_dbg(escore->dev, "%s(): RDB size = %d\n", __func__, size);
-       if (size == 0 || size % 4 != 0) {
-               dev_err(escore->dev,
-                       "%s(): Read Data Block with invalid size:%d\n",
-                       __func__, size);
-               rc = -EINVAL;
-               goto out;
-       }
-
-       if (len != size) {
-               dev_dbg(escore->dev, "%s(): Requested:%zd Received:%d\n",
-                        __func__, len, size);
-               if (len < size)
-                       flush_extra_blk = (size - len) % 4;
-               else
-                       len = size;
+               dev_err(escore->dev, "%s(): Read Data Block error %d\n",
+                               __func__, rc);
+               return rc;
        }
 
-       for (rdcnt = 0; rdcnt < len;) {
-               rc = escore_spi_read(escore, (char *)&temp, sizeof(temp));
-               if (rc < 0) {
-                       dev_err(escore->dev, "%s(): Read Data Block error %d\n",
-                                       __func__, rc);
-                       goto out;
-               }
+       for (rdcnt = 0; rdcnt < len; rdcnt += 2) {
+               temp = *((u16 *)buf);
                temp = be16_to_cpu(temp);
-               memcpy(buf, (char *)&temp, 2);
+               memcpy(buf, (char *)&temp, sizeof(temp));
                buf += 2;
-               rdcnt += 2;
        }
 
-       /* Store read data block size */
-       escore->datablock_dev.rdb_read_count = size;
-
-       /* No need to read in case of no extra bytes */
-       if (flush_extra_blk) {
-               /* Discard the extra bytes */
-               rc = escore_spi_read(escore, &flush_buf, flush_extra_blk);
-               if (rc < 0) {
-                       dev_err(escore->dev, "%s(): Read Data Block error in flushing %d\n",
-                                       __func__, rc);
-                       goto out;
-               }
-       }
-out:
        return rc;
 }
 
 static int escore_spi_boot_setup(struct escore_priv *escore)
 {
-       u32 boot_cmd = ES_SPI_BOOT_CMD;
-       u32 boot_ack;
-       u32 sbl_sync_cmd = ES_SPI_SBL_SYNC_CMD;
-       u32 sbl_sync_ack;
+       u16 boot_cmd = ES_SPI_BOOT_CMD;
+       u16 boot_ack;
+       u16 sbl_sync_cmd = ES_SPI_SYNC_CMD;
+       u16 sbl_sync_ack;
+       int retry = 5;
+       int iteration_count = 0;
        int rc;
-       u32 speed = ES_SPI_FW_SPEED;
-       u8 cmd_compl_mode;
-
-
+       u8 bits_per_word = ES_SPI_16BITS_PER_WORD;
 
        pr_debug("%s(): prepare for fw download\n", __func__);
-       rc = escore_spi_setup(speed);
-       if (rc < 0)
-               goto escore_spi_boot_setup_failed;
-       sbl_sync_cmd = cpu_to_be32(sbl_sync_cmd);
-
-       /* GPIO_A (INTR_API) transits from low to high once
-        * SBL SYNC command response is ready. So, for the command completion
-        * mode to "Interrupt" to read the SBL SYNC response.
-        */
-       cmd_compl_mode = escore->cmd_compl_mode;
-       if (escore->pdata->gpioa_gpio != -1)
-               escore->cmd_compl_mode = ES_CMD_COMP_INTR;
+       rc = escore_spi_set_bits_per_word(bits_per_word);
+       if (rc < 0) {
+               pr_err("%s(): Set SPI %d bits per word failed rc = %d\n",
+                      __func__, bits_per_word, rc);
+               return rc;
+       }
+       msleep(20);
+       sbl_sync_cmd = cpu_to_be16(sbl_sync_cmd);
 
        rc = escore_spi_write(escore, &sbl_sync_cmd, sizeof(sbl_sync_cmd));
+
        if (rc < 0) {
-               pr_err("%s(): firmware load failed sync write\n", __func__);
+               pr_err("%s(): firmware load failed sync write %d\n",
+                      __func__, rc);
                goto escore_spi_boot_setup_failed;
        }
 
-       if (escore->pdata->gpioa_gpio != -1) {
-               rc = wait_for_completion_timeout(&escore->cmd_compl,
-                               msecs_to_jiffies(ES_SBL_RESP_TOUT));
-               if (!rc) {
-                       pr_err("%s(): SBL SYNC response timed out\n", __func__);
-                       rc = -ETIMEDOUT;
-                       goto escore_spi_boot_setup_failed;
-               }
-       } else {
-               usleep_range(10000, 10500);
-       }
+       usleep_range(4000, 4050);
 
        rc = escore_spi_read(escore, &sbl_sync_ack, sizeof(sbl_sync_ack));
-       escore->cmd_compl_mode = cmd_compl_mode;
        if (rc < 0) {
-               pr_err("%s(): firmware load failed sync ack\n",
-                       __func__);
+               pr_err("%s(): firmware load failed sync ack %d\n",
+                      __func__, rc);
                goto escore_spi_boot_setup_failed;
        }
 
-       sbl_sync_ack = be32_to_cpu(sbl_sync_ack);
+       sbl_sync_ack = be16_to_cpu(sbl_sync_ack);
        pr_debug("%s(): SBL SYNC ACK = 0x%08x\n", __func__, sbl_sync_ack);
-       if (sbl_sync_ack != ES_SPI_SBL_SYNC_ACK) {
-               pr_err("%s(): sync ack pattern fail\n", __func__);
+       if (sbl_sync_ack != ES_SPI_SYNC_ACK) {
+               pr_err("%s(): sync ack pattern fail 0x%x\n", __func__,
+                               sbl_sync_ack);
                rc = -EIO;
                goto escore_spi_boot_setup_failed;
        }
+
+       usleep_range(4000, 4050);
        pr_debug("%s(): write ES_BOOT_CMD = 0x%04x\n", __func__, boot_cmd);
-       boot_cmd = cpu_to_be32(boot_cmd);
+       boot_cmd = cpu_to_be16(boot_cmd);
        rc = escore_spi_write(escore, &boot_cmd, sizeof(boot_cmd));
        if (rc < 0) {
-               pr_err("%s(): firmware load failed boot write\n",
-                       __func__);
+               pr_err("%s(): firmware load failed boot write %d\n",
+                      __func__, rc);
                goto escore_spi_boot_setup_failed;
        }
+       do {
+               usleep_range(ES_SPI_1MS_DELAY, ES_SPI_1MS_DELAY + 5);
+               rc = escore_spi_read(escore, &boot_ack, sizeof(boot_ack));
+               if (rc < 0) {
+                       pr_err("%s(): firmware load failed boot ack %d\n",
+                              __func__, rc);
+               }
 
-       usleep_range(ES_SPI_1MS_DELAY, ES_SPI_1MS_DELAY + 5);
-       rc = escore_spi_read(escore, &boot_ack, sizeof(boot_ack));
+               boot_ack = be16_to_cpu(boot_ack);
+               pr_debug("%s(): BOOT ACK = 0x%08x\n", __func__, boot_ack);
+               if (boot_ack != ES_SPI_BOOT_ACK) {
+                       pr_err("%s():boot ack pattern fail 0x%08x", __func__,
+                                       boot_ack);
+                       rc = -EIO;
+                       iteration_count++;
+               }
+       } while (rc && retry--);
        if (rc < 0) {
-               pr_err("%s(): firmware load failed boot ack\n",
-                       __func__);
-               goto escore_spi_boot_setup_failed;
-       }
-
-       boot_ack = be32_to_cpu(boot_ack);
-       pr_debug("%s(): BOOT ACK = 0x%08x\n", __func__, boot_ack);
-       if (boot_ack != ES_SPI_BOOT_ACK) {
-               pr_err("%s(): boot ack pattern fail\n", __func__);
-               rc = -EIO;
+               pr_err("%s(): boot ack pattern fail after %d iterations\n",
+                               __func__, iteration_count);
                goto escore_spi_boot_setup_failed;
        }
+       rc = escore_spi_setup(escore->pdata->spi_fw_download_speed);
 escore_spi_boot_setup_failed:
        return rc;
 }
@@ -398,18 +525,29 @@ int escore_spi_boot_finish(struct escore_priv *escore)
        u32 sync_ack;
        int rc = 0;
        int sync_retry = ES_SYNC_MAX_RETRY;
+       u8 bits_per_word = ES_SPI_32BITS_PER_WORD;
+
+       rc = escore_spi_set_bits_per_word(bits_per_word);
+       if (rc < 0) {
+               pr_err("%s(): Set SPI %d bits per word failed rc = %d\n",
+                      __func__, bits_per_word, rc);
+               return rc;
+       }
 
+       rc = escore_spi_setup(escore->pdata->spi_operational_speed);
+       msleep(50);
        /* sometimes earSmart chip sends success in second sync command */
        do {
                pr_debug("%s(): write ES_SYNC_CMD = 0x%08x\n",
                                __func__, sync_cmd);
                rc = escore_spi_cmd(escore, sync_cmd, &sync_ack);
+               pr_debug("%s(): rc=%d, sync_ack = 0x%08x\n", __func__, rc, \
+                       sync_ack);
                if (rc < 0) {
-                       pr_err("%s(): firmware load failed sync write\n",
-                                       __func__);
+                       pr_err("%s(): firmware load failed sync write %d\n",
+                              __func__, rc);
                        continue;
                }
-               pr_debug("%s(): sync_ack = 0x%08x\n", __func__, sync_ack);
                if (sync_ack != ES_SYNC_ACK) {
                        pr_err("%s(): firmware load failed sync ack pattern",
                                        __func__);
@@ -419,17 +557,85 @@ int escore_spi_boot_finish(struct escore_priv *escore)
                        break;
                }
        } while (sync_retry--);
-       escore_spi->max_speed_hz = ES_SPI_OPERATION_SPEED;
-       rc = escore_spi_setup(escore_spi->max_speed_hz);
        return rc;
 }
 
+static int escore_spi_abort_config(struct escore_priv *escore)
+{
+       int rc;
+
+       rc = escore_spi_setup(escore->pdata->spi_operational_speed);
+       if (rc < 0)
+               pr_err("%s(): config spi failed, rc = %d\n", __func__, rc);
+
+       return rc;
+}
+
+static int escore_spi_wdb_config(struct escore_priv *escore)
+{
+       return escore_spi_setup(escore->pdata->spi_wdb_speed);
+}
+
+static int escore_spi_reset_wdb_config(struct escore_priv *escore)
+{
+       return escore_spi_setup(escore->pdata->spi_operational_speed);
+}
+
+static int escore_spi_populate_dt_data(struct escore_priv *escore)
+{
+       struct esxxx_platform_data *pdata;
+       struct device_node *node = escore_spi->dev.of_node;
+       int rc = -EINVAL;
+
+       /* No node means  no dts provision, like Panda board */
+       if (node == NULL)
+               return 0;
+       pdata = escore->pdata;
+       if (pdata == NULL)
+               return rc;
+
+       /*
+       rc = of_property_read_u32(node, "adnc,spi-fw-download-speed",
+                       &pdata->spi_fw_download_speed);
+       if (rc || pdata->spi_fw_download_speed == 0) {
+               pr_err("%s, Error in parsing adnc,spi-fw-download-speed\n",
+                               __func__);
+               return rc;
+       }
+
+       rc = of_property_read_u32(node, "adnc,spi-operational-speed",
+                       &pdata->spi_operational_speed);
+       if (rc || pdata->spi_operational_speed == 0) {
+               pr_err("%s, Error in parsing adnc,spi-operational-speed\n",
+                               __func__);
+               return rc;
+       }
+       */
+
+       pdata->spi_fw_download_speed = 9600000;
+       pdata->spi_operational_speed = 4800000;
+
+       rc = of_property_read_u32(node, "adnc,spi-wdb-speed",
+                       &pdata->spi_wdb_speed);
+       if (rc || pdata->spi_wdb_speed == 0) {
+               pr_err("%s, Error in parsing adnc,spi-wdb-speed\n", __func__);
+               pr_debug("%s, Use operational speed for writing data block\n",
+                               __func__);
+               pdata->spi_wdb_speed = pdata->spi_operational_speed;
+               rc = 0;
+       }
+
+       return rc;
+
+}
 static void escore_spi_setup_pri_intf(struct escore_priv *escore)
 {
        escore->bus.ops.read = escore_spi_read;
        escore->bus.ops.write = escore_spi_write;
        escore->bus.ops.cmd = escore_spi_cmd;
        escore->streamdev = es_spi_streamdev;
+       escore->bus.ops.cpu_to_bus = escore_cpu_to_spi;
+       escore->bus.ops.bus_to_cpu = escore_spi_to_cpu;
 }
 
 static int escore_spi_setup_high_bw_intf(struct escore_priv *escore)
@@ -438,21 +644,33 @@ static int escore_spi_setup_high_bw_intf(struct escore_priv *escore)
 
        escore->boot_ops.setup = escore_spi_boot_setup;
        escore->boot_ops.finish = escore_spi_boot_finish;
-       escore->bus.ops.high_bw_write = escore_spi_write;
+       escore->bus.ops.high_bw_write = escore_spi_high_bw_write;
        escore->bus.ops.high_bw_read = escore_spi_read;
        escore->bus.ops.high_bw_cmd = escore_spi_cmd;
+       escore->boot_ops.escore_abort_config = escore_spi_abort_config;
        escore->bus.ops.rdb = escore_spi_datablock_read;
-       escore->bus.ops.cpu_to_bus = escore_cpu_to_spi;
-       escore->bus.ops.bus_to_cpu = escore_spi_to_cpu;
+       escore->bus.ops.cpu_to_high_bw_bus = escore_cpu_to_spi;
+       escore->bus.ops.high_bw_bus_to_cpu = escore_spi_to_cpu;
 
        rc = escore->probe(escore->dev);
        if (rc)
                goto out;
 
-       rc = escore->boot_ops.bootup(escore);
+       rc = escore_spi_populate_dt_data(escore);
        if (rc)
                goto out;
 
+       if (escore->pdata->spi_wdb_speed !=
+                       escore->pdata->spi_operational_speed) {
+               escore->datablock_dev.wdb_config = escore_spi_wdb_config;
+               escore->datablock_dev.wdb_reset_config =
+                       escore_spi_reset_wdb_config;
+       }
+
+       mutex_lock(&escore->access_lock);
+       rc = escore->boot_ops.bootup(escore);
+       mutex_unlock(&escore->access_lock);
+
 out:
        return rc;
 }
index bd92ce6966a05068eff839ed094e35482db37d37..e1c79d414867276f57f7d1f7c512c7468a4848e8 100644 (file)
 
 extern struct spi_driver escore_spi_driver;
 
-#define ES_SPI_BOOT_CMD                        0x00000001
-#define ES_SPI_BOOT_ACK                        0x00010001
-#define ES_SPI_SBL_SYNC_CMD            0x80000000
-#define ES_SPI_SBL_SYNC_ACK            0x8000FFFF
-
-#if defined(CONFIG_ARCH_OMAP)
-#define ES_SPI_FW_SPEED        12000000
-#define ES_SPI_OPERATION_SPEED 3000000
-#elif defined(CONFIG_ARCH_MSM)
-#define ES_SPI_FW_SPEED        9600000
-#define ES_SPI_OPERATION_SPEED 4800000
-#elif defined(CONFIG_ARCH_TEGRA)
-#define ES_SPI_FW_SPEED        9600000
-#define ES_SPI_OPERATION_SPEED 2000000
-#endif
+#define ES_SPI_BOOT_CMD                        0x0001
+
+#define ES_SPI_BOOT_ACK                        0x0001
+
+#define ES_SPI_SYNC_CMD                0x0000
+#define ES_SPI_SYNC_ACK                0x0000
+
+#define ES_SPI_8BITS_PER_WORD  8
+#define ES_SPI_16BITS_PER_WORD 16
+#define ES_SPI_32BITS_PER_WORD 32
 
 /* This is obtained after discussion with FW team.*/
 #define ESCORE_SPI_PACKET_LEN 256
@@ -41,8 +36,9 @@ extern struct spi_driver escore_spi_driver;
  */
 #define ES_SPI_STREAM_READ_DELAY 30
 
-#define ES_SPI_SYNCBYTE_CMD            0x00000000
-#define ES_SPI_SYNCBYTE_ACK            0x00000000
+#ifdef CONFIG_SND_SOC_ES_SPI_WRITE_DMA_MODE
+#define ES_SPI_DMA_MIN_BYTES   512
+#endif
 
 extern struct es_stream_device es_spi_streamdev;
 extern int escore_spi_init(void);
index 436501dfe1bae260fc80d7930b6231730ba823d4..6d18b9b67a5dd391889b317def6520537e291666 100644 (file)
@@ -17,7 +17,6 @@
 #include <linux/slab.h>
 #include <linux/err.h>
 #include <linux/kthread.h>
-#include <linux/esxxx.h>
 #include <linux/serial_core.h>
 #include <linux/tty.h>
 #include <linux/fs.h>
@@ -72,14 +71,20 @@ int escore_uart_read(struct escore_priv *escore, void *buf, int len)
 {
        int rc;
 
+       if (unlikely(!escore->uart_ready)) {
+               pr_err("%s(): Error UART is not open\n", __func__);
+               return -EIO;
+       }
+
        rc = escore_uart_read_internal(escore, buf, len);
 
-       if (rc < len)
-               rc = -EIO;
-       else
-               rc = 0;
+       if (rc < len) {
+               pr_err("%s() Uart Read Failed\n", __func__);
+               ESCORE_FW_RECOVERY_FORCED_OFF(escore);
+               return -EIO;
+       }
 
-       return rc;
+       return 0;
 }
 
 int escore_uart_write(struct escore_priv *escore, const void *buf, int len)
@@ -90,7 +95,13 @@ int escore_uart_write(struct escore_priv *escore, const void *buf, int len)
        mm_segment_t oldfs;
        loff_t pos = 0;
 
-        dev_dbg(escore->dev, "%s() size %d\n", __func__, len);
+       if (unlikely(!escore->uart_ready)) {
+               pr_err("%s(): Error UART is not open\n", __func__);
+               return -EIO;
+       }
+
+       dev_dbg(escore->dev, "%s() size %d\n", __func__, len);
+
 
        /*
         * we may call from user context via char dev, so allow
@@ -118,11 +129,14 @@ int escore_uart_write(struct escore_priv *escore, const void *buf, int len)
 err_out:
        /* restore old fs context */
        set_fs(oldfs);
-       if (count_remain)
+       if (count_remain) {
+               pr_err("%s() Uart write Failed\n", __func__);
+               ESCORE_FW_RECOVERY_FORCED_OFF(escore);
                rc = -EIO;
-       else
+       } else {
                rc = 0;
-        pr_debug("%s() returning %d\n", __func__, rc);
+       }
+       pr_debug("%s() returning %d\n", __func__, rc);
 
        return rc;
 }
@@ -136,11 +150,13 @@ int escore_uart_cmd(struct escore_priv *escore, u32 cmd, u32 *resp)
 
        dev_dbg(escore->dev,
                        "%s: cmd=0x%08x sr=0x%08x\n", __func__, cmd, sr);
+       INC_DISABLE_FW_RECOVERY_USE_CNT(escore);
 
+       *resp = 0;
        cmd = cpu_to_be32(cmd);
        err = escore_uart_write(escore, &cmd, sizeof(cmd));
        if (err || sr)
-               return err;
+               goto cmd_exit;
 
        do {
                usleep_range(ES_RESP_POLL_TOUT,
@@ -152,16 +168,16 @@ int escore_uart_cmd(struct escore_priv *escore, u32 cmd, u32 *resp)
                dev_dbg(escore->dev, "%s: *resp=0x%08x\n", __func__, *resp);
                if (err) {
                        dev_dbg(escore->dev,
-                               "%s: escore_uart_read() failure\n", __func__);
+                               "%s: uart_read() fail %d\n", __func__, err);
                } else if ((*resp & ES_ILLEGAL_CMD) == ES_ILLEGAL_CMD) {
                        dev_err(escore->dev, "%s: illegal command 0x%08x\n",
-                               __func__, cmd);
+                               __func__, be32_to_cpu(cmd));
                        err = -EINVAL;
                        goto cmd_exit;
                } else if (*resp == ES_NOT_READY) {
                        dev_dbg(escore->dev,
                                "%s: escore_uart_read() not ready\n", __func__);
-                       err = -ETIMEDOUT;
+                       err = -EBUSY;
                } else {
                        goto cmd_exit;
                }
@@ -170,6 +186,11 @@ int escore_uart_cmd(struct escore_priv *escore, u32 cmd, u32 *resp)
        } while (retry != 0);
 
 cmd_exit:
+       update_cmd_history(be32_to_cpu(cmd), *resp);
+       DEC_DISABLE_FW_RECOVERY_USE_CNT(escore);
+       if (err && ((*resp & ES_ILLEGAL_CMD) != ES_ILLEGAL_CMD))
+               ESCORE_FW_RECOVERY_FORCED_OFF(escore);
+
        return err;
 }
 
@@ -178,8 +199,11 @@ int escore_configure_tty(struct tty_struct *tty, u32 bps, int stop)
        int rc = 0;
 
        struct ktermios termios;
+#if defined(KERNEL_VERSION_3_8_0)
+       termios = tty->termios;
+#else
        termios = *tty->termios;
-
+#endif
        pr_debug("%s(): Requesting baud %u\n", __func__, bps);
 
        termios.c_cflag &= ~(CBAUD | CSIZE | PARENB);   /* clear csize, baud */
@@ -205,8 +229,11 @@ int escore_configure_tty(struct tty_struct *tty, u32 bps, int stop)
 
        rc = tty_set_termios(tty, &termios);
 
+#if defined(KERNEL_VERSION_3_8_0)
+        pr_debug("%s(): New baud %u\n", __func__, tty->termios.c_ospeed);
+#else
         pr_debug("%s(): New baud %u\n", __func__, tty->termios->c_ospeed);
-
+#endif
        return rc;
 }
 EXPORT_SYMBOL_GPL(escore_configure_tty);
@@ -220,8 +247,11 @@ int escore_uart_open(struct escore_priv *escore)
        unsigned long timeout = jiffies + msecs_to_jiffies(60000);
        int attempt = 0;
 
+       atomic_inc(&escore->uart_users);
+
        if (escore->uart_ready) {
-               pr_debug("%s() UART is already open\n", __func__);
+               pr_debug("%s() UART is already open, users count: %d\n",
+                        __func__, atomic_read(&escore->uart_users));
                return 0;
        }
 
@@ -259,8 +289,9 @@ int escore_uart_open(struct escore_priv *escore)
 int escore_uart_close(struct escore_priv *escore)
 {
 
-       if (!escore->uart_ready) {
-               pr_debug("%s() UART is already closed\n", __func__);
+       if (atomic_dec_return(&escore->uart_users)) {
+               pr_debug("%s() UART is busy to close, user count: %d\n",
+                        __func__, atomic_read(&escore->uart_users));
                return 0;
        }
 
@@ -273,11 +304,25 @@ int escore_uart_close(struct escore_priv *escore)
 
 int escore_uart_wait(struct escore_priv *escore)
 {
+#if defined(KERNEL_VERSION_3_8_0)
+       int timeout;
+       DECLARE_WAITQUEUE(wait, current);
+
+       add_wait_queue(&escore_uart.tty->read_wait, &wait);
+       set_task_state(current, TASK_INTERRUPTIBLE);
+       timeout = schedule_timeout(msecs_to_jiffies(50));
+
+       set_task_state(current, TASK_RUNNING);
+       remove_wait_queue(&escore_uart.tty->read_wait, &wait);
+       return timeout;
+#else
+
        /* wait on tty read queue until awoken or for 50ms */
        return wait_event_interruptible_timeout(
                escore_uart.tty->read_wait,
                escore_uart.tty->read_cnt,
                msecs_to_jiffies(50));
+#endif
 }
 
 int escore_uart_config(struct escore_priv *escore)
index 0004188245e1e192936d434735b1ed4f690de470..3fa8f2982fad345612e1976cd3480c3e9df3773d 100644 (file)
@@ -31,7 +31,7 @@
 #elif defined(CONFIG_ARCH_OMAP)
 #define UART_TTY_DEVICE_NODE           "/dev/ttyO3"
 #elif defined(CONFIG_ARCH_EXYNOS)
-#define UART_TTY_DEVICE_NODE           "/dev/ttySAC0"
+#define UART_TTY_DEVICE_NODE           "/dev/ttySAC1"
 #endif
 #define UART_TTY_BAUD_RATE_28_8_K      28800
 #define UART_TTY_BAUD_RATE_460_8_K     460800
index 13dfd5f91b38af35a60621d79aa02c8180b0353f..bfc8f88006f329b93bf62a2a75599fca52997427 100644 (file)
@@ -29,7 +29,6 @@
 #include <sound/initval.h>
 #include <sound/tlv.h>
 #include <linux/kthread.h>
-#include <linux/esxxx.h>
 #include <linux/serial_core.h>
 #include <linux/tty.h>
 
@@ -70,8 +69,8 @@ static int set_sbl_baud_rate(struct escore_priv *escore, u32 sbl_rate_req_cmd)
        rc = escore_uart_write(escore, &sbl_rate_req_cmd,
                        sizeof(sbl_rate_req_cmd));
        if (rc) {
-               pr_err("%s(): Baud rate setting for UART failed\n",
-                               __func__);
+               pr_err("%s(): Baud rate setting for UART fail %d\n",
+                      __func__, rc);
                rc = -EIO;
                return rc;
        }
@@ -136,11 +135,13 @@ static int escore_uart_wakeup(struct escore_priv *escore)
                goto escore_uart_wakeup_exit;
        }
 
-       /* Read an extra byte to flush UART read buffer. If this byte
-        * is not read, an extra byte is received in next UART read
-        * because of above write. No need to check response here.
-        */
-       escore_uart_read(&escore_priv, &wakeup_byte, 1);
+       /* Flush tty buffer to avoid extra byte
+        * received in next read cycle */
+       ret = tty_perform_flush(escore_uart.tty, TCIOFLUSH);
+       if (ret)
+               dev_err(escore->dev,
+                               "%s(): TTY buffer Flush is failed %d",
+                               __func__, ret);
 
 escore_uart_wakeup_exit:
        escore_uart_close(&escore_priv);
@@ -188,6 +189,11 @@ int escore_uart_boot_setup(struct escore_priv *escore)
 
        pr_debug("%s()\n", __func__);
 
+       /* Drop any prior data as we just reset the chip before this */
+       rc = tty_perform_flush(escore_uart.tty, TCIOFLUSH);
+       if (rc)
+               pr_err("%s(): TTY buffer Flush failed %d", __func__, rc);
+
        /* SBL SYNC BYTE 0x00 */
        pr_debug("%s(): write ESCORE_SBL_SYNC_CMD = 0x%02x\n", __func__,
                sbl_sync_cmd);
@@ -245,8 +251,11 @@ int escore_uart_boot_setup(struct escore_priv *escore)
                sbl_rate_req_cmd |= (escore->pdata->ext_clk_rate & 0xff);
 
                rc = set_sbl_baud_rate(escore, sbl_rate_req_cmd);
-               if (rc < 0)
+               if (rc < 0) {
+                       pr_err("%s(): set_sbl_baud_rate fail %d\n",
+                              __func__, rc);
                        goto escore_bootup_failed;
+               }
 
                escore_configure_tty(escore_uart.tty,
                                escore_uarths_baud[uart_tty_baud_rate],
@@ -262,7 +271,8 @@ int escore_uart_boot_setup(struct escore_priv *escore)
        memcpy(msg, (char *)&sbl_boot_cmd, 1);
        rc = escore_uart_write(escore, msg, 1);
        if (rc) {
-               pr_err("%s(): firmware load failed sbl boot write\n", __func__);
+               pr_err("%s(): firmware load failed sbl boot write %d\n",
+                      __func__, rc);
                rc = -EIO;
                goto escore_bootup_failed;
        }
@@ -276,7 +286,8 @@ int escore_uart_boot_setup(struct escore_priv *escore)
        } while (rc && retry--);
 
        if (rc) {
-               pr_err("%s(): firmware load failed boot ack\n", __func__);
+               pr_err("%s(): firmware load failed boot ack %d\n",
+                      __func__, rc);
                goto escore_bootup_failed;
        }
        pr_debug("%s(): sbl boot ack = 0x%02x\n", __func__, msg[0]);
@@ -294,7 +305,6 @@ escore_bootup_failed:
 
 int escore_uart_boot_finish(struct escore_priv *escore)
 {
-       char msg[4];
        int rc;
        u32 sync_cmd = (ES_SYNC_CMD << 16) | ES_SYNC_POLLING;
        u32 sync_ack;
@@ -307,16 +317,6 @@ int escore_uart_boot_finish(struct escore_priv *escore)
         */
        msleep(35);
 
-       /* Discard extra bytes from escore during firmware load. Host gets
-        * one more extra bytes after VS firmware download as per Bug 19441.
-        * As per bug #22191, in case of eS755 four extra bytes are received
-        * instead of 3 extra bytes. To make it generic, host reads 4 bytes.
-        * There is no need to check for response because host may get less
-        * bytes.
-        */
-       memset(msg, 0, 4);
-       rc = escore_uart_read(escore, msg, 4);
-
        /* now switch to firmware baud to talk to chip */
        if (escore->mode == SBL) {
                escore_configure_tty(escore_uart.tty,
@@ -326,6 +326,22 @@ int escore_uart_boot_finish(struct escore_priv *escore)
                        escore_uart.baudrate_vs, UART_TTY_STOP_BITS);
        }
 
+       /* Discard extra bytes from escore after firmware load. Host gets
+        * extra bytes after VS firmware download as per Bug 19441
+        * and as per bug #22191, in case of eS755 four extra bytes are received
+        * instead of 3 extra bytes.
+        * Also, as per the bug RDBNK-1455, extra bytes received after
+        * configuring the tty to new speed post VS fw download.
+        * To make it generic, host flushes extra bytes on UART.
+        * There is no need to check for response because host may get less
+        * bytes.
+        */
+       rc = tty_perform_flush(escore_uart.tty, TCIOFLUSH);
+       if (rc)
+               dev_err(escore->dev,
+                               "%s(): TTY buffer Flush is failed %d",
+                               __func__, rc);
+
        /* sometimes earSmart chip sends success in second sync command */
        do {
                pr_debug("%s(): write ES_SYNC_CMD = 0x%08x\n",
@@ -350,6 +366,108 @@ int escore_uart_boot_finish(struct escore_priv *escore)
        return rc;
 }
 
+/* This function must be called with access_lock acquired */
+static int escore_uart_int_osc_calibration(struct escore_priv *escore)
+{
+       u16 configure_uart = cpu_to_be16(0x00);
+       int sync_retry = ES_SYNC_MAX_RETRY;
+       u32 resp;
+       int rc = 0;
+
+       if (escore->bus.ops.high_bw_open) {
+               rc = escore->bus.ops.high_bw_open(escore);
+               if (rc < 0) {
+                       dev_err(escore->dev, "%s(): high_bw_open failed %d\n",
+                       __func__, rc);
+                       goto exit_osc_calib;
+               }
+       }
+
+       do {
+               rc = escore_cmd(escore,
+                               (ES_INT_OSC_MEASURE_START_VS << 16),
+                               &resp);
+               if (rc) {
+                       dev_err(escore->dev, "%s(): sending start UART calibration command failed %d",
+                                       __func__, rc);
+                       continue;
+               }
+
+               rc = escore->bus.ops.high_bw_write(escore,
+                       &configure_uart, sizeof(configure_uart));
+               if (rc < 0) {
+                       dev_err(escore->dev, "%s(): sending configure command on uart failed %d",
+                                       __func__, rc);
+                       continue;
+               }
+
+               usleep_range(5000, 5005);
+
+               rc = escore_cmd(escore,
+                               (ES_INT_OSC_MEASURE_QUERY_VS << 16),
+                               &resp);
+               if (rc) {
+                       dev_err(escore->dev, "%s(): sending check UART calibration command failed %d",
+                                       __func__, rc);
+                       continue;
+               } else if (resp ==
+                               (ES_INT_OSC_MEASURE_QUERY_VS << 16)) {
+                       dev_dbg(escore->dev, "%s(): caliberation was successful",
+                                       __func__);
+               } else {
+                       dev_err(escore->dev, "%s(): caliberation response 0x%08x",
+                                       __func__, resp);
+                       continue;
+               }
+               rc = escore->bus.ops.high_bw_cmd(escore, ES_SYNC_CMD << 16,
+                                                               &resp);
+               if (rc) {
+                       dev_err(escore->dev, "%s(): Sync cmd failed %d",
+                                                       __func__, rc);
+               } else if (resp == (ES_SYNC_CMD << 16)) {
+                       dev_dbg(escore->dev, "%s(): Sync successful", __func__);
+                       break;
+               } else {
+                       dev_dbg(escore->dev, "%s(): sync response 0x%08x",
+                                                       __func__, resp);
+
+                       /* Flush tty buffer to avoid extra byte
+                        * received in next read cycle */
+                       rc = tty_perform_flush(escore_uart.tty, TCIOFLUSH);
+                       if (rc)
+                               dev_err(escore->dev,
+                                       "%s(): TTY buffer Flush is failed %d",
+                                       __func__, rc);
+               }
+       } while (--sync_retry);
+
+       dev_dbg(escore->dev, "%s(), number of tries made : %d",
+               __func__, ES_SYNC_MAX_RETRY - sync_retry + 1);
+
+       if (!sync_retry) {
+               dev_err(escore->dev,
+               "%s(): UART caliberation failed. Continuing with Ext OSC",
+                                                       __func__);
+               /* In case of any issue switch the clock to ext oscillator */
+               rc = escore_switch_ext_osc(escore);
+               if (rc) {
+                       dev_err(escore->dev,
+                               "%s(): Error switching to external OSC %d\n",
+                               __func__, rc);
+               }
+       }
+       usleep_range(2000, 2005);
+
+       if (escore->bus.ops.high_bw_close) {
+               dev_dbg(escore->dev, "%s(), closing the UART",
+                                                       __func__);
+               escore->bus.ops.high_bw_close(escore);
+       }
+
+exit_osc_calib:
+       return rc;
+}
+
 static struct platform_device *escore_uart_pdev;
 
 static void escore_uart_setup_pri_intf(struct escore_priv *escore)
@@ -359,6 +477,8 @@ static void escore_uart_setup_pri_intf(struct escore_priv *escore)
        escore->bus.ops.cmd = escore_uart_cmd;
        escore->streamdev = es_uart_streamdev;
        escore->escore_uart_wakeup = escore_uart_wakeup;
+       escore->bus.ops.cpu_to_bus = escore_cpu_to_uart;
+       escore->bus.ops.bus_to_cpu = escore_uart_to_cpu;
 }
 
 static int escore_uart_setup_high_bw_intf(struct escore_priv *escore)
@@ -373,8 +493,9 @@ static int escore_uart_setup_high_bw_intf(struct escore_priv *escore)
        escore->boot_ops.escore_abort_config = escore_uart_abort_config;
        escore->boot_ops.setup = escore_uart_boot_setup;
        escore->boot_ops.finish = escore_uart_boot_finish;
-       escore->bus.ops.cpu_to_bus = escore_cpu_to_uart;
-       escore->bus.ops.bus_to_cpu = escore_uart_to_cpu;
+       escore->bus.ops.cpu_to_high_bw_bus = escore_cpu_to_uart;
+       escore->bus.ops.high_bw_bus_to_cpu = escore_uart_to_cpu;
+       escore->bus.ops.high_bw_calibrate = escore_uart_int_osc_calibration;
        escore->escore_uart_wakeup = escore_uart_wakeup;
 
 #if defined(CONFIG_SND_SOC_ES_UART_SBL_BAUD)
@@ -399,9 +520,9 @@ static int escore_uart_setup_high_bw_intf(struct escore_priv *escore)
        if (rc)
                goto out;
 
+       mutex_lock(&escore->access_lock);
        rc = escore->boot_ops.bootup(escore);
-       if (rc)
-               goto out;
+       mutex_unlock(&escore->access_lock);
 
 out:
        return rc;
@@ -435,11 +556,14 @@ int escore_uart_probe_thread(void *ptr)
        }
 
        rc = escore_probe(escore, dev, probe_intf, ES_CONTEXT_THREAD);
-
        if (rc) {
-               dev_err(dev, "%s(): UART common probe failed\n", __func__);
+               dev_err(dev, "%s(): UART common probe fail %d\n",
+                       __func__, rc);
                goto bootup_error;
        }
+
+       escore_uart_close(escore);
+
        return rc;
 
 bootup_error:
@@ -472,15 +596,6 @@ static int escore_uart_probe(struct platform_device *dev)
 static int escore_uart_remove(struct platform_device *dev)
 {
        int rc = 0;
-       /*
-        * ML: GPIO pins are not connected
-        *
-        * struct esxxx_platform_data *pdata = escore_priv.pdata;
-        *
-        * gpio_free(pdata->reset_gpio);
-        * gpio_free(pdata->wakeup_gpio);
-        * gpio_free(pdata->gpioa_gpio);
-        */
 
        if (escore_uart.file)
                escore_uart_close(&escore_priv);
@@ -503,10 +618,12 @@ int escore_uart_bus_init(struct escore_priv *escore)
 {
        int rc = 0;
 
+       atomic_set(&escore->uart_users, 0);
+
        escore_uart_pdev = platform_device_alloc("escore-codec.uart", -1);
        if (!escore_uart_pdev) {
-               pr_err("%s(): UART platform device allocation failed\n",
-                               __func__);
+               pr_err("%s: UART platform device allocation failed\n",
+                      __func__);
                rc = -ENOMEM;
                goto out;
        }
@@ -514,17 +631,16 @@ int escore_uart_bus_init(struct escore_priv *escore)
        rc = platform_device_add_data(escore_uart_pdev, &escore_uart_pdata,
                                sizeof(escore_uart_pdata));
        if (rc) {
-               pr_err("%s(): Error while adding UART device data\n", __func__);
+               pr_err("%s: Error adding UART device data %d\n", __func__, rc);
                platform_device_put(escore_uart_pdev);
                goto out;
        }
 
        rc = platform_device_add(escore_uart_pdev);
        if (rc) {
-               pr_err("%s(): Error while adding UART device\n", __func__);
+               pr_err("%s: Error adding UART device %d\n", __func__, rc);
                platform_device_put(escore_uart_pdev);
        }
-
 out:
        return rc;
 }
index b444ce72fe08242bbf969a9c23983a1a0de49a52..abf9024582b2386ae71c4d92746422ec80debf6e 100644 (file)
 #define _ESCORE_VERSION_H
 
 #if defined(CONFIG_SND_SOC_ES704_ESCORE) || defined(CONFIG_SND_SOC_ES705_ESCORE)
-#define ESCORE_VERSION "ESCORE_ES70X_1_3_0"
+#define ESCORE_VERSION "ESCORE_ES70X_1_4_0"
 #elif defined(CONFIG_SND_SOC_ES755)
-#define ESCORE_VERSION "ESCORE_ES75X_1_3_1"
+#define ESCORE_VERSION "ESCORE_ES75X_1_5_0"
 #elif defined(CONFIG_SND_SOC_ES804_ESCORE)
-#define ESCORE_VERSION "ESCORE_ES80X_1_3_0"
+#define ESCORE_VERSION "ESCORE_ES80X_1_4_0"
+#elif defined(CONFIG_SND_SOC_ES902_ESCORE)
+#define ESCORE_VERSION "ESCORE_ES90X_1_4_0"
+#elif defined(CONFIG_SND_SOC_ES854) || defined(CONFIG_SND_SOC_ES857)
+#define ESCORE_VERSION "ESCORE_ES85X_1_4_0"
 #endif
 
 #endif /* _ESCORE_VERSION_H */
index 85cbb06475ddbebd7aceb65faeba076626f99846..40a67d227a44e523fc7cbc0b4030c7e10d586ac2 100644 (file)
@@ -31,19 +31,12 @@ VS_KCONTROL(put, value)
 VS_KCONTROL(get, enum)
 VS_KCONTROL(put, enum)
 
-inline int escore_is_sleep_aborted(struct escore_priv *escore)
-{
-       if (unlikely(escore->sleep_abort))
-               return -EABORT;
-       else
-               return 0;
-}
-
 static int escore_vs_sleep(struct escore_priv *escore)
 {
        struct escore_voice_sense *voice_sense =
                        (struct escore_voice_sense *) escore_priv.voice_sense;
        u32 cmd, rsp;
+       int skip_vs_seq = 0, skip_vs_load = 0;
        int rc;
 #ifdef CONFIG_SND_SOC_ES_CVQ_TIME_MEASUREMENT
        struct timespec cvq_sleep_start;
@@ -61,12 +54,49 @@ static int escore_vs_sleep(struct escore_priv *escore)
 
        es_cvq_profiling(&cvq_sleep_start);
 
+       if (escore->escore_power_state == ES_SET_POWER_STATE_VS_OVERLAY &&
+               escore->es_vs_route_preset == voice_sense->vs_route_preset) {
+               dev_dbg(escore->dev,
+                       "%s() No route change. Skipping CVQ sequence\n",
+                       __func__);
+               skip_vs_seq = 1;
+               skip_vs_load = 1;
+               goto vs_set_low_power;
+       } else if (escore->escore_power_state == ES_SET_POWER_STATE_VS_OVERLAY) {
+               skip_vs_load = 1;
+               dev_dbg(escore->dev, "%s() already in VS overlay mode\n",
+                                                               __func__);
+               goto vs_set_presets;
+       }
+
+#ifdef CONFIG_SND_SOC_ES_AVOID_REPEAT_FW_DOWNLOAD
+       if (escore_get_vs_download_req(escore) == false) {
+               /*
+                * VS binary already copied.
+                * So No need to re-download Binary.
+                * But send the Overlay Power State Command
+                */
+               cmd = (ES_SET_POWER_STATE << 16) |
+                       ES_POWER_STATE_VS_OVERLAP;
+       } else {
+               cmd = (ES_SET_POWER_STATE << 16) |
+                       ES_SET_POWER_STATE_VS_OVERLAY;
+       }
+       rc = escore_cmd_nopm(escore, cmd, &rsp);
+       if (rc) {
+               dev_err(escore->dev, "%s(): Set Power State cmd fail %d\n",
+                       __func__, rc);
+               goto vs_sleep_err;
+       }
+
+       msleep(55); /* delay required for copying the VS firmware */
+#else
        /* Set smooth mute to 0 */
        cmd = ES_SET_SMOOTH_MUTE << 16 | ES_SMOOTH_MUTE_ZERO;
-       rc = escore->bus.ops.cmd(escore, cmd, &rsp);
+       rc = escore_cmd_nopm(escore, cmd, &rsp);
        if (rc) {
-               dev_err(escore->dev, "%s(): escore_cmd fail %d\n",
-                                       __func__, rc);
+               dev_err(escore->dev, "%s(): Set Smooth Mute cmd fail %d\n",
+                       __func__, rc);
                goto vs_sleep_err;
        }
        /* Its observed that an additional 30msec delay is needed for positive
@@ -76,14 +106,15 @@ static int escore_vs_sleep(struct escore_priv *escore)
        msleep(30);
        /* change power state to OVERLAY */
        cmd = (ES_SET_POWER_STATE << 16) | ES_SET_POWER_STATE_VS_OVERLAY;
-       rc = escore->bus.ops.cmd(escore, cmd, &rsp);
+       rc = escore_cmd_nopm(escore, cmd, &rsp);
        if (rc) {
-               dev_err(escore->dev, "%s(): escore_cmd fail %d\n",
-                                       __func__, rc);
+               dev_err(escore->dev, "%s(): Set Power State cmd fail %d\n",
+                       __func__, rc);
                goto vs_sleep_err;
        }
-
+       escore->mode = SBL;
        msleep(30);
+#endif
 
        rc = escore_is_sleep_aborted(escore);
        if (rc == -EABORT)
@@ -91,6 +122,29 @@ static int escore_vs_sleep(struct escore_priv *escore)
 
        es_cvq_profiling(&vs_load_start);
 
+#ifdef CONFIG_SND_SOC_ES_AVOID_REPEAT_FW_DOWNLOAD
+       if (escore_get_vs_download_req(escore) == true) {
+               rc = escore_vs_load(&escore_priv);
+               if (rc) {
+                       pr_err("%s(): VS fw download fail %d\n",
+                              __func__, rc);
+                       goto vs_sleep_err;
+               }
+               escore_set_vs_download_req(escore, false);
+       } else {
+               pr_debug("%s() VS firmware is already downloaded", __func__);
+
+               /* Setup the Event response */
+               cmd = (ES_SET_EVENT_RESP << 16) | \
+                                               escore->pdata->gpio_b_irq_type;
+               rc = escore_cmd_nopm(escore, cmd, &rsp);
+               if (rc < 0) {
+                       pr_err("%s(): Error %d in setting event response\n",
+                                       __func__, rc);
+                       goto vs_sleep_err;
+               }
+       }
+#else
        /* download VS firmware */
        rc = escore_vs_load(escore);
        if (rc) {
@@ -98,37 +152,55 @@ static int escore_vs_sleep(struct escore_priv *escore)
                                        __func__, rc);
                goto vs_sleep_err;
        }
+#endif
+
        escore->escore_power_state = ES_SET_POWER_STATE_VS_OVERLAY;
 
        es_cvq_profiling(&vs_load_end);
 
-       rc = escore_is_sleep_aborted(escore);
-       if (rc == -EABORT)
-               goto escore_sleep_aborted;
-
+vs_set_presets:
        cmd = ES_SET_PRESET << 16 | escore->es_vs_route_preset;
-       rc = escore->bus.ops.cmd(escore, cmd, &rsp);
+       rc = escore_cmd_nopm(escore, cmd, &rsp);
        if (rc) {
-               dev_err(escore->dev, "%s(): escore_cmd fail %d\n",
-                                       __func__, rc);
+               dev_err(escore->dev, "%s(): Set Preset cmd fail %d\n",
+                       __func__, rc);
                goto vs_sleep_err;
        }
+       voice_sense->vs_route_preset = escore->es_vs_route_preset;
+
+       msleep(20);
 
-       voice_sense->cvs_preset = escore->es_cvs_preset;
        cmd = ES_SET_CVS_PRESET << 16 | escore->es_cvs_preset;
-       rc = escore->bus.ops.cmd(escore, cmd, &rsp);
+       rc = escore_cmd_nopm(escore, cmd, &rsp);
        if (rc) {
-               dev_err(escore->dev, "%s(): escore_cmd fail %d\n",
-                                       __func__, rc);
+               dev_err(escore->dev, "%s(): Set CVS Preset cmd fail %d\n",
+                       __func__, rc);
                goto vs_sleep_err;
        }
+       voice_sense->cvs_preset = escore->es_cvs_preset;
 
        rc = escore_is_sleep_aborted(escore);
        if (rc == -EABORT)
                goto escore_sleep_aborted;
 
+       if (voice_sense->es_vs_keyword_length) {
+               cmd = ((ES_SET_VS_KW_LENGTH << 16) |
+                               voice_sense->es_vs_keyword_length);
+               rc = escore_cmd_nopm(escore, cmd, &rsp);
+               if (rc) {
+                       dev_err(escore->dev, "%s(): kw length cmd fail %d\n",
+                                       __func__, rc);
+                       goto vs_sleep_err;
+               }
+       }
+
        es_cvq_profiling(&wdb_start);
 
+       /* Reconfig API Interrupt mode */
+       rc = escore_reconfig_api_intr(escore);
+       if (rc)
+               goto vs_sleep_err;
+
        /* write background model and keywords files */
        rc = escore_vs_write_bkg_and_keywords(escore);
        if (rc) {
@@ -140,23 +212,19 @@ static int escore_vs_sleep(struct escore_priv *escore)
 
        es_cvq_profiling(&wdb_end);
 
-       rc = escore_is_sleep_aborted(escore);
-       if (rc == -EABORT)
-               goto escore_sleep_aborted;
-
        cmd = ES_SET_ALGO_PARAM_ID << 16 | ES_VS_PROCESSING_MOE;
-       rc = escore->bus.ops.cmd(escore, cmd, &rsp);
+       rc = escore_cmd_nopm(escore, cmd, &rsp);
        if (rc) {
-               dev_err(escore->dev, "%s(): escore_cmd fail %d\n",
-                               __func__, rc);
+               dev_err(escore->dev, "%s(): Set Algo Param ID cmd fail %d\n",
+                       __func__, rc);
                goto vs_sleep_err;
        }
 
        cmd = ES_SET_ALGO_PARAM << 16 | ES_VS_DETECT_KEYWORD;
-       rc = escore->bus.ops.cmd(escore, cmd, &rsp);
+       rc = escore_cmd_nopm(escore, cmd, &rsp);
        if (rc) {
-               dev_err(escore->dev, "%s(): escore_cmd fail %d\n",
-                                       __func__, rc);
+               dev_err(escore->dev, "%s(): Set Algo Param cmd fail %d\n",
+                       __func__, rc);
                goto vs_sleep_err;
        }
 
@@ -170,13 +238,25 @@ static int escore_vs_sleep(struct escore_priv *escore)
                goto vs_sleep_err;
        }
 
+vs_set_low_power:
+       /* Set flag to Wait for API Interrupt */
+       escore_set_api_intr_wait(escore);
+
        cmd = (ES_SET_POWER_STATE << 16) | ES_SET_POWER_STATE_VS_LOWPWR;
-       rc = escore->bus.ops.cmd(escore, cmd, &rsp);
+       rc = escore_cmd_nopm(escore, cmd, &rsp);
        if (rc) {
-               dev_err(escore->dev, "%s(): escore_cmd fail %d\n",
-                               __func__, rc);
+               dev_err(escore->dev, "%s(): Set Power State cmd fail %d\n",
+                       __func__, rc);
                goto vs_sleep_err;
        }
+
+       /* Wait for API Interrupt to confirm that device is in low power */
+       if (escore->pdata->gpioa_gpio != -1) {
+               rc = escore_api_intr_wait_completion(escore);
+               if (rc)
+                       goto vs_sleep_err;
+       }
+
        escore->escore_power_state = ES_SET_POWER_STATE_VS_LOWPWR;
 
 escore_sleep_aborted:
@@ -185,14 +265,18 @@ vs_sleep_err:
        es_cvq_profiling(&cvq_sleep_end);
 
 #ifdef CONFIG_SND_SOC_ES_CVQ_TIME_MEASUREMENT
-       vs_load_time = (timespec_sub(vs_load_end, vs_load_start));
-       wdb_time = (timespec_sub(wdb_end, wdb_start));
-       cvq_sleep_time = (timespec_sub(cvq_sleep_end, cvq_sleep_start));
 
-       dev_info(escore->dev, "VS firmware load time = %lu.%03lu sec\n",
-                       vs_load_time.tv_sec, (vs_load_time.tv_nsec)/1000000);
-       dev_info(escore->dev, "BKG and KW write time = %lu.%03lu sec\n",
-                       wdb_time.tv_sec, (wdb_time.tv_nsec)/1000000);
+       if (!skip_vs_load) {
+               vs_load_time = (timespec_sub(vs_load_end, vs_load_start));
+               dev_info(escore->dev, "VS firmware load time = %lu.%03lu sec\n",
+                               vs_load_time.tv_sec, (vs_load_time.tv_nsec)/1000000);
+       }
+       if (!skip_vs_seq) {
+               wdb_time = (timespec_sub(wdb_end, wdb_start));
+               dev_info(escore->dev, "BKG and KW write time = %lu.%03lu sec\n",
+                               wdb_time.tv_sec, (wdb_time.tv_nsec)/1000000);
+       }
+       cvq_sleep_time = (timespec_sub(cvq_sleep_end, cvq_sleep_start));
        dev_info(escore->dev, "Total CVQ sleep time = %lu.%03lu sec\n",
                cvq_sleep_time.tv_sec, (cvq_sleep_time.tv_nsec)/1000000);
 #endif
@@ -207,54 +291,59 @@ int escore_vs_wakeup(struct escore_priv *escore)
 
        dev_dbg(escore->dev, "%s()\n", __func__);
 
-       escore->sleep_abort = 1;
-
-       mutex_lock(&escore_priv.api_mutex);
-
-       /* If chip is in low power mode and keyword detection happens,
-        * it switch back to Normal(BOSKO) mode automatically.
-        */
        if (escore->escore_power_state == ES_SET_POWER_STATE_NORMAL) {
                dev_dbg(escore->dev, "%s() Already in normal mode\n", __func__);
-               escore->mode = STANDARD;
-               escore->pm_state = ES_PM_NORMAL;
+               goto out;
+       }
+
+       rc = escore_wakeup(escore);
+       if (rc) {
+               dev_err(escore->dev, "%s() wakeup failed rc = %d\n",
+                               __func__, rc);
                goto vs_wakeup_err;
        }
+       escore->escore_power_state = ES_SET_POWER_STATE_VS_OVERLAY;
 
-       /* If chip is in low power mode and Jack detection happens,
-        * it switch back to Overlay command mode and wakeup gpio
-        * toggling is not required
-        */
-       if (escore->escore_power_state == ES_SET_POWER_STATE_VS_LOWPWR) {
-               rc = escore_wakeup(escore);
-               if (rc) {
-                       dev_err(escore->dev, "%s() wakeup failed rc = %d\n",
-                                       __func__, rc);
-                       goto vs_wakeup_err;
-               }
-               escore->escore_power_state = ES_SET_POWER_STATE_VS_OVERLAY;
+       if (escore->intr_recvd) {
+               /* Total 60 ms Delay is required for firmware to be ready
+                * after wakeup */
+               msleep(60 - escore->delay.wakeup_to_vs);
+               dev_dbg(escore->dev,
+                       "%s() Keeping chip in CVQ command mode\n", __func__);
+               goto out;
        }
 
+       /* Set flag to Wait for API Interrupt */
+       escore_set_api_intr_wait(escore);
+
        /* change power state to Normal*/
        cmd = (ES_SET_POWER_STATE << 16) | ES_SET_POWER_STATE_NORMAL;
-       rc = escore->bus.ops.cmd(escore, cmd, &rsp);
+       rc = escore_cmd_nopm(escore, cmd, &rsp);
        if (rc < 0) {
-               dev_err(escore->dev, "%s() - failed sync cmd resume\n",
-                               __func__);
-               escore->pm_state = ES_PM_HOSED;
+               dev_err(escore->dev, "%s() - failed sync cmd resume %d\n",
+                       __func__, rc);
                goto vs_wakeup_err;
-       } else {
-               /* Time required for switching from VS to NS mode.
-                * This delay should be replaced with GPIO A event */
-               msleep(50);
-
-               escore->mode = STANDARD;
-               escore->pm_state = ES_PM_NORMAL;
-               escore->escore_power_state = ES_SET_POWER_STATE_NORMAL;
        }
+
+       if (escore->pdata->gpioa_gpio != -1) {
+               /* Wait for API Interrupt to confirm
+                * that device is ready to accept commands */
+               rc = escore_api_intr_wait_completion(escore);
+               if (rc)
+                       goto vs_wakeup_err;
+
+               /* Reconfig API Interrupt mode */
+               rc = escore_reconfig_api_intr(escore);
+               if (rc)
+                       goto vs_wakeup_err;
+       } else
+               msleep(escore->delay.vs_to_normal);
+
+       escore->mode = STANDARD;
+       escore->escore_power_state = ES_SET_POWER_STATE_NORMAL;
+
+out:
 vs_wakeup_err:
-       mutex_unlock(&escore_priv.api_mutex);
-       escore->sleep_abort = 0;
        return rc;
 }
 
@@ -264,26 +353,83 @@ static int escore_cvq_sleep_thread(void *ptr)
        int rc;
        u32 cmd, rsp;
 
-       mutex_lock(&escore_priv.api_mutex);
        rc = escore_vs_sleep(&escore_priv);
        if (rc != -EABORT)
                goto escore_cvq_sleep_thread_exit;
 
-       dev_dbg(escore->dev, "%s() CVQ sleep aborted\n",
-                       __func__);
-       /* change power state to Normal*/
-       cmd = (ES_SET_POWER_STATE << 16) | ES_SET_POWER_STATE_NORMAL;
-       rc = escore->bus.ops.cmd(escore, cmd, &rsp);
-       if (rc) {
-               dev_err(escore->dev,
-                       "%s() Power State Normal failed rc = %d\n",
-                       __func__, rc);
+       dev_dbg(escore->dev, "%s() CVQ sleep aborted\n", __func__);
+
+       /* Set flag to Wait for API Interrupt */
+       escore_set_api_intr_wait(escore);
+
+       /* Change power state to Normal.
+        * As per BAS-2581,
+        *   - Host should use power state command with supress response when
+        *     firmware is running
+        *   - Host should use power state command without supress response when
+        *     chip is in SBL mode.
+        * This command response may not be received and needs to be ignored.
+        * Actual firmware transition is verified after checking power state.
+        */
+       if (escore->mode != VOICESENSE_PENDING) {
+               if (escore->mode == SBL)
+                       /* BAS-3232: Change power state to Normal, send
+                        * command with SR bit disable on PRI interface,
+                        * but device won't send any response back */
+                       cmd = ES_SET_POWER_STATE_CMD << 16 |
+                                       ES_SET_POWER_STATE_NORMAL;
+               else
+                       /* BAS-3232: Change power state to Normal, send
+                        * command with SR bit enable on PRI interface */
+                       cmd = ES_SET_POWER_STATE << 16 |
+                                       ES_SET_POWER_STATE_NORMAL;
+               /* handle endianness */
+               cmd = escore->bus.ops.cpu_to_bus(escore, cmd);
+               rc = escore->bus.ops.write(escore, &cmd, sizeof(cmd));
+               update_cmd_history(escore->bus.ops.bus_to_cpu(escore,
+                                                       cmd), 0);
+               if (rc) {
+                       pr_err("%s() PRI INTF write is failed, rc = %d\n",
+                                       __func__, rc);
+                       goto escore_cvq_sleep_thread_exit;
+               }
+       }
+
+       if (escore->pdata->gpioa_gpio == -1) {
+               if (escore->mode == VOICESENSE)
+                       /* BAS-3232: Delay required before reading power
+                        * state in case of VOICESENSE mode:
+                        * es75x: 90 ms
+                        * es70x / es80x: 50 ms */
+                       msleep(escore->delay.vs_to_normal);
+               else
+                       /* BAS-3232: Total delay required before reading power
+                        * state is 60 ms in case of SBL and VOICESENSE_PENDING
+                        * mode */
+                       msleep(60);
+               cmd = ES_GET_POWER_STATE << 16;
+               rc = escore_cmd_nopm(escore, cmd, &rsp);
+               if (rc < 0) {
+                       pr_err("%s() Get Power State failed rc = %d\n",
+                                                       __func__, rc);
+                       goto escore_cvq_sleep_thread_exit;
+               }
+               if (rsp != ES_PS_NORMAL) {
+                       pr_err("%s() Power state is not normal, rsp = %x\n",
+                                       __func__, rsp);
+                       rc = -EINVAL;
+                       goto escore_cvq_sleep_thread_exit;
+               }
+       } else {
+               /* Wait for API Interrupt to confirm that
+                * device is in normal mode */
+               rc = escore_api_intr_wait_completion(escore);
+               if (rc)
+                       goto escore_cvq_sleep_thread_exit;
        }
        escore_priv.escore_power_state = ES_SET_POWER_STATE_NORMAL;
 
 escore_cvq_sleep_thread_exit:
-       mutex_unlock(&escore_priv.api_mutex);
-
        return rc;
 }
 
@@ -297,33 +443,28 @@ int escore_put_vs_sleep(struct snd_kcontrol *kcontrol,
                                        struct snd_ctl_elem_value *ucontrol)
 {
        struct escore_priv *escore = &escore_priv;
-       static struct task_struct *cvq_sleep_thread;
        unsigned int value;
        int rc = 0;
 
        value = ucontrol->value.integer.value[0];
 
+       mutex_lock(&escore->access_lock);
        if (value) {
 
                rc = escore_pm_get_sync();
                if (rc < 0) {
                        pr_err("%s(): pm_get_sync failed :%d\n", __func__, rc);
+                       mutex_unlock(&escore->access_lock);
                        return rc;
                }
 
-               cvq_sleep_thread = kthread_run(escore_cvq_sleep_thread,
-                               (void *) escore,
-                               "escore CVQ sleep thread");
-               if (IS_ERR_OR_NULL(cvq_sleep_thread)) {
-                       pr_err("%s(): can't create CVQ sleep thread = %p\n",
-                                       __func__, cvq_sleep_thread);
-                       rc = -ENOMEM;
-               }
+               rc = escore_cvq_sleep_thread(escore);
                escore_pm_put_autosuspend();
 
        } else
                rc = escore_vs_wakeup(&escore_priv);
 
+       mutex_unlock(&escore->access_lock);
        return rc;
 }
 
@@ -368,35 +509,86 @@ int escore_vs_sleep_enable(struct escore_priv *escore)
        return voice_sense->vs_active_keywords;
 }
 
+int escore_put_vs_keyword_length(struct snd_kcontrol *kcontrol,
+                                       struct snd_ctl_elem_value *ucontrol)
+{
+       struct escore_voice_sense *voice_sense =
+                       (struct escore_voice_sense *) escore_priv.voice_sense;
+       unsigned int value;
+       int rc = 0;
+       u32 cmd, rsp;
+
+       value = ucontrol->value.integer.value[0];
+
+       voice_sense->es_vs_keyword_length = value;
+
+       if (!escore_vs_sleep_enable(&escore_priv)) {
+               cmd = ((ES_SET_VS_KW_LENGTH << 16) |
+                               voice_sense->es_vs_keyword_length);
+               rc = escore_cmd_locked(&escore_priv, cmd, &rsp);
+               if (rc) {
+                       dev_err(escore_priv.dev, "%s(): kw length cmd fail %d\n",
+                                       __func__, rc);
+               }
+       }
+
+       return rc;
+}
+
+int escore_get_vs_keyword_length(struct snd_kcontrol *kcontrol,
+                                       struct snd_ctl_elem_value *ucontrol)
+{
+       struct escore_voice_sense *voice_sense =
+                       (struct escore_voice_sense *) escore_priv.voice_sense;
+       ucontrol->value.integer.value[0] = voice_sense->es_vs_keyword_length;
+
+       return 0;
+}
+
+int escore_get_keyword_overrun(struct snd_kcontrol *kcontrol,
+                                       struct snd_ctl_elem_value *ucontrol)
+{
+       int rc = 0;
+       u32 es_get_keyword_overrun = ESCORE_GET_KEYWORD_OVERRUN_ERROR << 16;
+       u32 rspn = 0;
+
+       rc = escore_cmd_locked(&escore_priv, es_get_keyword_overrun,
+                               &rspn);
+       if (rc < 0) {
+               dev_err(escore_priv.dev, "Failed to set the keyword length %d()",
+                               rc);
+               return rc;
+       }
+
+       ucontrol->value.enumerated.item[0] = rspn & 0x0000ffff;
+       dev_dbg(escore_priv.dev, "%s: Response 0x%08X", __func__,
+                               rspn);
+
+       return 0;
+}
+
 int escore_put_vs_activate_keyword(struct snd_kcontrol *kcontrol,
                                        struct snd_ctl_elem_value *ucontrol)
 {
        struct escore_priv *escore = &escore_priv;
-       struct escore_voice_sense *voice_sense =
-                       (struct escore_voice_sense *) escore->voice_sense;
        unsigned int value;
        int rc = 0;
-       int i;
 
        value = ucontrol->value.integer.value[0];
 
+       mutex_lock(&escore->access_lock);
        rc = escore_pm_get_sync();
        if (rc < 0) {
                dev_err(escore->dev, "%s(): pm_get_sync failed :%d\n",
                                __func__, rc);
-               return rc;
-       }
-
-       for (i = 0; i < MAX_NO_OF_VS_KW; i++) {
-               if (voice_sense->vs_active_keywords & (1 << i))
-                       release_firmware(voice_sense->kw[i]);
+               goto exit;
        }
 
-       voice_sense->vs_active_keywords = value;
-       rc = escore_vs_request_keywords(escore);
+       rc = escore_vs_request_keywords(escore, value);
 
        escore_pm_put_autosuspend();
-
+exit:
+       mutex_unlock(&escore->access_lock);
        return rc;
 }
 
@@ -475,6 +667,7 @@ int escore_vs_request_bkg(struct escore_priv *escore, const char *bkg_filename)
        if (rc) {
                dev_err(escore->dev, "%s(): request_firmware(%s) failed %d\n",
                                __func__, bkg_filename, rc);
+               return  rc;
        }
        return  rc;
 }
@@ -487,7 +680,7 @@ void escore_vs_release_bkg(struct escore_priv *escore)
        release_firmware(voice_sense->bkg);
 }
 
-int escore_vs_request_keywords(struct escore_priv *escore)
+int escore_vs_request_keywords(struct escore_priv *escore, unsigned int value)
 {
        struct escore_voice_sense *voice_sense =
                        (struct escore_voice_sense *) escore->voice_sense;
@@ -496,31 +689,63 @@ int escore_vs_request_keywords(struct escore_priv *escore)
        char kw_filename[] = "audience-vs-kw-1.bin";
        int size = sizeof(kw_filename)/sizeof(char);
 
+       /* Keyword number is based on bit positions. For an example, for keyword
+        * number 3, value is 100B i.e. 4 in decimal. Similarly for keywords 4
+        * and 5, 4th and 5th bit is set i.e. 11000 i.e. 18 (bit position is
+        * started from 1 here).
+        *
+        * Flow of function:
+        *      - Release already requested keyword
+        *      - Request new keyword if it is selected
+        *      - In case of error, release all keywords
+        */
+
        for (i = 0; i < MAX_NO_OF_VS_KW; i++) {
-               if (!(voice_sense->vs_active_keywords & (1 << i)))
+
+               /* Release keyword if it is requested before. This is required
+                * for kernel 3.10 in which if old keyword is not released,
+                * keyword data remains unchanged.
+                */
+               if (voice_sense->vs_active_keywords & BIT(i)) {
+                       dev_dbg(escore->dev, "%s(): release kw = %d\n",
+                                                       __func__, i + 1);
+                       release_firmware(voice_sense->kw[i]);
+                       voice_sense->vs_active_keywords &= (~BIT(i));
+               }
+
+               /* If keyword is not set, do not request it. */
+               if (!(value & BIT(i)))
                        continue;
 
+               /* Request selected keywords */
                snprintf(kw_filename, size, "audience-vs-kw-%d.bin", i + 1);
                dev_dbg(escore->dev, "%s(): kw filename = %s\n",
-                                       __func__, kw_filename);
+                               __func__, kw_filename);
                rc = request_firmware(
-                       (const struct firmware **)&(voice_sense->kw[i]),
-                       kw_filename, escore->dev);
+                               (const struct firmware **)&(voice_sense->kw[i]),
+                               kw_filename, escore->dev);
                if (rc) {
                        dev_err(escore->dev, "%s(): request kw(%d) failed %d\n",
                                        __func__, i + 1, rc);
                        goto request_firmware_kw_exit;
                }
+               voice_sense->vs_active_keywords |= BIT(i);
        }
 
        return rc;
 
 request_firmware_kw_exit:
-       while (i-- > 0) {
-               dev_err(escore->dev, "%s(): %d i = %d\n",
-                                       __func__, __LINE__, i);
-               release_firmware(voice_sense->kw[i]);
+
+       /* In case of failure, release all keywords */
+       for (i = 0; i < MAX_NO_OF_VS_KW; i++) {
+               if (voice_sense->vs_active_keywords & BIT(i)) {
+                       dev_dbg(escore->dev, "%s(): release kw %d\n",
+                                                       __func__, i + 1);
+                       release_firmware(voice_sense->kw[i]);
+               }
        }
+       voice_sense->vs_active_keywords = 0;
+
        return  rc;
 }
 
@@ -540,7 +765,7 @@ int escore_vs_write_bkg_and_keywords(struct escore_priv *escore)
 
        rc = escore_datablock_write(escore, voice_sense->bkg->data,
                        voice_sense->bkg->size);
-       if (rc < voice_sense->bkg->size) {
+       if ((rc < 0) || (rc < voice_sense->bkg->size)) {
                dev_err(escore->dev, "%s(): bkg write failed rc = %d\n",
                                                __func__, rc);
                goto escore_vs_write_bkg_keywords_exit;
@@ -552,7 +777,7 @@ int escore_vs_write_bkg_and_keywords(struct escore_priv *escore)
                dev_dbg(escore->dev, "%s(): Write kw = %d\n", __func__, i + 1);
                rc = escore_datablock_write(escore, voice_sense->kw[i]->data,
                                                voice_sense->kw[i]->size);
-               if (rc < voice_sense->kw[i]->size) {
+               if ((rc < 0) || (rc < voice_sense->kw[i]->size)) {
                        dev_err(escore->dev,
                                "%s(): kw %d write failed rc = %d\n",
                                __func__, i + 1, rc);
@@ -561,6 +786,7 @@ int escore_vs_write_bkg_and_keywords(struct escore_priv *escore)
        }
 
        escore_datablock_close(escore);
+
        return 0;
 
 escore_vs_write_bkg_keywords_exit:
@@ -572,16 +798,18 @@ static int escore_vs_isr(struct notifier_block *self, unsigned long action,
                void *dev)
 {
        struct escore_priv *escore = (struct escore_priv *)dev;
+       char *event[] = { "ACTION=ADNC_KW_DETECT", NULL };
        struct escore_voice_sense *voice_sense =
                (struct escore_voice_sense *) escore->voice_sense;
-       u32 smooth_mute = ES_SET_SMOOTH_MUTE << 16 | ES_SMOOTH_MUTE_ZERO;
+#ifndef CONFIG_SND_SOC_ES_VS_STREAMING
        u32 es_set_power_level = ES_SET_POWER_LEVEL << 16 | ES_POWER_LEVEL_6;
        u32 resp;
+#endif
        int rc = 0;
 
        dev_dbg(escore->dev, "%s(): Event: 0x%04x\n", __func__, (u32)action);
 
-       if ((action & 0xFF) != ES_VS_INTR_EVENT) {
+       if (!(action & ES_VS_INTR_EVENT)) {
                dev_dbg(escore->dev, "%s(): Invalid event callback 0x%04x\n",
                                __func__, (u32) action);
                return NOTIFY_DONE;
@@ -590,7 +818,12 @@ static int escore_vs_isr(struct notifier_block *self, unsigned long action,
                                __func__, (u32) action);
 
        if (voice_sense->cvs_preset != 0xFFFF && voice_sense->cvs_preset != 0) {
+#ifdef CONFIG_SND_SOC_ES_VS_STREAMING
+               /* Chip wakes up in VS Streaming mode */
+               escore->escore_power_state = ES_POWER_STATE_VS_STREAMING;
+#else
                escore->escore_power_state = ES_SET_POWER_STATE_NORMAL;
+#endif
                escore->mode = STANDARD;
        }
 
@@ -605,25 +838,39 @@ static int escore_vs_isr(struct notifier_block *self, unsigned long action,
         */
        if (voice_sense->cvs_preset != 0xFFFF &&
                        voice_sense->cvs_preset != 0) {
-
-               rc = escore_cmd(escore, smooth_mute, &resp);
+#ifndef CONFIG_SND_SOC_ES_VS_STREAMING
+               /* Following command will set the power level to 6,
+                  any subsequent preset will switch the oscillator
+                  to external */
+               rc = escore_cmd_locked(escore, es_set_power_level, &resp);
                if (rc < 0) {
-                       pr_err("%s(): Error setting smooth mute\n", __func__);
+                       pr_err("%s(): Error setting power level %d\n",
+                              __func__, rc);
                        goto voiceq_isr_exit;
                }
                usleep_range(2000, 2005);
-               rc = escore_cmd(escore, es_set_power_level, &resp);
-               if (rc < 0) {
-                       pr_err("%s(): Error setting power level\n", __func__);
-                       goto voiceq_isr_exit;
+#endif
+               /* Enable the clock before switching to external oscillator */
+               if (escore->pdata->esxxx_clk_cb)
+                       escore->pdata->esxxx_clk_cb(1);
+
+               /* Required only for the UART interface */
+               if (escore->bus.ops.high_bw_calibrate) {
+                       mutex_lock(&escore->access_lock);
+                       rc = escore->bus.ops.high_bw_calibrate(escore);
+                       mutex_unlock(&escore->access_lock);
+                       if (rc) {
+                               dev_err(escore->dev,
+                                       "%s() error calibrating the interface rc = %d\n",
+                                       __func__, rc);
+                               goto voiceq_isr_exit;
+                       }
                }
-               usleep_range(2000, 2005);
-
                /* Each time earSmart chip comes in BOSKO mode after
                 * VS detect, CVS mode will be disabled */
                voice_sense->cvs_preset = 0;
        }
-       kobject_uevent(&escore->dev->kobj, KOBJ_CHANGE);
+       kobject_uevent_env(&escore->dev->kobj, KOBJ_CHANGE, event);
 
        return NOTIFY_OK;
 
@@ -675,8 +922,8 @@ int escore_vs_load(struct escore_priv *escore)
 
        rc = escore->boot_ops.setup(escore);
        if (rc) {
-               dev_err(escore->dev, "%s(): fw download start error\n",
-                       __func__);
+               dev_err(escore->dev, "%s(): fw download start error %d\n",
+                       __func__, rc);
                goto escore_vs_fw_download_failed;
        }
 
@@ -693,8 +940,8 @@ int escore_vs_load(struct escore_priv *escore)
                                ((char *)voice_sense->vs->data) , 20);
                if (rc) {
                        dev_err(escore->dev,
-                               "%s(): vs firmware data write error\n",
-                               __func__);
+                               "%s(): vs firmware data write error %d\n",
+                               __func__, rc);
                        rc = -EIO;
                        goto escore_vs_fw_download_failed;
                }
@@ -704,62 +951,90 @@ int escore_vs_load(struct escore_priv *escore)
                rc = escore->bus.ops.high_bw_write(escore, &cmd , 4);
                if (rc) {
                        dev_err(escore->dev,
-                               "%s(): abort word write error\n", __func__);
+                               "%s(): abort word write error %d\n",
+                               __func__, rc);
                        rc = -EIO;
                        goto escore_vs_fw_download_failed;
                }
+               /* BAS-3232: 5ms delay is required after abort command write */
+               usleep_range(5000, 5050);
 
-               if (escore->high_bw_intf == ES_UART_INTF) {
+               if (escore->high_bw_intf == ES_UART_INTF ||
+                                       escore->high_bw_intf == ES_SPI_INTF) {
                        if (escore->boot_ops.escore_abort_config)
                                escore->boot_ops.escore_abort_config(escore);
                }
 
+               /* BAS-3232: Change power state to Normal, send command
+                * with SR bit disable on HIGH BW interface, but device won't
+                * send any response back */
                cmd = ES_SET_POWER_STATE_CMD << 16 | ES_SET_POWER_STATE_NORMAL;
-               rc = escore->bus.ops.high_bw_cmd(escore, cmd , &resp);
+               cmd = escore->bus.ops.cpu_to_high_bw_bus(escore, cmd);
+               rc = escore->bus.ops.high_bw_write(escore, &cmd, sizeof(cmd));
+               update_cmd_history(escore->bus.ops.high_bw_bus_to_cpu(escore,
+                                                               cmd), 0);
                if (rc) {
-                       dev_err(escore->dev, "%s(): power state cmd error\n",
-                                       __func__);
-                       rc = -EIO;
+                       pr_err("%s() HIGH BW INTF write is failed, rc = %d\n",
+                                       __func__, rc);
                        goto escore_vs_fw_download_failed;
                }
+
                rc = -EABORT;
                goto escore_sleep_aborted;
        }
+
        dev_dbg(escore->dev, "%s(): write vs firmware image\n", __func__);
 
+       /* Set flag to Wait for API Interrupt */
+       escore_set_api_intr_wait(escore);
+
        rc = escore->bus.ops.high_bw_write(escore,
                ((char *)voice_sense->vs->data) , voice_sense->vs->size);
        if (rc) {
-               dev_err(escore->dev, "%s(): vs firmware image write error\n",
-                       __func__);
+               dev_err(escore->dev, "%s(): vs firmware image write error %d\n",
+                       __func__, rc);
                rc = -EIO;
                goto escore_vs_fw_download_failed;
        }
 
-       rc = escore_is_sleep_aborted(escore);
-       if (rc == -EABORT)
-               goto escore_sleep_aborted;
-
        escore->mode = VOICESENSE;
 
        if (((struct escore_voice_sense *)escore->voice_sense)->vs_irq != true)
                escore_vs_init_intr(escore);
 
-       rc = escore->boot_ops.finish(escore);
-       if (rc) {
-               dev_err(escore->dev, "%s() vs fw download finish error\n",
-                       __func__);
-               goto escore_vs_fw_download_failed;
+       /* Wait for API Interrupt to confirm
+        * that firmware is ready to accept command */
+       if (escore->pdata->gpioa_gpio != -1) {
+               rc = escore_api_intr_wait_completion(escore);
+               if (rc)
+                       goto escore_vs_fw_download_failed;
+       } else {
+               /* boot_ops.finish is required only in the case of POLL mode
+                * command completion*/
+               rc = escore->boot_ops.finish(escore);
+               if (rc) {
+                       dev_err(escore->dev,
+                               "%s() vs fw download finish error %d\n",
+                               __func__, rc);
+                       goto escore_vs_fw_download_failed;
+               }
        }
 
        rc = escore_is_sleep_aborted(escore);
        if (rc == -EABORT)
                goto escore_sleep_aborted;
 
-       rc = escore_reconfig_intr(escore);
-       if (rc) {
-               dev_err(escore->dev, "%s() config resume failed after VS load rc = %d\n",
-                       __func__, rc);
+       /* Reconfig API Interrupt mode */
+       rc = escore_reconfig_api_intr(escore);
+       if (rc)
+               goto escore_vs_fw_download_failed;
+
+       /* Setup the Event response */
+       cmd = (ES_SET_EVENT_RESP << 16) | escore->pdata->gpio_b_irq_type;
+       rc = escore_cmd_nopm(escore, cmd, &resp);
+       if (rc < 0) {
+               pr_err("%s(): Error %d in setting event response\n",
+                               __func__, rc);
                goto escore_vs_fw_download_failed;
        }
 
@@ -791,10 +1066,13 @@ void escore_vs_exit(struct escore_priv *escore)
        struct escore_voice_sense *voice_sense =
                        (struct escore_voice_sense *) escore->voice_sense;
        int i;
-       release_firmware(voice_sense->bkg);
-       for (i = 0; i < MAX_NO_OF_VS_KW; i++)
-               if (voice_sense->kw[i])
+       for (i = 0; i < MAX_NO_OF_VS_KW; i++) {
+               if (voice_sense->vs_active_keywords & BIT(i)) {
+                       dev_dbg(escore->dev, "%s(): release kw = %d\n",
+                                                       __func__, i + 1);
                        release_firmware(voice_sense->kw[i]);
+               }
+       }
        kfree(voice_sense);
 }
 
@@ -815,6 +1093,7 @@ int escore_vs_init(struct escore_priv *escore)
        /* Initialize variables */
        voice_sense->cvs_preset = 0;
        voice_sense->vs_active_keywords = 0;
+       voice_sense->es_vs_keyword_length = 0;
 
        mutex_init(&voice_sense->vs_event_mutex);
 
@@ -833,6 +1112,7 @@ int escore_vs_init(struct escore_priv *escore)
        return rc;
 
 sysfs_init_err:
+       kfree(voice_sense);
 voice_sense_alloc_err:
        return rc;
 }
index da9bd26b585c7c1a5fdfd56e0fd4beee6cdecc43..f85b0cd681475e08d1d8424921db2add0ca0b0c1 100644 (file)
@@ -32,6 +32,11 @@ struct escore_voice_sense {
        u16 vs_get_event;
        struct mutex vs_event_mutex;
        u16 cvs_preset;
+       u16 vs_route_preset;
+       u16 es_vs_keyword_length;
+#ifdef CONFIG_SND_SOC_ES_AVOID_REPEAT_FW_DOWNLOAD
+       bool vs_download_req;
+#endif
 };
 
 extern int escore_vs_init(struct escore_priv *escore);
@@ -51,6 +56,12 @@ int escore_put_cvs_preset_value(struct snd_kcontrol *kcontrol,
                                        struct snd_ctl_elem_value *ucontrol);
 int escore_get_cvs_preset_value(struct snd_kcontrol *kcontrol,
                                        struct snd_ctl_elem_value *ucontrol);
+int escore_put_vs_keyword_length(struct snd_kcontrol *kcontrol,
+                                       struct snd_ctl_elem_value *ucontrol);
+int escore_get_vs_keyword_length(struct snd_kcontrol *kcontrol,
+                                       struct snd_ctl_elem_value *ucontrol);
+int escore_get_keyword_overrun(struct snd_kcontrol *kcontrol,
+                                       struct snd_ctl_elem_value *ucontrol);
 int escore_vs_sleep_enable(struct escore_priv *escore);
 int escore_put_vs_activate_keyword(struct snd_kcontrol *kcontrol,
                                        struct snd_ctl_elem_value *ucontrol);
@@ -61,7 +72,7 @@ int escore_vs_request_firmware(struct escore_priv *escore,
 void escore_vs_release_firmware(struct escore_priv *escore);
 int escore_vs_request_bkg(struct escore_priv *escore, const char *vs_filename);
 void escore_vs_release_bkg(struct escore_priv *escore);
-int escore_vs_request_keywords(struct escore_priv *escore);
+int escore_vs_request_keywords(struct escore_priv *escore, unsigned int value);
 void escore_vs_release_keywords(struct escore_priv *escore);
 int escore_vs_write_bkg_and_keywords(struct escore_priv *escore);
 int escore_vs_put_control_enum(struct snd_kcontrol *kcontrol,
@@ -73,5 +84,21 @@ int escore_vs_put_control_value(struct snd_kcontrol *kcontrol,
 int escore_vs_get_control_value(struct snd_kcontrol *kcontrol,
                           struct snd_ctl_elem_value *ucontrol);
 
+#ifdef CONFIG_SND_SOC_ES_AVOID_REPEAT_FW_DOWNLOAD
+static inline void escore_set_vs_download_req(struct escore_priv *escore,
+                                                               bool val)
+{
+       struct escore_voice_sense *voice_sense =
+               (struct escore_voice_sense *)escore->voice_sense;
+       voice_sense->vs_download_req = val;
+}
+
+static inline bool escore_get_vs_download_req(struct escore_priv *escore)
+{
+       struct escore_voice_sense *voice_sense =
+               (struct escore_voice_sense *)escore->voice_sense;
+       return voice_sense->vs_download_req;
+}
 
+#endif
 #endif /* _ESCORE_VS_H */
index 656e5239abb3bbe51f4f8a4dcf550e3c4dd1efed..a79a9820e7457ee33fe32cdac42a6ccd97ee34a9 100644 (file)
@@ -5,8 +5,6 @@
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  */
-
-
 #include "escore.h"
 #include "escore-i2c.h"
 #include "escore-slim.h"
@@ -24,6 +22,73 @@ struct escore_macro cmd_hist[ES_MAX_ROUTE_MACRO_CMD] = { {0} };
 #endif
 
 int cmd_hist_index;
+
+/* is_forced allows to force recover irrespective of the value of
+ * disable_fw_recovery_cnt. Helps in asynchronous cases (e.g. interrupt) */
+int escore_fw_recovery(struct escore_priv *escore, int is_forced)
+{
+       int ret = 0;
+       char *event[] = { "ACTION=ADNC_FW_RECOVERY", NULL };
+
+       if (escore->disable_fw_recovery_cnt && !is_forced)
+               return 0;
+
+       /* stop streaming thread if running */
+       if (escore->stream_thread &&
+                       (atomic_read(&escore->stream_thread->usage) > 0))
+               kthread_stop(escore->stream_thread);
+
+       dev_info(escore->dev, "%s(): is_forced = %d\n", __func__, is_forced);
+
+       escore_gpio_reset(escore);
+       ret = escore->boot_ops.bootup(escore);
+       if (ret < 0) {
+               dev_err(escore->dev, "%s(): Bootup failed %d\n", __func__, ret);
+               return ret;
+       }
+
+       escore->escore_power_state = ES_SET_POWER_STATE_NORMAL;
+
+       INC_DISABLE_FW_RECOVERY_USE_CNT(escore);
+       ret = escore_reconfig_intr(escore);
+       if (ret < 0)
+               dev_err(escore->dev, "%s(): Interrupt setup failed %d\n",
+                               __func__, ret);
+
+       DEC_DISABLE_FW_RECOVERY_USE_CNT(escore);
+       pm_runtime_mark_last_busy(escore->dev);
+
+       if (!ret) {
+               int rc;
+               if (escore->debug_buff == NULL) {
+                       escore->debug_buff = kmalloc(DBG_BLK_SIZE, GFP_KERNEL);
+                       if (escore->debug_buff == NULL) {
+                               dev_err(escore->dev,
+                               "%s():Not enough memory to read fw debug data\n"
+                               , __func__);
+                               return ret;
+                       }
+               }
+
+               rc = read_debug_data(escore->debug_buff);
+               if (rc < 0) {
+                       dev_err(escore->dev, "%s():Read Debug data failed %d\n",
+                               __func__, rc);
+                       kfree(escore->debug_buff);
+                       escore->debug_buff = NULL;
+               }
+
+               /* send uevent irrespective of read success
+                * 1. It's highly unlikely that debug read would fail
+                * 2. If it does, this uevent would cause manual debug read by
+                *    the application (via sys)
+                */
+               kobject_uevent_env(&escore->dev->kobj, KOBJ_CHANGE, event);
+       }
+
+       return ret;
+}
+
 /* History struture, log route commands to debug */
 /* Send a single command to the chip.
  *
@@ -36,19 +101,18 @@ int cmd_hist_index;
  * E* - any value that can be returned by the underlying HAL.
  */
 
-static int _escore_cmd(struct escore_priv *escore, u32 cmd, u32 *resp)
+int escore_cmd_nopm(struct escore_priv *escore, u32 cmd, u32 *resp)
 {
        int sr;
        int err;
 
        *resp = 0;
        sr = cmd & BIT(28);
-
        err = escore->bus.ops.cmd(escore, cmd, resp);
        if (err || sr)
                goto exit;
 
-       if (resp == 0) {
+       if ((*resp) == 0) {
                err = -ETIMEDOUT;
                dev_err(escore->dev, "no response to command 0x%08x\n", cmd);
        } else {
@@ -60,14 +124,26 @@ exit:
        return err;
 }
 
+int escore_cmd_locked(struct escore_priv *escore, u32 cmd, u32 *resp)
+{
+       int ret;
+
+       mutex_lock(&escore->access_lock);
+       ret = escore_pm_get_sync();
+       if (ret > -1) {
+               ret = escore_cmd_nopm(escore, cmd, resp);
+               escore_pm_put_autosuspend();
+       }
+       mutex_unlock(&escore->access_lock);
+       return ret;
+}
+
 int escore_cmd(struct escore_priv *escore, u32 cmd, u32 *resp)
 {
        int ret;
        ret = escore_pm_get_sync();
        if (ret > -1) {
-               mutex_lock(&escore_priv.api_mutex);
-               ret = _escore_cmd(escore, cmd, resp);
-               mutex_unlock(&escore_priv.api_mutex);
+               ret = escore_cmd_nopm(escore, cmd, resp);
                escore_pm_put_autosuspend();
        }
        return ret;
@@ -76,17 +152,20 @@ int escore_write_block(struct escore_priv *escore, const u32 *cmd_block)
 {
        int ret = 0;
        u32 resp;
+       mutex_lock(&escore->access_lock);
        ret = escore_pm_get_sync();
        if (ret > -1) {
-               mutex_lock(&escore_priv.api_mutex);
                while (*cmd_block != 0xffffffff) {
-                       _escore_cmd(escore, *cmd_block, &resp);
+                       ret = escore_cmd_nopm(escore, *cmd_block, &resp);
+                       if (ret)
+                               break;
+
                        usleep_range(1000, 1005);
                        cmd_block++;
                }
-               mutex_unlock(&escore->api_mutex);
                escore_pm_put_autosuspend();
        }
+       mutex_unlock(&escore->access_lock);
        return ret;
 }
 
@@ -115,10 +194,12 @@ int escore_prepare_msg(struct escore_priv *escore, unsigned int reg,
 
                switch (msg_len) {
                case 8:
-                       api_word[1] |= (val_mask & value);
+                       api_word[1] |= ((val_mask & value) <<
+                                               api_access->val_shift);
                        break;
                case 4:
-                       api_word[0] |= (val_mask & value);
+                       api_word[0] |= ((val_mask & value) <<
+                                               api_access->val_shift);
                        break;
                }
        } else {
@@ -134,7 +215,7 @@ int escore_prepare_msg(struct escore_priv *escore, unsigned int reg,
 
 }
 
-static unsigned int _escore_read(struct snd_soc_codec *codec, unsigned int reg)
+static int _escore_read(struct snd_soc_codec *codec, unsigned int reg)
 {
        struct escore_priv *escore = &escore_priv;
        u32 api_word[2] = {0};
@@ -146,13 +227,14 @@ static unsigned int _escore_read(struct snd_soc_codec *codec, unsigned int reg)
        rc = escore_prepare_msg(escore, reg, value, (char *) api_word,
                        &msg_len, ES_MSG_READ);
        if (rc) {
-               pr_err("%s(): Failed to prepare read message\n", __func__);
+               pr_err("%s(): Prepare read message fail %d\n",
+                      __func__, rc);
                goto out;
        }
 
-       rc = _escore_cmd(escore, api_word[0], &resp);
+       rc = escore_cmd_nopm(escore, api_word[0], &resp);
        if (rc < 0) {
-               pr_err("%s(): escore_cmd()", __func__);
+               pr_err("%s(): _escore_cmd failed, rc = %d", __func__, rc);
                return rc;
        }
        api_word[0] = escore->bus.last_response;
@@ -162,15 +244,37 @@ out:
        return value;
 }
 
-unsigned int escore_read(struct snd_soc_codec *codec, unsigned int reg)
+/* Locked variant of escore_read():
+ * Exclusive firmware access is guaranteed when this variant is called.
+ */
+int escore_read_locked(struct snd_soc_codec *codec, unsigned int reg)
+{
+       unsigned int ret = 0;
+       int rc;
+       struct escore_priv *escore = &escore_priv;
+
+       mutex_lock(&escore->access_lock);
+       rc = escore_pm_get_sync();
+       if (rc > -1) {
+               ret = _escore_read(codec, reg);
+               escore_pm_put_autosuspend();
+       }
+       mutex_unlock(&escore->access_lock);
+       return ret;
+}
+
+/* READ API to firmware:
+ * This API may be interrupted. If there is a series of READs  being issued to
+ * firmware, there must be a fw_access lock acquired in order to ensure the
+ * atomicity of entire operation.
+ */
+int escore_read(struct snd_soc_codec *codec, unsigned int reg)
 {
        unsigned int ret = 0;
        int rc;
        rc = escore_pm_get_sync();
        if (rc > -1) {
-               mutex_lock(&escore_priv.api_mutex);
                ret = _escore_read(codec, reg);
-               mutex_unlock(&escore_priv.api_mutex);
                escore_pm_put_autosuspend();
        }
        return ret;
@@ -189,12 +293,13 @@ static int _escore_write(struct snd_soc_codec *codec, unsigned int reg,
        rc = escore_prepare_msg(escore, reg, value, (char *) api_word,
                        &msg_len, ES_MSG_WRITE);
        if (rc) {
-               pr_err("%s(): Failed to prepare write message\n", __func__);
+               pr_err("%s(): Failed to prepare write message %d\n",
+                      __func__, rc);
                goto out;
        }
 
        for (i = 0; i < msg_len / 4; i++) {
-               rc = _escore_cmd(escore, api_word[i], &resp);
+               rc = escore_cmd_nopm(escore, api_word[i], &resp);
                if (rc < 0) {
                        pr_err("%s(): escore_cmd()", __func__);
                        return rc;
@@ -205,7 +310,7 @@ out:
        return rc;
 }
 
-/* This function should be called under api_mutex protection */
+/* This function must be called with access_lock acquired */
 int escore_reconfig_intr(struct escore_priv *escore)
 {
        int rc = 0;
@@ -218,7 +323,7 @@ int escore_reconfig_intr(struct escore_priv *escore)
                cmd |= escore->pdata->gpio_a_irq_type;
        }
 
-       rc = escore->bus.ops.cmd(escore, cmd, &resp);
+       rc = escore_cmd_nopm(escore, cmd, &resp);
        if (rc < 0) {
                dev_err(escore->dev,
                                "%s() - failed sync cmd resume rc = %d\n",
@@ -237,8 +342,9 @@ int escore_reconfig_intr(struct escore_priv *escore)
                }
        } else {
                /* Setup the Event response */
-               cmd = (ES_SET_EVENT_RESP << 16) | ES_RISING_EDGE;
-               rc = escore->bus.ops.cmd(escore, cmd, &resp);
+               cmd = (ES_SET_EVENT_RESP << 16) | \
+                                               escore->pdata->gpio_b_irq_type;
+               rc = escore_cmd_nopm(escore, cmd, &resp);
                if (rc < 0) {
                        dev_err(escore->dev,
                                "%s(): Error %d in setting event response\n",
@@ -274,38 +380,24 @@ int escore_datablock_wait(struct escore_priv *escore)
        return rc;
 }
 
-int escore_datablock_read(struct escore_priv *escore, void *buf,
-               size_t len, int id)
+/* Sends RDB ID to fw and gets data block size from the response */
+int escore_get_rdb_size(struct escore_priv *escore, int id)
 {
        int rc;
        int size;
-       u32 cmd;
-       int rdcnt = 0;
        u32 resp;
-       u8 flush_extra_blk = 0;
-       u32 flush_buf;
-
-       /* Reset read data block size */
-       escore->datablock_dev.rdb_read_count = 0;
-
-       mutex_lock(&escore->api_mutex);
-
-       if (escore->bus.ops.rdb) {
-               rc = escore->bus.ops.rdb(escore, buf, len, id);
-               goto out;
-       }
-       cmd = (ES_READ_DATA_BLOCK << 16) | (id & 0xFFFF);
+       u32 cmd = (ES_READ_DATA_BLOCK << 16) | (id & 0xFFFF);
 
        rc = escore->bus.ops.high_bw_cmd(escore, cmd, &resp);
        if (rc < 0) {
                pr_err("%s(): escore_cmd() failed rc = %d\n", __func__, rc);
-               goto out;
+               return rc;
        }
+
        if ((resp >> 16) != ES_READ_DATA_BLOCK) {
                pr_err("%s(): Invalid response received: 0x%08x\n",
                                __func__, resp);
-               rc = -EINVAL;
-               goto out;
+               return -EINVAL;
        }
 
        size = resp & 0xFFFF;
@@ -313,17 +405,26 @@ int escore_datablock_read(struct escore_priv *escore, void *buf,
        if (size == 0 || size % 4 != 0) {
                pr_err("%s(): Read Data Block with invalid size:%d\n",
                                __func__, size);
-               rc = -EINVAL;
-               goto out;
+               return -EINVAL;
        }
 
-       if (len != size) {
-               pr_debug("%s(): Requested:%zd Received:%d\n", __func__,
-                               len, size);
-               if (len < size)
-                       flush_extra_blk = (size - len) % 4;
-               else
-                       len = size;
+       return size;
+}
+
+/* Call escore_get_rdb_size before calling this as that's the one that actually
+ * sends RDB ID to fw. Attempt to read before sending ID would cause error */
+int escore_datablock_read(struct escore_priv *escore, void *buf,
+               size_t len)
+{
+       int rc;
+       int rdcnt = 0;
+
+       if (escore->bus.ops.rdb) {
+               /* returns 0 on success */
+               rc = escore->bus.ops.rdb(escore, buf, len);
+               if (rc)
+                       return rc;
+               return len;
        }
 
        for (rdcnt = 0; rdcnt < len;) {
@@ -331,37 +432,19 @@ int escore_datablock_read(struct escore_priv *escore, void *buf,
                if (rc < 0) {
                        pr_err("%s(): Read Data Block error %d\n",
                                        __func__, rc);
-                       goto out;
+                       return rc;
                }
                rdcnt += 4;
                buf += 4;
        }
-       /* Store read data block size */
-       escore->datablock_dev.rdb_read_count = size;
 
-       /* No need to read in case of no extra bytes */
-       if (flush_extra_blk) {
-               /* Discard the extra bytes */
-               rc = escore->bus.ops.high_bw_read(escore, &flush_buf,
-                                                       flush_extra_blk);
-               if (rc < 0) {
-                       pr_err("%s(): Read Data Block error in flushing %d\n",
-                                       __func__, rc);
-                       goto out;
-               }
-       }
-       mutex_unlock(&escore->api_mutex);
        return len;
-out:
-       mutex_unlock(&escore->api_mutex);
-       return rc;
 }
 
-/* This function should be called under api_mutex protection */
 int escore_datablock_write(struct escore_priv *escore, const void *buf,
                size_t len)
 {
-       int rc;
+       int rc, ret;
        int count;
        u32 resp;
        u32 cmd = ES_WRITE_DATA_BLOCK << 16;
@@ -370,7 +453,7 @@ int escore_datablock_write(struct escore_priv *escore, const void *buf,
        u8 *dptr = (u8 *) buf;
 #if defined(CONFIG_SND_SOC_ES_SPI) || \
        defined(CONFIG_SND_SOC_ES_HIGH_BW_BUS_SPI)
-       u16 resp16;
+       u32 resp32;
 #endif
 
 #ifdef ES_WDB_PROFILING
@@ -387,18 +470,36 @@ int escore_datablock_write(struct escore_priv *escore, const void *buf,
        es_profiling(&tstart);
        es_profiling(&tstart_cmd);
 
+       if (escore->datablock_dev.wdb_config) {
+               rc = escore->datablock_dev.wdb_config(escore);
+               if (rc < 0) {
+                       pr_err("%s(): WDB speed config error : %d\n",
+                                       __func__, rc);
+                       goto out;
+               }
+       }
+
        while (remaining) {
 
+               rc = escore_is_sleep_aborted(escore);
+               if (rc == -EABORT) {
+                       /* BAS-3232: On CVQ abort while WDB is running,
+                        * provide 5ms delay before performing abort
+                        * sequence. */
+                       usleep_range(5000, 5050);
+                       goto out;
+               }
+
                /* If multiple WDB blocks are written, some delay is required
                 * before starting next WDB. This delay is not documented but
                 * if this delay is not added, extra zeros are obsevred in
                 * escore_uart_read() causing WDB failure.
                 */
-               if (len > 512)
+               if (len > escore->es_wdb_max_size)
                        usleep_range(2000, 2050);
 
-               size = remaining > ES_WDB_MAX_SIZE ?
-                      ES_WDB_MAX_SIZE : remaining;
+               size = remaining > escore->es_wdb_max_size ?
+                      escore->es_wdb_max_size : remaining;
 
                cmd = ES_WRITE_DATA_BLOCK << 16;
                cmd = cmd | (size & 0xFFFF);
@@ -437,36 +538,45 @@ int escore_datablock_write(struct escore_priv *escore, const void *buf,
                        resp = 0;
 #if (defined(CONFIG_SND_SOC_ES_SPI)) || \
        defined(CONFIG_SND_SOC_ES_HIGH_BW_BUS_SPI)
-                       resp16 = 0;
-                       rc = escore->bus.ops.high_bw_read(escore, &resp16,
-                                       sizeof(resp16));
+                       resp32 = 0;
+                       rc = escore->bus.ops.high_bw_read(escore, &resp32,
+                                       sizeof(resp32));
                        if (rc < 0) {
                                pr_err("%s(): WDB last ACK read error:%d\n",
                                        __func__, rc);
                                goto out;
                        }
-                       if (resp16 == ES_WRITE_DATA_BLOCK_SPI) {
-                               resp = (cpu_to_be16(resp16)) << 16;
-                               resp16 = 0;
+                       resp = (cpu_to_be32(resp32));
+
+                       if (resp == 0) {
+                               pr_debug("%s(): Invalid response 0x%0x\n",
+                                               __func__, resp);
+                               rc = -EIO;
+                               continue;
+                       } else if ((resp >> 16) == 0) {
+                               /* Fw SPI interface is 16bit. So in the 32bit
+                                * read of command's response, sometimes fw
+                                * sends first 16bit in first 32bit read and
+                                * second 16bit in second 32bit. So this is
+                                * special condition handling to make response.
+                                */
                                rc = escore->bus.ops.high_bw_read(escore,
-                                               &resp16, sizeof(resp16));
+                                               &resp32, sizeof(resp32));
                                if (rc < 0) {
                                        pr_err("%s(): WDB last ACK read error:%d\n",
                                                __func__, rc);
                                        goto out;
-                               }
-                               resp |= cpu_to_be16(resp16);
-                               if (resp != (ES_WRITE_DATA_BLOCK << 16)) {
-                                       pr_debug("%s(): response not ready 0x%0x\n",
-                                                       __func__, resp);
-                                       rc = -EIO;
                                } else {
-                                       break;
+                                       resp = resp << 16;
+                                       resp |= (cpu_to_be32(resp32) >> 16);
                                }
-                       } else {
-                               pr_debug("%s(): Invalid response 0x%0x\n",
-                                               __func__, resp16);
+                       }
+                       if (resp != (ES_WRITE_DATA_BLOCK << 16)) {
+                               pr_debug("%s(): response not ready 0x%0x\n",
+                                               __func__, resp);
                                rc = -EIO;
+                       } else {
+                               break;
                        }
                        if (count % ES_SPI_CONT_RETRY == 0) {
                                usleep_range(ES_SPI_RETRY_DELAY,
@@ -481,7 +591,7 @@ int escore_datablock_write(struct escore_priv *escore, const void *buf,
                                goto out;
                        }
 
-                       resp = escore->bus.ops.bus_to_cpu(escore, resp);
+                       resp = escore->bus.ops.high_bw_bus_to_cpu(escore, resp);
                        if (resp != (ES_WRITE_DATA_BLOCK << 16)) {
                                pr_debug("%s(): response not ready 0x%0x\n",
                                                __func__, resp);
@@ -502,8 +612,17 @@ int escore_datablock_write(struct escore_priv *escore, const void *buf,
                dptr += size;
                remaining -= size;
        }
-       es_profiling(&tend_resp);
 
+       if (escore->datablock_dev.wdb_reset_config) {
+               rc = escore->datablock_dev.wdb_reset_config(escore);
+               if (rc < 0) {
+                       pr_err("%s(): WDB speed reset config error : %d\n",
+                                       __func__, rc);
+                       goto out;
+               }
+       }
+
+       es_profiling(&tend_resp);
        es_profiling(&tend);
 #ifdef ES_WDB_PROFILING
        tstart = (timespec_sub(tstart, tend));
@@ -523,312 +642,84 @@ int escore_datablock_write(struct escore_priv *escore, const void *buf,
        return len;
 
 out:
+       if (escore->datablock_dev.wdb_reset_config) {
+               ret = escore->datablock_dev.wdb_reset_config(escore);
+               if (ret < 0) {
+                       rc = ret;
+                       pr_err("%s(): WDB speed reset config error : %d\n",
+                                       __func__, rc);
+               }
+       }
+
        return rc;
 }
 
-int escore_write(struct snd_soc_codec *codec, unsigned int reg,
-                      unsigned int value)
+/*
+ * This function assumes chip isn't in sleep mode; which is when you typically
+ * need debug data
+ */
+int read_debug_data(void *buf)
 {
-       int ret;
-       ret = escore_pm_get_sync();
-       if (ret > -1) {
-               mutex_lock(&escore_priv.api_mutex);
-               ret = _escore_write(codec, reg, value);
-               mutex_unlock(&escore_priv.api_mutex);
-               escore_pm_put_autosuspend();
+       int ret = escore_datablock_open(&escore_priv);
+       if (ret) {
+               dev_err(escore_priv.dev,
+                       "%s(): can't open datablock device = %d\n", __func__,
+                       ret);
+               return ret;
        }
-       return ret;
 
-}
-int escore_read_and_clear_intr(struct escore_priv *escore)
-{
-       int value;
-       int ret;
-       struct snd_soc_codec *codec = escore->codec;
+       /* ignore size as it's fix; we are calling this to send RDB ID */
+       ret = escore_get_rdb_size(&escore_priv, DBG_ID);
+       if (ret < 0)
+               goto datablock_close;
 
-       pr_debug("%s()\n", __func__);
-       ret = escore_pm_get_sync();
-       if (ret > -1) {
-               mutex_lock(&escore_priv.api_mutex);
-               value = _escore_read(codec, escore->regs->get_intr_status);
-               if (value < 0) {
-                       pr_err("%s(): Reading System Interrupt Status failed\n",
-                               __func__);
-                       ret = value;
-                       goto read_error;
-               }
-               ret = _escore_write(codec, escore->regs->clear_intr_status,
-                               value);
-               if (ret < 0)
-                       pr_err("%s(): Clearing interrupt status failed\n",
-                               __func__);
-read_error:
-               mutex_unlock(&escore_priv.api_mutex);
-               escore_pm_put_autosuspend();
-       }
-       return ret;
+       ret = escore_datablock_read(&escore_priv, buf, DBG_BLK_SIZE);
+       if (ret < 0)
+               dev_err(escore_priv.dev,
+                       "%s(): failed to read debug data; err: %d\n", __func__,
+                       ret);
 
+datablock_close:
+       escore_datablock_close(&escore_priv);
+       return ret;
 }
 
-int escore_accdet_config(struct escore_priv *escore, int enable)
+/* Locked variant of escore_write():
+ * Exclusive firmware access is guaranteed when this variant is called.
+ */
+int escore_write_locked(struct snd_soc_codec *codec, unsigned int reg,
+                      unsigned int value)
 {
        int ret;
-       struct snd_soc_codec *codec = escore->codec;
+       struct escore_priv *escore = &escore_priv;
 
-       pr_debug("%s()\n", __func__);
+       mutex_lock(&escore->access_lock);
        ret = escore_pm_get_sync();
        if (ret > -1) {
-               mutex_lock(&escore_priv.api_mutex);
-               ret = _escore_write(codec, escore->regs->accdet_config, enable);
-               if (ret < 0)
-                       pr_err("Accdet detection enabling failed\n");
-               mutex_unlock(&escore_priv.api_mutex);
+               ret = _escore_write(codec, reg, value);
                escore_pm_put_autosuspend();
        }
+       mutex_unlock(&escore->access_lock);
        return ret;
-}
-EXPORT_SYMBOL_GPL(escore_accdet_config);
-
-static int _escore_btndet_config(struct escore_priv *escore, int enable)
-{
-       int rc;
-       struct snd_soc_codec *codec = escore->codec;
-       struct esxxx_accdet_config *accdet_cfg = &escore->pdata->accdet_cfg;
-
-       pr_debug("%s()\n", __func__);
-       rc = _escore_write(codec, escore->regs->enable_btndet, enable);
-       if (rc < 0) {
-               pr_err("Button detection enabling failed\n");
-               goto btndet_config_error;
-       }
-
-       if (enable) {
-               /* Enable serial button config */
-               if (accdet_cfg->btn_serial_cfg != -1) {
-                       rc = _escore_write(codec,
-                                       escore->regs->btn_serial_cfg,
-                                       accdet_cfg->btn_serial_cfg);
-                       if (rc < 0) {
-                               pr_err("Serial button config failed\n");
-                               goto btndet_config_error;
-                       }
-               }
-
-               /* Enable parallel button config */
-               if (accdet_cfg->btn_parallel_cfg != -1) {
-                       rc = _escore_write(codec,
-                                       escore->regs->btn_parallel_cfg,
-                                       accdet_cfg->btn_parallel_cfg);
-                       if (rc < 0) {
-                               pr_err("Parallel button config failed\n");
-                               goto btndet_config_error;
-                       }
-               }
-
-               /* Set button detection rate */
-               if (accdet_cfg->btn_detection_rate != -1) {
-                       rc = _escore_write(codec,
-                                       escore->regs->btn_detection_rate,
-                                       accdet_cfg->btn_detection_rate);
-                       if (rc < 0) {
-                               pr_err("Set button detection rate failed\n");
-                               goto btndet_config_error;
-                       }
-               }
-
-               /* Set settling time config for button press */
-               if (accdet_cfg->btn_press_settling_time != -1) {
-                       rc = _escore_write(codec,
-                                       escore->regs->btn_press_settling_time,
-                                       accdet_cfg->btn_press_settling_time);
-                       if (rc < 0) {
-                               pr_err("Set button settling time failed\n");
-                               goto btndet_config_error;
-                       }
-               }
-
-               /* Set bounce time config for button press */
-               if (accdet_cfg->btn_bounce_time != -1) {
-                       rc = _escore_write(codec,
-                                       escore->regs->btn_bounce_time,
-                                       accdet_cfg->btn_bounce_time);
-                       if (rc < 0) {
-                               pr_err("Set button bounce time failed\n");
-                               goto btndet_config_error;
-                       }
-               }
-
-               /*
-                * Sets the time duration for a button press necessary
-                * to classify a press detection event as a LONG button
-                * press
-                */
 
-               if (accdet_cfg->btn_long_press_time != -1) {
-                       rc = _escore_write(codec,
-                                       escore->regs->btn_long_press_time,
-                                       accdet_cfg->btn_long_press_time);
-               if (rc < 0) {
-                       pr_err("Long Button Press config failed\n");
-                       goto btndet_config_error;
-                       }
-               }
-       }
-
-btndet_config_error:
-       return rc;
 }
 
-int escore_btndet_config(struct escore_priv *escore, int enable)
+/* WRITE API to firmware:
+ * This API may be interrupted. If there is a series of WRITEs or READs  being
+ * issued to firmware, there must be a fw_access lock acquired in order to
+ * ensure the atomicity of entire operation.
+ */
+int escore_write(struct snd_soc_codec *codec, unsigned int reg,
+                      unsigned int value)
 {
        int ret;
-       pr_debug("%s()\n", __func__);
        ret = escore_pm_get_sync();
        if (ret > -1) {
-               mutex_lock(&escore_priv.api_mutex);
-               ret =  _escore_btndet_config(escore, enable);
-               mutex_unlock(&escore_priv.api_mutex);
+               ret = _escore_write(codec, reg, value);
                escore_pm_put_autosuspend();
        }
        return ret;
-}
-EXPORT_SYMBOL_GPL(escore_btndet_config);
-
-int escore_process_accdet(struct escore_priv *escore)
-{
-       int value;
-       struct snd_soc_codec *codec = escore->codec;
-
-       pr_debug("%s()\n", __func__);
-       value = escore_pm_get_sync();
-       if (value > -1) {
-               mutex_lock(&escore_priv.api_mutex);
-               /* Find out type of accessory using Get Accessory Detect
-                * Status Command */
-               value = _escore_read(codec, escore->regs->accdet_status);
-               if (value < 0) {
-                       pr_err("%s(): Enable button detect failed\n", __func__);
-                       goto accdet_error;
-               } else if (ES_IS_LRG_HEADPHONE(value))
-                       pr_info("%s(): LRG Headphone\n", __func__);
-               else
-                       pr_info("Unknown Accessory detected\n");
-accdet_error:
-               mutex_unlock(&escore_priv.api_mutex);
-               escore_pm_put_autosuspend();
-       }
-       return value;
-}
-EXPORT_SYMBOL_GPL(escore_process_accdet);
-
-/*
- * Placeholder for digital chip related interrupts
- */
-void escore_process_digital_intr(struct escore_priv *escore)
-{
-       if (!escore->process_digital)
-               return;
-
-       /* TODO: Add the generic digital interrupt handling */
-}
-
-/*
- * Processes the various analog interrupts. Detects the type of
- * accessory plugged in (either headphone or headset) and configures
- * the accessory if required.
- *
- * TODO: Report the jack plug/unplug event to userspace
- */
-void escore_process_analog_intr(struct escore_priv *escore)
-{
-       int rc = 0;
-       int value;
-
-       pr_debug("%s()\n", __func__);
-       if (!escore->process_analog)
-               goto process_analog_intr_error;
-
-       value = escore_read_and_clear_intr(escore);
-       if (value < 0)
-               goto process_analog_intr_error;
-
-       if (ES_IS_PLUG_EVENT(value)) {
-
-               pr_info("%s(): Plug event\n", __func__);
-               /* Enable accessory detection */
-               rc = escore_accdet_config(escore, ES_ACCDET_ENABLE);
-               if (rc < 0) {
-                       pr_err("%s(): Enabling accessory detection failed\n",
-                                       __func__);
-                       goto process_analog_intr_error;
-               }
-       } else if (ES_IS_UNPLUG_EVENT(value)) {
-
-               pr_info("%s(): Unplug event\n", __func__);
-               /* Disable button detection */
-               rc = escore_btndet_config(escore, ES_BTNDET_DISABLE);
-               if (rc < 0) {
-                       pr_err("%s(): Disabling button detection failed\n",
-                                       __func__);
-                       goto process_analog_intr_error;
-               }
-
-               /* Disable accessory detection */
-               rc = escore_accdet_config(escore, ES_ACCDET_DISABLE);
-               if (rc < 0) {
-                       pr_err("%s(): Disabling accessory detection failed\n",
-                                       __func__);
-                       goto process_analog_intr_error;
-               }
-       } else if (ES_IS_ACCDET_EVENT(value)) {
-
-               pr_info("%s(): Accdet event\n", __func__);
-               /* Process accessory detection */
-               rc = escore_process_accdet(escore);
-               if (rc < 0) {
-                       pr_err("%s(): Processing accessory detection failed\n",
-                                       __func__);
-                       goto process_analog_intr_error;
-               }
-
-       } else if (ES_IS_BTN_PRESS_EVENT(value)) {
-
-               if (ES_IS_SHORT_BTN_PARALLEL_PRESS(value))
-                       pr_info("%s(): Short button parallel press event\n",
-                                       __func__);
-               else if (ES_IS_SHORT_BTN_SERIAL_PRESS(value))
-                       pr_info("%s(): Short button serial press event\n",
-                                       __func__);
-               else if (ES_IS_LONG_BTN_PARALLEL_PRESS(value))
-                       pr_info("%s(): Long button parallel press event\n",
-                                       __func__);
-               else if (ES_IS_LONG_BTN_SERIAL_PRESS(value))
-                       pr_info("%s(): Long button serial press event\n",
-                                       __func__);
-       } else
-               pr_info("%s(): Unknown Interrupt %x\n", __func__, value);
-
-process_analog_intr_error:
-       return;
-}
-
-
-/*
- * Generic ISR for Audience chips. It is divided mainly into two parts to
- * process interrupts for:
- * 1) chips containing codec
- * 2) chips only having digital component
- */
 
-irqreturn_t escore_irq_work(int irq, void *data)
-{
-       struct escore_priv *escore = data;
-
-       escore_process_digital_intr(escore);
-
-       escore_process_analog_intr(escore);
-
-       return IRQ_HANDLED;
 }
 
 int escore_start_int_osc(struct escore_priv *escore)
@@ -841,10 +732,10 @@ int escore_start_int_osc(struct escore_priv *escore)
 
        /* Start internal Osc. */
        cmd = ES_INT_OSC_MEASURE_START << 16;
-       rc = escore->bus.ops.cmd(escore, cmd, &rsp);
+       rc = escore_cmd_nopm(escore, cmd, &rsp);
        if (rc) {
-               dev_err(escore->dev, "%s(): escore_cmd fail %d\n",
-                               __func__, rc);
+               dev_err(escore->dev, "%s(): Int Osc Msr Start cmd fail %d\n",
+                       __func__, rc);
                goto escore_int_osc_exit;
        }
 
@@ -856,10 +747,11 @@ int escore_start_int_osc(struct escore_priv *escore)
                 */
                msleep(20);
                cmd = ES_INT_OSC_MEASURE_STATUS << 16;
-               rc = escore->bus.ops.cmd(escore, cmd, &rsp);
+               rc = escore_cmd_nopm(escore, cmd, &rsp);
                if (rc) {
-                       dev_err(escore->dev, "%s(): escore_cmd fail %d\n",
-                                       __func__, rc);
+                       dev_err(escore->dev,
+                               "%s(): Int Osc Msr Sts cmd fail %d\n",
+                               __func__, rc);
                        goto escore_int_osc_exit;
                }
                rsp &= 0xFFFF;
@@ -879,23 +771,56 @@ escore_int_osc_exit:
        return rc;
 }
 
-static int escore_recover_wkup_failure(struct escore_priv *escore)
+/* Reconfig API Interrupt */
+int escore_reconfig_api_intr(struct escore_priv *escore)
 {
-       int ret;
-       ret = escore->boot_ops.bootup(escore);
-       if (ret) {
-               pr_err("%s recovery failed in bootup\n", __func__);
-               return ret;
+       int rc = 0;
+       u32 cmd = ES_SYNC_CMD << 16;
+       u32 rsp;
+
+       /*  GPIO_A is not configured, reconfigure is not required */
+       if (escore->pdata->gpioa_gpio == -1)
+               return rc;
+
+       pr_debug("%s(): Reconfig API Interrupt with mode %d\n",
+               __func__, escore->pdata->gpio_a_irq_type);
+
+       cmd |= escore->pdata->gpio_a_irq_type;
+       escore->cmd_compl_mode = ES_CMD_COMP_INTR;
+       rc = escore_cmd_nopm(escore,
+                       (cmd | (ES_SUPRESS_RESPONSE << 16)),
+                       &rsp);
+       if (rc) {
+               dev_err(escore->dev,
+                   "%s() - API interrupt reconfig failed, rc = %d\n",
+                   __func__, rc);
+               escore->cmd_compl_mode = ES_CMD_COMP_POLL;
        }
-       escore->escore_power_state = ES_SET_POWER_STATE_NORMAL;
 
-       if (escore->recover_wkup_failure)
-               ret = escore->recover_wkup_failure(escore);
+       return rc;
+}
 
-       if (ret)
-               pr_err("%s failed to reset codec config\n", __func__);
-       return ret;
+/* API Interrupt completion handler */
+int escore_api_intr_wait_completion(struct escore_priv *escore)
+{
+       int rc = 0;
+
+       pr_debug("%s(): Waiting for API interrupt", __func__);
+
+       rc = wait_for_completion_timeout(&escore->cmd_compl,
+                       msecs_to_jiffies(ES_API_INTR_TOUT_MSEC));
+       if (!rc) {
+               rc = -ETIMEDOUT;
+               dev_err(escore->dev,
+                       "%s(): API Interrupt wait timeout %d\n", __func__, rc);
+               escore->wait_api_intr = 0;
+       } else {
+               rc = 0;
+       }
+
+       return rc;
 }
+
 int escore_wakeup(struct escore_priv *escore)
 {
        u32 cmd = ES_SYNC_CMD << 16;
@@ -904,6 +829,7 @@ int escore_wakeup(struct escore_priv *escore)
        int retry = 20;
        u32 p_cmd = ES_GET_POWER_STATE << 16;
 
+       escore->cmd_compl_mode = ES_CMD_COMP_POLL;
        /* Enable the clocks */
        if (escore_priv.pdata->esxxx_clk_cb) {
                escore_priv.pdata->esxxx_clk_cb(1);
@@ -911,7 +837,13 @@ int escore_wakeup(struct escore_priv *escore)
                msleep(ES_PM_CLOCK_STABILIZATION);
        }
 
+       //if (escore->pri_intf == ES_SPI_INTF)
+       //      msleep(ES_WAKEUP_TIME);
+
        do {
+               /* Set flag to Wait for API Interrupt */
+               escore_set_api_intr_wait(escore);
+
                /* Toggle the wakeup pin H->L the L->H */
                if (escore->wakeup_intf == ES_UART_INTF &&
                                escore->escore_uart_wakeup) {
@@ -930,67 +862,119 @@ int escore_wakeup(struct escore_priv *escore)
                        gpio_set_value(escore->pdata->wakeup_gpio, 1);
                        usleep_range(1000, 1005);
                        gpio_set_value(escore->pdata->wakeup_gpio, 0);
-               } else {
-                       dev_err(escore->dev,
-                               "%s()Wakeup interface not defined\n", __func__);
-                       goto escore_wakeup_exit;
                }
-               /* Give the device time to "wakeup" */
-               msleep(ES_WAKEUP_TIME);
 
-               if (escore->pdata->gpioa_gpio != -1)
-                       cmd |= escore->pdata->gpio_a_irq_type;
+               if (escore->pdata->gpioa_gpio == -1) {
+                       /* Give the device time to "wakeup" */
+                       if (escore->escore_power_state ==
+                                       ES_SET_POWER_STATE_VS_LOWPWR)
+                               msleep(escore->delay.wakeup_to_vs);
+                       else if (escore->escore_power_state ==
+                                       ES_SET_POWER_STATE_MP_SLEEP)
+                               msleep(escore->delay.mpsleep_to_normal);
+                       else
+                               msleep(escore->delay.wakeup_to_normal);
 
-               if (escore->pri_intf == ES_SPI_INTF) {
-                       rc = escore_priv.bus.ops.cmd(escore, p_cmd, &rsp);
+/*
+                       if (escore->pri_intf == ES_SPI_INTF) {
+                               if (escore->pdata->gpioa_gpio == -1)
+                                       msleep(ES_WAKEUP_TIME);
+                               rc = escore_cmd_nopm(escore, p_cmd, &rsp);
+                               if (rc < 0) {
+                                       pr_err("%s(): get power state failed" \
+                                               " rc = %d\n", __func__, rc);
+                                       continue;
+                               }
+                               if ((rsp != ES_PS_NORMAL) &&
+                                       (rsp != ES_PS_OVERLAY)) {
+                                       rc = -1;
+                                       continue;
+                               }
+                       }
+*/
+
+                       /* Send sync command to verify device is active */
+                       rc = escore_cmd_nopm(escore, cmd, &rsp);
                        if (rc < 0) {
-                               pr_err("%s() - failed check power status\n",
-                                                       __func__);
-                               continue;
+                               dev_err(escore->dev,
+                                       "%s(): failed sync cmd resume %d\n",
+                                       __func__, rc);
                        }
-                       if  ((rsp != ES_PS_NORMAL) && (rsp != ES_PS_OVERLAY)) {
-                               rc = -1;
-                               continue;
+                       if (cmd != rsp) {
+                               dev_err(escore->dev,
+                                       "%s(): failed sync rsp resume %d\n",
+                                       __func__, rc);
+                               rc = -EIO;
                        }
-               }
+               } else {
+                       /* Wait for API Interrupt to confirm
+                        * that device is active */
+                       rc = escore_api_intr_wait_completion(escore);
+                       if (rc)
+                               goto escore_wakeup_exit;
 
-               rc = escore_priv.bus.ops.cmd(escore, cmd, &rsp);
-               if (rc < 0) {
-                       dev_err(escore->dev, "%s() - failed sync cmd resume\n",
-                                                       __func__);
-               }
-               if (cmd != rsp) {
-                       dev_err(escore->dev, "%s() - failed sync rsp resume\n",
-                                                       __func__);
-                       rc = -EIO;
+                       /* Reconfig API Interrupt mode after wakeup */
+                       rc = escore_reconfig_api_intr(escore);
+                       if (rc)
+                               goto escore_wakeup_exit;
                }
        } while (rc && --retry);
 
-       /* Set Interrupt mode after wakeup */
-       if (escore->pdata->gpioa_gpio != -1)
-               escore->cmd_compl_mode = ES_CMD_COMP_INTR;
+       /* Hack to avoid flase interrupts coming after deep sleep */
+       //msleep(350);
 
-       if  (rc) {
-               rc = escore_recover_wkup_failure(escore);
-               if (rc)
-                       pr_debug("%s failed to recover\n", __func__);
-               return rc;
-       }
        /* Set the Smooth Mute rate to Zero */
        cmd = ES_SET_SMOOTH_MUTE << 16 | ES_SMOOTH_MUTE_ZERO;
-       rc = escore->bus.ops.cmd(escore, cmd, &rsp);
-       if (rc)
-               dev_err(escore->dev, "%s(): escore_cmd fail %d\n",
-                               __func__, rc);
+       rc = escore_cmd_nopm(escore, cmd, &rsp);
+       if (rc) {
+               dev_err(escore->dev, "%s(): Set Smooth Mute cmd fail %d\n",
+                       __func__, rc);
+               goto escore_wakeup_exit;
+       }
 
 escore_wakeup_exit:
        return rc;
 }
 
+/* Update pm_status value to ES_PM_OFF / ES_PM_ON */
+int escore_pm_status_update(bool value)
+{
+       struct escore_priv *escore = &escore_priv;
+       int rc;
+
+       if (!escore->pm_enable) {
+               dev_info(escore->dev, "%s() RPM for device is not enabled\n",
+                                                       __func__);
+               return 0;
+       }
+
+       if (value == escore->pm_status) {
+               dev_info(escore->dev, "%s() Ignoring same value %d\n",
+                                               __func__, escore->pm_status);
+               return 0;
+       }
+
+       /* PM_STATUS OFF request */
+       if (value == ES_PM_OFF) {
+               rc = escore_pm_get_sync();
+               if (rc < 0) {
+                       dev_err(escore_priv.dev,
+                               "%s(): pm_get_sync failed :%d\n",
+                                       __func__, rc);
+                       return rc;
+               }
+       } else /* PM_STATUS ON request */
+               escore_pm_put_autosuspend();
+
+       escore->pm_status = value;
+
+       return 0;
+}
+
 int escore_get_runtime_pm_enum(struct snd_kcontrol *kcontrol,
                                        struct snd_ctl_elem_value *ucontrol)
 {
-       ucontrol->value.enumerated.item[0] = escore_priv.pm_enable;
+       ucontrol->value.enumerated.item[0] = escore_priv.pm_status;
 
        return 0;
 }
@@ -998,16 +982,7 @@ int escore_get_runtime_pm_enum(struct snd_kcontrol *kcontrol,
 int escore_put_runtime_pm_enum(struct snd_kcontrol *kcontrol,
                                        struct snd_ctl_elem_value *ucontrol)
 {
-       unsigned int value;
-
-       value = ucontrol->value.enumerated.item[0];
-
-       if (value)
-               escore_pm_enable();
-       else
-               escore_pm_disable();
-
-       return 0;
+       return escore_pm_status_update(ucontrol->value.enumerated.item[0]);
 }
 
 
@@ -1018,14 +993,16 @@ int escore_put_control_enum(struct snd_kcontrol *kcontrol,
        unsigned int reg = e->reg;
        unsigned int value;
        int rc = 0;
+       struct escore_priv *escore = &escore_priv;
+
+       mutex_lock(&escore->access_lock);
        rc = escore_pm_get_sync();
        if (rc > -1) {
-               mutex_lock(&escore_priv.api_mutex);
                value = ucontrol->value.enumerated.item[0];
                rc = _escore_write(NULL, reg, value);
-               mutex_unlock(&escore_priv.api_mutex);
                escore_pm_put_autosuspend();
        }
+       mutex_unlock(&escore->access_lock);
        return 0;
 }
 
@@ -1037,15 +1014,16 @@ int escore_get_control_enum(struct snd_kcontrol *kcontrol,
                (struct soc_enum *)kcontrol->private_value;
        unsigned int reg = e->reg;
        unsigned int value;
+       struct escore_priv *escore = &escore_priv;
 
+       mutex_lock(&escore->access_lock);
        ret = escore_pm_get_sync();
        if (ret > -1) {
-               mutex_lock(&escore_priv.api_mutex);
                value = _escore_read(NULL, reg);
                ucontrol->value.enumerated.item[0] = value;
-               mutex_unlock(&escore_priv.api_mutex);
                escore_pm_put_autosuspend();
        }
+       mutex_unlock(&escore->access_lock);
        return 0;
 }
 
@@ -1057,15 +1035,16 @@ int escore_put_control_value(struct snd_kcontrol *kcontrol,
        unsigned int reg = mc->reg;
        unsigned int value;
        int ret = 0;
+       struct escore_priv *escore = &escore_priv;
 
+       mutex_lock(&escore->access_lock);
        ret = escore_pm_get_sync();
        if (ret  > -1) {
-               mutex_lock(&escore_priv.api_mutex);
                value = ucontrol->value.integer.value[0];
                ret = _escore_write(NULL, reg, value);
-               mutex_unlock(&escore_priv.api_mutex);
                escore_pm_put_autosuspend();
        }
+       mutex_unlock(&escore->access_lock);
        return ret;
 }
 
@@ -1077,15 +1056,17 @@ int escore_get_control_value(struct snd_kcontrol *kcontrol,
                (struct soc_mixer_control *)kcontrol->private_value;
        unsigned int reg = mc->reg;
        unsigned int value;
+       struct escore_priv *escore = &escore_priv;
+
+       mutex_lock(&escore->access_lock);
        ret = escore_pm_get_sync();
        if (ret  > -1) {
-               mutex_lock(&escore_priv.api_mutex);
                value = _escore_read(NULL, reg);
                ucontrol->value.integer.value[0] = value;
-               mutex_unlock(&escore_priv.api_mutex);
                escore_pm_put_autosuspend();
                ret = 0;
        }
+       mutex_unlock(&escore->access_lock);
        return ret;
 }
 
@@ -1104,6 +1085,262 @@ int escore_get_streaming_mode(struct snd_kcontrol *kcontrol,
        return 0;
 }
 
+int escore_switch_ext_osc(struct escore_priv *escore)
+{
+       u32 cmd_resp;
+       int rc = 0;
+
+       dev_dbg(escore->dev, "%s(): Switch ext oscillator", __func__);
+
+       /* Sending preset command to switch to external oscillator */
+       rc = escore_cmd(escore, (ES_SET_PRESET << 16 | ES_ASR_PRESET),
+                       &cmd_resp);
+       if (rc) {
+               dev_err(escore_priv.dev, "%s(): Set Preset fail %d\n",
+                       __func__, rc);
+               goto cmd_error;
+       }
+       usleep_range(2000, 2005);
+
+       rc = escore_cmd(escore, (ES_GET_POWER_LEVEL << 16), &cmd_resp);
+       if (rc) {
+               dev_err(escore->dev, "%s(): Error getting power level %d\n",
+                       __func__, rc);
+               goto cmd_error;
+       } else if (cmd_resp != ((ES_GET_POWER_LEVEL << 16)
+                               | ES_POWER_LEVEL_6)) {
+               dev_err(escore->dev, "%s(): Invalid power level 0x%04x\n",
+                               __func__, cmd_resp);
+               rc = -EINVAL;
+       }
+       usleep_range(2000, 2005);
+
+cmd_error:
+       return rc;
+}
+
+static int _es_validate_fw_switch(struct escore_priv *escore)
+{
+       int ret = 0;
+       u32 cmd, resp = 0;
+
+       cmd = ES_SYNC_CMD << 16;
+       cmd |= escore->pdata->gpio_a_irq_type;
+
+       /* Reconfig API Interrupt mode */
+       ret = escore_reconfig_api_intr(escore);
+       if (ret)
+               goto exit;
+
+       ret = escore_cmd_nopm(escore, cmd, &resp);
+       if (ret < 0) {
+               pr_err("%s() Sync command failed %d\n", __func__, ret);
+               goto exit;
+       }
+
+       if (cmd != resp) {
+               pr_err("%s() Invalid sync response  %x\n", __func__, resp);
+               ret = -EIO;
+       }
+exit:
+       return ret;
+}
+
+/* This function must be called with access_lock acquired */
+int escore_af_to_ns(struct escore_priv *escore)
+{
+       int ret = 0;
+       u32 cmd, resp = 0;
+
+       cmd = (ES_SET_POWER_STATE << 16) | ES_SET_POWER_STATE_NORMAL;
+       ret = escore_cmd(escore, cmd, &resp);
+       if (ret) {
+               pr_err("%s(): Set Power State to Normal failed %d\n",
+                               __func__, ret);
+               goto exit;
+       }
+
+       msleep(35);
+
+       ret = _es_validate_fw_switch(escore);
+       if (ret) {
+               pr_err("%s(): Switching to NS mode failed %d\n", __func__, ret);
+               goto exit;
+       }
+
+       escore->mode = STANDARD;
+exit:
+       return ret;
+}
+
+
+/* This function must be called with access_lock acquired */
+int escore_ns_to_af(struct escore_priv *escore)
+{
+       int ret = 0;
+       u32 cmd, resp = 0;
+
+       if (!escore->boot_ops.setup || !escore->boot_ops.finish ||
+                       !escore->bus.ops.high_bw_write) {
+               pr_err("%s(): Required bus operations not implemented\n",
+                               __func__);
+               ret = -ENOSYS;
+               goto exit;
+       }
+
+       /*
+        * Need to call escore-pm handler explicitly to check whether chip
+        * needs a wakeup or it is already awake. If chip is brought to NS mode
+        * then we need to wait for 35ms before entering into AF Overlay mode.
+        *
+        * State diagram reference: Jira-2653
+        */
+       ret = escore_pm_get_sync();
+       if (ret < 0) {
+               pr_err("%s(): Failed to wakeup the chip %d\n", __func__, ret);
+               goto exit;
+       }
+
+       if (ret == 0) {
+               /*
+                * Chip is just brought to Normal mode (i.e. NS firmware).
+                * Wait for 35ms as before entering into AF Overlay mod
+                */
+               msleep(35);
+       }
+
+       cmd = (ES_SET_POWER_STATE << 16) | ES_POWER_STATE_AF_OVERLAY;
+       ret = escore_cmd_nopm(escore, cmd, &resp);
+       if (ret) {
+               pr_err("%s(): Failed to enter into AF overlay mode %d\n",
+                               __func__, ret);
+               goto overlay_fail;
+       }
+
+       /* Need to wait until chip is moved to Overlay mode. */
+       msleep(23);
+
+       if (escore->bus.ops.high_bw_open) {
+               ret = escore->bus.ops.high_bw_open(escore);
+               if (ret) {
+                       pr_err("%s(): high_bw_open failed %d\n", __func__, ret);
+                       goto highbw_dev_fail;
+               }
+       }
+
+       ret = escore->boot_ops.setup(escore);
+       if (ret) {
+               pr_err("%s(): AF download start error %d\n", __func__, ret);
+               goto fw_load_fail;
+       }
+
+
+       ret = escore->bus.ops.high_bw_write(escore, (char *)escore->af->data,
+                       escore->af->size);
+       if (ret < 0) {
+               pr_err("%s(): AF firmware download failed %d\n", __func__, ret);
+               goto fw_load_fail;
+       }
+
+       msleep(35);
+
+       ret = escore->boot_ops.finish(escore);
+       if (ret) {
+               pr_err("%s() AF download finish error %d\n", __func__, ret);
+               goto fw_load_fail;
+       }
+
+       pr_debug("%s(): AF Firmware download successful\n", __func__);
+
+       /* Setup the Event response */
+       cmd = (ES_SET_EVENT_RESP<<16) | escore->pdata->gpio_b_irq_type;
+       ret = escore_cmd_nopm(escore, cmd, &resp);
+       if (ret < 0) {
+               pr_err("%s(): Error %d in setting event response\n",
+                       __func__, ret);
+               goto fw_load_fail;
+       }
+
+       escore->mode = AF;
+
+fw_load_fail:
+       if (escore->bus.ops.high_bw_close) {
+               int rc = 0;
+               rc = escore->bus.ops.high_bw_close(escore);
+               if (rc) {
+                       pr_err("%s(): high_bw_close failed %d\n", __func__, rc);
+                       ret = (ret) ? : rc;
+               }
+       }
+
+overlay_fail:
+highbw_dev_fail:
+       escore_pm_put_autosuspend();
+exit:
+       return ret;
+}
+
+int escore_put_af_status(struct snd_kcontrol *kcontrol,
+               struct snd_ctl_elem_value *ucontrol)
+{
+       struct escore_priv *escore = &escore_priv;
+       int ret = 0;
+       int value;
+
+       value = ucontrol->value.enumerated.item[0];
+
+       if (!escore->af && value) {
+               ret = request_firmware((const struct firmware **)&escore->af,
+                               escore->fw_af_filename, escore->dev);
+               if (ret) {
+                       pr_err("%s(): request_firmware(%s) for AF failed %d\n",
+                                       __func__, escore->fw_af_filename, ret);
+                       escore_priv.flag.af = 0;
+                       goto exit;
+               }
+       }
+
+       escore->flag.af = 1;
+
+       if (value) {
+               if (escore->mode == AF) {
+                       pr_debug("%s(): Already in AF state\n", __func__);
+                       goto exit;
+               }
+
+               mutex_lock(&escore->access_lock);
+               ret = escore_ns_to_af(escore);
+               mutex_unlock(&escore->access_lock);
+       } else {
+               if (escore->mode != AF) {
+                       pr_debug("%s(): AF state already disabled\n", __func__);
+                       goto exit;
+               }
+
+               if (atomic_read(&escore->active_streams)) {
+                       pr_debug("%s(): Active stream detected\n", __func__);
+                       goto exit;
+               }
+
+               mutex_lock(&escore->access_lock);
+               ret = escore_af_to_ns(escore);
+               mutex_unlock(&escore->access_lock);
+       }
+
+exit:
+       return ret;
+}
+
+int escore_get_af_status(struct snd_kcontrol *kcontrol,
+               struct snd_ctl_elem_value *ucontrol)
+{
+       struct escore_priv *escore = &escore_priv;
+
+       ucontrol->value.enumerated.item[0] = (escore->mode == AF);
+       return 0;
+}
+
+
 void escore_register_notify(struct blocking_notifier_head *list,
                struct notifier_block *nb)
 {
@@ -1133,7 +1370,7 @@ int escore_probe(struct escore_priv *escore, struct device *dev, int curr_intf,
 {
        int rc = 0;
 
-       mutex_lock(&escore->api_mutex);
+       mutex_lock(&escore->intf_probed_mutex);
 
        /* Update intf_probed only when a valid interface is probed */
 
@@ -1146,15 +1383,10 @@ int escore_probe(struct escore_priv *escore, struct device *dev, int curr_intf,
        if (escore->intf_probed != (escore->pri_intf | escore->high_bw_intf)) {
                pr_debug("%s(): Both interfaces are not probed %d\n",
                                __func__, escore->intf_probed);
-               mutex_unlock(&escore->api_mutex);
-               return 0;
-       }
-       mutex_unlock(&escore->api_mutex);
-
-       if (escore->wakeup_intf == ES_UART_INTF && !escore->uart_ready) {
-               pr_err("%s(): Wakeup mechanism not initialized\n", __func__);
+               mutex_unlock(&escore->intf_probed_mutex);
                return 0;
        }
+       mutex_unlock(&escore->intf_probed_mutex);
 
        escore->bus.setup_prim_intf(escore);
 
@@ -1181,8 +1413,8 @@ int escore_probe(struct escore_priv *escore, struct device *dev, int curr_intf,
                if (context == ES_CONTEXT_THREAD) {
                        rc = escore_retrigger_probe();
                        if (rc)
-                               pr_err("%s(): Adding UART dummy dev failed\n",
-                                               __func__);
+                               pr_err("%s(): Adding UART dummy dev fail %d\n",
+                                      __func__, rc);
                }
        }
 
@@ -1227,7 +1459,8 @@ int escore_retrigger_probe(void)
 
        rc = platform_device_add(escore_dummy_device);
        if (rc) {
-               pr_err("%s(): Error while adding dummy device\n", __func__);
+               pr_err("%s(): Error while adding dummy device %d\n",
+                      __func__, rc);
                platform_device_put(escore_dummy_device);
        }
 out:
old mode 100755 (executable)
new mode 100644 (file)
index d335de0..a5bdf64
@@ -40,7 +40,6 @@
 #include <linux/pm_wakeup.h>
 #include <linux/mutex.h>
 #include <linux/spi/spi.h>
-#include <linux/esxxx.h>
 #include <linux/of_gpio.h>
 #include <linux/wait.h>
 #if defined(CONFIG_SND_SOC_ES_SLIM)
 #endif
 #include <linux/version.h>
 #include <linux/pm.h>
+#include "esxxx.h"
 #include "escore-uart.h"
-#include "adnc-sensorhub-api.h"
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0))
+#define KERNEL_VERSION_3_8_0
+#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0))
+#define KERNEL_VERSION_3_4_0
+#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0))
+#define KERNEL_VERSION_3_2_0
+#endif
 
 #define ES_READ_VE_OFFSET              0x0804
 #define ES_READ_VE_WIDTH               4
 #define DAI_INDEX(xid)         (xid - ES_I2S_PORTA)
 #endif
 
+/*
+ * Increment/decrement disable firmware recovery use count
+ * Firmware recovery will be performed when use count is ZERO or
+ * forced recovery requested in following function:
+ *   int escore_fw_recovery(struct escore_priv *escore, int is_forced)
+ */
+#define INC_DISABLE_FW_RECOVERY_USE_CNT(escore) \
+       do { \
+               escore->disable_fw_recovery_cnt++; \
+               dev_dbg(escore->dev, "%s(%d): fw_cnt++ = %d\n", \
+                       __func__, __LINE__, escore->disable_fw_recovery_cnt); \
+       } while (0)
+
+#define DEC_DISABLE_FW_RECOVERY_USE_CNT(escore) \
+       do { \
+               if (escore->disable_fw_recovery_cnt) \
+                       escore->disable_fw_recovery_cnt--; \
+               dev_dbg(escore->dev, "%s(%d): fw_cnt-- = %d\n", \
+                       __func__, __LINE__, escore->disable_fw_recovery_cnt); \
+       } while (0)
+
+#define FORCED_FW_RECOVERY_OFF 0
+#define FORCED_FW_RECOVERY_ON  1
+
+#define ESCORE_FW_RECOVERY_FORCED_OFF(escore) \
+       do { \
+               int ret = escore_fw_recovery(escore, FORCED_FW_RECOVERY_OFF); \
+               if (ret < 0) \
+                       pr_err("%s() Firmware recovery failed %d\n", __func__, \
+                               ret); \
+       } while (0)
+
 /* Standard commands used by all chips */
 
 #define ES_SR_BIT                      28 /* Suppress Response Bit */
 #define ES_SET_POWER_STATE_NORMAL      0x0004
 #define ES_SET_POWER_STATE_VS_OVERLAY  0x0005
 #define ES_SET_POWER_STATE_VS_LOWPWR   0x0006
+#ifdef CONFIG_SND_SOC_ES_VS_STREAMING
+#define ES_POWER_STATE_VS_STREAMING    0x0007
+#endif
+#ifdef CONFIG_SND_SOC_ES_AVOID_REPEAT_FW_DOWNLOAD
+#define ES_POWER_STATE_VS_OVERLAP      0x0008
+#endif
+#define ES_POWER_STATE_AF_OVERLAY      0x000A
 
 #define ES_SYNC_MAX_RETRY 5
 #define ES_SBL_RESP_TOUT       500 /* 500ms */
 #define ES_INT_OSC_MEASURE_START       0x9070
 #define ES_INT_OSC_MEASURE_STATUS      0x8071
 
+#define ES_INT_OSC_MEASURE_START_VS    0x905d
+#define ES_INT_OSC_MEASURE_QUERY_VS    0x805E
+#define ES_GET_POWER_LEVEL             0x8012
+#define ES_ASR_PRESET                  0x1bbc
+
 /*
  * Codec Interrupt event type
  */
 /* Software event, which is not generated by chip */
 #define ES_RECONFIG_INTR_EVENT         0x0020
 #define ES_MASK_INTR_EVENT             0x0000FFFF
-/*
- * Interrupt status bits
- */
-
-/* Specific to A212 Codec */
-#define ES_IS_CODEC_READY(x)           (x & 0x80)
-#define ES_IS_THERMAL_SHUTDOWN(x)      (x & 0x100)
-#define ES_IS_LO_SHORT_CKT(x)          (x & 0x200)
-#define ES_IS_HFL_SHORT_CKT(x)         (x & 0x400)
-#define ES_IS_HFR_SHORT_CKT(x)         (x & 0x800)
-#define ES_IS_HP_SHORT_CKT(x)          (x & 0x1000)
-#define ES_IS_EP_SHORT_CKT(x)          (x & 0x2000)
-#define ES_IS_PLUG_EVENT(x)            (x & 0x40)
-#define ES_IS_UNPLUG_EVENT(x)          (x & 0x20)
-
-/*
- * Accessory status bits
- */
-#define ES_IS_ACCDET_EVENT(x)                  (x & 0x10)
-#define ES_IS_SHORT_BTN_PARALLEL_PRESS(x)      (x & 0x01)
-#define ES_IS_LONG_BTN_PARALLEL_PRESS(x)       (x & 0x02)
-#define ES_IS_SHORT_BTN_SERIAL_PRESS(x)                (x & 0x04)
-#define ES_IS_LONG_BTN_SERIAL_PRESS(x)         (x & 0x08)
-#define ES_IS_BTN_PRESS_EVENT(x)               (x & 0x0f)
-
-#define ES_IS_LRGM_HEADSET(x)                  (x == 1)
-#define ES_IS_LRMG_HEADSET(x)                  (x == 3)
-#define ES_IS_LRG_HEADPHONE(x)                 (x == 2)
-#define ES_IS_HEADSET(x) (ES_IS_LRGM_HEADSET(x) || ES_IS_LRMG_HEADSET(x))
-
-#define ES_ACCDET_ENABLE       1
-#define ES_ACCDET_DISABLE      0
-
-#define ES_BTNDET_ENABLE       1
-#define ES_BTNDET_DISABLE      0
 
 #define ES_SYNC_POLLING                0x0000
 #define ES_SYNC_INTR_ACITVE_LOW        0x0001
 
 #define ES_WDB_CMD                     0x802f
 #define ES_RDB_CMD                     0x802e
-#define ES_WDB_MAX_SIZE                        512
 
 
 #define ES_SET_PRESET                  0x9031
 #define ES_SET_CVS_PRESET              0x906F
+#define ES_SET_VS_KW_LENGTH            0x902C
+#define ESCORE_GET_KEYWORD_OVERRUN_ERROR               0x802B
 #define ES_VS_PROCESSING_MOE           0x5003
 #define ES_VS_DETECT_KEYWORD           0x0000
 
 
 #define ES_READ_DATA_BLOCK                             0x802E
 #define ES_WRITE_DATA_BLOCK                            0x802F
-/* SPI sends data in Big endian format.*/
-#define ES_READ_DATA_BLOCK_SPI                         0x2E80
-#define ES_WRITE_DATA_BLOCK_SPI                                0x2F80
 
-#define ES_SET_SMOOTH_MUTE                             0x804E
+#define ES_SET_SMOOTH_MUTE                             0x904E
 #define ES_SMOOTH_MUTE_ZERO                            0x0000
 
 #define ES_SET_POWER_LEVEL                             0x8011
-#define ES_POWER_LEVEL_6                               0x0006
 
-#define ES_WAKEUP_TIME                         40
+#define DBG_ID       13
+#define DBG_BLK_SIZE (3 * 1024)
+#if (DBG_BLK_SIZE > PAGE_SIZE)
+#error "Making DBG_BLK_SIZE greater than PAGE_SIZE breaks sysfs read support"
+#endif
+
+enum {
+       ES_POWER_LEVEL_DISABLE = 0,
+       ES_POWER_LEVEL_MIN = 1,
+       ES_POWER_LEVEL_1 = ES_POWER_LEVEL_MIN,
+       ES_POWER_LEVEL_2,
+       ES_POWER_LEVEL_3,
+       ES_POWER_LEVEL_4,
+       ES_POWER_LEVEL_5,
+       ES_POWER_LEVEL_6,
+       ES_POWER_LEVEL_MAX = ES_POWER_LEVEL_6,
+};
+
+#define ES_WAKEUP_TIME                         30
 #define ES_PM_CLOCK_STABILIZATION              1 /* 1ms */
 #define ES_RESP_TOUT_MSEC                      20 /* 20ms */
 #define ES_RESP_TOUT                           20000 /* 20ms */
 #define ES_RESP_POLL_TOUT                      4000  /*  4ms */
 #define ES_FIN_TOUT                            10000 /* 10ms */
 #define ES_FIN_POLL_TOUT                       2000  /* 2ms */
+#define ES_API_INTR_TOUT_MSEC                  100 /* 100ms */
 #define ES_MAX_RETRIES         \
                        (ES_RESP_TOUT / ES_RESP_POLL_TOUT)
 #define ES_MAX_FIN_RETRIES             \
                        (ES_FIN_TOUT / ES_FIN_POLL_TOUT)
 
-#define ES_SPI_RETRY_DELAY 5000  /*  5ms */
-#define ES_SPI_MAX_RETRIES 20 /* Number of retries */
-#define ES_SPI_CONT_RETRY 5 /* Retry for read without delay */
-#define ES_SPI_1MS_DELAY 1000  /*1 ms*/
+#define ES_SPI_RETRY_DELAY     5000    /*  5ms */
+#define ES_SPI_MAX_RETRIES     20      /* Number of retries */
+#define ES_SPI_CONT_RETRY      5       /* Retry for read without delay */
+#define ES_SPI_1MS_DELAY       1000    /*1 ms*/
 
 #define ES_UART_WAKE_CMD       0xa
 
 #define ES_PS_NORMAL (ES_GET_POWER_STATE << 16 | ES_SET_POWER_STATE_NORMAL)
 #define ES_PS_OVERLAY (ES_GET_POWER_STATE << 16 | ES_SET_POWER_STATE_VS_OVERLAY)
 
+#define ES_DIGITAL_GAIN_MAX_NUM 48 /* Maximum number of digital gain allowed, equal to ES300_PASSOUT4+1 */
+
 enum {
        SBL,
        STANDARD,
        VOICESENSE_PENDING,
        VOICESENSE,
+       AF,
 };
 
 struct escore_reg_cache {
        int value;
-       int is_volatile;
 };
 
 struct escore_api_access {
@@ -241,6 +275,18 @@ struct escore_api_access {
 #define ES_SPI_INTF            (0x1 << 3)
 #define ES_UART_INTF           (0x1 << 4)
 
+enum {
+       ES_ACC_PLUGGED = 0x00,
+       ES_ACC_DETECTED,
+       ES_ACC_UNPLUGGED,
+       ES_ACC_BUTTON_PRESSED,
+       ES_ACC_BUTTON_RELEASED,
+
+       ES_ACC_INVALID = 0xFF,
+};
+
+#define ES_ACC_BTN_INVALID 0xFF
+
 enum {
        ES_CONTEXT_THREAD = 0x1,
        ES_CONTEXT_PROBE = 0x2,
@@ -257,13 +303,6 @@ enum {
        ES_SLIM_CH_UND,
 };
 
-enum {
-       ES_PM_NORMAL,
-       ES_PM_RUNTIME_SLEEP,
-       ES_PM_ASLEEP,
-       ES_PM_HOSED,
-};
-
 /* Notifier chain priority */
 enum {
        ES_LOW,
@@ -277,6 +316,12 @@ enum {
        ES_NORMAL_STREAMING,
 };
 
+/* PM status modes */
+enum {
+       ES_PM_OFF,
+       ES_PM_ON,
+};
+
 struct escore_slim_dai_data {
        unsigned int rate;
        unsigned int *ch_num;
@@ -323,28 +368,14 @@ struct es_datablock_device {
        int (*read)(struct escore_priv *escore, void *buf, int len);
        int (*close)(struct escore_priv *escore);
        int (*wait)(struct escore_priv *escore);
+       int (*wdb_config)(struct escore_priv *escore);
+       int (*wdb_reset_config)(struct escore_priv *escore);
        char *rdb_read_buffer;
        int rdb_read_count;
        struct mutex datablock_read_mutex;
        struct mutex datablock_mutex;
 };
 
-struct escore_intr_regs {
-       u32 get_intr_status;
-       u32 clear_intr_status;
-       u32 set_intr_mask;
-       u32 accdet_config;
-       u32 accdet_status;
-       u32 enable_btndet;
-
-       u32 btn_serial_cfg;
-       u32 btn_parallel_cfg;
-       u32 btn_detection_rate;
-       u32 btn_press_settling_time;
-       u32 btn_bounce_time;
-       u32 btn_long_press_time;
-};
-
 struct escore_flags {
        u32 is_codec:1;
        u32 is_fw_ready:1;
@@ -358,7 +389,8 @@ struct escore_flags {
        u32 sleep_enable:1;
        u32 sleep_abort:1;
        u32 ns:1;
-       u32 zoom:2;     /* Value can be in range 0-3 */
+       u32 af:1;
+       u32 af_mode:2;  /* Value can be in range 0-3 */
 };
 
 /*Generic boot ops*/
@@ -385,7 +417,10 @@ struct escore_bus_ops {
        int (*high_bw_close)(struct escore_priv *escore);
        u32 (*cpu_to_bus)(struct escore_priv *escore, u32 resp);
        u32 (*bus_to_cpu)(struct escore_priv *escore, u32 resp);
-       int (*rdb)(struct escore_priv *escore, void *buf, size_t len, int id);
+       u32 (*cpu_to_high_bw_bus)(struct escore_priv *escore, u32 resp);
+       u32 (*high_bw_bus_to_cpu)(struct escore_priv *escore, u32 resp);
+       int (*rdb)(struct escore_priv *escore, void *buf, size_t len);
+       int (*high_bw_calibrate)(struct escore_priv *escore);
 };
 
 /*Generic bus function*/
@@ -427,10 +462,17 @@ struct escore_pdata {
        int (*remove)(struct platform_device *dev);
 };
 
+/* Delay required before different power transition stage, must be in ms */
+struct escore_delay {
+       u8 wakeup_to_normal; /* Deep Sleep / Sleep to Normal */
+       u8 wakeup_to_vs;
+       u8 vs_to_normal;
+       u8 mpsleep_to_normal; /* Used for es755 only */
+};
+
 #ifdef CONFIG_ARCH_MSM
 #define ES705_PRESET_ARRAY_SIZE                10
 #endif
-
 #define        ES_MAX_ROUTE_MACRO_CMD          300
 /* Max size of cmd_history line */
 #define ES_MAX_CMD_HISTORY_LINE_SIZE   100
@@ -443,8 +485,11 @@ struct escore_priv {
        struct snd_soc_dai_ops i2s_dai_ops;
        struct snd_soc_dai_ops slim_dai_ops;
        struct firmware *standard;
+       struct firmware *af;
+       const char *fw_af_filename;
        int mode;
        struct escore_flags flag;
+       u32 intr_recvd;
        unsigned int pri_intf;
        unsigned int high_bw_intf;
        unsigned int wakeup_intf;
@@ -463,15 +508,20 @@ struct escore_priv {
        int (*sleep)(struct escore_priv *escore);
        int (*wakeup)(struct escore_priv *escore);
        int (*escore_uart_wakeup)(struct escore_priv *escore);
-       int (*recover_wkup_failure)(struct escore_priv *escore);
 
        int pm_use_vs;
-       int pm_enable;
-       int system_suspend;
+       int pm_enable; /* enable / disable runtime pm support for device */
+       bool pm_status; /* on ES_PM_OFF, call escore_pm_get_sync, increment
+                        * pm usage count and keep device into running mode.
+                        * on ES_PM_ON, call escore_pm_auto_suspend, decrement
+                        * pm usage count and allow device to go into
+                        * suspend mode.*/
        struct escore_pm_ops non_vs_pm_ops;
        struct escore_pm_ops vs_pm_ops;
+       int es_wdb_max_size;
        u16 es_vs_route_preset;
        u16 es_cvs_preset;
+       u32 default_cvq_mic;
        int es_streaming_mode;
        int cmd_history_size;
        int sleep_abort;
@@ -490,6 +540,8 @@ struct escore_priv {
        int (*set_streaming)(struct escore_priv *escore, int val);
        int (*set_datalogging)(struct escore_priv *escore, int val);
        int (*config_jack)(struct escore_priv *escore);
+       int (*disable_codec_irq)(struct escore_priv *escore);
+       int (*enable_codec_irq)(struct escore_priv *escore);
 
        struct escore_slim_dai_data *slim_dai_data;
        struct escore_i2s_dai_data *i2s_dai_data;
@@ -511,8 +563,9 @@ struct escore_priv {
        struct slim_device *intf_client;
        struct slim_device *gen0_client;
 
-       struct mutex api_mutex;
+       struct mutex intf_probed_mutex;
        struct mutex streaming_mutex;
+       struct mutex access_lock;
 /* if 705 */
        struct mutex abort_mutex;
        struct mutex wake_mutex;
@@ -526,7 +579,6 @@ struct escore_priv {
        struct regulator *vcc_i2c;
 #endif
        int sleep_delay;
-       int vs_abort_kw;
        int wake_count;
        int fw_requested;
        u16 preset;
@@ -535,8 +587,10 @@ struct escore_priv {
        u16 algo_preset_two;
 /* endif 705 */
 
+       int selected_endpoint; /* Selected endpoint(pathID) for following digital gain setting */
+       u32 digital_gain[ES_DIGITAL_GAIN_MAX_NUM];
+
        struct mutex pm_mutex;
-       int pm_state;
 
        struct mutex msg_list_mutex;
        struct list_head msg_list;
@@ -553,15 +607,13 @@ struct escore_priv {
 
        struct task_struct *stream_thread;
        wait_queue_head_t stream_in_q;
+       wait_queue_head_t irq_waitq;
 
        struct snd_soc_codec_driver *soc_codec_dev_escore;
        struct snd_soc_dai_driver *dai;
        u32 dai_nr;
        u32 api_addr_max;
        atomic_t active_streams;
-       u8 process_analog;
-       u8 process_digital;
-       struct escore_intr_regs *regs;
 
        struct escore_api_access *api_access;
        struct escore_reg_cache *reg_cache;
@@ -576,14 +628,24 @@ struct escore_priv {
        u8 cmd_compl_mode;
        u8 wait_api_intr;
        u8 uart_ready;
+       atomic_t uart_users;
        u8 non_vs_sleep_state;
        u16 current_preset;
        u8 button_config_required;
        u8 defer_intr_config;
        u8 can_mpsleep;
-       u8 output_mode;
        u8 capture_mode;
+       u8 pri_pb_mode;
+       u8 sec_pb_mode;
+       u8 hpf_mode;
        u32 dhwpt_cmd;
+       u8 dhwpt_enabled;
+       u8 dhwpt_capture_on;
+       u8 base_route_setup;
+       u32 dhwpt_mode;
+       u32 mp_sleep_requested;
+       struct workqueue_struct *power_transition_wq;
+       struct delayed_work mp_sleep_work;
        int intf_probed;
        char *device_name;
        char *interface_device_name;
@@ -594,31 +656,43 @@ struct escore_priv {
        struct mutex escore_event_type_mutex;
        u8 device_up_called;
        bool is_probe_error;
+
+#ifdef CONFIG_ARCH_MSM
+       u16 preset_uplink_array[ES705_PRESET_ARRAY_SIZE];
+       u16 preset_downlink_array[ES705_PRESET_ARRAY_SIZE];
+#endif
+
 #ifdef CONFIG_ARCH_MSM8974
        bool i2c_pull_up;
 #endif
        bool codec_clk_en;
        u16 hs_delay;
+       int acc_det_status;
+       int acc_btn_pressed;
+       u32 power_saving_mode;
+       u32 disable_fw_recovery_cnt;
+       unsigned char *debug_buff;
+       struct escore_delay delay;
+
+       int pcm_format;
 };
 
 #define escore_resp(obj) ((obj)->bus.last_response)
 extern struct escore_priv escore_priv;
-extern int escore_read_and_clear_intr(struct escore_priv *escore);
-extern int escore_accdet_config(struct escore_priv *escore, int enable);
-extern int escore_btndet_config(struct escore_priv *escore, int enable);
-extern int escore_process_accdet(struct escore_priv *escore);
-
-extern void escore_process_analog_intr(struct escore_priv *escore);
-extern void escore_process_digital_intr(struct escore_priv *escore);
 
 extern void escore_gpio_reset(struct escore_priv *escore);
 
-extern irqreturn_t escore_irq_work(int irq, void *data);
 extern int escore_cmd(struct escore_priv *escore, u32 cmd, u32 *resp);
+int escore_cmd_nopm(struct escore_priv *escore, u32 cmd, u32 *resp);
+int escore_cmd_locked(struct escore_priv *escore, u32 cmd, u32 *resp);
 extern int escore_write_block(struct escore_priv *escore,
                const u32 *cmd_block);
-extern unsigned int escore_read(struct snd_soc_codec *codec,
+int escore_read_locked(struct snd_soc_codec *codec,
                               unsigned int reg);
+extern int escore_read(struct snd_soc_codec *codec,
+                              unsigned int reg);
+int escore_write_locked(struct snd_soc_codec *codec, unsigned int reg,
+                      unsigned int value);
 extern int escore_write(struct snd_soc_codec *codec, unsigned int reg,
                       unsigned int value);
 extern int escore_prepare_msg(struct escore_priv *escore, unsigned int reg,
@@ -635,6 +709,7 @@ int escore_put_runtime_pm_enum(struct snd_kcontrol *kcontrol,
                                        struct snd_ctl_elem_value *ucontrol);
 int escore_get_runtime_pm_enum(struct snd_kcontrol *kcontrol,
                                        struct snd_ctl_elem_value *ucontrol);
+int escore_pm_status_update(bool value);
 int escore_put_streaming_mode(struct snd_kcontrol *kcontrol,
                                  struct snd_ctl_elem_value *ucontrol);
 int escore_get_streaming_mode(struct snd_kcontrol *kcontrol,
@@ -643,36 +718,52 @@ void escore_register_notify(struct blocking_notifier_head *list,
                struct notifier_block *nb);
 int escore_probe(struct escore_priv *escore, struct device *dev, int curr_intf,
                int context);
+int escore_get_rdb_size(struct escore_priv *escore, int id);
 extern int escore_datablock_read(struct escore_priv *escore, void *buf,
-                                       size_t len, int id);
+                                       size_t len);
 extern int escore_datablock_write(struct escore_priv *escore, const void *buf,
                                        size_t len);
 extern int escore_datablock_open(struct escore_priv *escore);
 extern int escore_datablock_close(struct escore_priv *escore);
 extern int escore_datablock_wait(struct escore_priv *escore);
-extern int escore_datablock_read(struct escore_priv *escore, void *buf,
-                                       size_t len, int id);
 int escore_start_int_osc(struct escore_priv *escore);
-void escore_pm_init(void);
+int escore_switch_ext_osc(struct escore_priv *escore);
 void escore_pm_enable(void);
-void escore_pm_disable(void);
 void escore_pm_vs_enable(struct escore_priv *escore, bool value);
 int escore_suspend(struct device *dev);
 int escore_resume(struct device *dev);
+int escore_api_intr_wait_completion(struct escore_priv *escore);
+int escore_reconfig_api_intr(struct escore_priv *escore);
 int escore_wakeup(struct escore_priv *escore);
 void escore_pm_put_autosuspend(void);
 int escore_pm_get_sync(void);
 int escore_platform_init(void);
 int escore_retrigger_probe(void);
-bool escore_is_probe_error(void);
+int escore_ns_to_af(struct escore_priv *escore);
+int escore_af_to_ns(struct escore_priv *escore);
+int escore_put_af_status(struct snd_kcontrol *kcontrol,
+               struct snd_ctl_elem_value *ucontrol);
+int escore_get_af_status(struct snd_kcontrol *kcontrol,
+               struct snd_ctl_elem_value *ucontrol);
+int escore_fw_recovery(struct escore_priv *escore, int is_forced);
+int read_debug_data(void *buf);
 extern int escore_reconfig_intr(struct escore_priv *escore);
 extern const struct dev_pm_ops escore_pm_ops;
+bool escore_is_probe_error(void);
 
 #define ESCORE_STREAM_DISABLE  0
 #define ESCORE_STREAM_ENABLE   1
 #define ESCORE_DATALOGGING_CMD_ENABLE    0x803f0001
 #define ESCORE_DATALOGGING_CMD_DISABLE   0x803f0000
 
+static inline int escore_is_sleep_aborted(struct escore_priv *escore)
+{
+       if (unlikely(escore->sleep_abort))
+               return -EABORT;
+       else
+               return 0;
+}
+
 /* Take api_mutex before calling this function */
 static inline void update_cmd_history(u32 cmd, u32 resp)
 {
@@ -681,4 +772,19 @@ static inline void update_cmd_history(u32 cmd, u32 resp)
        get_monotonic_boottime(&cmd_hist[cmd_hist_index].timestamp);
        cmd_hist_index = (cmd_hist_index + 1) % ES_MAX_ROUTE_MACRO_CMD;
 }
+
+/* Set flag to wait for API Interrupt */
+static inline void escore_set_api_intr_wait(struct escore_priv *escore)
+{
+       /*  GPIO_A is not configured, set flag is not required */
+       if (escore->pdata->gpioa_gpio == -1)
+               return;
+
+       pr_debug("%s(): Called", __func__);
+       if (!escore->wait_api_intr)
+               escore->wait_api_intr = 1;
+       else
+               pr_debug("%s(): wait_api_intr is already set\n", __func__);
+       return;
+}
 #endif /* _ESCORE_H */
diff --git a/sound/soc/codecs/audience/esxxx.h b/sound/soc/codecs/audience/esxxx.h
new file mode 100644 (file)
index 0000000..3ebab7e
--- /dev/null
@@ -0,0 +1,117 @@
+/*
+ * esxxx.h - header for esxxx I2C interface
+ *
+ * Copyright (C) 2011-2012 Audience, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ *
+ */
+
+#ifndef __ESXXX_H__
+#define __ESXXX_H__
+
+#include <linux/types.h>
+
+/* External clock rate to earSmart chips */
+
+#define ES_EXT_CLK_6000KHZ  0x00 /* 6.0 MHz    */
+#define ES_EXT_CLK_6144KHZ  0x01 /* 6.144 MHz  */
+#define ES_EXT_CLK_9600KHZ  0x02 /* 9.6 MHz    */
+#define ES_EXT_CLK_12000KHZ 0x03 /* 12.0 MHz   */
+#define ES_EXT_CLK_12288KHZ 0x04 /* 12.288 MHz */
+#define ES_EXT_CLK_13000KHZ 0x05 /* 13.0 MHz   */
+#define ES_EXT_CLK_15360KHZ 0x06 /* 15.36 MHz  */
+#define ES_EXT_CLK_18432KHZ 0x07 /* 18.432 MHz */
+#define ES_EXT_CLK_19200KHZ 0x08 /* 19.2 MHz   */
+#define ES_EXT_CLK_24000KHZ 0x09 /* 24 MHz     */
+#define ES_EXT_CLK_24576KHZ 0x0a /* 24.576 MHz */
+#define ES_EXT_CLK_26000KHZ 0x0b /* 26 MHz     */
+
+/*
+ * IRQ type
+ */
+
+enum {
+       ES_DISABLED,
+       ES_ACTIVE_LOW,
+       ES_ACTIVE_HIGH,
+       ES_FALLING_EDGE,
+       ES_RISING_EDGE,
+};
+
+/*
+ * Firmware API completion mode: Polling or Interrupt
+ */
+enum {
+       ES_CMD_COMP_POLL,
+       ES_CMD_COMP_INTR,
+};
+
+/* es755 specific */
+
+/* Button Press Detection possible values */
+enum {
+       ES_BTN_DET_DIS,
+       ES_BTN_DET_EN,
+};
+
+/* Button Controls */
+union es755_btn_ctl1 {
+       u8 value;
+       struct {
+               u8 res1:7;
+               u8 btn_press_det:1;
+       } fields;
+};
+
+struct esxxx_accdet_config {
+       int     btn_serial_cfg;
+       int     btn_parallel_cfg;
+       int     btn_detection_rate;
+       int     btn_press_settling_time;
+       int     btn_bounce_time;
+       int     btn_long_press_time;
+       int     debounce_timer;
+       int     plug_det_enabled;
+       int     mic_det_enabled;
+       u8    hs_mg_select;
+};
+
+struct escore_priv;
+
+
+struct esxxx_platform_data {
+       unsigned int    irq_base, irq_end;
+       unsigned int    gpio_a_irq_type;
+       unsigned int    gpio_b_irq_type;
+       int     reset_gpio;
+       int     wakeup_gpio;
+       int     gpioa_gpio;
+       int     gpiob_gpio;
+       int     accdet_gpio;
+       int     uart_gpio;
+       int     extclk_gpio;
+       bool    enable_hs_uart_intf;
+       u8      ext_clk_rate;
+       u8      cmd_comp_mode;
+       struct  esxxx_accdet_config accdet_cfg;
+       void    *priv;
+       int     (*esxxx_clk_cb) (int);
+       int     spi_fw_download_speed;
+       int     spi_operational_speed;
+       int     spi_wdb_speed;
+};
+
+#endif /* __ESXXX_H__ */
diff --git a/sound/soc/codecs/audience/mq100-sensorhub.h b/sound/soc/codecs/audience/mq100-sensorhub.h
deleted file mode 100644 (file)
index 42bce52..0000000
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * mq100_sensorhub.h --  Audience eS705 ALSA SoC Audio driver
- *
- * Copyright 2011 Audience, Inc.
- *
- * Author:
- *
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#ifndef _MQ100_SENSORHUB_H
-#define _MQ100_SENSORHUB_H
-
-enum {
-       MQ100_MIC_CONFIG,
-       MQ100_AEC_MODE,
-       MQ100_VEQ_ENABLE,
-       MQ100_DEREVERB_ENABLE,
-       MQ100_DEREVERB_GAIN,
-       MQ100_BWE_ENABLE,
-       MQ100_BWE_HIGH_BAND_GAIN,
-       MQ100_BWE_MAX_SNR,
-       MQ100_BWE_POST_EQ_ENABLE,
-       MQ100_SLIMBUS_LINK_MULTI_CHANNEL,
-       MQ100_POWER_STATE,
-       MQ100_FE_STREAMING,
-       MQ100_PRESET,
-       MQ100_ALGO_PROCESSING,
-       MQ100_ALGO_SAMPLE_RATE,
-       MQ100_CHANGE_STATUS,
-       MQ100_MIX_SAMPLE_RATE,
-       MQ100_FW_FIRST_CHAR,
-       MQ100_FW_NEXT_CHAR,
-       MQ100_EVENT_RESPONSE,
-       MQ100_VOICE_SENSE_ENABLE,
-       MQ100_VOICE_SENSE_SET_KEYWORD,
-       MQ100_VOICE_SENSE_EVENT,
-       MQ100_VOICE_SENSE_TRAINING_MODE,
-       MQ100_VOICE_SENSE_DETECTION_SENSITIVITY,
-       MQ100_VOICE_ACTIVITY_DETECTION_SENSITIVITY,
-       MQ100_VOICE_SENSE_TRAINING_RECORD,
-       MQ100_VOICE_SENSE_TRAINING_STATUS,
-       MQ100_VOICE_SENSE_DEMO_ENABLE,
-       MQ100_VS_STORED_KEYWORD,
-       MQ100_VS_INT_OSC_MEASURE_START,
-       MQ100_VS_INT_OSC_MEASURE_STATUS,
-       MQ100_CVS_PRESET,
-       MQ100_RX_ENABLE,
-       MQ100_API_ADDR_MAX,
-};
-
-/*
- * Device parameter command codes
- */
-#define MQ100_DEV_PARAM_OFFSET         0x2000
-#define MQ100_GET_DEV_PARAM            0x800b
-#define MQ100_SET_DEV_PARAM_ID         0x900c
-#define MQ100_SET_DEV_PARAM            0x900d
-
-/*
- * Algoithm parameter command codes
- */
-#define MQ100_ALGO_PARAM_OFFSET                0x0000
-#define MQ100_GET_ALGO_PARAM           0x8016
-#define MQ100_SET_ALGO_PARAM_ID                0x9017
-#define MQ100_SET_ALGO_PARAM           0x9018
-#define ES_GET_EVENT                           0x806D
-
-/* MQ100 states */
-#define MQ100_STATE_RESET (0)
-#define MQ100_STATE_NORMAL (1)
-extern void mq100_indicate_state_change(u8 val);
-int mq100_bootup(struct escore_priv *mq100);
-irqreturn_t mq100_irq_work(int irq, void *data);
-int mq100_core_probe(struct device *dev);
-#endif
index 08c73bec7c78fa72667b023dd26acce5e888ec6e..e3a8bd2fe4f3cefec8ba79df145f532ebe231af1 100644 (file)
@@ -645,7 +645,6 @@ static const struct snd_kcontrol_new tegra_t210ref_controls[] = {
 
 static int tegra_t210ref_suspend_pre(struct snd_soc_card *card)
 {
-       struct snd_soc_jack_gpio *gpio = &tegra_t210ref_hp_jack_gpio;
        unsigned int idx;
 
        /* DAPM dai link stream work for non pcm links */
@@ -654,9 +653,6 @@ static int tegra_t210ref_suspend_pre(struct snd_soc_card *card)
                        INIT_DELAYED_WORK(&card->rtd[idx].delayed_work, NULL);
        }
 
-       if (gpio_is_valid(gpio->gpio))
-               disable_irq(gpio_to_irq(gpio->gpio));
-
        return 0;
 }
 
@@ -678,20 +674,11 @@ static int tegra_t210ref_suspend_post(struct snd_soc_card *card)
 static int tegra_t210ref_resume_pre(struct snd_soc_card *card)
 {
        struct tegra_t210ref *machine = snd_soc_card_get_drvdata(card);
-       struct snd_soc_jack_gpio *gpio = &tegra_t210ref_hp_jack_gpio;
-       int ret, val;
+       int ret;
 
        if (machine->digital_reg)
                ret = regulator_enable(machine->digital_reg);
 
-       if (gpio_is_valid(gpio->gpio)) {
-               val = gpio_get_value(gpio->gpio);
-               val = gpio->invert ? !val : val;
-               if (gpio->jack)
-                       snd_soc_jack_report(gpio->jack, val, gpio->report);
-               enable_irq(gpio_to_irq(gpio->gpio));
-       }
-
        if (!machine->clock_enabled) {
                machine->clock_enabled = 1;
                tegra_alt_asoc_utils_clk_enable(&machine->audio_clock);