* 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
* 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
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
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
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
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"
* 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
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
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
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
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)
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
+
+++ /dev/null
-#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
-/*
- * 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
#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);
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",
};
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);
"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",
};
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",
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[] = {
};
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 =
};
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 =
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)
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;
}
}
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),
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),
/* 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)),
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),
};
/* 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"},
{"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"},
{"SPKRL", NULL, "SPKRL PGA"},
{"SPKRR", NULL, "SPKRR PGA"},
{"EP", NULL, "EP PGA"},
- /* Dummy entry */
- {"EPR", NULL, "DAC0R"},
};
{
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;
}
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,
};
.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),
},
.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),
.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),
},
};
-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,
VP_CSOUT2,
VP_FEOUT1,
VP_FEOUT2,
- AUDIOZOOM_CSOUT,
- AUDIOZOOM_AOUT1,
+ AUDIOFOCUS_CSOUT1,
+ AUDIOFOCUS_CSOUT2,
MM_AUDOUT1,
MM_AUDOUT2,
MM_PASSOUT1,
PASS_AUDOUT3,
PASS_AUDOUT4,
PASS_AO1,
- PASS_MO2,
+ PASS_AO2,
MONOUT1,
MONOUT2,
MONOUT3,
VP,
PT,
MM,
- AUDIOZOOM,
+ AUDIOFOCUS,
VP_MM,
PT_VP,
PT_VP_DSM,
VP_DSM,
- AZ_DSM,
+ AF_DSM,
PT_COPY,
PT_4CH,
VP_2CSOUT,
};
#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,
#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];
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 };
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[] = {
};
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] = {
.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);
}
/*
- 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;
}
*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);
}
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 */
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;
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) {
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",
* 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) {
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;
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 */
/* 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) {
}
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;
}
}
/* 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;
}
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;
}
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,
escore->slim_dai_data[dai_id].rate);
atomic_inc(&escore->active_streams);
}
-
}
break;
case SND_SOC_DAPM_POST_PMD:
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;
}
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,
escore->slim_dai_data[dai_id].rate);
atomic_inc(&escore->active_streams);
}
+
}
break;
case SND_SOC_DAPM_POST_PMD:
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;
}
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++) {
}
}
+ 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:
}
}
+ 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,
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++) {
}
}
+ 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:
}
}
+ 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
unsigned int reg = e->reg;
u16 value;
- value = escore_read(codec, reg);
+ value = escore_read_locked(codec, reg);
ucontrol->value.enumerated.item[0] = value;
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,
}
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,
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);
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;
(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;
(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;
}
/* 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;
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 =
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) {
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;
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
escore->algo_type_off = algo_type;
}
out:
+ mutex_unlock(&codec->mutex);
return ret;
}
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,
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;
}
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;
}
/* 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;
}
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;
/* 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;
}
/* 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;
}
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)
{
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;
}
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;
}
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;
(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;
}
unsigned int reg = e->reg;
u16 value;
- value = escore_read(codec, reg);
+ value = escore_read_locked(codec, reg);
ucontrol->value.enumerated.item[0] = value;
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)
{
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;
}
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;
}
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;
}
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"
};
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",
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",
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,
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,
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,
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 =
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 =
&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),
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"),
{"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"},
{"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"},
{"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"},
{"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"},
{"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"},
{"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"},
{"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"},
{"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"},
{"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"},
{"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"},
{"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"},
{"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"},
{"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"},
{"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"},
{"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"},
{"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"},
{"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"},
{"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"},
{"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"},
{"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"},
{"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"},
{"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"},
{"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"},
{"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"},
{"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 */
const char *algo_text[ALGO_MAX] = {
[VP] = "VP",
[MM] = "MM",
- [AUDIOZOOM] = "AudioZoom",
+ [AUDIOFOCUS] = "AudioFocus",
[PASSTHRU] = "Passthru",
};
{
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;
}
#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,
};
FILTER_TXCHANMGR5,
FILTER_VP = 0x13,
- FILTER_AZ,
+ FILTER_AF,
FILTER_MM,
FILTER_PASSTHRU,
FILTER_BEEP,
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,
};
/* 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. */
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 */
#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] = {
.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) },
.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,
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) },
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) },
.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,
.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 = {
.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,
.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,
.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 */
#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
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[];
};
#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 },
{ "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
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)
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[] = {
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;
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,
{
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;
}
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++) {
if (!value)
break;
}
+ mutex_unlock(&escore->access_lock);
/* Null terminate the string*/
*verbuf = '\0';
pr_debug("Audience fw ver %s\n", versionbuffer);
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);
}
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,
&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
};
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;
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) {
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;
return rc;
}
+
static int es755_slim_set_channel_map(struct snd_soc_dai *dai,
unsigned int tx_num,
unsigned int *tx_slot,
}
#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)
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:
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 };
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:
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;
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 */
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);
* 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:
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);
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,
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,
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)
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,
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;
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;
}
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,
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 =
/* 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;
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 */
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:
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",
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;
}
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) {
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;
}
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;
}
return 0;
}
+
static int es755_put_hs_delay_value(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
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"
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,
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)
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;
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;
}
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;
}
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,
.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)
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;
/* 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);
/* 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);
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;
}
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) {
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;
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;
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,
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 {
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;
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 &&
}
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)
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);
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:
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;
}
{
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
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
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);
}
irq_exit:
+ escore_pm_put_autosuspend();
+err_pm_get_sync:
+ escore->intr_recvd = 0;
+ pr_info("%s(): @@@@@@ Exit #####\n", __func__);
return IRQ_HANDLED;
}
.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
/**/
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);
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",
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__);
}
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",
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);
__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) {
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;
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) {
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",
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;
}
/* 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)
#endif
return rc;
-regs_memalloc_error:
event_intr_error:
if (pdata->gpioa_gpio != -1)
free_irq(gpio_to_irq(pdata->gpioa_gpio), NULL);
#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);
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)
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);
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
#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
#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 {
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;
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*/
ES_PORT_FS_DURATION,
ES_BUTTON_CTRL1,
- ES_BUTTON_CTRL2,
- ES_BUTTON_CTRL3,
- ES_BUTTON_CTRL4,
ES_PRIMARY_MUX,
ES_SECONDARY_MUX,
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,
ES_SBUSTX5_MUX,
ES_CODEC_VALUE,
+ ES_CODEC_ADDR,
ES_POWER_STATE,
ES_RUNTIME_PM,
ES_VS_INT_OSC_MEASURE_START,
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
/*
* 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,
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"
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 */
* 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>
#include "escore.h"
#include "escore-uart-common.h"
-#include "mq100-sensorhub.h"
/* Index offset for the 3 character devices types. */
enum {
CDEV_COMMAND,
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)
{
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);
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;
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:
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
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,
goto streamdev_open_err;
}
/* Set NS baud rate after VS to NS switching */
- /*
if (escore->streamdev.config)
escore->streamdev.config(escore);
- */
}
/* initialize stream buffer */
/* 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)))
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)
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;
}
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;
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;
/*
* 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);
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);
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__);
= (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;
}
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);
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) {
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) {
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;
}
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;
= (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;
escore->cmd_history_size = 0;
return 0;
}
-
static const struct file_operations datablock_fops = {
.owner = THIS_MODULE,
.read = datablock_read,
.release = datablock_release,
};
+
static const struct file_operations cmd_history_fops = {
.owner = THIS_MODULE,
.read = cmd_history_read,
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);
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)
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
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)
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;
}
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);
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;
}
} 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;
}
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;
}
__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);
__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;
}
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)
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;
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:
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);
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,
};
#define _ESCORE_I2C_H
#include "escore.h"
-#include "mq100-sensorhub.h"
#define ES_I2C_BOOT_CMD 0x0001
#define ES_I2C_BOOT_ACK 0x0101
#include <sound/initval.h>
#include <sound/tlv.h>
#include <linux/kthread.h>
-#include <linux/esxxx.h>
#include "escore.h"
#include "escore-list.h"
}
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;
u32 resp;
pr_debug("%s()\n", __func__);
-
if (!escore)
escore = &escore_priv;
}
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);
* 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"
#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)
{
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;
}
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__);
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;
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)
{
.comp = NULL,
};
+
rc = slim_get_logical_addr(sbdev, escore->gen0_client->e_addr,
6, &(escore->gen0_client->laddr));
if (rc)
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;
}
wr += sz;
}
+ if (rc)
+ ESCORE_FW_RECOVERY_FORCED_OFF(escore);
+
return rc;
}
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,
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;
}
} 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;
}
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;
}
__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);
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;
}
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 */
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:
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);
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;
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;
}
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;
}
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)
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);
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,
} 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 {
}
} 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;
}
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;
}
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__);
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)
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;
}
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
*/
#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);
#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>
{
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)
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
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;
}
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,
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;
}
} 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;
}
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 */
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);
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;
}
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;
}
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)
#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
#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>
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;
}
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);
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);
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],
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;
}
} 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]);
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;
*/
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,
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",
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)
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)
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)
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;
}
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:
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);
{
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;
}
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;
}
#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 */
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;
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
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)
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) {
__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) {
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;
}
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:
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
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;
}
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;
}
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;
}
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;
}
if (rc) {
dev_err(escore->dev, "%s(): request_firmware(%s) failed %d\n",
__func__, bkg_filename, rc);
+ return rc;
}
return rc;
}
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;
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;
}
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;
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);
}
escore_datablock_close(escore);
+
return 0;
escore_vs_write_bkg_keywords_exit:
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;
__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;
}
*/
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;
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;
}
((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;
}
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;
}
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);
}
/* 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);
return rc;
sysfs_init_err:
+ kfree(voice_sense);
voice_sense_alloc_err:
return rc;
}
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);
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);
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,
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 */
* 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"
#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.
*
* 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 {
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;
{
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;
}
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 {
}
-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};
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;
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;
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;
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;
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",
}
} 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",
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;
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;) {
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;
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
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);
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,
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);
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));
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)
/* 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;
}
*/
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;
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;
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);
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) {
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;
}
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]);
}
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;
}
(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;
}
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;
}
(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;
}
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)
{
{
int rc = 0;
- mutex_lock(&escore->api_mutex);
+ mutex_lock(&escore->intf_probed_mutex);
/* Update intf_probed only when a valid interface is probed */
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);
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);
}
}
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:
#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 {
#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,
ES_SLIM_CH_UND,
};
-enum {
- ES_PM_NORMAL,
- ES_PM_RUNTIME_SLEEP,
- ES_PM_ASLEEP,
- ES_PM_HOSED,
-};
-
/* Notifier chain priority */
enum {
ES_LOW,
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;
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;
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*/
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*/
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
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;
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;
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;
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;
struct regulator *vcc_i2c;
#endif
int sleep_delay;
- int vs_abort_kw;
int wake_count;
int fw_requested;
u16 preset;
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;
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;
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;
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,
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,
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)
{
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 */
--- /dev/null
+/*
+ * 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__ */
+++ /dev/null
-/*
- * 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
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 */
INIT_DELAYED_WORK(&card->rtd[idx].delayed_work, NULL);
}
- if (gpio_is_valid(gpio->gpio))
- disable_irq(gpio_to_irq(gpio->gpio));
-
return 0;
}
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);