Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 


Quelle  wcd9335.c   Sprache: C

 
// SPDX-License-Identifier: GPL-2.0
// Copyright (c) 2015-2016, The Linux Foundation. All rights reserved.
// Copyright (c) 2017-2018, Linaro Limited

#include <linux/module.h>
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/cleanup.h>
#include <linux/device.h>
#include <linux/wait.h>
#include <linux/bitops.h>
#include <linux/regulator/consumer.h>
#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/kernel.h>
#include <linux/slimbus.h>
#include <sound/soc.h>
#include <sound/pcm_params.h>
#include <sound/soc-dapm.h>
#include <linux/gpio/consumer.h>
#include <linux/of.h>
#include <linux/of_irq.h>
#include <sound/tlv.h>
#include <sound/info.h>
#include "wcd9335.h"
#include "wcd-clsh-v2.h"

#include <dt-bindings/sound/qcom,wcd9335.h>

#define WCD9335_RATES_MASK (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 |\
       SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000 |\
       SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_192000)
/* Fractional Rates */
#define WCD9335_FRAC_RATES_MASK (SNDRV_PCM_RATE_44100)
#define WCD9335_FORMATS_S16_S24_LE (SNDRV_PCM_FMTBIT_S16_LE | \
      SNDRV_PCM_FMTBIT_S24_LE)

/* slave port water mark level
 *   (0: 6bytes, 1: 9bytes, 2: 12 bytes, 3: 15 bytes)
 */

#define SLAVE_PORT_WATER_MARK_6BYTES  0
#define SLAVE_PORT_WATER_MARK_9BYTES  1
#define SLAVE_PORT_WATER_MARK_12BYTES 2
#define SLAVE_PORT_WATER_MARK_15BYTES 3
#define SLAVE_PORT_WATER_MARK_SHIFT 1
#define SLAVE_PORT_ENABLE           1
#define SLAVE_PORT_DISABLE          0
#define WCD9335_SLIM_WATER_MARK_VAL \
 ((SLAVE_PORT_WATER_MARK_12BYTES << SLAVE_PORT_WATER_MARK_SHIFT) | \
  (SLAVE_PORT_ENABLE))

#define WCD9335_SLIM_NUM_PORT_REG 3
#define WCD9335_SLIM_PGD_PORT_INT_TX_EN0 (WCD9335_SLIM_PGD_PORT_INT_EN0 + 2)

#define WCD9335_MCLK_CLK_12P288MHZ 12288000
#define WCD9335_MCLK_CLK_9P6MHZ  9600000

#define WCD9335_SLIM_CLOSE_TIMEOUT 1000
#define WCD9335_SLIM_IRQ_OVERFLOW (1 << 0)
#define WCD9335_SLIM_IRQ_UNDERFLOW (1 << 1)
#define WCD9335_SLIM_IRQ_PORT_CLOSED (1 << 2)

#define WCD9335_NUM_INTERPOLATORS 9
#define WCD9335_RX_START 16
#define WCD9335_SLIM_CH_START 128
#define WCD9335_MAX_MICBIAS 4
#define WCD9335_MAX_VALID_ADC_MUX  13
#define WCD9335_INVALID_ADC_MUX 9

#define  TX_HPF_CUT_OFF_FREQ_MASK 0x60
#define  CF_MIN_3DB_4HZ   0x0
#define  CF_MIN_3DB_75HZ  0x1
#define  CF_MIN_3DB_150HZ  0x2
#define WCD9335_DMIC_CLK_DIV_2  0x0
#define WCD9335_DMIC_CLK_DIV_3  0x1
#define WCD9335_DMIC_CLK_DIV_4  0x2
#define WCD9335_DMIC_CLK_DIV_6  0x3
#define WCD9335_DMIC_CLK_DIV_8  0x4
#define WCD9335_DMIC_CLK_DIV_16  0x5
#define WCD9335_DMIC_CLK_DRIVE_DEFAULT 0x02
#define WCD9335_AMIC_PWR_LEVEL_LP 0
#define WCD9335_AMIC_PWR_LEVEL_DEFAULT 1
#define WCD9335_AMIC_PWR_LEVEL_HP 2
#define WCD9335_AMIC_PWR_LVL_MASK 0x60
#define WCD9335_AMIC_PWR_LVL_SHIFT 0x5

#define WCD9335_DEC_PWR_LVL_MASK 0x06
#define WCD9335_DEC_PWR_LVL_LP 0x02
#define WCD9335_DEC_PWR_LVL_HP 0x04
#define WCD9335_DEC_PWR_LVL_DF 0x00

#define WCD9335_SLIM_RX_CH(p) \
 {.port = p + WCD9335_RX_START, .shift = p,}

#define WCD9335_SLIM_TX_CH(p) \
 {.port = p, .shift = p,}

/* vout step value */
#define WCD9335_CALCULATE_VOUT_D(req_mv) (((req_mv - 650) * 10) / 25)

#define WCD9335_INTERPOLATOR_PATH(id)   \
 {"RX INT" #id "_1 MIX1 INP0""RX0""SLIM RX0"}, \
 {"RX INT" #id "_1 MIX1 INP0""RX1""SLIM RX1"}, \
 {"RX INT" #id "_1 MIX1 INP0""RX2""SLIM RX2"}, \
 {"RX INT" #id "_1 MIX1 INP0""RX3""SLIM RX3"}, \
 {"RX INT" #id "_1 MIX1 INP0""RX4""SLIM RX4"}, \
 {"RX INT" #id "_1 MIX1 INP0""RX5""SLIM RX5"}, \
 {"RX INT" #id "_1 MIX1 INP0""RX6""SLIM RX6"}, \
 {"RX INT" #id "_1 MIX1 INP0""RX7""SLIM RX7"}, \
 {"RX INT" #id "_1 MIX1 INP1""RX0""SLIM RX0"}, \
 {"RX INT" #id "_1 MIX1 INP1""RX1""SLIM RX1"}, \
 {"RX INT" #id "_1 MIX1 INP1""RX2""SLIM RX2"}, \
 {"RX INT" #id "_1 MIX1 INP1""RX3""SLIM RX3"}, \
 {"RX INT" #id "_1 MIX1 INP1""RX4""SLIM RX4"}, \
 {"RX INT" #id "_1 MIX1 INP1""RX5""SLIM RX5"}, \
 {"RX INT" #id "_1 MIX1 INP1""RX6""SLIM RX6"}, \
 {"RX INT" #id "_1 MIX1 INP1""RX7""SLIM RX7"}, \
 {"RX INT" #id "_1 MIX1 INP2""RX0""SLIM RX0"}, \
 {"RX INT" #id "_1 MIX1 INP2""RX1""SLIM RX1"}, \
 {"RX INT" #id "_1 MIX1 INP2""RX2""SLIM RX2"}, \
 {"RX INT" #id "_1 MIX1 INP2""RX3""SLIM RX3"}, \
 {"RX INT" #id "_1 MIX1 INP2""RX4""SLIM RX4"}, \
 {"RX INT" #id "_1 MIX1 INP2""RX5""SLIM RX5"}, \
 {"RX INT" #id "_1 MIX1 INP2""RX6""SLIM RX6"}, \
 {"RX INT" #id "_1 MIX1 INP2""RX7""SLIM RX7"}, \
 {"RX INT" #id "_2 MUX""RX0""SLIM RX0"}, \
 {"RX INT" #id "_2 MUX""RX1""SLIM RX1"}, \
 {"RX INT" #id "_2 MUX""RX2""SLIM RX2"}, \
 {"RX INT" #id "_2 MUX""RX3""SLIM RX3"}, \
 {"RX INT" #id "_2 MUX""RX4""SLIM RX4"}, \
 {"RX INT" #id "_2 MUX""RX5""SLIM RX5"}, \
 {"RX INT" #id "_2 MUX""RX6""SLIM RX6"}, \
 {"RX INT" #id "_2 MUX""RX7""SLIM RX7"}, \
 {"RX INT" #id "_1 MIX1", NULL, "RX INT" #id "_1 MIX1 INP0"}, \
 {"RX INT" #id "_1 MIX1", NULL, "RX INT" #id "_1 MIX1 INP1"}, \
 {"RX INT" #id "_1 MIX1", NULL, "RX INT" #id "_1 MIX1 INP2"}, \
 {"RX INT" #id " SEC MIX", NULL, "RX INT" #id "_2 MUX"},  \
 {"RX INT" #id " SEC MIX", NULL, "RX INT" #id "_1 MIX1"}, \
 {"RX INT" #id " MIX2", NULL, "RX INT" #id " SEC MIX"},  \
 {"RX INT" #id " INTERP", NULL, "RX INT" #id " MIX2"}

#define WCD9335_ADC_MUX_PATH(id)   \
 {"AIF1_CAP Mixer""SLIM TX" #id"SLIM TX" #id " MUX"}, \
 {"AIF2_CAP Mixer""SLIM TX" #id"SLIM TX" #id " MUX"}, \
 {"AIF3_CAP Mixer""SLIM TX" #id"SLIM TX" #id " MUX"}, \
 {"SLIM TX" #id " MUX""DEC" #id"ADC MUX" #id}, \
 {"ADC MUX" #id"DMIC""DMIC MUX" #id}, \
 {"ADC MUX" #id"AMIC""AMIC MUX" #id}, \
 {"DMIC MUX" #id"DMIC0""DMIC0"},  \
 {"DMIC MUX" #id"DMIC1""DMIC1"},  \
 {"DMIC MUX" #id"DMIC2""DMIC2"},  \
 {"DMIC MUX" #id"DMIC3""DMIC3"},  \
 {"DMIC MUX" #id"DMIC4""DMIC4"},  \
 {"DMIC MUX" #id"DMIC5""DMIC5"},  \
 {"AMIC MUX" #id"ADC1""ADC1"},  \
 {"AMIC MUX" #id"ADC2""ADC2"},  \
 {"AMIC MUX" #id"ADC3""ADC3"},  \
 {"AMIC MUX" #id"ADC4""ADC4"},  \
 {"AMIC MUX" #id"ADC5""ADC5"},  \
 {"AMIC MUX" #id"ADC6""ADC6"}

#define NUM_CODEC_DAIS          7

enum {
 WCD9335_RX0 = 0,
 WCD9335_RX1,
 WCD9335_RX2,
 WCD9335_RX3,
 WCD9335_RX4,
 WCD9335_RX5,
 WCD9335_RX6,
 WCD9335_RX7,
 WCD9335_RX8,
 WCD9335_RX9,
 WCD9335_RX10,
 WCD9335_RX11,
 WCD9335_RX12,
 WCD9335_RX_MAX,
};

enum {
 WCD9335_TX0 = 0,
 WCD9335_TX1,
 WCD9335_TX2,
 WCD9335_TX3,
 WCD9335_TX4,
 WCD9335_TX5,
 WCD9335_TX6,
 WCD9335_TX7,
 WCD9335_TX8,
 WCD9335_TX9,
 WCD9335_TX10,
 WCD9335_TX11,
 WCD9335_TX12,
 WCD9335_TX13,
 WCD9335_TX14,
 WCD9335_TX15,
 WCD9335_TX_MAX,
};

enum {
 SIDO_SOURCE_INTERNAL = 0,
 SIDO_SOURCE_RCO_BG,
};

enum wcd9335_sido_voltage {
 SIDO_VOLTAGE_SVS_MV = 950,
 SIDO_VOLTAGE_NOMINAL_MV = 1100,
};

enum {
 COMPANDER_1, /* HPH_L */
 COMPANDER_2, /* HPH_R */
 COMPANDER_3, /* LO1_DIFF */
 COMPANDER_4, /* LO2_DIFF */
 COMPANDER_5, /* LO3_SE */
 COMPANDER_6, /* LO4_SE */
 COMPANDER_7, /* SWR SPK CH1 */
 COMPANDER_8, /* SWR SPK CH2 */
 COMPANDER_MAX,
};

enum {
 INTn_2_INP_SEL_ZERO = 0,
 INTn_2_INP_SEL_RX0,
 INTn_2_INP_SEL_RX1,
 INTn_2_INP_SEL_RX2,
 INTn_2_INP_SEL_RX3,
 INTn_2_INP_SEL_RX4,
 INTn_2_INP_SEL_RX5,
 INTn_2_INP_SEL_RX6,
 INTn_2_INP_SEL_RX7,
 INTn_2_INP_SEL_PROXIMITY,
};

enum {
 INTn_1_MIX_INP_SEL_ZERO = 0,
 INTn_1_MIX_INP_SEL_DEC0,
 INTn_1_MIX_INP_SEL_DEC1,
 INTn_1_MIX_INP_SEL_IIR0,
 INTn_1_MIX_INP_SEL_IIR1,
 INTn_1_MIX_INP_SEL_RX0,
 INTn_1_MIX_INP_SEL_RX1,
 INTn_1_MIX_INP_SEL_RX2,
 INTn_1_MIX_INP_SEL_RX3,
 INTn_1_MIX_INP_SEL_RX4,
 INTn_1_MIX_INP_SEL_RX5,
 INTn_1_MIX_INP_SEL_RX6,
 INTn_1_MIX_INP_SEL_RX7,

};

enum {
 INTERP_EAR = 0,
 INTERP_HPHL,
 INTERP_HPHR,
 INTERP_LO1,
 INTERP_LO2,
 INTERP_LO3,
 INTERP_LO4,
 INTERP_SPKR1,
 INTERP_SPKR2,
};

enum wcd_clock_type {
 WCD_CLK_OFF,
 WCD_CLK_RCO,
 WCD_CLK_MCLK,
};

enum {
 MIC_BIAS_1 = 1,
 MIC_BIAS_2,
 MIC_BIAS_3,
 MIC_BIAS_4
};

enum {
 MICB_PULLUP_ENABLE,
 MICB_PULLUP_DISABLE,
 MICB_ENABLE,
 MICB_DISABLE,
};

struct wcd9335_slim_ch {
 u32 ch_num;
 u16 port;
 u16 shift;
 struct list_head list;
};

struct wcd_slim_codec_dai_data {
 struct list_head slim_ch_list;
 struct slim_stream_config sconfig;
 struct slim_stream_runtime *sruntime;
};

struct wcd9335_codec {
 struct device *dev;
 struct clk *mclk;
 struct clk *native_clk;
 u32 mclk_rate;

 struct slim_device *slim;
 struct slim_device *slim_ifc_dev;
 struct regmap *regmap;
 struct regmap *if_regmap;
 struct regmap_irq_chip_data *irq_data;

 struct wcd9335_slim_ch rx_chs[WCD9335_RX_MAX];
 struct wcd9335_slim_ch tx_chs[WCD9335_TX_MAX];
 u32 num_rx_port;
 u32 num_tx_port;

 enum wcd9335_sido_voltage sido_voltage;

 struct wcd_slim_codec_dai_data dai[NUM_CODEC_DAIS];
 struct snd_soc_component *component;

 int master_bias_users;
 int clk_mclk_users;
 int clk_rco_users;
 int sido_ccl_cnt;
 enum wcd_clock_type clk_type;

 struct wcd_clsh_ctrl *clsh_ctrl;
 u32 hph_mode;
 int prim_int_users[WCD9335_NUM_INTERPOLATORS];

 int comp_enabled[COMPANDER_MAX];

 int intr1;
 struct gpio_desc *reset_gpio;

 unsigned int rx_port_value[WCD9335_RX_MAX];
 unsigned int tx_port_value[WCD9335_TX_MAX];
 int hph_l_gain;
 int hph_r_gain;
 u32 rx_bias_count;

 /*TX*/
 int micb_ref[WCD9335_MAX_MICBIAS];
 int pullup_ref[WCD9335_MAX_MICBIAS];

 int dmic_0_1_clk_cnt;
 int dmic_2_3_clk_cnt;
 int dmic_4_5_clk_cnt;
};

struct wcd9335_irq {
 int irq;
 irqreturn_t (*handler)(int irq, void *data);
 char *name;
};

static const char * const wcd9335_supplies[] = {
 "vdd-buck""vdd-buck-sido""vdd-tx""vdd-rx""vdd-io",
};

static const struct wcd9335_slim_ch wcd9335_tx_chs[WCD9335_TX_MAX] = {
 WCD9335_SLIM_TX_CH(0),
 WCD9335_SLIM_TX_CH(1),
 WCD9335_SLIM_TX_CH(2),
 WCD9335_SLIM_TX_CH(3),
 WCD9335_SLIM_TX_CH(4),
 WCD9335_SLIM_TX_CH(5),
 WCD9335_SLIM_TX_CH(6),
 WCD9335_SLIM_TX_CH(7),
 WCD9335_SLIM_TX_CH(8),
 WCD9335_SLIM_TX_CH(9),
 WCD9335_SLIM_TX_CH(10),
 WCD9335_SLIM_TX_CH(11),
 WCD9335_SLIM_TX_CH(12),
 WCD9335_SLIM_TX_CH(13),
 WCD9335_SLIM_TX_CH(14),
 WCD9335_SLIM_TX_CH(15),
};

static const struct wcd9335_slim_ch wcd9335_rx_chs[WCD9335_RX_MAX] = {
 WCD9335_SLIM_RX_CH(0),  /* 16 */
 WCD9335_SLIM_RX_CH(1),  /* 17 */
 WCD9335_SLIM_RX_CH(2),
 WCD9335_SLIM_RX_CH(3),
 WCD9335_SLIM_RX_CH(4),
 WCD9335_SLIM_RX_CH(5),
 WCD9335_SLIM_RX_CH(6),
 WCD9335_SLIM_RX_CH(7),
 WCD9335_SLIM_RX_CH(8),
 WCD9335_SLIM_RX_CH(9),
 WCD9335_SLIM_RX_CH(10),
 WCD9335_SLIM_RX_CH(11),
 WCD9335_SLIM_RX_CH(12),
};

struct interp_sample_rate {
 int rate;
 int rate_val;
};

static const struct interp_sample_rate int_mix_rate_val[] = {
 {48000, 0x4}, /* 48K */
 {96000, 0x5}, /* 96K */
 {192000, 0x6}, /* 192K */
};

static const struct interp_sample_rate int_prim_rate_val[] = {
 {8000, 0x0}, /* 8K */
 {16000, 0x1}, /* 16K */
 {24000, -EINVAL},/* 24K */
 {32000, 0x3}, /* 32K */
 {48000, 0x4}, /* 48K */
 {96000, 0x5}, /* 96K */
 {192000, 0x6}, /* 192K */
 {384000, 0x7}, /* 384K */
 {44100, 0x8}, /* 44.1K */
};

struct wcd9335_reg_mask_val {
 u16 reg;
 u8 mask;
 u8 val;
};

static const struct wcd9335_reg_mask_val wcd9335_codec_reg_init[] = {
 /* Rbuckfly/R_EAR(32) */
 {WCD9335_CDC_CLSH_K2_MSB, 0x0F, 0x00},
 {WCD9335_CDC_CLSH_K2_LSB, 0xFF, 0x60},
 {WCD9335_CPE_SS_DMIC_CFG, 0x80, 0x00},
 {WCD9335_CDC_BOOST0_BOOST_CTL, 0x70, 0x50},
 {WCD9335_CDC_BOOST1_BOOST_CTL, 0x70, 0x50},
 {WCD9335_CDC_RX7_RX_PATH_CFG1, 0x08, 0x08},
 {WCD9335_CDC_RX8_RX_PATH_CFG1, 0x08, 0x08},
 {WCD9335_ANA_LO_1_2, 0x3C, 0X3C},
 {WCD9335_DIFF_LO_COM_SWCAP_REFBUF_FREQ, 0x70, 0x00},
 {WCD9335_DIFF_LO_COM_PA_FREQ, 0x70, 0x40},
 {WCD9335_SOC_MAD_AUDIO_CTL_2, 0x03, 0x03},
 {WCD9335_CDC_TOP_TOP_CFG1, 0x02, 0x02},
 {WCD9335_CDC_TOP_TOP_CFG1, 0x01, 0x01},
 {WCD9335_EAR_CMBUFF, 0x08, 0x00},
 {WCD9335_CDC_TX9_SPKR_PROT_PATH_CFG0, 0x01, 0x01},
 {WCD9335_CDC_TX10_SPKR_PROT_PATH_CFG0, 0x01, 0x01},
 {WCD9335_CDC_TX11_SPKR_PROT_PATH_CFG0, 0x01, 0x01},
 {WCD9335_CDC_TX12_SPKR_PROT_PATH_CFG0, 0x01, 0x01},
 {WCD9335_CDC_COMPANDER7_CTL3, 0x80, 0x80},
 {WCD9335_CDC_COMPANDER8_CTL3, 0x80, 0x80},
 {WCD9335_CDC_COMPANDER7_CTL7, 0x01, 0x01},
 {WCD9335_CDC_COMPANDER8_CTL7, 0x01, 0x01},
 {WCD9335_CDC_RX0_RX_PATH_CFG0, 0x01, 0x01},
 {WCD9335_CDC_RX1_RX_PATH_CFG0, 0x01, 0x01},
 {WCD9335_CDC_RX2_RX_PATH_CFG0, 0x01, 0x01},
 {WCD9335_CDC_RX3_RX_PATH_CFG0, 0x01, 0x01},
 {WCD9335_CDC_RX4_RX_PATH_CFG0, 0x01, 0x01},
 {WCD9335_CDC_RX5_RX_PATH_CFG0, 0x01, 0x01},
 {WCD9335_CDC_RX6_RX_PATH_CFG0, 0x01, 0x01},
 {WCD9335_CDC_RX7_RX_PATH_CFG0, 0x01, 0x01},
 {WCD9335_CDC_RX8_RX_PATH_CFG0, 0x01, 0x01},
 {WCD9335_CDC_RX0_RX_PATH_MIX_CFG, 0x01, 0x01},
 {WCD9335_CDC_RX1_RX_PATH_MIX_CFG, 0x01, 0x01},
 {WCD9335_CDC_RX2_RX_PATH_MIX_CFG, 0x01, 0x01},
 {WCD9335_CDC_RX3_RX_PATH_MIX_CFG, 0x01, 0x01},
 {WCD9335_CDC_RX4_RX_PATH_MIX_CFG, 0x01, 0x01},
 {WCD9335_CDC_RX5_RX_PATH_MIX_CFG, 0x01, 0x01},
 {WCD9335_CDC_RX6_RX_PATH_MIX_CFG, 0x01, 0x01},
 {WCD9335_CDC_RX7_RX_PATH_MIX_CFG, 0x01, 0x01},
 {WCD9335_CDC_RX8_RX_PATH_MIX_CFG, 0x01, 0x01},
 {WCD9335_VBADC_IBIAS_FE, 0x0C, 0x08},
 {WCD9335_RCO_CTRL_2, 0x0F, 0x08},
 {WCD9335_RX_BIAS_FLYB_MID_RST, 0xF0, 0x10},
 {WCD9335_FLYBACK_CTRL_1, 0x20, 0x20},
 {WCD9335_HPH_OCP_CTL, 0xFF, 0x5A},
 {WCD9335_HPH_L_TEST, 0x01, 0x01},
 {WCD9335_HPH_R_TEST, 0x01, 0x01},
 {WCD9335_CDC_BOOST0_BOOST_CFG1, 0x3F, 0x12},
 {WCD9335_CDC_BOOST0_BOOST_CFG2, 0x1C, 0x08},
 {WCD9335_CDC_COMPANDER7_CTL7, 0x1E, 0x18},
 {WCD9335_CDC_BOOST1_BOOST_CFG1, 0x3F, 0x12},
 {WCD9335_CDC_BOOST1_BOOST_CFG2, 0x1C, 0x08},
 {WCD9335_CDC_COMPANDER8_CTL7, 0x1E, 0x18},
 {WCD9335_CDC_TX0_TX_PATH_SEC7, 0xFF, 0x45},
 {WCD9335_CDC_RX0_RX_PATH_SEC0, 0xFC, 0xF4},
 {WCD9335_HPH_REFBUFF_LP_CTL, 0x08, 0x08},
 {WCD9335_HPH_REFBUFF_LP_CTL, 0x06, 0x02},
};

/* Cutoff frequency for high pass filter */
static const char * const cf_text[] = {
 "CF_NEG_3DB_4HZ""CF_NEG_3DB_75HZ""CF_NEG_3DB_150HZ"
};

static const char * const rx_cf_text[] = {
 "CF_NEG_3DB_4HZ""CF_NEG_3DB_75HZ""CF_NEG_3DB_150HZ",
 "CF_NEG_3DB_0P48HZ"
};

static const char * const rx_int0_7_mix_mux_text[] = {
 "ZERO""RX0""RX1""RX2""RX3""RX4""RX5",
 "RX6""RX7""PROXIMITY"
};

static const char * const rx_int_mix_mux_text[] = {
 "ZERO""RX0""RX1""RX2""RX3""RX4""RX5",
 "RX6""RX7"
};

static const char * const rx_prim_mix_text[] = {
 "ZERO""DEC0""DEC1""IIR0""IIR1""RX0""RX1""RX2",
 "RX3""RX4""RX5""RX6""RX7"
};

static const char * const rx_int_dem_inp_mux_text[] = {
 "NORMAL_DSM_OUT""CLSH_DSM_OUT",
};

static const char * const rx_int0_interp_mux_text[] = {
 "ZERO""RX INT0 MIX2",
};

static const char * const rx_int1_interp_mux_text[] = {
 "ZERO""RX INT1 MIX2",
};

static const char * const rx_int2_interp_mux_text[] = {
 "ZERO""RX INT2 MIX2",
};

static const char * const rx_int3_interp_mux_text[] = {
 "ZERO""RX INT3 MIX2",
};

static const char * const rx_int4_interp_mux_text[] = {
 "ZERO""RX INT4 MIX2",
};

static const char * const rx_int5_interp_mux_text[] = {
 "ZERO""RX INT5 MIX2",
};

static const char * const rx_int6_interp_mux_text[] = {
 "ZERO""RX INT6 MIX2",
};

static const char * const rx_int7_interp_mux_text[] = {
 "ZERO""RX INT7 MIX2",
};

static const char * const rx_int8_interp_mux_text[] = {
 "ZERO""RX INT8 SEC MIX"
};

static const char * const rx_hph_mode_mux_text[] = {
 "Class H Invalid""Class-H Hi-Fi""Class-H Low Power""Class-AB",
 "Class-H Hi-Fi Low Power"
};

static const char *const slim_rx_mux_text[] = {
 "ZERO""AIF1_PB""AIF2_PB""AIF3_PB""AIF4_PB",
};

static const char * const adc_mux_text[] = {
 "DMIC""AMIC""ANC_FB_TUNE1""ANC_FB_TUNE2"
};

static const char * const dmic_mux_text[] = {
 "ZERO""DMIC0""DMIC1""DMIC2""DMIC3""DMIC4""DMIC5",
 "SMIC0""SMIC1""SMIC2""SMIC3"
};

static const char * const dmic_mux_alt_text[] = {
 "ZERO""DMIC0""DMIC1""DMIC2""DMIC3""DMIC4""DMIC5",
};

static const char * const amic_mux_text[] = {
 "ZERO""ADC1""ADC2""ADC3""ADC4""ADC5""ADC6"
};

static const char * const sb_tx0_mux_text[] = {
 "ZERO""RX_MIX_TX0""DEC0""DEC0_192"
};

static const char * const sb_tx1_mux_text[] = {
 "ZERO""RX_MIX_TX1""DEC1""DEC1_192"
};

static const char * const sb_tx2_mux_text[] = {
 "ZERO""RX_MIX_TX2""DEC2""DEC2_192"
};

static const char * const sb_tx3_mux_text[] = {
 "ZERO""RX_MIX_TX3""DEC3""DEC3_192"
};

static const char * const sb_tx4_mux_text[] = {
 "ZERO""RX_MIX_TX4""DEC4""DEC4_192"
};

static const char * const sb_tx5_mux_text[] = {
 "ZERO""RX_MIX_TX5""DEC5""DEC5_192"
};

static const char * const sb_tx6_mux_text[] = {
 "ZERO""RX_MIX_TX6""DEC6""DEC6_192"
};

static const char * const sb_tx7_mux_text[] = {
 "ZERO""RX_MIX_TX7""DEC7""DEC7_192"
};

static const char * const sb_tx8_mux_text[] = {
 "ZERO""RX_MIX_TX8""DEC8""DEC8_192"
};

static const DECLARE_TLV_DB_SCALE(digital_gain, -8400, 100, -8400);
static const DECLARE_TLV_DB_SCALE(line_gain, 0, 7, 1);
static const DECLARE_TLV_DB_SCALE(analog_gain, 0, 25, 1);
static const DECLARE_TLV_DB_SCALE(ear_pa_gain, 0, 150, 0);

static const struct soc_enum cf_dec0_enum =
 SOC_ENUM_SINGLE(WCD9335_CDC_TX0_TX_PATH_CFG0, 5, 3, cf_text);

static const struct soc_enum cf_dec1_enum =
 SOC_ENUM_SINGLE(WCD9335_CDC_TX1_TX_PATH_CFG0, 5, 3, cf_text);

static const struct soc_enum cf_dec2_enum =
 SOC_ENUM_SINGLE(WCD9335_CDC_TX2_TX_PATH_CFG0, 5, 3, cf_text);

static const struct soc_enum cf_dec3_enum =
 SOC_ENUM_SINGLE(WCD9335_CDC_TX3_TX_PATH_CFG0, 5, 3, cf_text);

static const struct soc_enum cf_dec4_enum =
 SOC_ENUM_SINGLE(WCD9335_CDC_TX4_TX_PATH_CFG0, 5, 3, cf_text);

static const struct soc_enum cf_dec5_enum =
 SOC_ENUM_SINGLE(WCD9335_CDC_TX5_TX_PATH_CFG0, 5, 3, cf_text);

static const struct soc_enum cf_dec6_enum =
 SOC_ENUM_SINGLE(WCD9335_CDC_TX6_TX_PATH_CFG0, 5, 3, cf_text);

static const struct soc_enum cf_dec7_enum =
 SOC_ENUM_SINGLE(WCD9335_CDC_TX7_TX_PATH_CFG0, 5, 3, cf_text);

static const struct soc_enum cf_dec8_enum =
 SOC_ENUM_SINGLE(WCD9335_CDC_TX8_TX_PATH_CFG0, 5, 3, cf_text);

static const struct soc_enum cf_int0_1_enum =
 SOC_ENUM_SINGLE(WCD9335_CDC_RX0_RX_PATH_CFG2, 0, 4, rx_cf_text);

static SOC_ENUM_SINGLE_DECL(cf_int0_2_enum, WCD9335_CDC_RX0_RX_PATH_MIX_CFG, 2,
       rx_cf_text);

static const struct soc_enum cf_int1_1_enum =
 SOC_ENUM_SINGLE(WCD9335_CDC_RX1_RX_PATH_CFG2, 0, 4, rx_cf_text);

static SOC_ENUM_SINGLE_DECL(cf_int1_2_enum, WCD9335_CDC_RX1_RX_PATH_MIX_CFG, 2,
       rx_cf_text);

static const struct soc_enum cf_int2_1_enum =
 SOC_ENUM_SINGLE(WCD9335_CDC_RX2_RX_PATH_CFG2, 0, 4, rx_cf_text);

static SOC_ENUM_SINGLE_DECL(cf_int2_2_enum, WCD9335_CDC_RX2_RX_PATH_MIX_CFG, 2,
       rx_cf_text);

static const struct soc_enum cf_int3_1_enum =
 SOC_ENUM_SINGLE(WCD9335_CDC_RX3_RX_PATH_CFG2, 0, 4, rx_cf_text);

static SOC_ENUM_SINGLE_DECL(cf_int3_2_enum, WCD9335_CDC_RX3_RX_PATH_MIX_CFG, 2,
       rx_cf_text);

static const struct soc_enum cf_int4_1_enum =
 SOC_ENUM_SINGLE(WCD9335_CDC_RX4_RX_PATH_CFG2, 0, 4, rx_cf_text);

static SOC_ENUM_SINGLE_DECL(cf_int4_2_enum, WCD9335_CDC_RX4_RX_PATH_MIX_CFG, 2,
       rx_cf_text);

static const struct soc_enum cf_int5_1_enum =
 SOC_ENUM_SINGLE(WCD9335_CDC_RX5_RX_PATH_CFG2, 0, 4, rx_cf_text);

static SOC_ENUM_SINGLE_DECL(cf_int5_2_enum, WCD9335_CDC_RX5_RX_PATH_MIX_CFG, 2,
       rx_cf_text);

static const struct soc_enum cf_int6_1_enum =
 SOC_ENUM_SINGLE(WCD9335_CDC_RX6_RX_PATH_CFG2, 0, 4, rx_cf_text);

static SOC_ENUM_SINGLE_DECL(cf_int6_2_enum, WCD9335_CDC_RX6_RX_PATH_MIX_CFG, 2,
       rx_cf_text);

static const struct soc_enum cf_int7_1_enum =
 SOC_ENUM_SINGLE(WCD9335_CDC_RX7_RX_PATH_CFG2, 0, 4, rx_cf_text);

static SOC_ENUM_SINGLE_DECL(cf_int7_2_enum, WCD9335_CDC_RX7_RX_PATH_MIX_CFG, 2,
       rx_cf_text);

static const struct soc_enum cf_int8_1_enum =
 SOC_ENUM_SINGLE(WCD9335_CDC_RX8_RX_PATH_CFG2, 0, 4, rx_cf_text);

static SOC_ENUM_SINGLE_DECL(cf_int8_2_enum, WCD9335_CDC_RX8_RX_PATH_MIX_CFG, 2,
       rx_cf_text);

static const struct soc_enum rx_hph_mode_mux_enum =
 SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(rx_hph_mode_mux_text),
       rx_hph_mode_mux_text);

static const struct soc_enum slim_rx_mux_enum =
 SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(slim_rx_mux_text), slim_rx_mux_text);

static const struct soc_enum rx_int0_2_mux_chain_enum =
 SOC_ENUM_SINGLE(WCD9335_CDC_RX_INP_MUX_RX_INT0_CFG1, 0, 10,
   rx_int0_7_mix_mux_text);

static const struct soc_enum rx_int1_2_mux_chain_enum =
 SOC_ENUM_SINGLE(WCD9335_CDC_RX_INP_MUX_RX_INT1_CFG1, 0, 9,
   rx_int_mix_mux_text);

static const struct soc_enum rx_int2_2_mux_chain_enum =
 SOC_ENUM_SINGLE(WCD9335_CDC_RX_INP_MUX_RX_INT2_CFG1, 0, 9,
   rx_int_mix_mux_text);

static const struct soc_enum rx_int3_2_mux_chain_enum =
 SOC_ENUM_SINGLE(WCD9335_CDC_RX_INP_MUX_RX_INT3_CFG1, 0, 9,
   rx_int_mix_mux_text);

static const struct soc_enum rx_int4_2_mux_chain_enum =
 SOC_ENUM_SINGLE(WCD9335_CDC_RX_INP_MUX_RX_INT4_CFG1, 0, 9,
   rx_int_mix_mux_text);

static const struct soc_enum rx_int5_2_mux_chain_enum =
 SOC_ENUM_SINGLE(WCD9335_CDC_RX_INP_MUX_RX_INT5_CFG1, 0, 9,
   rx_int_mix_mux_text);

static const struct soc_enum rx_int6_2_mux_chain_enum =
 SOC_ENUM_SINGLE(WCD9335_CDC_RX_INP_MUX_RX_INT6_CFG1, 0, 9,
   rx_int_mix_mux_text);

static const struct soc_enum rx_int7_2_mux_chain_enum =
 SOC_ENUM_SINGLE(WCD9335_CDC_RX_INP_MUX_RX_INT7_CFG1, 0, 10,
   rx_int0_7_mix_mux_text);

static const struct soc_enum rx_int8_2_mux_chain_enum =
 SOC_ENUM_SINGLE(WCD9335_CDC_RX_INP_MUX_RX_INT8_CFG1, 0, 9,
   rx_int_mix_mux_text);

static const struct soc_enum rx_int0_1_mix_inp0_chain_enum =
 SOC_ENUM_SINGLE(WCD9335_CDC_RX_INP_MUX_RX_INT0_CFG0, 0, 13,
   rx_prim_mix_text);

static const struct soc_enum rx_int0_1_mix_inp1_chain_enum =
 SOC_ENUM_SINGLE(WCD9335_CDC_RX_INP_MUX_RX_INT0_CFG0, 4, 13,
   rx_prim_mix_text);

static const struct soc_enum rx_int0_1_mix_inp2_chain_enum =
 SOC_ENUM_SINGLE(WCD9335_CDC_RX_INP_MUX_RX_INT0_CFG1, 4, 13,
   rx_prim_mix_text);

static const struct soc_enum rx_int1_1_mix_inp0_chain_enum =
 SOC_ENUM_SINGLE(WCD9335_CDC_RX_INP_MUX_RX_INT1_CFG0, 0, 13,
   rx_prim_mix_text);

static const struct soc_enum rx_int1_1_mix_inp1_chain_enum =
 SOC_ENUM_SINGLE(WCD9335_CDC_RX_INP_MUX_RX_INT1_CFG0, 4, 13,
   rx_prim_mix_text);

static const struct soc_enum rx_int1_1_mix_inp2_chain_enum =
 SOC_ENUM_SINGLE(WCD9335_CDC_RX_INP_MUX_RX_INT1_CFG1, 4, 13,
   rx_prim_mix_text);

static const struct soc_enum rx_int2_1_mix_inp0_chain_enum =
 SOC_ENUM_SINGLE(WCD9335_CDC_RX_INP_MUX_RX_INT2_CFG0, 0, 13,
   rx_prim_mix_text);

static const struct soc_enum rx_int2_1_mix_inp1_chain_enum =
 SOC_ENUM_SINGLE(WCD9335_CDC_RX_INP_MUX_RX_INT2_CFG0, 4, 13,
   rx_prim_mix_text);

static const struct soc_enum rx_int2_1_mix_inp2_chain_enum =
 SOC_ENUM_SINGLE(WCD9335_CDC_RX_INP_MUX_RX_INT2_CFG1, 4, 13,
   rx_prim_mix_text);

static const struct soc_enum rx_int3_1_mix_inp0_chain_enum =
 SOC_ENUM_SINGLE(WCD9335_CDC_RX_INP_MUX_RX_INT3_CFG0, 0, 13,
   rx_prim_mix_text);

static const struct soc_enum rx_int3_1_mix_inp1_chain_enum =
 SOC_ENUM_SINGLE(WCD9335_CDC_RX_INP_MUX_RX_INT3_CFG0, 4, 13,
   rx_prim_mix_text);

static const struct soc_enum rx_int3_1_mix_inp2_chain_enum =
 SOC_ENUM_SINGLE(WCD9335_CDC_RX_INP_MUX_RX_INT3_CFG1, 4, 13,
   rx_prim_mix_text);

static const struct soc_enum rx_int4_1_mix_inp0_chain_enum =
 SOC_ENUM_SINGLE(WCD9335_CDC_RX_INP_MUX_RX_INT4_CFG0, 0, 13,
   rx_prim_mix_text);

static const struct soc_enum rx_int4_1_mix_inp1_chain_enum =
 SOC_ENUM_SINGLE(WCD9335_CDC_RX_INP_MUX_RX_INT4_CFG0, 4, 13,
   rx_prim_mix_text);

static const struct soc_enum rx_int4_1_mix_inp2_chain_enum =
 SOC_ENUM_SINGLE(WCD9335_CDC_RX_INP_MUX_RX_INT4_CFG1, 4, 13,
   rx_prim_mix_text);

static const struct soc_enum rx_int5_1_mix_inp0_chain_enum =
 SOC_ENUM_SINGLE(WCD9335_CDC_RX_INP_MUX_RX_INT5_CFG0, 0, 13,
   rx_prim_mix_text);

static const struct soc_enum rx_int5_1_mix_inp1_chain_enum =
 SOC_ENUM_SINGLE(WCD9335_CDC_RX_INP_MUX_RX_INT5_CFG0, 4, 13,
   rx_prim_mix_text);

static const struct soc_enum rx_int5_1_mix_inp2_chain_enum =
 SOC_ENUM_SINGLE(WCD9335_CDC_RX_INP_MUX_RX_INT5_CFG1, 4, 13,
   rx_prim_mix_text);

static const struct soc_enum rx_int6_1_mix_inp0_chain_enum =
 SOC_ENUM_SINGLE(WCD9335_CDC_RX_INP_MUX_RX_INT6_CFG0, 0, 13,
   rx_prim_mix_text);

static const struct soc_enum rx_int6_1_mix_inp1_chain_enum =
 SOC_ENUM_SINGLE(WCD9335_CDC_RX_INP_MUX_RX_INT6_CFG0, 4, 13,
   rx_prim_mix_text);

static const struct soc_enum rx_int6_1_mix_inp2_chain_enum =
 SOC_ENUM_SINGLE(WCD9335_CDC_RX_INP_MUX_RX_INT6_CFG1, 4, 13,
   rx_prim_mix_text);

static const struct soc_enum rx_int7_1_mix_inp0_chain_enum =
 SOC_ENUM_SINGLE(WCD9335_CDC_RX_INP_MUX_RX_INT7_CFG0, 0, 13,
   rx_prim_mix_text);

static const struct soc_enum rx_int7_1_mix_inp1_chain_enum =
 SOC_ENUM_SINGLE(WCD9335_CDC_RX_INP_MUX_RX_INT7_CFG0, 4, 13,
   rx_prim_mix_text);

static const struct soc_enum rx_int7_1_mix_inp2_chain_enum =
 SOC_ENUM_SINGLE(WCD9335_CDC_RX_INP_MUX_RX_INT7_CFG1, 4, 13,
   rx_prim_mix_text);

static const struct soc_enum rx_int8_1_mix_inp0_chain_enum =
 SOC_ENUM_SINGLE(WCD9335_CDC_RX_INP_MUX_RX_INT8_CFG0, 0, 13,
   rx_prim_mix_text);

static const struct soc_enum rx_int8_1_mix_inp1_chain_enum =
 SOC_ENUM_SINGLE(WCD9335_CDC_RX_INP_MUX_RX_INT8_CFG0, 4, 13,
   rx_prim_mix_text);

static const struct soc_enum rx_int8_1_mix_inp2_chain_enum =
 SOC_ENUM_SINGLE(WCD9335_CDC_RX_INP_MUX_RX_INT8_CFG1, 4, 13,
   rx_prim_mix_text);

static const struct soc_enum rx_int0_dem_inp_mux_enum =
 SOC_ENUM_SINGLE(WCD9335_CDC_RX0_RX_PATH_SEC0, 0,
   ARRAY_SIZE(rx_int_dem_inp_mux_text),
   rx_int_dem_inp_mux_text);

static const struct soc_enum rx_int1_dem_inp_mux_enum =
 SOC_ENUM_SINGLE(WCD9335_CDC_RX1_RX_PATH_SEC0, 0,
   ARRAY_SIZE(rx_int_dem_inp_mux_text),
   rx_int_dem_inp_mux_text);

static const struct soc_enum rx_int2_dem_inp_mux_enum =
 SOC_ENUM_SINGLE(WCD9335_CDC_RX2_RX_PATH_SEC0, 0,
   ARRAY_SIZE(rx_int_dem_inp_mux_text),
   rx_int_dem_inp_mux_text);

static const struct soc_enum rx_int0_interp_mux_enum =
 SOC_ENUM_SINGLE(WCD9335_CDC_RX0_RX_PATH_CTL, 5, 2,
   rx_int0_interp_mux_text);

static const struct soc_enum rx_int1_interp_mux_enum =
 SOC_ENUM_SINGLE(WCD9335_CDC_RX1_RX_PATH_CTL, 5, 2,
   rx_int1_interp_mux_text);

static const struct soc_enum rx_int2_interp_mux_enum =
 SOC_ENUM_SINGLE(WCD9335_CDC_RX2_RX_PATH_CTL, 5, 2,
   rx_int2_interp_mux_text);

static const struct soc_enum rx_int3_interp_mux_enum =
 SOC_ENUM_SINGLE(WCD9335_CDC_RX3_RX_PATH_CTL, 5, 2,
   rx_int3_interp_mux_text);

static const struct soc_enum rx_int4_interp_mux_enum =
 SOC_ENUM_SINGLE(WCD9335_CDC_RX4_RX_PATH_CTL, 5, 2,
   rx_int4_interp_mux_text);

static const struct soc_enum rx_int5_interp_mux_enum =
 SOC_ENUM_SINGLE(WCD9335_CDC_RX5_RX_PATH_CTL, 5, 2,
   rx_int5_interp_mux_text);

static const struct soc_enum rx_int6_interp_mux_enum =
 SOC_ENUM_SINGLE(WCD9335_CDC_RX6_RX_PATH_CTL, 5, 2,
   rx_int6_interp_mux_text);

static const struct soc_enum rx_int7_interp_mux_enum =
 SOC_ENUM_SINGLE(WCD9335_CDC_RX7_RX_PATH_CTL, 5, 2,
   rx_int7_interp_mux_text);

static const struct soc_enum rx_int8_interp_mux_enum =
 SOC_ENUM_SINGLE(WCD9335_CDC_RX8_RX_PATH_CTL, 5, 2,
   rx_int8_interp_mux_text);

static const struct soc_enum tx_adc_mux0_chain_enum =
 SOC_ENUM_SINGLE(WCD9335_CDC_TX_INP_MUX_ADC_MUX0_CFG1, 0, 4,
   adc_mux_text);

static const struct soc_enum tx_adc_mux1_chain_enum =
 SOC_ENUM_SINGLE(WCD9335_CDC_TX_INP_MUX_ADC_MUX1_CFG1, 0, 4,
   adc_mux_text);

static const struct soc_enum tx_adc_mux2_chain_enum =
 SOC_ENUM_SINGLE(WCD9335_CDC_TX_INP_MUX_ADC_MUX2_CFG1, 0, 4,
   adc_mux_text);

static const struct soc_enum tx_adc_mux3_chain_enum =
 SOC_ENUM_SINGLE(WCD9335_CDC_TX_INP_MUX_ADC_MUX3_CFG1, 0, 4,
   adc_mux_text);

static const struct soc_enum tx_adc_mux4_chain_enum =
 SOC_ENUM_SINGLE(WCD9335_CDC_TX_INP_MUX_ADC_MUX4_CFG0, 6, 4,
   adc_mux_text);

static const struct soc_enum tx_adc_mux5_chain_enum =
 SOC_ENUM_SINGLE(WCD9335_CDC_TX_INP_MUX_ADC_MUX5_CFG0, 6, 4,
   adc_mux_text);

static const struct soc_enum tx_adc_mux6_chain_enum =
 SOC_ENUM_SINGLE(WCD9335_CDC_TX_INP_MUX_ADC_MUX6_CFG0, 6, 4,
   adc_mux_text);

static const struct soc_enum tx_adc_mux7_chain_enum =
 SOC_ENUM_SINGLE(WCD9335_CDC_TX_INP_MUX_ADC_MUX7_CFG0, 6, 4,
   adc_mux_text);

static const struct soc_enum tx_adc_mux8_chain_enum =
 SOC_ENUM_SINGLE(WCD9335_CDC_TX_INP_MUX_ADC_MUX8_CFG0, 6, 4,
   adc_mux_text);

static const struct soc_enum tx_dmic_mux0_enum =
 SOC_ENUM_SINGLE(WCD9335_CDC_TX_INP_MUX_ADC_MUX0_CFG0, 3, 11,
   dmic_mux_text);

static const struct soc_enum tx_dmic_mux1_enum =
 SOC_ENUM_SINGLE(WCD9335_CDC_TX_INP_MUX_ADC_MUX1_CFG0, 3, 11,
   dmic_mux_text);

static const struct soc_enum tx_dmic_mux2_enum =
 SOC_ENUM_SINGLE(WCD9335_CDC_TX_INP_MUX_ADC_MUX2_CFG0, 3, 11,
   dmic_mux_text);

static const struct soc_enum tx_dmic_mux3_enum =
 SOC_ENUM_SINGLE(WCD9335_CDC_TX_INP_MUX_ADC_MUX3_CFG0, 3, 11,
   dmic_mux_text);

static const struct soc_enum tx_dmic_mux4_enum =
 SOC_ENUM_SINGLE(WCD9335_CDC_TX_INP_MUX_ADC_MUX4_CFG0, 3, 7,
   dmic_mux_alt_text);

static const struct soc_enum tx_dmic_mux5_enum =
 SOC_ENUM_SINGLE(WCD9335_CDC_TX_INP_MUX_ADC_MUX5_CFG0, 3, 7,
   dmic_mux_alt_text);

static const struct soc_enum tx_dmic_mux6_enum =
 SOC_ENUM_SINGLE(WCD9335_CDC_TX_INP_MUX_ADC_MUX6_CFG0, 3, 7,
   dmic_mux_alt_text);

static const struct soc_enum tx_dmic_mux7_enum =
 SOC_ENUM_SINGLE(WCD9335_CDC_TX_INP_MUX_ADC_MUX7_CFG0, 3, 7,
   dmic_mux_alt_text);

static const struct soc_enum tx_dmic_mux8_enum =
 SOC_ENUM_SINGLE(WCD9335_CDC_TX_INP_MUX_ADC_MUX8_CFG0, 3, 7,
   dmic_mux_alt_text);

static const struct soc_enum tx_amic_mux0_enum =
 SOC_ENUM_SINGLE(WCD9335_CDC_TX_INP_MUX_ADC_MUX0_CFG0, 0, 7,
   amic_mux_text);

static const struct soc_enum tx_amic_mux1_enum =
 SOC_ENUM_SINGLE(WCD9335_CDC_TX_INP_MUX_ADC_MUX1_CFG0, 0, 7,
   amic_mux_text);

static const struct soc_enum tx_amic_mux2_enum =
 SOC_ENUM_SINGLE(WCD9335_CDC_TX_INP_MUX_ADC_MUX2_CFG0, 0, 7,
   amic_mux_text);

static const struct soc_enum tx_amic_mux3_enum =
 SOC_ENUM_SINGLE(WCD9335_CDC_TX_INP_MUX_ADC_MUX3_CFG0, 0, 7,
   amic_mux_text);

static const struct soc_enum tx_amic_mux4_enum =
 SOC_ENUM_SINGLE(WCD9335_CDC_TX_INP_MUX_ADC_MUX4_CFG0, 0, 7,
   amic_mux_text);

static const struct soc_enum tx_amic_mux5_enum =
 SOC_ENUM_SINGLE(WCD9335_CDC_TX_INP_MUX_ADC_MUX5_CFG0, 0, 7,
   amic_mux_text);

static const struct soc_enum tx_amic_mux6_enum =
 SOC_ENUM_SINGLE(WCD9335_CDC_TX_INP_MUX_ADC_MUX6_CFG0, 0, 7,
   amic_mux_text);

static const struct soc_enum tx_amic_mux7_enum =
 SOC_ENUM_SINGLE(WCD9335_CDC_TX_INP_MUX_ADC_MUX7_CFG0, 0, 7,
   amic_mux_text);

static const struct soc_enum tx_amic_mux8_enum =
 SOC_ENUM_SINGLE(WCD9335_CDC_TX_INP_MUX_ADC_MUX8_CFG0, 0, 7,
   amic_mux_text);

static const struct soc_enum sb_tx0_mux_enum =
 SOC_ENUM_SINGLE(WCD9335_CDC_IF_ROUTER_TX_MUX_CFG0, 0, 4,
   sb_tx0_mux_text);

static const struct soc_enum sb_tx1_mux_enum =
 SOC_ENUM_SINGLE(WCD9335_CDC_IF_ROUTER_TX_MUX_CFG0, 2, 4,
   sb_tx1_mux_text);

static const struct soc_enum sb_tx2_mux_enum =
 SOC_ENUM_SINGLE(WCD9335_CDC_IF_ROUTER_TX_MUX_CFG0, 4, 4,
   sb_tx2_mux_text);

static const struct soc_enum sb_tx3_mux_enum =
 SOC_ENUM_SINGLE(WCD9335_CDC_IF_ROUTER_TX_MUX_CFG0, 6, 4,
   sb_tx3_mux_text);

static const struct soc_enum sb_tx4_mux_enum =
 SOC_ENUM_SINGLE(WCD9335_CDC_IF_ROUTER_TX_MUX_CFG1, 0, 4,
   sb_tx4_mux_text);

static const struct soc_enum sb_tx5_mux_enum =
 SOC_ENUM_SINGLE(WCD9335_CDC_IF_ROUTER_TX_MUX_CFG1, 2, 4,
   sb_tx5_mux_text);

static const struct soc_enum sb_tx6_mux_enum =
 SOC_ENUM_SINGLE(WCD9335_CDC_IF_ROUTER_TX_MUX_CFG1, 4, 4,
   sb_tx6_mux_text);

static const struct soc_enum sb_tx7_mux_enum =
 SOC_ENUM_SINGLE(WCD9335_CDC_IF_ROUTER_TX_MUX_CFG1, 6, 4,
   sb_tx7_mux_text);

static const struct soc_enum sb_tx8_mux_enum =
 SOC_ENUM_SINGLE(WCD9335_CDC_IF_ROUTER_TX_MUX_CFG2, 0, 4,
   sb_tx8_mux_text);

static const struct snd_kcontrol_new rx_int0_2_mux =
 SOC_DAPM_ENUM("RX INT0_2 MUX Mux", rx_int0_2_mux_chain_enum);

static const struct snd_kcontrol_new rx_int1_2_mux =
 SOC_DAPM_ENUM("RX INT1_2 MUX Mux", rx_int1_2_mux_chain_enum);

static const struct snd_kcontrol_new rx_int2_2_mux =
 SOC_DAPM_ENUM("RX INT2_2 MUX Mux", rx_int2_2_mux_chain_enum);

static const struct snd_kcontrol_new rx_int3_2_mux =
 SOC_DAPM_ENUM("RX INT3_2 MUX Mux", rx_int3_2_mux_chain_enum);

static const struct snd_kcontrol_new rx_int4_2_mux =
 SOC_DAPM_ENUM("RX INT4_2 MUX Mux", rx_int4_2_mux_chain_enum);

static const struct snd_kcontrol_new rx_int5_2_mux =
 SOC_DAPM_ENUM("RX INT5_2 MUX Mux", rx_int5_2_mux_chain_enum);

static const struct snd_kcontrol_new rx_int6_2_mux =
 SOC_DAPM_ENUM("RX INT6_2 MUX Mux", rx_int6_2_mux_chain_enum);

static const struct snd_kcontrol_new rx_int7_2_mux =
 SOC_DAPM_ENUM("RX INT7_2 MUX Mux", rx_int7_2_mux_chain_enum);

static const struct snd_kcontrol_new rx_int8_2_mux =
 SOC_DAPM_ENUM("RX INT8_2 MUX Mux", rx_int8_2_mux_chain_enum);

static const struct snd_kcontrol_new rx_int0_1_mix_inp0_mux =
 SOC_DAPM_ENUM("RX INT0_1 MIX1 INP0 Mux", rx_int0_1_mix_inp0_chain_enum);

static const struct snd_kcontrol_new rx_int0_1_mix_inp1_mux =
 SOC_DAPM_ENUM("RX INT0_1 MIX1 INP1 Mux", rx_int0_1_mix_inp1_chain_enum);

static const struct snd_kcontrol_new rx_int0_1_mix_inp2_mux =
 SOC_DAPM_ENUM("RX INT0_1 MIX1 INP2 Mux", rx_int0_1_mix_inp2_chain_enum);

static const struct snd_kcontrol_new rx_int1_1_mix_inp0_mux =
 SOC_DAPM_ENUM("RX INT1_1 MIX1 INP0 Mux", rx_int1_1_mix_inp0_chain_enum);

static const struct snd_kcontrol_new rx_int1_1_mix_inp1_mux =
 SOC_DAPM_ENUM("RX INT1_1 MIX1 INP1 Mux", rx_int1_1_mix_inp1_chain_enum);

static const struct snd_kcontrol_new rx_int1_1_mix_inp2_mux =
 SOC_DAPM_ENUM("RX INT1_1 MIX1 INP2 Mux", rx_int1_1_mix_inp2_chain_enum);

static const struct snd_kcontrol_new rx_int2_1_mix_inp0_mux =
 SOC_DAPM_ENUM("RX INT2_1 MIX1 INP0 Mux", rx_int2_1_mix_inp0_chain_enum);

static const struct snd_kcontrol_new rx_int2_1_mix_inp1_mux =
 SOC_DAPM_ENUM("RX INT2_1 MIX1 INP1 Mux", rx_int2_1_mix_inp1_chain_enum);

static const struct snd_kcontrol_new rx_int2_1_mix_inp2_mux =
 SOC_DAPM_ENUM("RX INT2_1 MIX1 INP2 Mux", rx_int2_1_mix_inp2_chain_enum);

static const struct snd_kcontrol_new rx_int3_1_mix_inp0_mux =
 SOC_DAPM_ENUM("RX INT3_1 MIX1 INP0 Mux", rx_int3_1_mix_inp0_chain_enum);

static const struct snd_kcontrol_new rx_int3_1_mix_inp1_mux =
 SOC_DAPM_ENUM("RX INT3_1 MIX1 INP1 Mux", rx_int3_1_mix_inp1_chain_enum);

static const struct snd_kcontrol_new rx_int3_1_mix_inp2_mux =
 SOC_DAPM_ENUM("RX INT3_1 MIX1 INP2 Mux", rx_int3_1_mix_inp2_chain_enum);

static const struct snd_kcontrol_new rx_int4_1_mix_inp0_mux =
 SOC_DAPM_ENUM("RX INT4_1 MIX1 INP0 Mux", rx_int4_1_mix_inp0_chain_enum);

static const struct snd_kcontrol_new rx_int4_1_mix_inp1_mux =
 SOC_DAPM_ENUM("RX INT4_1 MIX1 INP1 Mux", rx_int4_1_mix_inp1_chain_enum);

static const struct snd_kcontrol_new rx_int4_1_mix_inp2_mux =
 SOC_DAPM_ENUM("RX INT4_1 MIX1 INP2 Mux", rx_int4_1_mix_inp2_chain_enum);

static const struct snd_kcontrol_new rx_int5_1_mix_inp0_mux =
 SOC_DAPM_ENUM("RX INT5_1 MIX1 INP0 Mux", rx_int5_1_mix_inp0_chain_enum);

static const struct snd_kcontrol_new rx_int5_1_mix_inp1_mux =
 SOC_DAPM_ENUM("RX INT5_1 MIX1 INP1 Mux", rx_int5_1_mix_inp1_chain_enum);

static const struct snd_kcontrol_new rx_int5_1_mix_inp2_mux =
 SOC_DAPM_ENUM("RX INT5_1 MIX1 INP2 Mux", rx_int5_1_mix_inp2_chain_enum);

static const struct snd_kcontrol_new rx_int6_1_mix_inp0_mux =
 SOC_DAPM_ENUM("RX INT6_1 MIX1 INP0 Mux", rx_int6_1_mix_inp0_chain_enum);

static const struct snd_kcontrol_new rx_int6_1_mix_inp1_mux =
 SOC_DAPM_ENUM("RX INT6_1 MIX1 INP1 Mux", rx_int6_1_mix_inp1_chain_enum);

static const struct snd_kcontrol_new rx_int6_1_mix_inp2_mux =
 SOC_DAPM_ENUM("RX INT6_1 MIX1 INP2 Mux", rx_int6_1_mix_inp2_chain_enum);

static const struct snd_kcontrol_new rx_int7_1_mix_inp0_mux =
 SOC_DAPM_ENUM("RX INT7_1 MIX1 INP0 Mux", rx_int7_1_mix_inp0_chain_enum);

static const struct snd_kcontrol_new rx_int7_1_mix_inp1_mux =
 SOC_DAPM_ENUM("RX INT7_1 MIX1 INP1 Mux", rx_int7_1_mix_inp1_chain_enum);

static const struct snd_kcontrol_new rx_int7_1_mix_inp2_mux =
 SOC_DAPM_ENUM("RX INT7_1 MIX1 INP2 Mux", rx_int7_1_mix_inp2_chain_enum);

static const struct snd_kcontrol_new rx_int8_1_mix_inp0_mux =
 SOC_DAPM_ENUM("RX INT8_1 MIX1 INP0 Mux", rx_int8_1_mix_inp0_chain_enum);

static const struct snd_kcontrol_new rx_int8_1_mix_inp1_mux =
 SOC_DAPM_ENUM("RX INT8_1 MIX1 INP1 Mux", rx_int8_1_mix_inp1_chain_enum);

static const struct snd_kcontrol_new rx_int8_1_mix_inp2_mux =
 SOC_DAPM_ENUM("RX INT8_1 MIX1 INP2 Mux", rx_int8_1_mix_inp2_chain_enum);

static const struct snd_kcontrol_new rx_int0_interp_mux =
 SOC_DAPM_ENUM("RX INT0 INTERP Mux", rx_int0_interp_mux_enum);

static const struct snd_kcontrol_new rx_int1_interp_mux =
 SOC_DAPM_ENUM("RX INT1 INTERP Mux", rx_int1_interp_mux_enum);

static const struct snd_kcontrol_new rx_int2_interp_mux =
 SOC_DAPM_ENUM("RX INT2 INTERP Mux", rx_int2_interp_mux_enum);

static const struct snd_kcontrol_new rx_int3_interp_mux =
 SOC_DAPM_ENUM("RX INT3 INTERP Mux", rx_int3_interp_mux_enum);

static const struct snd_kcontrol_new rx_int4_interp_mux =
 SOC_DAPM_ENUM("RX INT4 INTERP Mux", rx_int4_interp_mux_enum);

static const struct snd_kcontrol_new rx_int5_interp_mux =
 SOC_DAPM_ENUM("RX INT5 INTERP Mux", rx_int5_interp_mux_enum);

static const struct snd_kcontrol_new rx_int6_interp_mux =
 SOC_DAPM_ENUM("RX INT6 INTERP Mux", rx_int6_interp_mux_enum);

static const struct snd_kcontrol_new rx_int7_interp_mux =
 SOC_DAPM_ENUM("RX INT7 INTERP Mux", rx_int7_interp_mux_enum);

static const struct snd_kcontrol_new rx_int8_interp_mux =
 SOC_DAPM_ENUM("RX INT8 INTERP Mux", rx_int8_interp_mux_enum);

static const struct snd_kcontrol_new tx_dmic_mux0 =
 SOC_DAPM_ENUM("DMIC MUX0 Mux", tx_dmic_mux0_enum);

static const struct snd_kcontrol_new tx_dmic_mux1 =
 SOC_DAPM_ENUM("DMIC MUX1 Mux", tx_dmic_mux1_enum);

static const struct snd_kcontrol_new tx_dmic_mux2 =
 SOC_DAPM_ENUM("DMIC MUX2 Mux", tx_dmic_mux2_enum);

static const struct snd_kcontrol_new tx_dmic_mux3 =
 SOC_DAPM_ENUM("DMIC MUX3 Mux", tx_dmic_mux3_enum);

static const struct snd_kcontrol_new tx_dmic_mux4 =
 SOC_DAPM_ENUM("DMIC MUX4 Mux", tx_dmic_mux4_enum);

static const struct snd_kcontrol_new tx_dmic_mux5 =
 SOC_DAPM_ENUM("DMIC MUX5 Mux", tx_dmic_mux5_enum);

static const struct snd_kcontrol_new tx_dmic_mux6 =
 SOC_DAPM_ENUM("DMIC MUX6 Mux", tx_dmic_mux6_enum);

static const struct snd_kcontrol_new tx_dmic_mux7 =
 SOC_DAPM_ENUM("DMIC MUX7 Mux", tx_dmic_mux7_enum);

static const struct snd_kcontrol_new tx_dmic_mux8 =
 SOC_DAPM_ENUM("DMIC MUX8 Mux", tx_dmic_mux8_enum);

static const struct snd_kcontrol_new tx_amic_mux0 =
 SOC_DAPM_ENUM("AMIC MUX0 Mux", tx_amic_mux0_enum);

static const struct snd_kcontrol_new tx_amic_mux1 =
 SOC_DAPM_ENUM("AMIC MUX1 Mux", tx_amic_mux1_enum);

static const struct snd_kcontrol_new tx_amic_mux2 =
 SOC_DAPM_ENUM("AMIC MUX2 Mux", tx_amic_mux2_enum);

static const struct snd_kcontrol_new tx_amic_mux3 =
 SOC_DAPM_ENUM("AMIC MUX3 Mux", tx_amic_mux3_enum);

static const struct snd_kcontrol_new tx_amic_mux4 =
 SOC_DAPM_ENUM("AMIC MUX4 Mux", tx_amic_mux4_enum);

static const struct snd_kcontrol_new tx_amic_mux5 =
 SOC_DAPM_ENUM("AMIC MUX5 Mux", tx_amic_mux5_enum);

static const struct snd_kcontrol_new tx_amic_mux6 =
 SOC_DAPM_ENUM("AMIC MUX6 Mux", tx_amic_mux6_enum);

static const struct snd_kcontrol_new tx_amic_mux7 =
 SOC_DAPM_ENUM("AMIC MUX7 Mux", tx_amic_mux7_enum);

static const struct snd_kcontrol_new tx_amic_mux8 =
 SOC_DAPM_ENUM("AMIC MUX8 Mux", tx_amic_mux8_enum);

static const struct snd_kcontrol_new sb_tx0_mux =
 SOC_DAPM_ENUM("SLIM TX0 MUX Mux", sb_tx0_mux_enum);

static const struct snd_kcontrol_new sb_tx1_mux =
 SOC_DAPM_ENUM("SLIM TX1 MUX Mux", sb_tx1_mux_enum);

static const struct snd_kcontrol_new sb_tx2_mux =
 SOC_DAPM_ENUM("SLIM TX2 MUX Mux", sb_tx2_mux_enum);

static const struct snd_kcontrol_new sb_tx3_mux =
 SOC_DAPM_ENUM("SLIM TX3 MUX Mux", sb_tx3_mux_enum);

static const struct snd_kcontrol_new sb_tx4_mux =
 SOC_DAPM_ENUM("SLIM TX4 MUX Mux", sb_tx4_mux_enum);

static const struct snd_kcontrol_new sb_tx5_mux =
 SOC_DAPM_ENUM("SLIM TX5 MUX Mux", sb_tx5_mux_enum);

static const struct snd_kcontrol_new sb_tx6_mux =
 SOC_DAPM_ENUM("SLIM TX6 MUX Mux", sb_tx6_mux_enum);

static const struct snd_kcontrol_new sb_tx7_mux =
 SOC_DAPM_ENUM("SLIM TX7 MUX Mux", sb_tx7_mux_enum);

static const struct snd_kcontrol_new sb_tx8_mux =
 SOC_DAPM_ENUM("SLIM TX8 MUX Mux", sb_tx8_mux_enum);

static int slim_rx_mux_get(struct snd_kcontrol *kc,
      struct snd_ctl_elem_value *ucontrol)
{
 struct snd_soc_dapm_widget *w = snd_soc_dapm_kcontrol_widget(kc);
 struct wcd9335_codec *wcd = dev_get_drvdata(w->dapm->dev);
 u32 port_id = w->shift;

 ucontrol->value.enumerated.item[0] = wcd->rx_port_value[port_id];

 return 0;
}

static int slim_rx_mux_put(struct snd_kcontrol *kc,
      struct snd_ctl_elem_value *ucontrol)
{
 struct snd_soc_dapm_widget *w = snd_soc_dapm_kcontrol_widget(kc);
 struct wcd9335_codec *wcd = dev_get_drvdata(w->dapm->dev);
 struct soc_enum *e = (struct soc_enum *)kc->private_value;
 struct snd_soc_dapm_update *update = NULL;
 u32 port_id = w->shift;

 if (wcd->rx_port_value[port_id] == ucontrol->value.enumerated.item[0])
  return 0;

 wcd->rx_port_value[port_id] = ucontrol->value.enumerated.item[0];

 /* Remove channel from any list it's in before adding it to a new one */
 list_del_init(&wcd->rx_chs[port_id].list);

 switch (wcd->rx_port_value[port_id]) {
 case 0:
  /* Channel already removed from lists. Nothing to do here */
  break;
 case 1:
  list_add_tail(&wcd->rx_chs[port_id].list,
         &wcd->dai[AIF1_PB].slim_ch_list);
  break;
 case 2:
  list_add_tail(&wcd->rx_chs[port_id].list,
         &wcd->dai[AIF2_PB].slim_ch_list);
  break;
 case 3:
  list_add_tail(&wcd->rx_chs[port_id].list,
         &wcd->dai[AIF3_PB].slim_ch_list);
  break;
 case 4:
  list_add_tail(&wcd->rx_chs[port_id].list,
         &wcd->dai[AIF4_PB].slim_ch_list);
  break;
 default:
  dev_err(wcd->dev, "Unknown AIF %d\n", wcd->rx_port_value[port_id]);
  goto err;
 }

 snd_soc_dapm_mux_update_power(w->dapm, kc, wcd->rx_port_value[port_id],
          e, update);

 return 0;
err:
 return -EINVAL;
}

static int slim_tx_mixer_get(struct snd_kcontrol *kc,
        struct snd_ctl_elem_value *ucontrol)
{

 struct snd_soc_dapm_context *dapm = snd_soc_dapm_kcontrol_dapm(kc);
 struct wcd9335_codec *wcd = dev_get_drvdata(dapm->dev);
 struct snd_soc_dapm_widget *widget = snd_soc_dapm_kcontrol_widget(kc);
 struct soc_mixer_control *mixer =
   (struct soc_mixer_control *)kc->private_value;
 int dai_id = widget->shift;
 int port_id = mixer->shift;

 ucontrol->value.integer.value[0] = wcd->tx_port_value[port_id] == dai_id;

 return 0;
}

static int slim_tx_mixer_put(struct snd_kcontrol *kc,
        struct snd_ctl_elem_value *ucontrol)
{

 struct snd_soc_dapm_widget *widget = snd_soc_dapm_kcontrol_widget(kc);
 struct wcd9335_codec *wcd = dev_get_drvdata(widget->dapm->dev);
 struct snd_soc_dapm_update *update = NULL;
 struct soc_mixer_control *mixer =
   (struct soc_mixer_control *)kc->private_value;
 int enable = ucontrol->value.integer.value[0];
 int dai_id = widget->shift;
 int port_id = mixer->shift;

 switch (dai_id) {
 case AIF1_CAP:
 case AIF2_CAP:
 case AIF3_CAP:
  /* only add to the list if value not set */
  if (enable && wcd->tx_port_value[port_id] != dai_id) {
   wcd->tx_port_value[port_id] = dai_id;
   list_add_tail(&wcd->tx_chs[port_id].list,
     &wcd->dai[dai_id].slim_ch_list);
  } else if (!enable && wcd->tx_port_value[port_id] == dai_id) {
   wcd->tx_port_value[port_id] = -1;
   list_del_init(&wcd->tx_chs[port_id].list);
  }
  break;
 default:
  dev_err(wcd->dev, "Unknown AIF %d\n", dai_id);
  return -EINVAL;
 }

 snd_soc_dapm_mixer_update_power(widget->dapm, kc, enable, update);

 return 0;
}

static const struct snd_kcontrol_new slim_rx_mux[WCD9335_RX_MAX] = {
 SOC_DAPM_ENUM_EXT("SLIM RX0 Mux", slim_rx_mux_enum,
     slim_rx_mux_get, slim_rx_mux_put),
 SOC_DAPM_ENUM_EXT("SLIM RX1 Mux", slim_rx_mux_enum,
     slim_rx_mux_get, slim_rx_mux_put),
 SOC_DAPM_ENUM_EXT("SLIM RX2 Mux", slim_rx_mux_enum,
     slim_rx_mux_get, slim_rx_mux_put),
 SOC_DAPM_ENUM_EXT("SLIM RX3 Mux", slim_rx_mux_enum,
     slim_rx_mux_get, slim_rx_mux_put),
 SOC_DAPM_ENUM_EXT("SLIM RX4 Mux", slim_rx_mux_enum,
     slim_rx_mux_get, slim_rx_mux_put),
 SOC_DAPM_ENUM_EXT("SLIM RX5 Mux", slim_rx_mux_enum,
     slim_rx_mux_get, slim_rx_mux_put),
 SOC_DAPM_ENUM_EXT("SLIM RX6 Mux", slim_rx_mux_enum,
     slim_rx_mux_get, slim_rx_mux_put),
 SOC_DAPM_ENUM_EXT("SLIM RX7 Mux", slim_rx_mux_enum,
     slim_rx_mux_get, slim_rx_mux_put),
};

static const struct snd_kcontrol_new aif1_cap_mixer[] = {
 SOC_SINGLE_EXT("SLIM TX0", SND_SOC_NOPM, WCD9335_TX0, 1, 0,
   slim_tx_mixer_get, slim_tx_mixer_put),
 SOC_SINGLE_EXT("SLIM TX1", SND_SOC_NOPM, WCD9335_TX1, 1, 0,
   slim_tx_mixer_get, slim_tx_mixer_put),
 SOC_SINGLE_EXT("SLIM TX2", SND_SOC_NOPM, WCD9335_TX2, 1, 0,
   slim_tx_mixer_get, slim_tx_mixer_put),
 SOC_SINGLE_EXT("SLIM TX3", SND_SOC_NOPM, WCD9335_TX3, 1, 0,
   slim_tx_mixer_get, slim_tx_mixer_put),
 SOC_SINGLE_EXT("SLIM TX4", SND_SOC_NOPM, WCD9335_TX4, 1, 0,
   slim_tx_mixer_get, slim_tx_mixer_put),
 SOC_SINGLE_EXT("SLIM TX5", SND_SOC_NOPM, WCD9335_TX5, 1, 0,
   slim_tx_mixer_get, slim_tx_mixer_put),
 SOC_SINGLE_EXT("SLIM TX6", SND_SOC_NOPM, WCD9335_TX6, 1, 0,
   slim_tx_mixer_get, slim_tx_mixer_put),
 SOC_SINGLE_EXT("SLIM TX7", SND_SOC_NOPM, WCD9335_TX7, 1, 0,
   slim_tx_mixer_get, slim_tx_mixer_put),
 SOC_SINGLE_EXT("SLIM TX8", SND_SOC_NOPM, WCD9335_TX8, 1, 0,
   slim_tx_mixer_get, slim_tx_mixer_put),
 SOC_SINGLE_EXT("SLIM TX9", SND_SOC_NOPM, WCD9335_TX9, 1, 0,
   slim_tx_mixer_get, slim_tx_mixer_put),
 SOC_SINGLE_EXT("SLIM TX10", SND_SOC_NOPM, WCD9335_TX10, 1, 0,
   slim_tx_mixer_get, slim_tx_mixer_put),
 SOC_SINGLE_EXT("SLIM TX11", SND_SOC_NOPM, WCD9335_TX11, 1, 0,
   slim_tx_mixer_get, slim_tx_mixer_put),
 SOC_SINGLE_EXT("SLIM TX13", SND_SOC_NOPM, WCD9335_TX13, 1, 0,
   slim_tx_mixer_get, slim_tx_mixer_put),
};

static const struct snd_kcontrol_new aif2_cap_mixer[] = {
 SOC_SINGLE_EXT("SLIM TX0", SND_SOC_NOPM, WCD9335_TX0, 1, 0,
   slim_tx_mixer_get, slim_tx_mixer_put),
 SOC_SINGLE_EXT("SLIM TX1", SND_SOC_NOPM, WCD9335_TX1, 1, 0,
   slim_tx_mixer_get, slim_tx_mixer_put),
 SOC_SINGLE_EXT("SLIM TX2", SND_SOC_NOPM, WCD9335_TX2, 1, 0,
   slim_tx_mixer_get, slim_tx_mixer_put),
 SOC_SINGLE_EXT("SLIM TX3", SND_SOC_NOPM, WCD9335_TX3, 1, 0,
   slim_tx_mixer_get, slim_tx_mixer_put),
 SOC_SINGLE_EXT("SLIM TX4", SND_SOC_NOPM, WCD9335_TX4, 1, 0,
   slim_tx_mixer_get, slim_tx_mixer_put),
 SOC_SINGLE_EXT("SLIM TX5", SND_SOC_NOPM, WCD9335_TX5, 1, 0,
   slim_tx_mixer_get, slim_tx_mixer_put),
 SOC_SINGLE_EXT("SLIM TX6", SND_SOC_NOPM, WCD9335_TX6, 1, 0,
   slim_tx_mixer_get, slim_tx_mixer_put),
 SOC_SINGLE_EXT("SLIM TX7", SND_SOC_NOPM, WCD9335_TX7, 1, 0,
   slim_tx_mixer_get, slim_tx_mixer_put),
 SOC_SINGLE_EXT("SLIM TX8", SND_SOC_NOPM, WCD9335_TX8, 1, 0,
   slim_tx_mixer_get, slim_tx_mixer_put),
 SOC_SINGLE_EXT("SLIM TX9", SND_SOC_NOPM, WCD9335_TX9, 1, 0,
   slim_tx_mixer_get, slim_tx_mixer_put),
 SOC_SINGLE_EXT("SLIM TX10", SND_SOC_NOPM, WCD9335_TX10, 1, 0,
   slim_tx_mixer_get, slim_tx_mixer_put),
 SOC_SINGLE_EXT("SLIM TX11", SND_SOC_NOPM, WCD9335_TX11, 1, 0,
   slim_tx_mixer_get, slim_tx_mixer_put),
 SOC_SINGLE_EXT("SLIM TX13", SND_SOC_NOPM, WCD9335_TX13, 1, 0,
   slim_tx_mixer_get, slim_tx_mixer_put),
};

static const struct snd_kcontrol_new aif3_cap_mixer[] = {
 SOC_SINGLE_EXT("SLIM TX0", SND_SOC_NOPM, WCD9335_TX0, 1, 0,
   slim_tx_mixer_get, slim_tx_mixer_put),
 SOC_SINGLE_EXT("SLIM TX1", SND_SOC_NOPM, WCD9335_TX1, 1, 0,
   slim_tx_mixer_get, slim_tx_mixer_put),
 SOC_SINGLE_EXT("SLIM TX2", SND_SOC_NOPM, WCD9335_TX2, 1, 0,
   slim_tx_mixer_get, slim_tx_mixer_put),
 SOC_SINGLE_EXT("SLIM TX3", SND_SOC_NOPM, WCD9335_TX3, 1, 0,
   slim_tx_mixer_get, slim_tx_mixer_put),
 SOC_SINGLE_EXT("SLIM TX4", SND_SOC_NOPM, WCD9335_TX4, 1, 0,
   slim_tx_mixer_get, slim_tx_mixer_put),
 SOC_SINGLE_EXT("SLIM TX5", SND_SOC_NOPM, WCD9335_TX5, 1, 0,
   slim_tx_mixer_get, slim_tx_mixer_put),
 SOC_SINGLE_EXT("SLIM TX6", SND_SOC_NOPM, WCD9335_TX6, 1, 0,
   slim_tx_mixer_get, slim_tx_mixer_put),
 SOC_SINGLE_EXT("SLIM TX7", SND_SOC_NOPM, WCD9335_TX7, 1, 0,
   slim_tx_mixer_get, slim_tx_mixer_put),
 SOC_SINGLE_EXT("SLIM TX8", SND_SOC_NOPM, WCD9335_TX8, 1, 0,
   slim_tx_mixer_get, slim_tx_mixer_put),
};

static int wcd9335_put_dec_enum(struct snd_kcontrol *kc,
    struct snd_ctl_elem_value *ucontrol)
{
 struct snd_soc_dapm_context *dapm = snd_soc_dapm_kcontrol_dapm(kc);
 struct snd_soc_component *component = snd_soc_dapm_to_component(dapm);
 struct soc_enum *e = (struct soc_enum *)kc->private_value;
 unsigned int val, reg, sel;

 val = ucontrol->value.enumerated.item[0];

 switch (e->reg) {
 case WCD9335_CDC_TX_INP_MUX_ADC_MUX0_CFG1:
  reg = WCD9335_CDC_TX0_TX_PATH_CFG0;
  break;
 case WCD9335_CDC_TX_INP_MUX_ADC_MUX1_CFG1:
  reg = WCD9335_CDC_TX1_TX_PATH_CFG0;
  break;
 case WCD9335_CDC_TX_INP_MUX_ADC_MUX2_CFG1:
  reg = WCD9335_CDC_TX2_TX_PATH_CFG0;
  break;
 case WCD9335_CDC_TX_INP_MUX_ADC_MUX3_CFG1:
  reg = WCD9335_CDC_TX3_TX_PATH_CFG0;
  break;
 case WCD9335_CDC_TX_INP_MUX_ADC_MUX4_CFG0:
  reg = WCD9335_CDC_TX4_TX_PATH_CFG0;
  break;
 case WCD9335_CDC_TX_INP_MUX_ADC_MUX5_CFG0:
  reg = WCD9335_CDC_TX5_TX_PATH_CFG0;
  break;
 case WCD9335_CDC_TX_INP_MUX_ADC_MUX6_CFG0:
  reg = WCD9335_CDC_TX6_TX_PATH_CFG0;
  break;
 case WCD9335_CDC_TX_INP_MUX_ADC_MUX7_CFG0:
  reg = WCD9335_CDC_TX7_TX_PATH_CFG0;
  break;
 case WCD9335_CDC_TX_INP_MUX_ADC_MUX8_CFG0:
  reg = WCD9335_CDC_TX8_TX_PATH_CFG0;
  break;
 default:
  return -EINVAL;
 }

 /* AMIC: 0, DMIC: 1 */
 sel = val ? WCD9335_CDC_TX_ADC_AMIC_SEL : WCD9335_CDC_TX_ADC_DMIC_SEL;
 snd_soc_component_update_bits(component, reg,
          WCD9335_CDC_TX_ADC_AMIC_DMIC_SEL_MASK,
          sel);

 return snd_soc_dapm_put_enum_double(kc, ucontrol);
}

static int wcd9335_int_dem_inp_mux_put(struct snd_kcontrol *kc,
     struct snd_ctl_elem_value *ucontrol)
{
 struct soc_enum *e = (struct soc_enum *)kc->private_value;
 struct snd_soc_component *component;
 int reg, val;

 component = snd_soc_dapm_kcontrol_component(kc);
 val = ucontrol->value.enumerated.item[0];

 if (e->reg == WCD9335_CDC_RX0_RX_PATH_SEC0)
  reg = WCD9335_CDC_RX0_RX_PATH_CFG0;
 else if (e->reg == WCD9335_CDC_RX1_RX_PATH_SEC0)
  reg = WCD9335_CDC_RX1_RX_PATH_CFG0;
 else if (e->reg == WCD9335_CDC_RX2_RX_PATH_SEC0)
  reg = WCD9335_CDC_RX2_RX_PATH_CFG0;
 else
  return -EINVAL;

 /* Set Look Ahead Delay */
 snd_soc_component_update_bits(component, reg,
    WCD9335_CDC_RX_PATH_CFG0_DLY_ZN_EN_MASK,
    val ? WCD9335_CDC_RX_PATH_CFG0_DLY_ZN_EN : 0);
 /* Set DEM INP Select */
 return snd_soc_dapm_put_enum_double(kc, ucontrol);
}

static const struct snd_kcontrol_new rx_int0_dem_inp_mux =
 SOC_DAPM_ENUM_EXT("RX INT0 DEM MUX Mux", rx_int0_dem_inp_mux_enum,
     snd_soc_dapm_get_enum_double,
     wcd9335_int_dem_inp_mux_put);

static const struct snd_kcontrol_new rx_int1_dem_inp_mux =
 SOC_DAPM_ENUM_EXT("RX INT1 DEM MUX Mux", rx_int1_dem_inp_mux_enum,
     snd_soc_dapm_get_enum_double,
     wcd9335_int_dem_inp_mux_put);

static const struct snd_kcontrol_new rx_int2_dem_inp_mux =
 SOC_DAPM_ENUM_EXT("RX INT2 DEM MUX Mux", rx_int2_dem_inp_mux_enum,
     snd_soc_dapm_get_enum_double,
     wcd9335_int_dem_inp_mux_put);

static const struct snd_kcontrol_new tx_adc_mux0 =
 SOC_DAPM_ENUM_EXT("ADC MUX0 Mux", tx_adc_mux0_chain_enum,
     snd_soc_dapm_get_enum_double,
     wcd9335_put_dec_enum);

static const struct snd_kcontrol_new tx_adc_mux1 =
 SOC_DAPM_ENUM_EXT("ADC MUX1 Mux", tx_adc_mux1_chain_enum,
     snd_soc_dapm_get_enum_double,
     wcd9335_put_dec_enum);

static const struct snd_kcontrol_new tx_adc_mux2 =
 SOC_DAPM_ENUM_EXT("ADC MUX2 Mux", tx_adc_mux2_chain_enum,
     snd_soc_dapm_get_enum_double,
     wcd9335_put_dec_enum);

static const struct snd_kcontrol_new tx_adc_mux3 =
 SOC_DAPM_ENUM_EXT("ADC MUX3 Mux", tx_adc_mux3_chain_enum,
     snd_soc_dapm_get_enum_double,
     wcd9335_put_dec_enum);

static const struct snd_kcontrol_new tx_adc_mux4 =
 SOC_DAPM_ENUM_EXT("ADC MUX4 Mux", tx_adc_mux4_chain_enum,
     snd_soc_dapm_get_enum_double,
     wcd9335_put_dec_enum);

static const struct snd_kcontrol_new tx_adc_mux5 =
 SOC_DAPM_ENUM_EXT("ADC MUX5 Mux", tx_adc_mux5_chain_enum,
     snd_soc_dapm_get_enum_double,
     wcd9335_put_dec_enum);

static const struct snd_kcontrol_new tx_adc_mux6 =
 SOC_DAPM_ENUM_EXT("ADC MUX6 Mux", tx_adc_mux6_chain_enum,
     snd_soc_dapm_get_enum_double,
     wcd9335_put_dec_enum);

static const struct snd_kcontrol_new tx_adc_mux7 =
 SOC_DAPM_ENUM_EXT("ADC MUX7 Mux", tx_adc_mux7_chain_enum,
     snd_soc_dapm_get_enum_double,
     wcd9335_put_dec_enum);

static const struct snd_kcontrol_new tx_adc_mux8 =
 SOC_DAPM_ENUM_EXT("ADC MUX8 Mux", tx_adc_mux8_chain_enum,
     snd_soc_dapm_get_enum_double,
     wcd9335_put_dec_enum);

static int wcd9335_set_mix_interpolator_rate(struct snd_soc_dai *dai,
          int rate_val,
          u32 rate)
{
 struct snd_soc_component *component = dai->component;
 struct wcd9335_codec *wcd = dev_get_drvdata(component->dev);
 struct wcd9335_slim_ch *ch;
 int val, j;

 list_for_each_entry(ch, &wcd->dai[dai->id].slim_ch_list, list) {
  for (j = 0; j < WCD9335_NUM_INTERPOLATORS; j++) {
   val = snd_soc_component_read(component,
     WCD9335_CDC_RX_INP_MUX_RX_INT_CFG1(j)) &
     WCD9335_CDC_RX_INP_MUX_RX_INT_SEL_MASK;

   if (val == (ch->shift + INTn_2_INP_SEL_RX0))
    snd_soc_component_update_bits(component,
      WCD9335_CDC_RX_PATH_MIX_CTL(j),
      WCD9335_CDC_MIX_PCM_RATE_MASK,
      rate_val);
  }
 }

 return 0;
}

static int wcd9335_set_prim_interpolator_rate(struct snd_soc_dai *dai,
           u8 rate_val,
           u32 rate)
{
 struct snd_soc_component *comp = dai->component;
 struct wcd9335_codec *wcd = dev_get_drvdata(comp->dev);
 struct wcd9335_slim_ch *ch;
 u8 cfg0, cfg1, inp0_sel, inp1_sel, inp2_sel;
 int inp, j;

 list_for_each_entry(ch, &wcd->dai[dai->id].slim_ch_list, list) {
  inp = ch->shift + INTn_1_MIX_INP_SEL_RX0;
  /*
 * Loop through all interpolator MUX inputs and find out
 * to which interpolator input, the slim rx port
 * is connected
 */

  for (j = 0; j < WCD9335_NUM_INTERPOLATORS; j++) {
   cfg0 = snd_soc_component_read(comp,
     WCD9335_CDC_RX_INP_MUX_RX_INT_CFG0(j));
   cfg1 = snd_soc_component_read(comp,
     WCD9335_CDC_RX_INP_MUX_RX_INT_CFG1(j));

   inp0_sel = cfg0 &
     WCD9335_CDC_RX_INP_MUX_RX_INT_SEL_MASK;
   inp1_sel = (cfg0 >> 4) &
     WCD9335_CDC_RX_INP_MUX_RX_INT_SEL_MASK;
   inp2_sel = (cfg1 >> 4) &
     WCD9335_CDC_RX_INP_MUX_RX_INT_SEL_MASK;

   if ((inp0_sel == inp) ||  (inp1_sel == inp) ||
       (inp2_sel == inp)) {
    /* rate is in Hz */
    if ((j == 0) && (rate == 44100))
     dev_info(wcd->dev,
      "Cannot set 44.1KHz on INT0\n");
    else
     snd_soc_component_update_bits(comp,
      WCD9335_CDC_RX_PATH_CTL(j),
      WCD9335_CDC_MIX_PCM_RATE_MASK,
      rate_val);
   }
  }
 }

 return 0;
}

static int wcd9335_set_interpolator_rate(struct snd_soc_dai *dai, u32 rate)
{
 int i;

 /* set mixing path rate */
 for (i = 0; i < ARRAY_SIZE(int_mix_rate_val); i++) {
  if (rate == int_mix_rate_val[i].rate) {
   wcd9335_set_mix_interpolator_rate(dai,
     int_mix_rate_val[i].rate_val, rate);
   break;
  }
 }

 /* set primary path sample rate */
 for (i = 0; i < ARRAY_SIZE(int_prim_rate_val); i++) {
  if (rate == int_prim_rate_val[i].rate) {
   wcd9335_set_prim_interpolator_rate(dai,
     int_prim_rate_val[i].rate_val, rate);
   break;
  }
 }

 return 0;
}

static int wcd9335_slim_set_hw_params(struct wcd9335_codec *wcd,
     struct wcd_slim_codec_dai_data *dai_data,
     int direction)
{
 struct list_head *slim_ch_list = &dai_data->slim_ch_list;
 struct slim_stream_config *cfg = &dai_data->sconfig;
 struct wcd9335_slim_ch *ch;
 u16 payload = 0;
 int ret, i;

 cfg->ch_count = 0;
 cfg->direction = direction;
 cfg->port_mask = 0;

 /* Configure slave interface device */
 list_for_each_entry(ch, slim_ch_list, list) {
  cfg->ch_count++;
  payload |= 1 << ch->shift;
  cfg->port_mask |= BIT(ch->port);
 }

 cfg->chs = kcalloc(cfg->ch_count, sizeof(unsigned int), GFP_KERNEL);
 if (!cfg->chs)
  return -ENOMEM;

 i = 0;
 list_for_each_entry(ch, slim_ch_list, list) {
  cfg->chs[i++] = ch->ch_num;
  if (direction == SNDRV_PCM_STREAM_PLAYBACK) {
   /* write to interface device */
   ret = regmap_write(wcd->if_regmap,
    WCD9335_SLIM_PGD_RX_PORT_MULTI_CHNL_0(ch->port),
    payload);

   if (ret < 0)
    goto err;

   /* configure the slave port for water mark and enable*/
   ret = regmap_write(wcd->if_regmap,
     WCD9335_SLIM_PGD_RX_PORT_CFG(ch->port),
     WCD9335_SLIM_WATER_MARK_VAL);
   if (ret < 0)
    goto err;
  } else {
   ret = regmap_write(wcd->if_regmap,
    WCD9335_SLIM_PGD_TX_PORT_MULTI_CHNL_0(ch->port),
    payload & 0x00FF);
   if (ret < 0)
    goto err;

   /* ports 8,9 */
   ret = regmap_write(wcd->if_regmap,
    WCD9335_SLIM_PGD_TX_PORT_MULTI_CHNL_1(ch->port),
    (payload & 0xFF00)>>8);
   if (ret < 0)
    goto err;

   /* configure the slave port for water mark and enable*/
   ret = regmap_write(wcd->if_regmap,
     WCD9335_SLIM_PGD_TX_PORT_CFG(ch->port),
     WCD9335_SLIM_WATER_MARK_VAL);

   if (ret < 0)
    goto err;
  }
 }

 dai_data->sruntime = slim_stream_allocate(wcd->slim, "WCD9335-SLIM");

 return 0;

err:
 dev_err(wcd->dev, "Error Setting slim hw params\n");
 kfree(cfg->chs);
 cfg->chs = NULL;

 return ret;
}

static int wcd9335_set_decimator_rate(struct snd_soc_dai *dai,
          u8 rate_val, u32 rate)
{
 struct snd_soc_component *comp = dai->component;
 struct wcd9335_codec *wcd = snd_soc_component_get_drvdata(comp);
 u8 shift = 0, shift_val = 0, tx_mux_sel;
 struct wcd9335_slim_ch *ch;
 int tx_port, tx_port_reg;
 int decimator = -1;

 list_for_each_entry(ch, &wcd->dai[dai->id].slim_ch_list, list) {
  tx_port = ch->port;
  if ((tx_port == 12) || (tx_port >= 14)) {
   dev_err(wcd->dev, "Invalid SLIM TX%u port DAI ID:%d\n",
    tx_port, dai->id);
   return -EINVAL;
  }
  /* Find the SB TX MUX input - which decimator is connected */
  if (tx_port < 4) {
   tx_port_reg = WCD9335_CDC_IF_ROUTER_TX_MUX_CFG0;
   shift = (tx_port << 1);
   shift_val = 0x03;
  } else if (tx_port < 8) {
   tx_port_reg = WCD9335_CDC_IF_ROUTER_TX_MUX_CFG1;
   shift = ((tx_port - 4) << 1);
   shift_val = 0x03;
  } else if (tx_port < 11) {
   tx_port_reg = WCD9335_CDC_IF_ROUTER_TX_MUX_CFG2;
   shift = ((tx_port - 8) << 1);
   shift_val = 0x03;
  } else if (tx_port == 11) {
   tx_port_reg = WCD9335_CDC_IF_ROUTER_TX_MUX_CFG3;
   shift = 0;
   shift_val = 0x0F;
  } else /* (tx_port == 13) */ {
   tx_port_reg = WCD9335_CDC_IF_ROUTER_TX_MUX_CFG3;
   shift = 4;
   shift_val = 0x03;
  }

  tx_mux_sel = snd_soc_component_read(comp, tx_port_reg) &
            (shift_val << shift);

  tx_mux_sel = tx_mux_sel >> shift;
  if (tx_port <= 8) {
   if ((tx_mux_sel == 0x2) || (tx_mux_sel == 0x3))
    decimator = tx_port;
  } else if (tx_port <= 10) {
   if ((tx_mux_sel == 0x1) || (tx_mux_sel == 0x2))
    decimator = ((tx_port == 9) ? 7 : 6);
  } else if (tx_port == 11) {
   if ((tx_mux_sel >= 1) && (tx_mux_sel < 7))
    decimator = tx_mux_sel - 1;
  } else if (tx_port == 13) {
   if ((tx_mux_sel == 0x1) || (tx_mux_sel == 0x2))
    decimator = 5;
  }

  if (decimator >= 0) {
   snd_soc_component_update_bits(comp,
     WCD9335_CDC_TX_PATH_CTL(decimator),
     WCD9335_CDC_TX_PATH_CTL_PCM_RATE_MASK,
     rate_val);
  } else if ((tx_port <= 8) && (tx_mux_sel == 0x01)) {
   /* Check if the TX Mux input is RX MIX TXn */
   dev_err(wcd->dev, "RX_MIX_TX%u going to SLIM TX%u\n",
    tx_port, tx_port);
  } else {
   dev_err(wcd->dev, "ERROR: Invalid decimator: %d\n",
    decimator);
   return -EINVAL;
  }
 }

 return 0;
}

static int wcd9335_hw_params(struct snd_pcm_substream *substream,
      struct snd_pcm_hw_params *params,
      struct snd_soc_dai *dai)
{
 struct wcd9335_codec *wcd;
 int ret, tx_fs_rate = 0;

 wcd = snd_soc_component_get_drvdata(dai->component);

 switch (substream->stream) {
 case SNDRV_PCM_STREAM_PLAYBACK:
  ret = wcd9335_set_interpolator_rate(dai, params_rate(params));
  if (ret) {
   dev_err(wcd->dev, "cannot set sample rate: %u\n",
    params_rate(params));
   return ret;
  }
  switch (params_width(params)) {
  case 16 ... 24:
   wcd->dai[dai->id].sconfig.bps = params_width(params);
   break;
  default:
   dev_err(wcd->dev, "%s: Invalid format 0x%x\n",
    __func__, params_width(params));
   return -EINVAL;
  }
  break;

 case SNDRV_PCM_STREAM_CAPTURE:
  switch (params_rate(params)) {
  case 8000:
   tx_fs_rate = 0;
   break;
  case 16000:
   tx_fs_rate = 1;
   break;
  case 32000:
   tx_fs_rate = 3;
   break;
  case 48000:
   tx_fs_rate = 4;
   break;
  case 96000:
   tx_fs_rate = 5;
   break;
  case 192000:
   tx_fs_rate = 6;
   break;
  case 384000:
   tx_fs_rate = 7;
   break;
  default:
   dev_err(wcd->dev, "%s: Invalid TX sample rate: %d\n",
    __func__, params_rate(params));
   return -EINVAL;

  }

  ret = wcd9335_set_decimator_rate(dai, tx_fs_rate,
      params_rate(params));
  if (ret < 0) {
   dev_err(wcd->dev, "Cannot set TX Decimator rate\n");
   return ret;
  }
  switch (params_width(params)) {
  case 16 ... 32:
   wcd->dai[dai->id].sconfig.bps = params_width(params);
   break;
  default:
   dev_err(wcd->dev, "%s: Invalid format 0x%x\n",
    __func__, params_width(params));
   return -EINVAL;
  }
  break;
 default:
  dev_err(wcd->dev, "Invalid stream type %d\n",
   substream->stream);
  return -EINVAL;
 }

 wcd->dai[dai->id].sconfig.rate = params_rate(params);
 wcd9335_slim_set_hw_params(wcd, &wcd->dai[dai->id], substream->stream);

 return 0;
}

static int wcd9335_trigger(struct snd_pcm_substream *substream, int cmd,
      struct snd_soc_dai *dai)
{
 struct wcd_slim_codec_dai_data *dai_data;
 struct wcd9335_codec *wcd;
 struct slim_stream_config *cfg;

 wcd = snd_soc_component_get_drvdata(dai->component);

 dai_data = &wcd->dai[dai->id];

 switch (cmd) {
 case SNDRV_PCM_TRIGGER_START:
 case SNDRV_PCM_TRIGGER_RESUME:
 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
  cfg = &dai_data->sconfig;
  slim_stream_prepare(dai_data->sruntime, cfg);
  slim_stream_enable(dai_data->sruntime);
  break;
 case SNDRV_PCM_TRIGGER_STOP:
 case SNDRV_PCM_TRIGGER_SUSPEND:
 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
  slim_stream_disable(dai_data->sruntime);
  slim_stream_unprepare(dai_data->sruntime);
  break;
 default:
  break;
 }

 return 0;
}

static int wcd9335_set_channel_map(struct snd_soc_dai *dai,
       unsigned int tx_num,
       const unsigned int *tx_slot,
       unsigned int rx_num,
       const unsigned int *rx_slot)
{
 struct wcd9335_codec *wcd;
 int i;

 wcd = snd_soc_component_get_drvdata(dai->component);

 if (!tx_slot || !rx_slot) {
  dev_err(wcd->dev, "Invalid tx_slot=%p, rx_slot=%p\n",
   tx_slot, rx_slot);
  return -EINVAL;
 }

 wcd->num_rx_port = rx_num;
 for (i = 0; i < rx_num; i++) {
  wcd->rx_chs[i].ch_num = rx_slot[i];
  INIT_LIST_HEAD(&wcd->rx_chs[i].list);
 }

 wcd->num_tx_port = tx_num;
 for (i = 0; i < tx_num; i++) {
  wcd->tx_chs[i].ch_num = tx_slot[i];
  INIT_LIST_HEAD(&wcd->tx_chs[i].list);
 }

 return 0;
}

static int wcd9335_get_channel_map(const struct snd_soc_dai *dai,
       unsigned int *tx_num, unsigned int *tx_slot,
       unsigned int *rx_num, unsigned int *rx_slot)
{
 struct wcd9335_slim_ch *ch;
 struct wcd9335_codec *wcd;
 int i = 0;

 wcd = snd_soc_component_get_drvdata(dai->component);

 switch (dai->id) {
 case AIF1_PB:
 case AIF2_PB:
 case AIF3_PB:
 case AIF4_PB:
  if (!rx_slot || !rx_num) {
   dev_err(wcd->dev, "Invalid rx_slot %p or rx_num %p\n",
    rx_slot, rx_num);
   return -EINVAL;
  }

  list_for_each_entry(ch, &wcd->dai[dai->id].slim_ch_list, list)
   rx_slot[i++] = ch->ch_num;

  *rx_num = i;
  break;
 case AIF1_CAP:
 case AIF2_CAP:
 case AIF3_CAP:
  if (!tx_slot || !tx_num) {
   dev_err(wcd->dev, "Invalid tx_slot %p or tx_num %p\n",
    tx_slot, tx_num);
   return -EINVAL;
  }
  list_for_each_entry(ch, &wcd->dai[dai->id].slim_ch_list, list)
   tx_slot[i++] = ch->ch_num;

  *tx_num = i;
  break;
 default:
  dev_err(wcd->dev, "Invalid DAI ID %x\n", dai->id);
  break;
 }

 return 0;
}

static const struct snd_soc_dai_ops wcd9335_dai_ops = {
 .hw_params = wcd9335_hw_params,
 .trigger = wcd9335_trigger,
 .set_channel_map = wcd9335_set_channel_map,
 .get_channel_map = wcd9335_get_channel_map,
};

static struct snd_soc_dai_driver wcd9335_slim_dais[] = {
 [0] = {
  .name = "wcd9335_rx1",
  .id = AIF1_PB,
  .playback = {
   .stream_name = "AIF1 Playback",
   .rates = WCD9335_RATES_MASK | WCD9335_FRAC_RATES_MASK |
     SNDRV_PCM_RATE_384000,
   .formats = WCD9335_FORMATS_S16_S24_LE,
   .rate_max = 384000,
   .rate_min = 8000,
   .channels_min = 1,
   .channels_max = 2,
  },
  .ops = &wcd9335_dai_ops,
 },
 [1] = {
  .name = "wcd9335_tx1",
  .id = AIF1_CAP,
  .capture = {
   .stream_name = "AIF1 Capture",
   .rates = WCD9335_RATES_MASK,
   .formats = SNDRV_PCM_FMTBIT_S16_LE,
   .rate_min = 8000,
   .rate_max = 192000,
   .channels_min = 1,
   .channels_max = 4,
  },
  .ops = &wcd9335_dai_ops,
 },
 [2] = {
  .name = "wcd9335_rx2",
  .id = AIF2_PB,
  .playback = {
   .stream_name = "AIF2 Playback",
   .rates = WCD9335_RATES_MASK | WCD9335_FRAC_RATES_MASK |
     SNDRV_PCM_RATE_384000,
   .formats = WCD9335_FORMATS_S16_S24_LE,
   .rate_min = 8000,
   .rate_max = 384000,
   .channels_min = 1,
   .channels_max = 2,
  },
  .ops = &wcd9335_dai_ops,
 },
 [3] = {
  .name = "wcd9335_tx2",
--> --------------------

--> maximum size reached

--> --------------------

Messung V0.5
C=92 H=98 G=94

¤ Dauer der Verarbeitung: 0.27 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Produkte
     Quellcodebibliothek

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....

Besucherstatistik

Besucherstatistik

Monitoring

Montastic status badge