Quellcodebibliothek Statistik Leitseite products/sources/formale Sprachen/C/Linux/sound/soc/codecs/   (Open Source Betriebssystem Version 6.17.9©)  Datei vom 24.10.2025 mit Größe 190 kB image not shown  

Quelle  wcd934x.c   Sprache: C

 
// SPDX-License-Identifier: GPL-2.0
// Copyright (c) 2019, Linaro Limited

#include <linux/cleanup.h>
#include <linux/clk.h>
#include <linux/clk-provider.h>
#include <linux/interrupt.h>
#include <linux/kernel.h>
#include <linux/mfd/wcd934x/registers.h>
#include <linux/mfd/wcd934x/wcd934x.h>
#include <linux/module.h>
#include <linux/mutex.h>
#include <linux/of_clk.h>
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/regmap.h>
#include <linux/slab.h>
#include <linux/slimbus.h>
#include <sound/pcm_params.h>
#include <sound/soc.h>
#include <sound/soc-dapm.h>
#include <sound/tlv.h>
#include "wcd-clsh-v2.h"
#include "wcd-mbhc-v2.h"

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

#define WCD934X_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 WCD934X_FRAC_RATES_MASK (SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_88200 |\
     SNDRV_PCM_RATE_176400)
#define WCD934X_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 WCD934X_SLIM_WATER_MARK_VAL \
 ((SLAVE_PORT_WATER_MARK_12BYTES << SLAVE_PORT_WATER_MARK_SHIFT) | \
  (SLAVE_PORT_ENABLE))

#define WCD934X_SLIM_NUM_PORT_REG 3
#define WCD934X_SLIM_PGD_PORT_INT_TX_EN0 (WCD934X_SLIM_PGD_PORT_INT_EN0 + 2)
#define WCD934X_SLIM_IRQ_OVERFLOW BIT(0)
#define WCD934X_SLIM_IRQ_UNDERFLOW BIT(1)
#define WCD934X_SLIM_IRQ_PORT_CLOSED BIT(2)

#define WCD934X_MCLK_CLK_12P288MHZ 12288000
#define WCD934X_MCLK_CLK_9P6MHZ  9600000

/* Only valid for 9.6 MHz mclk */
#define WCD9XXX_DMIC_SAMPLE_RATE_2P4MHZ 2400000
#define WCD9XXX_DMIC_SAMPLE_RATE_4P8MHZ 4800000

/* Only valid for 12.288 MHz mclk */
#define WCD9XXX_DMIC_SAMPLE_RATE_4P096MHZ 4096000

#define WCD934X_DMIC_CLK_DIV_2  0x0
#define WCD934X_DMIC_CLK_DIV_3  0x1
#define WCD934X_DMIC_CLK_DIV_4  0x2
#define WCD934X_DMIC_CLK_DIV_6  0x3
#define WCD934X_DMIC_CLK_DIV_8  0x4
#define WCD934X_DMIC_CLK_DIV_16  0x5
#define WCD934X_DMIC_CLK_DRIVE_DEFAULT 0x02

#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 WCD934X_RX_START  16
#define WCD934X_NUM_INTERPOLATORS 9
#define WCD934X_RX_PATH_CTL_OFFSET 20
#define WCD934X_MAX_VALID_ADC_MUX 13
#define WCD934X_INVALID_ADC_MUX  9

#define WCD934X_SLIM_RX_CH(p) \
 {.port = p + WCD934X_RX_START, .shift = p,}

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

/* Feature masks to distinguish codec version */
#define DSD_DISABLED_MASK   0
#define SLNQ_DISABLED_MASK  1

#define DSD_DISABLED   BIT(DSD_DISABLED_MASK)
#define SLNQ_DISABLED  BIT(SLNQ_DISABLED_MASK)

/* As fine version info cannot be retrieved before wcd probe.
 * Define three coarse versions for possible future use before wcd probe.
 */

#define WCD_VERSION_WCD9340_1_0     0x400
#define WCD_VERSION_WCD9341_1_0     0x410
#define WCD_VERSION_WCD9340_1_1     0x401
#define WCD_VERSION_WCD9341_1_1     0x411
#define WCD934X_AMIC_PWR_LEVEL_LP 0
#define WCD934X_AMIC_PWR_LEVEL_DEFAULT 1
#define WCD934X_AMIC_PWR_LEVEL_HP 2
#define WCD934X_AMIC_PWR_LEVEL_HYBRID 3
#define WCD934X_AMIC_PWR_LVL_MASK 0x60
#define WCD934X_AMIC_PWR_LVL_SHIFT 0x5

#define WCD934X_DEC_PWR_LVL_MASK 0x06
#define WCD934X_DEC_PWR_LVL_LP  0x02
#define WCD934X_DEC_PWR_LVL_HP  0x04
#define WCD934X_DEC_PWR_LVL_DF  0x00
#define WCD934X_DEC_PWR_LVL_HYBRID WCD934X_DEC_PWR_LVL_DF

#define WCD934X_DEF_MICBIAS_MV 1800
#define WCD934X_MAX_MICBIAS_MV 2850

#define WCD_IIR_FILTER_SIZE (sizeof(u32) * BAND_MAX)

#define WCD_IIR_FILTER_CTL(xname, iidx, bidx) \
{ \
 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
 .info = wcd934x_iir_filter_info, \
 .get = wcd934x_get_iir_band_audio_mixer, \
 .put = wcd934x_put_iir_band_audio_mixer, \
 .private_value = (unsigned long)&(struct wcd_iir_filter_ctl) { \
  .iir_idx = iidx, \
  .band_idx = bidx, \
  .bytes_ext = {.max = WCD_IIR_FILTER_SIZE, }, \
 } \
}

/* Z value defined in milliohm */
#define WCD934X_ZDET_VAL_32             32000
#define WCD934X_ZDET_VAL_400            400000
#define WCD934X_ZDET_VAL_1200           1200000
#define WCD934X_ZDET_VAL_100K           100000000
/* Z floating defined in ohms */
#define WCD934X_ZDET_FLOATING_IMPEDANCE 0x0FFFFFFE

#define WCD934X_ZDET_NUM_MEASUREMENTS   900
#define WCD934X_MBHC_GET_C1(c)          ((c & 0xC000) >> 14)
#define WCD934X_MBHC_GET_X1(x)          (x & 0x3FFF)
/* Z value compared in milliOhm */
#define WCD934X_MBHC_IS_SECOND_RAMP_REQUIRED(z) ((z > 400000) || (z < 32000))
#define WCD934X_MBHC_ZDET_CONST         (86 * 16384)
#define WCD934X_MBHC_MOISTURE_RREF      R_24_KOHM
#define WCD934X_MBHC_MAX_BUTTONS (8)
#define WCD_MBHC_HS_V_MAX           1600

#define WCD934X_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 INP0""IIR0""IIR0"}, \
 {"RX INT" #id "_1 MIX1 INP0""IIR1""IIR1"}, \
 {"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 INP1""IIR0""IIR0"}, \
 {"RX INT" #id "_1 MIX1 INP1""IIR1""IIR1"}, \
 {"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 "_1 MIX1 INP2""IIR0""IIR0"},  \
 {"RX INT" #id "_1 MIX1 INP2""IIR1""IIR1"},  \
 {"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 "_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 "_2 MUX", NULL, "INT" #id "_CLK"}, \
 {"RX INT" #id "_2 MUX", NULL, "DSMDEM" #id "_CLK"}, \
 {"RX INT" #id "_2 INTERP", NULL, "RX INT" #id "_2 MUX"}, \
 {"RX INT" #id " SEC MIX", NULL, "RX INT" #id "_2 INTERP"}, \
 {"RX INT" #id "_1 INTERP", NULL, "RX INT" #id "_1 MIX1"}, \
 {"RX INT" #id "_1 INTERP", NULL, "INT" #id "_CLK"}, \
 {"RX INT" #id "_1 INTERP", NULL, "DSMDEM" #id "_CLK"}, \
 {"RX INT" #id " SEC MIX", NULL, "RX INT" #id "_1 INTERP"}

#define WCD934X_INTERPOLATOR_MIX2(id)   \
 {"RX INT" #id " MIX2", NULL, "RX INT" #id " SEC MIX"}, \
 {"RX INT" #id " MIX2", NULL, "RX INT" #id " MIX2 INP"}

#define WCD934X_SLIM_RX_AIF_PATH(id) \
 {"SLIM RX"#id" MUX""AIF1_PB""AIF1 PB"}, \
 {"SLIM RX"#id" MUX""AIF2_PB""AIF2 PB"}, \
 {"SLIM RX"#id" MUX""AIF3_PB""AIF3 PB"}, \
 {"SLIM RX"#id" MUX""AIF4_PB""AIF4 PB"},   \
 {"SLIM RX"#id, NULL, "SLIM RX"#id" MUX"}

#define WCD934X_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"}

#define WCD934X_IIR_INP_MUX(id) \
 {"IIR" #id, NULL, "IIR" #id " INP0 MUX"}, \
 {"IIR" #id " INP0 MUX""DEC0""ADC MUX0"}, \
 {"IIR" #id " INP0 MUX""DEC1""ADC MUX1"}, \
 {"IIR" #id " INP0 MUX""DEC2""ADC MUX2"}, \
 {"IIR" #id " INP0 MUX""DEC3""ADC MUX3"}, \
 {"IIR" #id " INP0 MUX""DEC4""ADC MUX4"}, \
 {"IIR" #id " INP0 MUX""DEC5""ADC MUX5"}, \
 {"IIR" #id " INP0 MUX""DEC6""ADC MUX6"}, \
 {"IIR" #id " INP0 MUX""DEC7""ADC MUX7"}, \
 {"IIR" #id " INP0 MUX""DEC8""ADC MUX8"}, \
 {"IIR" #id " INP0 MUX""RX0""SLIM RX0"}, \
 {"IIR" #id " INP0 MUX""RX1""SLIM RX1"}, \
 {"IIR" #id " INP0 MUX""RX2""SLIM RX2"}, \
 {"IIR" #id " INP0 MUX""RX3""SLIM RX3"}, \
 {"IIR" #id " INP0 MUX""RX4""SLIM RX4"}, \
 {"IIR" #id " INP0 MUX""RX5""SLIM RX5"}, \
 {"IIR" #id " INP0 MUX""RX6""SLIM RX6"}, \
 {"IIR" #id " INP0 MUX""RX7""SLIM RX7"}, \
 {"IIR" #id, NULL, "IIR" #id " INP1 MUX"}, \
 {"IIR" #id " INP1 MUX""DEC0""ADC MUX0"}, \
 {"IIR" #id " INP1 MUX""DEC1""ADC MUX1"}, \
 {"IIR" #id " INP1 MUX""DEC2""ADC MUX2"}, \
 {"IIR" #id " INP1 MUX""DEC3""ADC MUX3"}, \
 {"IIR" #id " INP1 MUX""DEC4""ADC MUX4"}, \
 {"IIR" #id " INP1 MUX""DEC5""ADC MUX5"}, \
 {"IIR" #id " INP1 MUX""DEC6""ADC MUX6"}, \
 {"IIR" #id " INP1 MUX""DEC7""ADC MUX7"}, \
 {"IIR" #id " INP1 MUX""DEC8""ADC MUX8"}, \
 {"IIR" #id " INP1 MUX""RX0""SLIM RX0"}, \
 {"IIR" #id " INP1 MUX""RX1""SLIM RX1"}, \
 {"IIR" #id " INP1 MUX""RX2""SLIM RX2"}, \
 {"IIR" #id " INP1 MUX""RX3""SLIM RX3"}, \
 {"IIR" #id " INP1 MUX""RX4""SLIM RX4"}, \
 {"IIR" #id " INP1 MUX""RX5""SLIM RX5"}, \
 {"IIR" #id " INP1 MUX""RX6""SLIM RX6"}, \
 {"IIR" #id " INP1 MUX""RX7""SLIM RX7"}, \
 {"IIR" #id, NULL, "IIR" #id " INP2 MUX"}, \
 {"IIR" #id " INP2 MUX""DEC0""ADC MUX0"}, \
 {"IIR" #id " INP2 MUX""DEC1""ADC MUX1"}, \
 {"IIR" #id " INP2 MUX""DEC2""ADC MUX2"}, \
 {"IIR" #id " INP2 MUX""DEC3""ADC MUX3"}, \
 {"IIR" #id " INP2 MUX""DEC4""ADC MUX4"}, \
 {"IIR" #id " INP2 MUX""DEC5""ADC MUX5"}, \
 {"IIR" #id " INP2 MUX""DEC6""ADC MUX6"}, \
 {"IIR" #id " INP2 MUX""DEC7""ADC MUX7"}, \
 {"IIR" #id " INP2 MUX""DEC8""ADC MUX8"}, \
 {"IIR" #id " INP2 MUX""RX0""SLIM RX0"}, \
 {"IIR" #id " INP2 MUX""RX1""SLIM RX1"}, \
 {"IIR" #id " INP2 MUX""RX2""SLIM RX2"}, \
 {"IIR" #id " INP2 MUX""RX3""SLIM RX3"}, \
 {"IIR" #id " INP2 MUX""RX4""SLIM RX4"}, \
 {"IIR" #id " INP2 MUX""RX5""SLIM RX5"}, \
 {"IIR" #id " INP2 MUX""RX6""SLIM RX6"}, \
 {"IIR" #id " INP2 MUX""RX7""SLIM RX7"}, \
 {"IIR" #id, NULL, "IIR" #id " INP3 MUX"}, \
 {"IIR" #id " INP3 MUX""DEC0""ADC MUX0"}, \
 {"IIR" #id " INP3 MUX""DEC1""ADC MUX1"}, \
 {"IIR" #id " INP3 MUX""DEC2""ADC MUX2"}, \
 {"IIR" #id " INP3 MUX""DEC3""ADC MUX3"}, \
 {"IIR" #id " INP3 MUX""DEC4""ADC MUX4"}, \
 {"IIR" #id " INP3 MUX""DEC5""ADC MUX5"}, \
 {"IIR" #id " INP3 MUX""DEC6""ADC MUX6"}, \
 {"IIR" #id " INP3 MUX""DEC7""ADC MUX7"}, \
 {"IIR" #id " INP3 MUX""DEC8""ADC MUX8"}, \
 {"IIR" #id " INP3 MUX""RX0""SLIM RX0"}, \
 {"IIR" #id " INP3 MUX""RX1""SLIM RX1"}, \
 {"IIR" #id " INP3 MUX""RX2""SLIM RX2"}, \
 {"IIR" #id " INP3 MUX""RX3""SLIM RX3"}, \
 {"IIR" #id " INP3 MUX""RX4""SLIM RX4"}, \
 {"IIR" #id " INP3 MUX""RX5""SLIM RX5"}, \
 {"IIR" #id " INP3 MUX""RX6""SLIM RX6"}, \
 {"IIR" #id " INP3 MUX""RX7""SLIM RX7"}

#define WCD934X_SLIM_TX_AIF_PATH(id) \
 {"AIF1_CAP Mixer""SLIM TX" #id"SLIM TX" #id }, \
 {"AIF2_CAP Mixer""SLIM TX" #id"SLIM TX" #id }, \
 {"AIF3_CAP Mixer""SLIM TX" #id"SLIM TX" #id }, \
 {"SLIM TX" #id, NULL, "CDC_IF TX" #id " MUX"}

#define WCD934X_MAX_MICBIAS MIC_BIAS_4
#define NUM_CODEC_DAIS          9

enum {
 SIDO_SOURCE_INTERNAL,
 SIDO_SOURCE_RCO_BG,
};

enum {
 INTERP_EAR = 0,
 INTERP_HPHL,
 INTERP_HPHR,
 INTERP_LO1,
 INTERP_LO2,
 INTERP_LO3_NA, /* LO3 not avalible in Tavil */
 INTERP_LO4_NA,
 INTERP_SPKR1, /*INT7 WSA Speakers via soundwire */
 INTERP_SPKR2, /*INT8 WSA Speakers via soundwire */
 INTERP_MAX,
};

enum {
 WCD934X_RX0 = 0,
 WCD934X_RX1,
 WCD934X_RX2,
 WCD934X_RX3,
 WCD934X_RX4,
 WCD934X_RX5,
 WCD934X_RX6,
 WCD934X_RX7,
 WCD934X_RX8,
 WCD934X_RX9,
 WCD934X_RX10,
 WCD934X_RX11,
 WCD934X_RX12,
 WCD934X_RX_MAX,
};

enum {
 WCD934X_TX0 = 0,
 WCD934X_TX1,
 WCD934X_TX2,
 WCD934X_TX3,
 WCD934X_TX4,
 WCD934X_TX5,
 WCD934X_TX6,
 WCD934X_TX7,
 WCD934X_TX8,
 WCD934X_TX9,
 WCD934X_TX10,
 WCD934X_TX11,
 WCD934X_TX12,
 WCD934X_TX13,
 WCD934X_TX14,
 WCD934X_TX15,
 WCD934X_TX_MAX,
};

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

static const struct wcd934x_slim_ch wcd934x_tx_chs[WCD934X_TX_MAX] = {
 WCD934X_SLIM_TX_CH(0),
 WCD934X_SLIM_TX_CH(1),
 WCD934X_SLIM_TX_CH(2),
 WCD934X_SLIM_TX_CH(3),
 WCD934X_SLIM_TX_CH(4),
 WCD934X_SLIM_TX_CH(5),
 WCD934X_SLIM_TX_CH(6),
 WCD934X_SLIM_TX_CH(7),
 WCD934X_SLIM_TX_CH(8),
 WCD934X_SLIM_TX_CH(9),
 WCD934X_SLIM_TX_CH(10),
 WCD934X_SLIM_TX_CH(11),
 WCD934X_SLIM_TX_CH(12),
 WCD934X_SLIM_TX_CH(13),
 WCD934X_SLIM_TX_CH(14),
 WCD934X_SLIM_TX_CH(15),
};

static const struct wcd934x_slim_ch wcd934x_rx_chs[WCD934X_RX_MAX] = {
 WCD934X_SLIM_RX_CH(0),  /* 16 */
 WCD934X_SLIM_RX_CH(1),  /* 17 */
 WCD934X_SLIM_RX_CH(2),
 WCD934X_SLIM_RX_CH(3),
 WCD934X_SLIM_RX_CH(4),
 WCD934X_SLIM_RX_CH(5),
 WCD934X_SLIM_RX_CH(6),
 WCD934X_SLIM_RX_CH(7),
 WCD934X_SLIM_RX_CH(8),
 WCD934X_SLIM_RX_CH(9),
 WCD934X_SLIM_RX_CH(10),
 WCD934X_SLIM_RX_CH(11),
 WCD934X_SLIM_RX_CH(12),
};

/* Codec supports 2 IIR filters */
enum {
 IIR0 = 0,
 IIR1,
 IIR_MAX,
};

/* Each IIR has 5 Filter Stages */
enum {
 BAND1 = 0,
 BAND2,
 BAND3,
 BAND4,
 BAND5,
 BAND_MAX,
};

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

enum {
 INTn_1_INP_SEL_ZERO = 0,
 INTn_1_INP_SEL_DEC0,
 INTn_1_INP_SEL_DEC1,
 INTn_1_INP_SEL_IIR0,
 INTn_1_INP_SEL_IIR1,
 INTn_1_INP_SEL_RX0,
 INTn_1_INP_SEL_RX1,
 INTn_1_INP_SEL_RX2,
 INTn_1_INP_SEL_RX3,
 INTn_1_INP_SEL_RX4,
 INTn_1_INP_SEL_RX5,
 INTn_1_INP_SEL_RX6,
 INTn_1_INP_SEL_RX7,
};

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,
};

struct interp_sample_rate {
 int sample_rate;
 int rate_val;
};

static const struct interp_sample_rate sr_val_tbl[] = {
 {8000, 0x0},
 {16000, 0x1},
 {32000, 0x3},
 {48000, 0x4},
 {96000, 0x5},
 {192000, 0x6},
 {384000, 0x7},
 {44100, 0x9},
 {88200, 0xA},
 {176400, 0xB},
 {352800, 0xC},
};

struct wcd934x_mbhc_zdet_param {
 u16 ldo_ctl;
 u16 noff;
 u16 nshift;
 u16 btn5;
 u16 btn6;
 u16 btn7;
};

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

static const struct regmap_range_cfg wcd934x_ifc_ranges[] = {
 {
  .name = "WCD9335-IFC-DEV",
  .range_min =  0x0,
  .range_max = 0xffff,
  .selector_reg = 0x800,
  .selector_mask = 0xfff,
  .selector_shift = 0,
  .window_start = 0x800,
  .window_len = 0x400,
 },
};

static const struct regmap_config wcd934x_ifc_regmap_config = {
 .reg_bits = 16,
 .val_bits = 8,
 .max_register = 0xffff,
 .ranges = wcd934x_ifc_ranges,
 .num_ranges = ARRAY_SIZE(wcd934x_ifc_ranges),
};

struct wcd934x_codec {
 struct device *dev;
 struct clk_hw hw;
 struct clk *extclk;
 struct regmap *regmap;
 struct regmap *if_regmap;
 struct slim_device *sdev;
 struct slim_device *sidev;
 struct wcd_clsh_ctrl *clsh_ctrl;
 struct snd_soc_component *component;
 struct wcd934x_slim_ch rx_chs[WCD934X_RX_MAX];
 struct wcd934x_slim_ch tx_chs[WCD934X_TX_MAX];
 struct wcd_slim_codec_dai_data dai[NUM_CODEC_DAIS];
 int rate;
 u32 version;
 u32 hph_mode;
 u32 tx_port_value[WCD934X_TX_MAX];
 u32 rx_port_value[WCD934X_RX_MAX];
 int sido_input_src;
 int dmic_0_1_clk_cnt;
 int dmic_2_3_clk_cnt;
 int dmic_4_5_clk_cnt;
 int dmic_sample_rate;
 int comp_enabled[COMPANDER_MAX];
 int sysclk_users;
 struct mutex sysclk_mutex;
 /* mbhc module */
 struct wcd_mbhc *mbhc;
 struct wcd_mbhc_config mbhc_cfg;
 struct wcd_mbhc_intr intr_ids;
 bool mbhc_started;
 struct mutex micb_lock;
 u32 micb_ref[WCD934X_MAX_MICBIAS];
 u32 pullup_ref[WCD934X_MAX_MICBIAS];
 u32 micb2_mv;
};

#define to_wcd934x_codec(_hw) container_of(_hw, struct wcd934x_codec, hw)

struct wcd_iir_filter_ctl {
 unsigned int iir_idx;
 unsigned int band_idx;
 struct soc_bytes_ext bytes_ext;
};

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);

/* 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_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 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_sidetone_mix_text[] = {
 "ZERO""SRC0""SRC1""SRC_SUM"
};

static const char * const iir_inp_mux_text[] = {
 "ZERO""DEC0""DEC1""DEC2""DEC3""DEC4""DEC5""DEC6",
 "DEC7""DEC8""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_1_interp_mux_text[] = {
 "ZERO""RX INT0_1 MIX1",
};

static const char * const rx_int1_1_interp_mux_text[] = {
 "ZERO""RX INT1_1 MIX1",
};

static const char * const rx_int2_1_interp_mux_text[] = {
 "ZERO""RX INT2_1 MIX1",
};

static const char * const rx_int3_1_interp_mux_text[] = {
 "ZERO""RX INT3_1 MIX1",
};

static const char * const rx_int4_1_interp_mux_text[] = {
 "ZERO""RX INT4_1 MIX1",
};

static const char * const rx_int7_1_interp_mux_text[] = {
 "ZERO""RX INT7_1 MIX1",
};

static const char * const rx_int8_1_interp_mux_text[] = {
 "ZERO""RX INT8_1 MIX1",
};

static const char * const rx_int0_2_interp_mux_text[] = {
 "ZERO""RX INT0_2 MUX",
};

static const char * const rx_int1_2_interp_mux_text[] = {
 "ZERO""RX INT1_2 MUX",
};

static const char * const rx_int2_2_interp_mux_text[] = {
 "ZERO""RX INT2_2 MUX",
};

static const char * const rx_int3_2_interp_mux_text[] = {
 "ZERO""RX INT3_2 MUX",
};

static const char * const rx_int4_2_interp_mux_text[] = {
 "ZERO""RX INT4_2 MUX",
};

static const char * const rx_int7_2_interp_mux_text[] = {
 "ZERO""RX INT7_2 MUX",
};

static const char * const rx_int8_2_interp_mux_text[] = {
 "ZERO""RX INT8_2 MUX",
};

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

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

static const char * const amic4_5_sel_text[] = {
 "AMIC4""AMIC5"
};

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

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

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

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

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

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

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

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

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

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

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

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

static const char * const cdc_if_tx11_mux_text[] = {
 "DEC_0_5""DEC_9_12""MAD_AUDIO""MAD_BRDCST"
};

static const char * const cdc_if_tx11_inp1_mux_text[] = {
 "ZERO""DEC0""DEC1""DEC2""DEC3""DEC4",
 "DEC5""RX_MIX_TX5""DEC9_10""DEC11_12"
};

static const char * const cdc_if_tx13_mux_text[] = {
 "CDC_DEC_5""MAD_BRDCST"
};

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

static SOC_ENUM_SINGLE_DECL(cf_int8_2_enum, WCD934X_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(WCD934X_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(WCD934X_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(WCD934X_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(WCD934X_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(WCD934X_CDC_RX_INP_MUX_RX_INT4_CFG1, 0, 9,
   rx_int_mix_mux_text);

static const struct soc_enum rx_int7_2_mux_chain_enum =
 SOC_ENUM_SINGLE(WCD934X_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(WCD934X_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(WCD934X_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(WCD934X_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(WCD934X_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(WCD934X_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(WCD934X_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(WCD934X_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(WCD934X_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(WCD934X_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(WCD934X_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(WCD934X_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(WCD934X_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(WCD934X_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(WCD934X_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(WCD934X_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(WCD934X_CDC_RX_INP_MUX_RX_INT4_CFG1, 4, 13,
   rx_prim_mix_text);

static const struct soc_enum rx_int7_1_mix_inp0_chain_enum =
 SOC_ENUM_SINGLE(WCD934X_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(WCD934X_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(WCD934X_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(WCD934X_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(WCD934X_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(WCD934X_CDC_RX_INP_MUX_RX_INT8_CFG1, 4, 13,
   rx_prim_mix_text);

static const struct soc_enum rx_int0_mix2_inp_mux_enum =
 SOC_ENUM_SINGLE(WCD934X_CDC_RX_INP_MUX_SIDETONE_SRC_CFG0, 0, 4,
   rx_sidetone_mix_text);

static const struct soc_enum rx_int1_mix2_inp_mux_enum =
 SOC_ENUM_SINGLE(WCD934X_CDC_RX_INP_MUX_SIDETONE_SRC_CFG0, 2, 4,
   rx_sidetone_mix_text);

static const struct soc_enum rx_int2_mix2_inp_mux_enum =
 SOC_ENUM_SINGLE(WCD934X_CDC_RX_INP_MUX_SIDETONE_SRC_CFG0, 4, 4,
   rx_sidetone_mix_text);

static const struct soc_enum rx_int3_mix2_inp_mux_enum =
 SOC_ENUM_SINGLE(WCD934X_CDC_RX_INP_MUX_SIDETONE_SRC_CFG0, 6, 4,
   rx_sidetone_mix_text);

static const struct soc_enum rx_int4_mix2_inp_mux_enum =
 SOC_ENUM_SINGLE(WCD934X_CDC_RX_INP_MUX_SIDETONE_SRC_CFG1, 0, 4,
   rx_sidetone_mix_text);

static const struct soc_enum rx_int7_mix2_inp_mux_enum =
 SOC_ENUM_SINGLE(WCD934X_CDC_RX_INP_MUX_SIDETONE_SRC_CFG1, 2, 4,
   rx_sidetone_mix_text);

static const struct soc_enum iir0_inp0_mux_enum =
 SOC_ENUM_SINGLE(WCD934X_CDC_SIDETONE_IIR_INP_MUX_IIR0_MIX_CFG0,
   0, 18, iir_inp_mux_text);

static const struct soc_enum iir0_inp1_mux_enum =
 SOC_ENUM_SINGLE(WCD934X_CDC_SIDETONE_IIR_INP_MUX_IIR0_MIX_CFG1,
   0, 18, iir_inp_mux_text);

static const struct soc_enum iir0_inp2_mux_enum =
 SOC_ENUM_SINGLE(WCD934X_CDC_SIDETONE_IIR_INP_MUX_IIR0_MIX_CFG2,
   0, 18, iir_inp_mux_text);

static const struct soc_enum iir0_inp3_mux_enum =
 SOC_ENUM_SINGLE(WCD934X_CDC_SIDETONE_IIR_INP_MUX_IIR0_MIX_CFG3,
   0, 18, iir_inp_mux_text);

static const struct soc_enum iir1_inp0_mux_enum =
 SOC_ENUM_SINGLE(WCD934X_CDC_SIDETONE_IIR_INP_MUX_IIR1_MIX_CFG0,
   0, 18, iir_inp_mux_text);

static const struct soc_enum iir1_inp1_mux_enum =
 SOC_ENUM_SINGLE(WCD934X_CDC_SIDETONE_IIR_INP_MUX_IIR1_MIX_CFG1,
   0, 18, iir_inp_mux_text);

static const struct soc_enum iir1_inp2_mux_enum =
 SOC_ENUM_SINGLE(WCD934X_CDC_SIDETONE_IIR_INP_MUX_IIR1_MIX_CFG2,
   0, 18, iir_inp_mux_text);

static const struct soc_enum iir1_inp3_mux_enum =
 SOC_ENUM_SINGLE(WCD934X_CDC_SIDETONE_IIR_INP_MUX_IIR1_MIX_CFG3,
   0, 18, iir_inp_mux_text);

static const struct soc_enum rx_int0_dem_inp_mux_enum =
 SOC_ENUM_SINGLE(WCD934X_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(WCD934X_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(WCD934X_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 tx_adc_mux0_enum =
 SOC_ENUM_SINGLE(WCD934X_CDC_TX_INP_MUX_ADC_MUX0_CFG1, 0,
   ARRAY_SIZE(adc_mux_text), adc_mux_text);
static const struct soc_enum tx_adc_mux1_enum =
 SOC_ENUM_SINGLE(WCD934X_CDC_TX_INP_MUX_ADC_MUX1_CFG1, 0,
   ARRAY_SIZE(adc_mux_text), adc_mux_text);
static const struct soc_enum tx_adc_mux2_enum =
 SOC_ENUM_SINGLE(WCD934X_CDC_TX_INP_MUX_ADC_MUX2_CFG1, 0,
   ARRAY_SIZE(adc_mux_text), adc_mux_text);
static const struct soc_enum tx_adc_mux3_enum =
 SOC_ENUM_SINGLE(WCD934X_CDC_TX_INP_MUX_ADC_MUX3_CFG1, 0,
   ARRAY_SIZE(adc_mux_text), adc_mux_text);
static const struct soc_enum tx_adc_mux4_enum =
 SOC_ENUM_SINGLE(WCD934X_CDC_TX_INP_MUX_ADC_MUX0_CFG1, 2,
   ARRAY_SIZE(adc_mux_text), adc_mux_text);
static const struct soc_enum tx_adc_mux5_enum =
 SOC_ENUM_SINGLE(WCD934X_CDC_TX_INP_MUX_ADC_MUX1_CFG1, 2,
   ARRAY_SIZE(adc_mux_text), adc_mux_text);
static const struct soc_enum tx_adc_mux6_enum =
 SOC_ENUM_SINGLE(WCD934X_CDC_TX_INP_MUX_ADC_MUX2_CFG1, 2,
   ARRAY_SIZE(adc_mux_text), adc_mux_text);
static const struct soc_enum tx_adc_mux7_enum =
 SOC_ENUM_SINGLE(WCD934X_CDC_TX_INP_MUX_ADC_MUX3_CFG1, 2,
   ARRAY_SIZE(adc_mux_text), adc_mux_text);
static const struct soc_enum tx_adc_mux8_enum =
 SOC_ENUM_SINGLE(WCD934X_CDC_TX_INP_MUX_ADC_MUX1_CFG1, 4,
   ARRAY_SIZE(adc_mux_text), adc_mux_text);

static const struct soc_enum rx_int0_1_interp_mux_enum =
 SOC_ENUM_SINGLE(SND_SOC_NOPM, 0, 2,
   rx_int0_1_interp_mux_text);

static const struct soc_enum rx_int1_1_interp_mux_enum =
 SOC_ENUM_SINGLE(SND_SOC_NOPM, 0, 2,
   rx_int1_1_interp_mux_text);

static const struct soc_enum rx_int2_1_interp_mux_enum =
 SOC_ENUM_SINGLE(SND_SOC_NOPM, 0, 2,
   rx_int2_1_interp_mux_text);

static const struct soc_enum rx_int3_1_interp_mux_enum =
 SOC_ENUM_SINGLE(SND_SOC_NOPM, 0, 2, rx_int3_1_interp_mux_text);

static const struct soc_enum rx_int4_1_interp_mux_enum =
 SOC_ENUM_SINGLE(SND_SOC_NOPM, 0, 2, rx_int4_1_interp_mux_text);

static const struct soc_enum rx_int7_1_interp_mux_enum =
 SOC_ENUM_SINGLE(SND_SOC_NOPM, 0, 2, rx_int7_1_interp_mux_text);

static const struct soc_enum rx_int8_1_interp_mux_enum =
 SOC_ENUM_SINGLE(SND_SOC_NOPM, 0, 2, rx_int8_1_interp_mux_text);

static const struct soc_enum rx_int0_2_interp_mux_enum =
 SOC_ENUM_SINGLE(SND_SOC_NOPM, 0, 2, rx_int0_2_interp_mux_text);

static const struct soc_enum rx_int1_2_interp_mux_enum =
 SOC_ENUM_SINGLE(SND_SOC_NOPM, 0, 2, rx_int1_2_interp_mux_text);

static const struct soc_enum rx_int2_2_interp_mux_enum =
 SOC_ENUM_SINGLE(SND_SOC_NOPM, 0, 2, rx_int2_2_interp_mux_text);

static const struct soc_enum rx_int3_2_interp_mux_enum =
 SOC_ENUM_SINGLE(SND_SOC_NOPM, 0, 2, rx_int3_2_interp_mux_text);

static const struct soc_enum rx_int4_2_interp_mux_enum =
 SOC_ENUM_SINGLE(SND_SOC_NOPM, 0, 2, rx_int4_2_interp_mux_text);

static const struct soc_enum rx_int7_2_interp_mux_enum =
 SOC_ENUM_SINGLE(SND_SOC_NOPM, 0, 2, rx_int7_2_interp_mux_text);

static const struct soc_enum rx_int8_2_interp_mux_enum =
 SOC_ENUM_SINGLE(SND_SOC_NOPM, 0, 2, rx_int8_2_interp_mux_text);

static const struct soc_enum tx_dmic_mux0_enum =
 SOC_ENUM_SINGLE(WCD934X_CDC_TX_INP_MUX_ADC_MUX0_CFG0, 3, 7,
   dmic_mux_text);

static const struct soc_enum tx_dmic_mux1_enum =
 SOC_ENUM_SINGLE(WCD934X_CDC_TX_INP_MUX_ADC_MUX1_CFG0, 3, 7,
   dmic_mux_text);

static const struct soc_enum tx_dmic_mux2_enum =
 SOC_ENUM_SINGLE(WCD934X_CDC_TX_INP_MUX_ADC_MUX2_CFG0, 3, 7,
   dmic_mux_text);

static const struct soc_enum tx_dmic_mux3_enum =
 SOC_ENUM_SINGLE(WCD934X_CDC_TX_INP_MUX_ADC_MUX3_CFG0, 3, 7,
   dmic_mux_text);

static const struct soc_enum tx_dmic_mux4_enum =
 SOC_ENUM_SINGLE(WCD934X_CDC_TX_INP_MUX_ADC_MUX4_CFG0, 3, 7,
   dmic_mux_text);

static const struct soc_enum tx_dmic_mux5_enum =
 SOC_ENUM_SINGLE(WCD934X_CDC_TX_INP_MUX_ADC_MUX5_CFG0, 3, 7,
   dmic_mux_text);

static const struct soc_enum tx_dmic_mux6_enum =
 SOC_ENUM_SINGLE(WCD934X_CDC_TX_INP_MUX_ADC_MUX6_CFG0, 3, 7,
   dmic_mux_text);

static const struct soc_enum tx_dmic_mux7_enum =
 SOC_ENUM_SINGLE(WCD934X_CDC_TX_INP_MUX_ADC_MUX7_CFG0, 3, 7,
   dmic_mux_text);

static const struct soc_enum tx_dmic_mux8_enum =
 SOC_ENUM_SINGLE(WCD934X_CDC_TX_INP_MUX_ADC_MUX8_CFG0, 3, 7,
   dmic_mux_text);

static const struct soc_enum tx_amic_mux0_enum =
 SOC_ENUM_SINGLE(WCD934X_CDC_TX_INP_MUX_ADC_MUX0_CFG0, 0, 5,
   amic_mux_text);
static const struct soc_enum tx_amic_mux1_enum =
 SOC_ENUM_SINGLE(WCD934X_CDC_TX_INP_MUX_ADC_MUX1_CFG0, 0, 5,
   amic_mux_text);
static const struct soc_enum tx_amic_mux2_enum =
 SOC_ENUM_SINGLE(WCD934X_CDC_TX_INP_MUX_ADC_MUX2_CFG0, 0, 5,
   amic_mux_text);
static const struct soc_enum tx_amic_mux3_enum =
 SOC_ENUM_SINGLE(WCD934X_CDC_TX_INP_MUX_ADC_MUX3_CFG0, 0, 5,
   amic_mux_text);
static const struct soc_enum tx_amic_mux4_enum =
 SOC_ENUM_SINGLE(WCD934X_CDC_TX_INP_MUX_ADC_MUX4_CFG0, 0, 5,
   amic_mux_text);
static const struct soc_enum tx_amic_mux5_enum =
 SOC_ENUM_SINGLE(WCD934X_CDC_TX_INP_MUX_ADC_MUX5_CFG0, 0, 5,
   amic_mux_text);
static const struct soc_enum tx_amic_mux6_enum =
 SOC_ENUM_SINGLE(WCD934X_CDC_TX_INP_MUX_ADC_MUX6_CFG0, 0, 5,
   amic_mux_text);
static const struct soc_enum tx_amic_mux7_enum =
 SOC_ENUM_SINGLE(WCD934X_CDC_TX_INP_MUX_ADC_MUX7_CFG0, 0, 5,
   amic_mux_text);
static const struct soc_enum tx_amic_mux8_enum =
 SOC_ENUM_SINGLE(WCD934X_CDC_TX_INP_MUX_ADC_MUX8_CFG0, 0, 5,
   amic_mux_text);

static const struct soc_enum tx_amic4_5_enum =
 SOC_ENUM_SINGLE(WCD934X_TX_NEW_AMIC_4_5_SEL, 7, 2, amic4_5_sel_text);

static const struct soc_enum cdc_if_tx0_mux_enum =
 SOC_ENUM_SINGLE(WCD934X_CDC_IF_ROUTER_TX_MUX_CFG0, 0,
   ARRAY_SIZE(cdc_if_tx0_mux_text), cdc_if_tx0_mux_text);
static const struct soc_enum cdc_if_tx1_mux_enum =
 SOC_ENUM_SINGLE(WCD934X_CDC_IF_ROUTER_TX_MUX_CFG0, 2,
   ARRAY_SIZE(cdc_if_tx1_mux_text), cdc_if_tx1_mux_text);
static const struct soc_enum cdc_if_tx2_mux_enum =
 SOC_ENUM_SINGLE(WCD934X_CDC_IF_ROUTER_TX_MUX_CFG0, 4,
   ARRAY_SIZE(cdc_if_tx2_mux_text), cdc_if_tx2_mux_text);
static const struct soc_enum cdc_if_tx3_mux_enum =
 SOC_ENUM_SINGLE(WCD934X_CDC_IF_ROUTER_TX_MUX_CFG0, 6,
   ARRAY_SIZE(cdc_if_tx3_mux_text), cdc_if_tx3_mux_text);
static const struct soc_enum cdc_if_tx4_mux_enum =
 SOC_ENUM_SINGLE(WCD934X_CDC_IF_ROUTER_TX_MUX_CFG1, 0,
   ARRAY_SIZE(cdc_if_tx4_mux_text), cdc_if_tx4_mux_text);
static const struct soc_enum cdc_if_tx5_mux_enum =
 SOC_ENUM_SINGLE(WCD934X_CDC_IF_ROUTER_TX_MUX_CFG1, 2,
   ARRAY_SIZE(cdc_if_tx5_mux_text), cdc_if_tx5_mux_text);
static const struct soc_enum cdc_if_tx6_mux_enum =
 SOC_ENUM_SINGLE(WCD934X_CDC_IF_ROUTER_TX_MUX_CFG1, 4,
   ARRAY_SIZE(cdc_if_tx6_mux_text), cdc_if_tx6_mux_text);
static const struct soc_enum cdc_if_tx7_mux_enum =
 SOC_ENUM_SINGLE(WCD934X_CDC_IF_ROUTER_TX_MUX_CFG1, 6,
   ARRAY_SIZE(cdc_if_tx7_mux_text), cdc_if_tx7_mux_text);
static const struct soc_enum cdc_if_tx8_mux_enum =
 SOC_ENUM_SINGLE(WCD934X_CDC_IF_ROUTER_TX_MUX_CFG2, 0,
   ARRAY_SIZE(cdc_if_tx8_mux_text), cdc_if_tx8_mux_text);
static const struct soc_enum cdc_if_tx9_mux_enum =
 SOC_ENUM_SINGLE(WCD934X_CDC_IF_ROUTER_TX_MUX_CFG2, 2,
   ARRAY_SIZE(cdc_if_tx9_mux_text), cdc_if_tx9_mux_text);
static const struct soc_enum cdc_if_tx10_mux_enum =
 SOC_ENUM_SINGLE(WCD934X_CDC_IF_ROUTER_TX_MUX_CFG2, 4,
   ARRAY_SIZE(cdc_if_tx10_mux_text), cdc_if_tx10_mux_text);
static const struct soc_enum cdc_if_tx11_inp1_mux_enum =
 SOC_ENUM_SINGLE(WCD934X_CDC_IF_ROUTER_TX_MUX_CFG3, 0,
   ARRAY_SIZE(cdc_if_tx11_inp1_mux_text),
   cdc_if_tx11_inp1_mux_text);
static const struct soc_enum cdc_if_tx11_mux_enum =
 SOC_ENUM_SINGLE(WCD934X_DATA_HUB_SB_TX11_INP_CFG, 0,
   ARRAY_SIZE(cdc_if_tx11_mux_text), cdc_if_tx11_mux_text);
static const struct soc_enum cdc_if_tx13_inp1_mux_enum =
 SOC_ENUM_SINGLE(WCD934X_CDC_IF_ROUTER_TX_MUX_CFG3, 4,
   ARRAY_SIZE(cdc_if_tx13_inp1_mux_text),
   cdc_if_tx13_inp1_mux_text);
static const struct soc_enum cdc_if_tx13_mux_enum =
 SOC_ENUM_SINGLE(WCD934X_DATA_HUB_SB_TX13_INP_CFG, 0,
   ARRAY_SIZE(cdc_if_tx13_mux_text), cdc_if_tx13_mux_text);

static const struct wcd_mbhc_field wcd_mbhc_fields[WCD_MBHC_REG_FUNC_MAX] = {
 WCD_MBHC_FIELD(WCD_MBHC_L_DET_EN, WCD934X_ANA_MBHC_MECH, 0x80),
 WCD_MBHC_FIELD(WCD_MBHC_GND_DET_EN, WCD934X_ANA_MBHC_MECH, 0x40),
 WCD_MBHC_FIELD(WCD_MBHC_MECH_DETECTION_TYPE, WCD934X_ANA_MBHC_MECH, 0x20),
 WCD_MBHC_FIELD(WCD_MBHC_MIC_CLAMP_CTL, WCD934X_MBHC_NEW_PLUG_DETECT_CTL, 0x30),
 WCD_MBHC_FIELD(WCD_MBHC_ELECT_DETECTION_TYPE, WCD934X_ANA_MBHC_ELECT, 0x08),
 WCD_MBHC_FIELD(WCD_MBHC_HS_L_DET_PULL_UP_CTRL, WCD934X_MBHC_NEW_PLUG_DETECT_CTL, 0xC0),
 WCD_MBHC_FIELD(WCD_MBHC_HS_L_DET_PULL_UP_COMP_CTRL, WCD934X_ANA_MBHC_MECH, 0x04),
 WCD_MBHC_FIELD(WCD_MBHC_HPHL_PLUG_TYPE, WCD934X_ANA_MBHC_MECH, 0x10),
 WCD_MBHC_FIELD(WCD_MBHC_GND_PLUG_TYPE, WCD934X_ANA_MBHC_MECH, 0x08),
 WCD_MBHC_FIELD(WCD_MBHC_SW_HPH_LP_100K_TO_GND, WCD934X_ANA_MBHC_MECH, 0x01),
 WCD_MBHC_FIELD(WCD_MBHC_ELECT_SCHMT_ISRC, WCD934X_ANA_MBHC_ELECT, 0x06),
 WCD_MBHC_FIELD(WCD_MBHC_FSM_EN, WCD934X_ANA_MBHC_ELECT, 0x80),
 WCD_MBHC_FIELD(WCD_MBHC_INSREM_DBNC, WCD934X_MBHC_NEW_PLUG_DETECT_CTL, 0x0F),
 WCD_MBHC_FIELD(WCD_MBHC_BTN_DBNC, WCD934X_MBHC_NEW_CTL_1, 0x03),
 WCD_MBHC_FIELD(WCD_MBHC_HS_VREF, WCD934X_MBHC_NEW_CTL_2, 0x03),
 WCD_MBHC_FIELD(WCD_MBHC_HS_COMP_RESULT, WCD934X_ANA_MBHC_RESULT_3, 0x08),
 WCD_MBHC_FIELD(WCD_MBHC_IN2P_CLAMP_STATE, WCD934X_ANA_MBHC_RESULT_3, 0x10),
 WCD_MBHC_FIELD(WCD_MBHC_MIC_SCHMT_RESULT, WCD934X_ANA_MBHC_RESULT_3, 0x20),
 WCD_MBHC_FIELD(WCD_MBHC_HPHL_SCHMT_RESULT, WCD934X_ANA_MBHC_RESULT_3, 0x80),
 WCD_MBHC_FIELD(WCD_MBHC_HPHR_SCHMT_RESULT, WCD934X_ANA_MBHC_RESULT_3, 0x40),
 WCD_MBHC_FIELD(WCD_MBHC_OCP_FSM_EN, WCD934X_HPH_OCP_CTL, 0x10),
 WCD_MBHC_FIELD(WCD_MBHC_BTN_RESULT, WCD934X_ANA_MBHC_RESULT_3, 0x07),
 WCD_MBHC_FIELD(WCD_MBHC_BTN_ISRC_CTL, WCD934X_ANA_MBHC_ELECT, 0x70),
 WCD_MBHC_FIELD(WCD_MBHC_ELECT_RESULT, WCD934X_ANA_MBHC_RESULT_3, 0xFF),
 WCD_MBHC_FIELD(WCD_MBHC_MICB_CTRL, WCD934X_ANA_MICB2, 0xC0),
 WCD_MBHC_FIELD(WCD_MBHC_HPH_CNP_WG_TIME, WCD934X_HPH_CNP_WG_TIME, 0xFF),
 WCD_MBHC_FIELD(WCD_MBHC_HPHR_PA_EN, WCD934X_ANA_HPH, 0x40),
 WCD_MBHC_FIELD(WCD_MBHC_HPHL_PA_EN, WCD934X_ANA_HPH, 0x80),
 WCD_MBHC_FIELD(WCD_MBHC_HPH_PA_EN, WCD934X_ANA_HPH, 0xC0),
 WCD_MBHC_FIELD(WCD_MBHC_SWCH_LEVEL_REMOVE, WCD934X_ANA_MBHC_RESULT_3, 0x10),
 WCD_MBHC_FIELD(WCD_MBHC_ANC_DET_EN, WCD934X_MBHC_CTL_BCS, 0x02),
 WCD_MBHC_FIELD(WCD_MBHC_FSM_STATUS, WCD934X_MBHC_STATUS_SPARE_1, 0x01),
 WCD_MBHC_FIELD(WCD_MBHC_MUX_CTL, WCD934X_MBHC_NEW_CTL_2, 0x70),
 WCD_MBHC_FIELD(WCD_MBHC_MOISTURE_STATUS, WCD934X_MBHC_NEW_FSM_STATUS, 0x20),
 WCD_MBHC_FIELD(WCD_MBHC_HPHR_GND, WCD934X_HPH_PA_CTL2, 0x40),
 WCD_MBHC_FIELD(WCD_MBHC_HPHL_GND, WCD934X_HPH_PA_CTL2, 0x10),
 WCD_MBHC_FIELD(WCD_MBHC_HPHL_OCP_DET_EN, WCD934X_HPH_L_TEST, 0x01),
 WCD_MBHC_FIELD(WCD_MBHC_HPHR_OCP_DET_EN, WCD934X_HPH_R_TEST, 0x01),
 WCD_MBHC_FIELD(WCD_MBHC_HPHL_OCP_STATUS, WCD934X_INTR_PIN1_STATUS0, 0x04),
 WCD_MBHC_FIELD(WCD_MBHC_HPHR_OCP_STATUS, WCD934X_INTR_PIN1_STATUS0, 0x08),
 WCD_MBHC_FIELD(WCD_MBHC_ADC_EN, WCD934X_MBHC_NEW_CTL_1, 0x08),
 WCD_MBHC_FIELD(WCD_MBHC_ADC_COMPLETE, WCD934X_MBHC_NEW_FSM_STATUS, 0x40),
 WCD_MBHC_FIELD(WCD_MBHC_ADC_TIMEOUT, WCD934X_MBHC_NEW_FSM_STATUS, 0x80),
 WCD_MBHC_FIELD(WCD_MBHC_ADC_RESULT, WCD934X_MBHC_NEW_ADC_RESULT, 0xFF),
 WCD_MBHC_FIELD(WCD_MBHC_MICB2_VOUT, WCD934X_ANA_MICB2, 0x3F),
 WCD_MBHC_FIELD(WCD_MBHC_ADC_MODE, WCD934X_MBHC_NEW_CTL_1, 0x10),
 WCD_MBHC_FIELD(WCD_MBHC_DETECTION_DONE, WCD934X_MBHC_NEW_CTL_1, 0x04),
 WCD_MBHC_FIELD(WCD_MBHC_ELECT_ISRC_EN, WCD934X_ANA_MBHC_ZDET, 0x02),
};

static int wcd934x_set_sido_input_src(struct wcd934x_codec *wcd, int sido_src)
{
 if (sido_src == wcd->sido_input_src)
  return 0;

 if (sido_src == SIDO_SOURCE_RCO_BG) {
  regmap_update_bits(wcd->regmap, WCD934X_ANA_RCO,
       WCD934X_ANA_RCO_BG_EN_MASK,
       WCD934X_ANA_RCO_BG_ENABLE);
  usleep_range(100, 110);
 }
 wcd->sido_input_src = sido_src;

 return 0;
}

static int wcd934x_enable_ana_bias_and_sysclk(struct wcd934x_codec *wcd)
{
 mutex_lock(&wcd->sysclk_mutex);

 if (++wcd->sysclk_users != 1) {
  mutex_unlock(&wcd->sysclk_mutex);
  return 0;
 }
 mutex_unlock(&wcd->sysclk_mutex);

 regmap_update_bits(wcd->regmap, WCD934X_ANA_BIAS,
      WCD934X_ANA_BIAS_EN_MASK,
      WCD934X_ANA_BIAS_EN);
 regmap_update_bits(wcd->regmap, WCD934X_ANA_BIAS,
      WCD934X_ANA_PRECHRG_EN_MASK,
      WCD934X_ANA_PRECHRG_EN);
 /*
 * 1ms delay is required after pre-charge is enabled
 * as per HW requirement
 */

 usleep_range(1000, 1100);
 regmap_update_bits(wcd->regmap, WCD934X_ANA_BIAS,
      WCD934X_ANA_PRECHRG_EN_MASK, 0);
 regmap_update_bits(wcd->regmap, WCD934X_ANA_BIAS,
      WCD934X_ANA_PRECHRG_MODE_MASK, 0);

 /*
 * In data clock contrl register is changed
 * to CLK_SYS_MCLK_PRG
 */


 regmap_update_bits(wcd->regmap, WCD934X_CLK_SYS_MCLK_PRG,
      WCD934X_EXT_CLK_BUF_EN_MASK,
      WCD934X_EXT_CLK_BUF_EN);
 regmap_update_bits(wcd->regmap, WCD934X_CLK_SYS_MCLK_PRG,
      WCD934X_EXT_CLK_DIV_RATIO_MASK,
      WCD934X_EXT_CLK_DIV_BY_2);
 regmap_update_bits(wcd->regmap, WCD934X_CLK_SYS_MCLK_PRG,
      WCD934X_MCLK_SRC_MASK,
      WCD934X_MCLK_SRC_EXT_CLK);
 regmap_update_bits(wcd->regmap, WCD934X_CLK_SYS_MCLK_PRG,
      WCD934X_MCLK_EN_MASK, WCD934X_MCLK_EN);
 regmap_update_bits(wcd->regmap,
      WCD934X_CDC_CLK_RST_CTRL_FS_CNT_CONTROL,
      WCD934X_CDC_FS_MCLK_CNT_EN_MASK,
      WCD934X_CDC_FS_MCLK_CNT_ENABLE);
 regmap_update_bits(wcd->regmap,
      WCD934X_CDC_CLK_RST_CTRL_MCLK_CONTROL,
      WCD934X_MCLK_EN_MASK,
      WCD934X_MCLK_EN);
 regmap_update_bits(wcd->regmap, WCD934X_CODEC_RPM_CLK_GATE,
      WCD934X_CODEC_RPM_CLK_GATE_MASK, 0x0);
 /*
 * 10us sleep is required after clock is enabled
 * as per HW requirement
 */

 usleep_range(10, 15);

 wcd934x_set_sido_input_src(wcd, SIDO_SOURCE_RCO_BG);

 return 0;
}

static int wcd934x_disable_ana_bias_and_syclk(struct wcd934x_codec *wcd)
{
 mutex_lock(&wcd->sysclk_mutex);
 if (--wcd->sysclk_users != 0) {
  mutex_unlock(&wcd->sysclk_mutex);
  return 0;
 }
 mutex_unlock(&wcd->sysclk_mutex);

 regmap_update_bits(wcd->regmap, WCD934X_CLK_SYS_MCLK_PRG,
      WCD934X_EXT_CLK_BUF_EN_MASK |
      WCD934X_MCLK_EN_MASK, 0x0);
 regmap_update_bits(wcd->regmap, WCD934X_ANA_BIAS,
      WCD934X_ANA_BIAS_EN_MASK, 0);
 regmap_update_bits(wcd->regmap, WCD934X_ANA_BIAS,
      WCD934X_ANA_PRECHRG_EN_MASK, 0);

 return 0;
}

static int __wcd934x_cdc_mclk_enable(struct wcd934x_codec *wcd, bool enable)
{
 int ret = 0;

 if (enable) {
  ret = clk_prepare_enable(wcd->extclk);

  if (ret) {
   dev_err(wcd->dev, "%s: ext clk enable failed\n",
    __func__);
   return ret;
  }
  ret = wcd934x_enable_ana_bias_and_sysclk(wcd);
 } else {
  int val;

  regmap_read(wcd->regmap, WCD934X_CDC_CLK_RST_CTRL_SWR_CONTROL,
       &val);

  /* Don't disable clock if soundwire using it.*/
  if (val & WCD934X_CDC_SWR_CLK_EN_MASK)
   return 0;

  wcd934x_disable_ana_bias_and_syclk(wcd);
  clk_disable_unprepare(wcd->extclk);
 }

 return ret;
}

static int wcd934x_codec_enable_mclk(struct snd_soc_dapm_widget *w,
         struct snd_kcontrol *kc, int event)
{
 struct snd_soc_component *comp = snd_soc_dapm_to_component(w->dapm);
 struct wcd934x_codec *wcd = dev_get_drvdata(comp->dev);

 switch (event) {
 case SND_SOC_DAPM_PRE_PMU:
  return __wcd934x_cdc_mclk_enable(wcd, true);
 case SND_SOC_DAPM_POST_PMD:
  return __wcd934x_cdc_mclk_enable(wcd, false);
 }

 return 0;
}

static int wcd934x_get_version(struct wcd934x_codec *wcd)
{
 int val1, val2, ver, ret;
 struct regmap *regmap;
 u16 id_minor;
 u32 version_mask = 0;

 regmap = wcd->regmap;
 ver = 0;

 ret = regmap_bulk_read(regmap, WCD934X_CHIP_TIER_CTRL_CHIP_ID_BYTE0,
          (u8 *)&id_minor, sizeof(u16));

 if (ret)
  return ret;

 regmap_read(regmap, WCD934X_CHIP_TIER_CTRL_EFUSE_VAL_OUT14, &val1);
 regmap_read(regmap, WCD934X_CHIP_TIER_CTRL_EFUSE_VAL_OUT15, &val2);

 version_mask |= (!!((u8)val1 & 0x80)) << DSD_DISABLED_MASK;
 version_mask |= (!!((u8)val2 & 0x01)) << SLNQ_DISABLED_MASK;

 switch (version_mask) {
 case DSD_DISABLED | SLNQ_DISABLED:
  if (id_minor == 0)
   ver = WCD_VERSION_WCD9340_1_0;
  else if (id_minor == 0x01)
   ver = WCD_VERSION_WCD9340_1_1;
  break;
 case SLNQ_DISABLED:
  if (id_minor == 0)
   ver = WCD_VERSION_WCD9341_1_0;
  else if (id_minor == 0x01)
   ver = WCD_VERSION_WCD9341_1_1;
  break;
 }

 wcd->version = ver;
 dev_info(wcd->dev, "WCD934X Minor:0x%x Version:0x%x\n", id_minor, ver);

 return 0;
}

static void wcd934x_enable_efuse_sensing(struct wcd934x_codec *wcd)
{
 int rc, val;

 __wcd934x_cdc_mclk_enable(wcd, true);

 regmap_update_bits(wcd->regmap,
      WCD934X_CHIP_TIER_CTRL_EFUSE_CTL,
      WCD934X_EFUSE_SENSE_STATE_MASK,
      WCD934X_EFUSE_SENSE_STATE_DEF);
 regmap_update_bits(wcd->regmap,
      WCD934X_CHIP_TIER_CTRL_EFUSE_CTL,
      WCD934X_EFUSE_SENSE_EN_MASK,
      WCD934X_EFUSE_SENSE_ENABLE);
 /*
 * 5ms sleep required after enabling efuse control
 * before checking the status.
 */

 usleep_range(5000, 5500);
 wcd934x_set_sido_input_src(wcd, SIDO_SOURCE_RCO_BG);

 rc = regmap_read(wcd->regmap,
    WCD934X_CHIP_TIER_CTRL_EFUSE_STATUS, &val);
 if (rc || (!(val & 0x01)))
  WARN(1, "%s: Efuse sense is not complete val=%x, ret=%d\n",
       __func__, val, rc);

 __wcd934x_cdc_mclk_enable(wcd, false);
}

static int wcd934x_swrm_clock(struct wcd934x_codec *wcd, bool enable)
{
 if (enable) {
  __wcd934x_cdc_mclk_enable(wcd, true);
  regmap_update_bits(wcd->regmap,
       WCD934X_CDC_CLK_RST_CTRL_SWR_CONTROL,
       WCD934X_CDC_SWR_CLK_EN_MASK,
       WCD934X_CDC_SWR_CLK_ENABLE);
 } else {
  regmap_update_bits(wcd->regmap,
       WCD934X_CDC_CLK_RST_CTRL_SWR_CONTROL,
       WCD934X_CDC_SWR_CLK_EN_MASK, 0);
  __wcd934x_cdc_mclk_enable(wcd, false);
 }

 return 0;
}

static int wcd934x_set_prim_interpolator_rate(struct snd_soc_dai *dai,
           u8 rate_val, u32 rate)
{
 struct snd_soc_component *comp = dai->component;
 struct wcd934x_codec *wcd = dev_get_drvdata(comp->dev);
 struct wcd934x_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_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 < WCD934X_NUM_INTERPOLATORS; j++) {
   /* Interpolators 5 and 6 are not aviliable in Tavil */
   if (j == INTERP_LO3_NA || j == INTERP_LO4_NA)
    continue;

   cfg0 = snd_soc_component_read(comp,
     WCD934X_CDC_RX_INP_MUX_RX_INT_CFG0(j));
   cfg1 = snd_soc_component_read(comp,
     WCD934X_CDC_RX_INP_MUX_RX_INT_CFG1(j));

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

   if ((inp0_sel == inp) ||  (inp1_sel == inp) ||
       (inp2_sel == inp)) {
    /* rate is in Hz */
    /*
 * Ear and speaker primary path does not support
 * native sample rates
 */

    if ((j == INTERP_EAR || j == INTERP_SPKR1 ||
         j == INTERP_SPKR2) && rate == 44100)
     dev_err(wcd->dev,
      "Cannot set 44.1KHz on INT%d\n",
      j);
    else
     snd_soc_component_update_bits(comp,
           WCD934X_CDC_RX_PATH_CTL(j),
           WCD934X_CDC_MIX_PCM_RATE_MASK,
           rate_val);
   }
  }
 }

 return 0;
}

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

 list_for_each_entry(ch, &wcd->dai[dai->id].slim_ch_list, list) {
  for (j = 0; j < WCD934X_NUM_INTERPOLATORS; j++) {
   /* Interpolators 5 and 6 are not aviliable in Tavil */
   if (j == INTERP_LO3_NA || j == INTERP_LO4_NA)
    continue;
   val = snd_soc_component_read(component,
     WCD934X_CDC_RX_INP_MUX_RX_INT_CFG1(j)) &
     WCD934X_CDC_RX_INP_MUX_RX_INT_SEL_MASK;

   if (val == (ch->shift + INTn_2_INP_SEL_RX0)) {
    /*
 * Ear mix path supports only 48, 96, 192,
 * 384KHz only
 */

    if ((j == INTERP_EAR) &&
        (rate_val < 0x4 ||
         rate_val > 0x7)) {
     dev_err(component->dev,
      "Invalid rate for AIF_PB DAI(%d)\n",
      dai->id);
     return -EINVAL;
    }

    snd_soc_component_update_bits(component,
           WCD934X_CDC_RX_PATH_MIX_CTL(j),
           WCD934X_CDC_MIX_PCM_RATE_MASK,
           rate_val);
   }
  }
 }

 return 0;
}

static int wcd934x_set_interpolator_rate(struct snd_soc_dai *dai,
      u32 sample_rate)
{
 int rate_val = 0;
 int i, ret;

 for (i = 0; i < ARRAY_SIZE(sr_val_tbl); i++) {
  if (sample_rate == sr_val_tbl[i].sample_rate) {
   rate_val = sr_val_tbl[i].rate_val;
   break;
  }
 }
 if ((i == ARRAY_SIZE(sr_val_tbl)) || (rate_val < 0)) {
  dev_err(dai->dev, "Unsupported sample rate: %d\n", sample_rate);
  return -EINVAL;
 }

 ret = wcd934x_set_prim_interpolator_rate(dai, (u8)rate_val,
       sample_rate);
 if (ret)
  return ret;
 ret = wcd934x_set_mix_interpolator_rate(dai, (u8)rate_val,
      sample_rate);

 return ret;
}

static int wcd934x_set_decimator_rate(struct snd_soc_dai *dai,
          u8 rate_val, u32 rate)
{
 struct snd_soc_component *comp = dai->component;
 struct wcd934x_codec *wcd = snd_soc_component_get_drvdata(comp);
 u8 shift = 0, shift_val = 0, tx_mux_sel;
 struct wcd934x_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;
  /* Find the SB TX MUX input - which decimator is connected */
  switch (tx_port) {
  case 0 ...  3:
   tx_port_reg = WCD934X_CDC_IF_ROUTER_TX_MUX_CFG0;
   shift = (tx_port << 1);
   shift_val = 0x03;
   break;
  case 4 ... 7:
   tx_port_reg = WCD934X_CDC_IF_ROUTER_TX_MUX_CFG1;
   shift = ((tx_port - 4) << 1);
   shift_val = 0x03;
   break;
  case 8 ... 10:
   tx_port_reg = WCD934X_CDC_IF_ROUTER_TX_MUX_CFG2;
   shift = ((tx_port - 8) << 1);
   shift_val = 0x03;
   break;
  case 11:
   tx_port_reg = WCD934X_CDC_IF_ROUTER_TX_MUX_CFG3;
   shift = 0;
   shift_val = 0x0F;
   break;
  case 13:
   tx_port_reg = WCD934X_CDC_IF_ROUTER_TX_MUX_CFG3;
   shift = 4;
   shift_val = 0x03;
   break;
  default:
   dev_err(wcd->dev, "Invalid SLIM TX%u port DAI ID:%d\n",
    tx_port, dai->id);
   return -EINVAL;
  }

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

  tx_mux_sel = tx_mux_sel >> shift;
  switch (tx_port) {
  case 0 ... 8:
   if ((tx_mux_sel == 0x2) || (tx_mux_sel == 0x3))
    decimator = tx_port;
   break;
  case 9 ... 10:
   if ((tx_mux_sel == 0x1) || (tx_mux_sel == 0x2))
    decimator = ((tx_port == 9) ? 7 : 6);
   break;
  case 11:
   if ((tx_mux_sel >= 1) && (tx_mux_sel < 7))
    decimator = tx_mux_sel - 1;
   break;
  case 13:
   if ((tx_mux_sel == 0x1) || (tx_mux_sel == 0x2))
    decimator = 5;
   break;
  default:
   dev_err(wcd->dev, "ERROR: Invalid tx_port: %d\n",
    tx_port);
   return -EINVAL;
  }

  snd_soc_component_update_bits(comp,
          WCD934X_CDC_TX_PATH_CTL(decimator),
          WCD934X_CDC_TX_PATH_CTL_PCM_RATE_MASK,
          rate_val);
 }

 return 0;
}

static int wcd934x_slim_set_hw_params(struct wcd934x_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 wcd934x_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,
      WCD934X_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,
     WCD934X_SLIM_PGD_RX_PORT_CFG(ch->port),
     WCD934X_SLIM_WATER_MARK_VAL);
   if (ret < 0)
    goto err;
  } else {
   ret = regmap_write(wcd->if_regmap,
    WCD934X_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,
    WCD934X_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,
     WCD934X_SLIM_PGD_TX_PORT_CFG(ch->port),
     WCD934X_SLIM_WATER_MARK_VAL);

   if (ret < 0)
    goto err;
  }
 }

 dai_data->sruntime = slim_stream_allocate(wcd->sdev, "WCD934x-SLIM");

 return 0;

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

 return ret;
}

static int wcd934x_hw_params(struct snd_pcm_substream *substream,
        struct snd_pcm_hw_params *params,
        struct snd_soc_dai *dai)
{
 struct wcd934x_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 = wcd934x_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, "Invalid format 0x%x\n",
    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, "Invalid TX sample rate: %d\n",
    params_rate(params));
   return -EINVAL;

  }

  ret = wcd934x_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, "Invalid format 0x%x\n",
    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);

 return wcd934x_slim_set_hw_params(wcd, &wcd->dai[dai->id], substream->stream);
}

static int wcd934x_hw_free(struct snd_pcm_substream *substream,
      struct snd_soc_dai *dai)
{
 struct wcd_slim_codec_dai_data *dai_data;
 struct wcd934x_codec *wcd;

 wcd = snd_soc_component_get_drvdata(dai->component);

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

 kfree(dai_data->sconfig.chs);

 return 0;
}

static int wcd934x_trigger(struct snd_pcm_substream *substream, int cmd,
      struct snd_soc_dai *dai)
{
 struct wcd_slim_codec_dai_data *dai_data;
 struct wcd934x_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 wcd934x_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 wcd934x_codec *wcd;
 int i;

 wcd = snd_soc_component_get_drvdata(dai->component);

 if (tx_num > WCD934X_TX_MAX || rx_num > WCD934X_RX_MAX) {
  dev_err(wcd->dev, "Invalid tx %d or rx %d channel count\n",
   tx_num, rx_num);
  return -EINVAL;
 }

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

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

 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 wcd934x_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 wcd934x_slim_ch *ch;
 struct wcd934x_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 wcd934x_dai_ops = {
 .hw_params = wcd934x_hw_params,
 .hw_free = wcd934x_hw_free,
 .trigger = wcd934x_trigger,
 .set_channel_map = wcd934x_set_channel_map,
 .get_channel_map = wcd934x_get_channel_map,
};

static struct snd_soc_dai_driver wcd934x_slim_dais[] = {
 [0] = {
  .name = "wcd934x_rx1",
  .id = AIF1_PB,
  .playback = {
   .stream_name = "AIF1 Playback",
   .rates = WCD934X_RATES_MASK | WCD934X_FRAC_RATES_MASK,
   .formats = WCD934X_FORMATS_S16_S24_LE,
   .rate_max = 192000,
   .rate_min = 8000,
   .channels_min = 1,
   .channels_max = 2,
  },
  .ops = &wcd934x_dai_ops,
 },
 [1] = {
  .name = "wcd934x_tx1",
  .id = AIF1_CAP,
  .capture = {
   .stream_name = "AIF1 Capture",
   .rates = WCD934X_RATES_MASK,
   .formats = SNDRV_PCM_FMTBIT_S16_LE,
   .rate_min = 8000,
   .rate_max = 192000,
   .channels_min = 1,
   .channels_max = 4,
  },
  .ops = &wcd934x_dai_ops,
 },
 [2] = {
  .name = "wcd934x_rx2",
  .id = AIF2_PB,
  .playback = {
   .stream_name = "AIF2 Playback",
   .rates = WCD934X_RATES_MASK | WCD934X_FRAC_RATES_MASK,
   .formats = WCD934X_FORMATS_S16_S24_LE,
   .rate_min = 8000,
   .rate_max = 192000,
   .channels_min = 1,
   .channels_max = 2,
  },
  .ops = &wcd934x_dai_ops,
 },
 [3] = {
  .name = "wcd934x_tx2",
  .id = AIF2_CAP,
  .capture = {
   .stream_name = "AIF2 Capture",
   .rates = WCD934X_RATES_MASK,
   .formats = SNDRV_PCM_FMTBIT_S16_LE,
   .rate_min = 8000,
   .rate_max = 192000,
   .channels_min = 1,
   .channels_max = 4,
  },
  .ops = &wcd934x_dai_ops,
 },
 [4] = {
  .name = "wcd934x_rx3",
  .id = AIF3_PB,
  .playback = {
   .stream_name = "AIF3 Playback",
   .rates = WCD934X_RATES_MASK | WCD934X_FRAC_RATES_MASK,
   .formats = WCD934X_FORMATS_S16_S24_LE,
   .rate_min = 8000,
   .rate_max = 192000,
   .channels_min = 1,
   .channels_max = 2,
  },
  .ops = &wcd934x_dai_ops,
 },
 [5] = {
  .name = "wcd934x_tx3",
  .id = AIF3_CAP,
  .capture = {
   .stream_name = "AIF3 Capture",
   .rates = WCD934X_RATES_MASK,
   .formats = SNDRV_PCM_FMTBIT_S16_LE,
   .rate_min = 8000,
   .rate_max = 192000,
   .channels_min = 1,
   .channels_max = 4,
  },
  .ops = &wcd934x_dai_ops,
 },
 [6] = {
  .name = "wcd934x_rx4",
  .id = AIF4_PB,
  .playback = {
   .stream_name = "AIF4 Playback",
   .rates = WCD934X_RATES_MASK | WCD934X_FRAC_RATES_MASK,
   .formats = WCD934X_FORMATS_S16_S24_LE,
   .rate_min = 8000,
   .rate_max = 192000,
   .channels_min = 1,
   .channels_max = 2,
  },
  .ops = &wcd934x_dai_ops,
 },
};

static int swclk_gate_enable(struct clk_hw *hw)
{
 return wcd934x_swrm_clock(to_wcd934x_codec(hw), true);
}

static void swclk_gate_disable(struct clk_hw *hw)
{
 wcd934x_swrm_clock(to_wcd934x_codec(hw), false);
}

static int swclk_gate_is_enabled(struct clk_hw *hw)
{
 struct wcd934x_codec *wcd = to_wcd934x_codec(hw);
 int ret, val;

 regmap_read(wcd->regmap, WCD934X_CDC_CLK_RST_CTRL_SWR_CONTROL, &val);
 ret = val & WCD934X_CDC_SWR_CLK_EN_MASK;

 return ret;
}

static unsigned long swclk_recalc_rate(struct clk_hw *hw,
           unsigned long parent_rate)
{
 return parent_rate / 2;
}

static const struct clk_ops swclk_gate_ops = {
 .prepare = swclk_gate_enable,
 .unprepare = swclk_gate_disable,
 .is_enabled = swclk_gate_is_enabled,
 .recalc_rate = swclk_recalc_rate,

};

static struct clk *wcd934x_register_mclk_output(struct wcd934x_codec *wcd)
{
 struct clk *parent = wcd->extclk;
 struct device *dev = wcd->dev;
 struct device_node *np = dev->parent->of_node;
 const char *parent_clk_name = NULL;
 const char *clk_name = "mclk";
 struct clk_hw *hw;
 struct clk_init_data init;
 int ret;

 if (of_property_read_u32(np, "clock-frequency", &wcd->rate))
  return NULL;

 parent_clk_name = __clk_get_name(parent);

 of_property_read_string(np, "clock-output-names", &clk_name);

 init.name = clk_name;
 init.ops = &swclk_gate_ops;
 init.flags = 0;
 init.parent_names = &parent_clk_name;
 init.num_parents = 1;
 wcd->hw.init = &init;

 hw = &wcd->hw;
 ret = devm_clk_hw_register(wcd->dev->parent, hw);
 if (ret)
  return ERR_PTR(ret);

 ret = devm_of_clk_add_hw_provider(dev, of_clk_hw_simple_get, hw);
 if (ret)
  return ERR_PTR(ret);

 return NULL;
}

static int wcd934x_get_micbias_val(struct device *dev, const char *micbias,
       u32 *micb_mv)
{
--> --------------------

--> maximum size reached

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

Messung V0.5
C=96 H=96 G=95

¤ Dauer der Verarbeitung: 0.12 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.