linux/sound/soc/codecs/msm8916-wcd-digital.c
<<
>>
Prefs
   1/* Copyright (c) 2016, The Linux Foundation. All rights reserved.
   2 *
   3 * This program is free software; you can redistribute it and/or modify
   4 * it under the terms of the GNU General Public License version 2 and
   5 * only version 2 as published by the Free Software Foundation.
   6 *
   7 * This program is distributed in the hope that it will be useful,
   8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
   9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  10 * GNU General Public License for more details.
  11 */
  12
  13#include <linux/module.h>
  14#include <linux/err.h>
  15#include <linux/kernel.h>
  16#include <linux/delay.h>
  17#include <linux/types.h>
  18#include <linux/clk.h>
  19#include <linux/of.h>
  20#include <linux/platform_device.h>
  21#include <linux/regmap.h>
  22#include <linux/mfd/syscon.h>
  23#include <sound/soc.h>
  24#include <sound/pcm.h>
  25#include <sound/pcm_params.h>
  26#include <sound/tlv.h>
  27
  28#define LPASS_CDC_CLK_RX_RESET_CTL              (0x000)
  29#define LPASS_CDC_CLK_TX_RESET_B1_CTL           (0x004)
  30#define CLK_RX_RESET_B1_CTL_TX1_RESET_MASK      BIT(0)
  31#define CLK_RX_RESET_B1_CTL_TX2_RESET_MASK      BIT(1)
  32#define LPASS_CDC_CLK_DMIC_B1_CTL               (0x008)
  33#define DMIC_B1_CTL_DMIC0_CLK_SEL_MASK          GENMASK(3, 1)
  34#define DMIC_B1_CTL_DMIC0_CLK_SEL_DIV2          (0x0 << 1)
  35#define DMIC_B1_CTL_DMIC0_CLK_SEL_DIV3          (0x1 << 1)
  36#define DMIC_B1_CTL_DMIC0_CLK_SEL_DIV4          (0x2 << 1)
  37#define DMIC_B1_CTL_DMIC0_CLK_SEL_DIV6          (0x3 << 1)
  38#define DMIC_B1_CTL_DMIC0_CLK_SEL_DIV16         (0x4 << 1)
  39#define DMIC_B1_CTL_DMIC0_CLK_EN_MASK           BIT(0)
  40#define DMIC_B1_CTL_DMIC0_CLK_EN_ENABLE         BIT(0)
  41
  42#define LPASS_CDC_CLK_RX_I2S_CTL                (0x00C)
  43#define RX_I2S_CTL_RX_I2S_MODE_MASK             BIT(5)
  44#define RX_I2S_CTL_RX_I2S_MODE_16               BIT(5)
  45#define RX_I2S_CTL_RX_I2S_MODE_32               0
  46#define RX_I2S_CTL_RX_I2S_FS_RATE_MASK          GENMASK(2, 0)
  47#define RX_I2S_CTL_RX_I2S_FS_RATE_F_8_KHZ       0x0
  48#define RX_I2S_CTL_RX_I2S_FS_RATE_F_16_KHZ      0x1
  49#define RX_I2S_CTL_RX_I2S_FS_RATE_F_32_KHZ      0x2
  50#define RX_I2S_CTL_RX_I2S_FS_RATE_F_48_KHZ      0x3
  51#define RX_I2S_CTL_RX_I2S_FS_RATE_F_96_KHZ      0x4
  52#define RX_I2S_CTL_RX_I2S_FS_RATE_F_192_KHZ     0x5
  53#define LPASS_CDC_CLK_TX_I2S_CTL                (0x010)
  54#define TX_I2S_CTL_TX_I2S_MODE_MASK             BIT(5)
  55#define TX_I2S_CTL_TX_I2S_MODE_16               BIT(5)
  56#define TX_I2S_CTL_TX_I2S_MODE_32               0
  57#define TX_I2S_CTL_TX_I2S_FS_RATE_MASK          GENMASK(2, 0)
  58#define TX_I2S_CTL_TX_I2S_FS_RATE_F_8_KHZ       0x0
  59#define TX_I2S_CTL_TX_I2S_FS_RATE_F_16_KHZ      0x1
  60#define TX_I2S_CTL_TX_I2S_FS_RATE_F_32_KHZ      0x2
  61#define TX_I2S_CTL_TX_I2S_FS_RATE_F_48_KHZ      0x3
  62#define TX_I2S_CTL_TX_I2S_FS_RATE_F_96_KHZ      0x4
  63#define TX_I2S_CTL_TX_I2S_FS_RATE_F_192_KHZ     0x5
  64
  65#define LPASS_CDC_CLK_OTHR_RESET_B1_CTL         (0x014)
  66#define LPASS_CDC_CLK_TX_CLK_EN_B1_CTL          (0x018)
  67#define LPASS_CDC_CLK_OTHR_CTL                  (0x01C)
  68#define LPASS_CDC_CLK_RX_B1_CTL                 (0x020)
  69#define LPASS_CDC_CLK_MCLK_CTL                  (0x024)
  70#define MCLK_CTL_MCLK_EN_MASK                   BIT(0)
  71#define MCLK_CTL_MCLK_EN_ENABLE                 BIT(0)
  72#define MCLK_CTL_MCLK_EN_DISABLE                0
  73#define LPASS_CDC_CLK_PDM_CTL                   (0x028)
  74#define LPASS_CDC_CLK_PDM_CTL_PDM_EN_MASK       BIT(0)
  75#define LPASS_CDC_CLK_PDM_CTL_PDM_EN            BIT(0)
  76#define LPASS_CDC_CLK_PDM_CTL_PDM_CLK_SEL_MASK  BIT(1)
  77#define LPASS_CDC_CLK_PDM_CTL_PDM_CLK_SEL_FB    BIT(1)
  78#define LPASS_CDC_CLK_PDM_CTL_PDM_CLK_PDM_CLK   0
  79
  80#define LPASS_CDC_CLK_SD_CTL                    (0x02C)
  81#define LPASS_CDC_RX1_B1_CTL                    (0x040)
  82#define LPASS_CDC_RX2_B1_CTL                    (0x060)
  83#define LPASS_CDC_RX3_B1_CTL                    (0x080)
  84#define LPASS_CDC_RX1_B2_CTL                    (0x044)
  85#define LPASS_CDC_RX2_B2_CTL                    (0x064)
  86#define LPASS_CDC_RX3_B2_CTL                    (0x084)
  87#define LPASS_CDC_RX1_B3_CTL                    (0x048)
  88#define LPASS_CDC_RX2_B3_CTL                    (0x068)
  89#define LPASS_CDC_RX3_B3_CTL                    (0x088)
  90#define LPASS_CDC_RX1_B4_CTL                    (0x04C)
  91#define LPASS_CDC_RX2_B4_CTL                    (0x06C)
  92#define LPASS_CDC_RX3_B4_CTL                    (0x08C)
  93#define LPASS_CDC_RX1_B5_CTL                    (0x050)
  94#define LPASS_CDC_RX2_B5_CTL                    (0x070)
  95#define LPASS_CDC_RX3_B5_CTL                    (0x090)
  96#define LPASS_CDC_RX1_B6_CTL                    (0x054)
  97#define RXn_B6_CTL_MUTE_MASK                    BIT(0)
  98#define RXn_B6_CTL_MUTE_ENABLE                  BIT(0)
  99#define RXn_B6_CTL_MUTE_DISABLE                 0
 100#define LPASS_CDC_RX2_B6_CTL                    (0x074)
 101#define LPASS_CDC_RX3_B6_CTL                    (0x094)
 102#define LPASS_CDC_RX1_VOL_CTL_B1_CTL            (0x058)
 103#define LPASS_CDC_RX2_VOL_CTL_B1_CTL            (0x078)
 104#define LPASS_CDC_RX3_VOL_CTL_B1_CTL            (0x098)
 105#define LPASS_CDC_RX1_VOL_CTL_B2_CTL            (0x05C)
 106#define LPASS_CDC_RX2_VOL_CTL_B2_CTL            (0x07C)
 107#define LPASS_CDC_RX3_VOL_CTL_B2_CTL            (0x09C)
 108#define LPASS_CDC_TOP_GAIN_UPDATE               (0x0A0)
 109#define LPASS_CDC_TOP_CTL                       (0x0A4)
 110#define TOP_CTL_DIG_MCLK_FREQ_MASK              BIT(0)
 111#define TOP_CTL_DIG_MCLK_FREQ_F_12_288MHZ       0
 112#define TOP_CTL_DIG_MCLK_FREQ_F_9_6MHZ          BIT(0)
 113
 114#define LPASS_CDC_DEBUG_DESER1_CTL              (0x0E0)
 115#define LPASS_CDC_DEBUG_DESER2_CTL              (0x0E4)
 116#define LPASS_CDC_DEBUG_B1_CTL_CFG              (0x0E8)
 117#define LPASS_CDC_DEBUG_B2_CTL_CFG              (0x0EC)
 118#define LPASS_CDC_DEBUG_B3_CTL_CFG              (0x0F0)
 119#define LPASS_CDC_IIR1_GAIN_B1_CTL              (0x100)
 120#define LPASS_CDC_IIR2_GAIN_B1_CTL              (0x140)
 121#define LPASS_CDC_IIR1_GAIN_B2_CTL              (0x104)
 122#define LPASS_CDC_IIR2_GAIN_B2_CTL              (0x144)
 123#define LPASS_CDC_IIR1_GAIN_B3_CTL              (0x108)
 124#define LPASS_CDC_IIR2_GAIN_B3_CTL              (0x148)
 125#define LPASS_CDC_IIR1_GAIN_B4_CTL              (0x10C)
 126#define LPASS_CDC_IIR2_GAIN_B4_CTL              (0x14C)
 127#define LPASS_CDC_IIR1_GAIN_B5_CTL              (0x110)
 128#define LPASS_CDC_IIR2_GAIN_B5_CTL              (0x150)
 129#define LPASS_CDC_IIR1_GAIN_B6_CTL              (0x114)
 130#define LPASS_CDC_IIR2_GAIN_B6_CTL              (0x154)
 131#define LPASS_CDC_IIR1_GAIN_B7_CTL              (0x118)
 132#define LPASS_CDC_IIR2_GAIN_B7_CTL              (0x158)
 133#define LPASS_CDC_IIR1_GAIN_B8_CTL              (0x11C)
 134#define LPASS_CDC_IIR2_GAIN_B8_CTL              (0x15C)
 135#define LPASS_CDC_IIR1_CTL                      (0x120)
 136#define LPASS_CDC_IIR2_CTL                      (0x160)
 137#define LPASS_CDC_IIR1_GAIN_TIMER_CTL           (0x124)
 138#define LPASS_CDC_IIR2_GAIN_TIMER_CTL           (0x164)
 139#define LPASS_CDC_IIR1_COEF_B1_CTL              (0x128)
 140#define LPASS_CDC_IIR2_COEF_B1_CTL              (0x168)
 141#define LPASS_CDC_IIR1_COEF_B2_CTL              (0x12C)
 142#define LPASS_CDC_IIR2_COEF_B2_CTL              (0x16C)
 143#define LPASS_CDC_CONN_RX1_B1_CTL               (0x180)
 144#define LPASS_CDC_CONN_RX1_B2_CTL               (0x184)
 145#define LPASS_CDC_CONN_RX1_B3_CTL               (0x188)
 146#define LPASS_CDC_CONN_RX2_B1_CTL               (0x18C)
 147#define LPASS_CDC_CONN_RX2_B2_CTL               (0x190)
 148#define LPASS_CDC_CONN_RX2_B3_CTL               (0x194)
 149#define LPASS_CDC_CONN_RX3_B1_CTL               (0x198)
 150#define LPASS_CDC_CONN_RX3_B2_CTL               (0x19C)
 151#define LPASS_CDC_CONN_TX_B1_CTL                (0x1A0)
 152#define LPASS_CDC_CONN_EQ1_B1_CTL               (0x1A8)
 153#define LPASS_CDC_CONN_EQ1_B2_CTL               (0x1AC)
 154#define LPASS_CDC_CONN_EQ1_B3_CTL               (0x1B0)
 155#define LPASS_CDC_CONN_EQ1_B4_CTL               (0x1B4)
 156#define LPASS_CDC_CONN_EQ2_B1_CTL               (0x1B8)
 157#define LPASS_CDC_CONN_EQ2_B2_CTL               (0x1BC)
 158#define LPASS_CDC_CONN_EQ2_B3_CTL               (0x1C0)
 159#define LPASS_CDC_CONN_EQ2_B4_CTL               (0x1C4)
 160#define LPASS_CDC_CONN_TX_I2S_SD1_CTL           (0x1C8)
 161#define LPASS_CDC_TX1_VOL_CTL_TIMER             (0x280)
 162#define LPASS_CDC_TX2_VOL_CTL_TIMER             (0x2A0)
 163#define LPASS_CDC_TX1_VOL_CTL_GAIN              (0x284)
 164#define LPASS_CDC_TX2_VOL_CTL_GAIN              (0x2A4)
 165#define LPASS_CDC_TX1_VOL_CTL_CFG               (0x288)
 166#define TX_VOL_CTL_CFG_MUTE_EN_MASK             BIT(0)
 167#define TX_VOL_CTL_CFG_MUTE_EN_ENABLE           BIT(0)
 168
 169#define LPASS_CDC_TX2_VOL_CTL_CFG               (0x2A8)
 170#define LPASS_CDC_TX1_MUX_CTL                   (0x28C)
 171#define TX_MUX_CTL_CUT_OFF_FREQ_MASK            GENMASK(5, 4)
 172#define TX_MUX_CTL_CUT_OFF_FREQ_SHIFT           4
 173#define TX_MUX_CTL_CF_NEG_3DB_4HZ               (0x0 << 4)
 174#define TX_MUX_CTL_CF_NEG_3DB_75HZ              (0x1 << 4)
 175#define TX_MUX_CTL_CF_NEG_3DB_150HZ             (0x2 << 4)
 176#define TX_MUX_CTL_HPF_BP_SEL_MASK              BIT(3)
 177#define TX_MUX_CTL_HPF_BP_SEL_BYPASS            BIT(3)
 178#define TX_MUX_CTL_HPF_BP_SEL_NO_BYPASS         0
 179
 180#define LPASS_CDC_TX2_MUX_CTL                   (0x2AC)
 181#define LPASS_CDC_TX1_CLK_FS_CTL                (0x290)
 182#define LPASS_CDC_TX2_CLK_FS_CTL                (0x2B0)
 183#define LPASS_CDC_TX1_DMIC_CTL                  (0x294)
 184#define LPASS_CDC_TX2_DMIC_CTL                  (0x2B4)
 185#define TXN_DMIC_CTL_CLK_SEL_MASK               GENMASK(2, 0)
 186#define TXN_DMIC_CTL_CLK_SEL_DIV2               0x0
 187#define TXN_DMIC_CTL_CLK_SEL_DIV3               0x1
 188#define TXN_DMIC_CTL_CLK_SEL_DIV4               0x2
 189#define TXN_DMIC_CTL_CLK_SEL_DIV6               0x3
 190#define TXN_DMIC_CTL_CLK_SEL_DIV16              0x4
 191
 192#define MSM8916_WCD_DIGITAL_RATES (SNDRV_PCM_RATE_8000 | \
 193                                   SNDRV_PCM_RATE_16000 | \
 194                                   SNDRV_PCM_RATE_32000 | \
 195                                   SNDRV_PCM_RATE_48000)
 196#define MSM8916_WCD_DIGITAL_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\
 197                                     SNDRV_PCM_FMTBIT_S32_LE)
 198
 199struct msm8916_wcd_digital_priv {
 200        struct clk *ahbclk, *mclk;
 201};
 202
 203static const unsigned long rx_gain_reg[] = {
 204        LPASS_CDC_RX1_VOL_CTL_B2_CTL,
 205        LPASS_CDC_RX2_VOL_CTL_B2_CTL,
 206        LPASS_CDC_RX3_VOL_CTL_B2_CTL,
 207};
 208
 209static const unsigned long tx_gain_reg[] = {
 210        LPASS_CDC_TX1_VOL_CTL_GAIN,
 211        LPASS_CDC_TX2_VOL_CTL_GAIN,
 212};
 213
 214static const char *const rx_mix1_text[] = {
 215        "ZERO", "IIR1", "IIR2", "RX1", "RX2", "RX3"
 216};
 217
 218static const char *const dec_mux_text[] = {
 219        "ZERO", "ADC1", "ADC2", "ADC3", "DMIC1", "DMIC2"
 220};
 221
 222static const char *const cic_mux_text[] = { "AMIC", "DMIC" };
 223static const char *const rx_mix2_text[] = { "ZERO", "IIR1", "IIR2" };
 224static const char *const adc2_mux_text[] = { "ZERO", "INP2", "INP3" };
 225
 226/* RX1 MIX1 */
 227static const struct soc_enum rx_mix1_inp_enum[] = {
 228        SOC_ENUM_SINGLE(LPASS_CDC_CONN_RX1_B1_CTL, 0, 6, rx_mix1_text),
 229        SOC_ENUM_SINGLE(LPASS_CDC_CONN_RX1_B1_CTL, 3, 6, rx_mix1_text),
 230        SOC_ENUM_SINGLE(LPASS_CDC_CONN_RX1_B2_CTL, 0, 6, rx_mix1_text),
 231};
 232
 233/* RX1 MIX2 */
 234static const struct soc_enum rx_mix2_inp1_chain_enum = SOC_ENUM_SINGLE(
 235                                LPASS_CDC_CONN_RX1_B3_CTL, 0, 3, rx_mix2_text);
 236
 237/* RX2 MIX1 */
 238static const struct soc_enum rx2_mix1_inp_enum[] = {
 239        SOC_ENUM_SINGLE(LPASS_CDC_CONN_RX2_B1_CTL, 0, 6, rx_mix1_text),
 240        SOC_ENUM_SINGLE(LPASS_CDC_CONN_RX2_B1_CTL, 3, 6, rx_mix1_text),
 241        SOC_ENUM_SINGLE(LPASS_CDC_CONN_RX2_B2_CTL, 0, 6, rx_mix1_text),
 242};
 243
 244/* RX2 MIX2 */
 245static const struct soc_enum rx2_mix2_inp1_chain_enum = SOC_ENUM_SINGLE(
 246                                LPASS_CDC_CONN_RX2_B3_CTL, 0, 3, rx_mix2_text);
 247
 248/* RX3 MIX1 */
 249static const struct soc_enum rx3_mix1_inp_enum[] = {
 250        SOC_ENUM_SINGLE(LPASS_CDC_CONN_RX3_B1_CTL, 0, 6, rx_mix1_text),
 251        SOC_ENUM_SINGLE(LPASS_CDC_CONN_RX3_B1_CTL, 3, 6, rx_mix1_text),
 252        SOC_ENUM_SINGLE(LPASS_CDC_CONN_RX3_B2_CTL, 0, 6, rx_mix1_text),
 253};
 254
 255/* DEC */
 256static const struct soc_enum dec1_mux_enum = SOC_ENUM_SINGLE(
 257                                LPASS_CDC_CONN_TX_B1_CTL, 0, 6, dec_mux_text);
 258static const struct soc_enum dec2_mux_enum = SOC_ENUM_SINGLE(
 259                                LPASS_CDC_CONN_TX_B1_CTL, 3, 6, dec_mux_text);
 260
 261/* CIC */
 262static const struct soc_enum cic1_mux_enum = SOC_ENUM_SINGLE(
 263                                LPASS_CDC_TX1_MUX_CTL, 0, 2, cic_mux_text);
 264static const struct soc_enum cic2_mux_enum = SOC_ENUM_SINGLE(
 265                                LPASS_CDC_TX2_MUX_CTL, 0, 2, cic_mux_text);
 266
 267/* RDAC2 MUX */
 268static const struct snd_kcontrol_new dec1_mux = SOC_DAPM_ENUM(
 269                                "DEC1 MUX Mux", dec1_mux_enum);
 270static const struct snd_kcontrol_new dec2_mux = SOC_DAPM_ENUM(
 271                                "DEC2 MUX Mux", dec2_mux_enum);
 272static const struct snd_kcontrol_new cic1_mux = SOC_DAPM_ENUM(
 273                                "CIC1 MUX Mux", cic1_mux_enum);
 274static const struct snd_kcontrol_new cic2_mux = SOC_DAPM_ENUM(
 275                                "CIC2 MUX Mux", cic2_mux_enum);
 276static const struct snd_kcontrol_new rx_mix1_inp1_mux = SOC_DAPM_ENUM(
 277                                "RX1 MIX1 INP1 Mux", rx_mix1_inp_enum[0]);
 278static const struct snd_kcontrol_new rx_mix1_inp2_mux = SOC_DAPM_ENUM(
 279                                "RX1 MIX1 INP2 Mux", rx_mix1_inp_enum[1]);
 280static const struct snd_kcontrol_new rx_mix1_inp3_mux = SOC_DAPM_ENUM(
 281                                "RX1 MIX1 INP3 Mux", rx_mix1_inp_enum[2]);
 282static const struct snd_kcontrol_new rx2_mix1_inp1_mux = SOC_DAPM_ENUM(
 283                                "RX2 MIX1 INP1 Mux", rx2_mix1_inp_enum[0]);
 284static const struct snd_kcontrol_new rx2_mix1_inp2_mux = SOC_DAPM_ENUM(
 285                                "RX2 MIX1 INP2 Mux", rx2_mix1_inp_enum[1]);
 286static const struct snd_kcontrol_new rx2_mix1_inp3_mux = SOC_DAPM_ENUM(
 287                                "RX2 MIX1 INP3 Mux", rx2_mix1_inp_enum[2]);
 288static const struct snd_kcontrol_new rx3_mix1_inp1_mux = SOC_DAPM_ENUM(
 289                                "RX3 MIX1 INP1 Mux", rx3_mix1_inp_enum[0]);
 290static const struct snd_kcontrol_new rx3_mix1_inp2_mux = SOC_DAPM_ENUM(
 291                                "RX3 MIX1 INP2 Mux", rx3_mix1_inp_enum[1]);
 292static const struct snd_kcontrol_new rx3_mix1_inp3_mux = SOC_DAPM_ENUM(
 293                                "RX3 MIX1 INP3 Mux", rx3_mix1_inp_enum[2]);
 294
 295/* Digital Gain control -38.4 dB to +38.4 dB in 0.3 dB steps */
 296static const DECLARE_TLV_DB_SCALE(digital_gain, -3840, 30, 0);
 297
 298/* Cutoff Freq for High Pass Filter at -3dB */
 299static const char * const hpf_cutoff_text[] = {
 300        "4Hz", "75Hz", "150Hz",
 301};
 302
 303static SOC_ENUM_SINGLE_DECL(tx1_hpf_cutoff_enum, LPASS_CDC_TX1_MUX_CTL, 4,
 304                            hpf_cutoff_text);
 305static SOC_ENUM_SINGLE_DECL(tx2_hpf_cutoff_enum, LPASS_CDC_TX2_MUX_CTL, 4,
 306                            hpf_cutoff_text);
 307
 308/* cut off for dc blocker inside rx chain */
 309static const char * const dc_blocker_cutoff_text[] = {
 310        "4Hz", "75Hz", "150Hz",
 311};
 312
 313static SOC_ENUM_SINGLE_DECL(rx1_dcb_cutoff_enum, LPASS_CDC_RX1_B4_CTL, 0,
 314                            dc_blocker_cutoff_text);
 315static SOC_ENUM_SINGLE_DECL(rx2_dcb_cutoff_enum, LPASS_CDC_RX2_B4_CTL, 0,
 316                            dc_blocker_cutoff_text);
 317static SOC_ENUM_SINGLE_DECL(rx3_dcb_cutoff_enum, LPASS_CDC_RX3_B4_CTL, 0,
 318                            dc_blocker_cutoff_text);
 319
 320static const struct snd_kcontrol_new msm8916_wcd_digital_snd_controls[] = {
 321        SOC_SINGLE_S8_TLV("RX1 Digital Volume", LPASS_CDC_RX1_VOL_CTL_B2_CTL,
 322                          -128, 127, digital_gain),
 323        SOC_SINGLE_S8_TLV("RX2 Digital Volume", LPASS_CDC_RX2_VOL_CTL_B2_CTL,
 324                          -128, 127, digital_gain),
 325        SOC_SINGLE_S8_TLV("RX3 Digital Volume", LPASS_CDC_RX3_VOL_CTL_B2_CTL,
 326                          -128, 127, digital_gain),
 327        SOC_SINGLE_S8_TLV("TX1 Digital Volume", LPASS_CDC_TX1_VOL_CTL_GAIN,
 328                          -128, 127, digital_gain),
 329        SOC_SINGLE_S8_TLV("TX2 Digital Volume", LPASS_CDC_TX2_VOL_CTL_GAIN,
 330                          -128, 127, digital_gain),
 331        SOC_ENUM("TX1 HPF Cutoff", tx1_hpf_cutoff_enum),
 332        SOC_ENUM("TX2 HPF Cutoff", tx2_hpf_cutoff_enum),
 333        SOC_SINGLE("TX1 HPF Switch", LPASS_CDC_TX1_MUX_CTL, 3, 1, 0),
 334        SOC_SINGLE("TX2 HPF Switch", LPASS_CDC_TX2_MUX_CTL, 3, 1, 0),
 335        SOC_ENUM("RX1 DCB Cutoff", rx1_dcb_cutoff_enum),
 336        SOC_ENUM("RX2 DCB Cutoff", rx2_dcb_cutoff_enum),
 337        SOC_ENUM("RX3 DCB Cutoff", rx3_dcb_cutoff_enum),
 338        SOC_SINGLE("RX1 DCB Switch", LPASS_CDC_RX1_B5_CTL, 2, 1, 0),
 339        SOC_SINGLE("RX2 DCB Switch", LPASS_CDC_RX2_B5_CTL, 2, 1, 0),
 340        SOC_SINGLE("RX3 DCB Switch", LPASS_CDC_RX3_B5_CTL, 2, 1, 0),
 341        SOC_SINGLE("RX1 Mute Switch", LPASS_CDC_RX1_B6_CTL, 0, 1, 0),
 342        SOC_SINGLE("RX2 Mute Switch", LPASS_CDC_RX2_B6_CTL, 0, 1, 0),
 343        SOC_SINGLE("RX3 Mute Switch", LPASS_CDC_RX3_B6_CTL, 0, 1, 0),
 344};
 345
 346static int msm8916_wcd_digital_enable_interpolator(
 347                                                struct snd_soc_dapm_widget *w,
 348                                                struct snd_kcontrol *kcontrol,
 349                                                int event)
 350{
 351        struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
 352
 353        switch (event) {
 354        case SND_SOC_DAPM_POST_PMU:
 355                /* apply the digital gain after the interpolator is enabled */
 356                usleep_range(10000, 10100);
 357                snd_soc_write(codec, rx_gain_reg[w->shift],
 358                              snd_soc_read(codec, rx_gain_reg[w->shift]));
 359                break;
 360        }
 361        return 0;
 362}
 363
 364static int msm8916_wcd_digital_enable_dec(struct snd_soc_dapm_widget *w,
 365                                          struct snd_kcontrol *kcontrol,
 366                                          int event)
 367{
 368        struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
 369        unsigned int decimator = w->shift + 1;
 370        u16 dec_reset_reg, tx_vol_ctl_reg, tx_mux_ctl_reg;
 371        u8 dec_hpf_cut_of_freq;
 372
 373        dec_reset_reg = LPASS_CDC_CLK_TX_RESET_B1_CTL;
 374        tx_vol_ctl_reg = LPASS_CDC_TX1_VOL_CTL_CFG + 32 * (decimator - 1);
 375        tx_mux_ctl_reg = LPASS_CDC_TX1_MUX_CTL + 32 * (decimator - 1);
 376
 377        switch (event) {
 378        case SND_SOC_DAPM_PRE_PMU:
 379                /* Enable TX digital mute */
 380                snd_soc_update_bits(codec, tx_vol_ctl_reg,
 381                                    TX_VOL_CTL_CFG_MUTE_EN_MASK,
 382                                    TX_VOL_CTL_CFG_MUTE_EN_ENABLE);
 383                dec_hpf_cut_of_freq = snd_soc_read(codec, tx_mux_ctl_reg) &
 384                                        TX_MUX_CTL_CUT_OFF_FREQ_MASK;
 385                dec_hpf_cut_of_freq >>= TX_MUX_CTL_CUT_OFF_FREQ_SHIFT;
 386                if (dec_hpf_cut_of_freq != TX_MUX_CTL_CF_NEG_3DB_150HZ) {
 387                        /* set cut of freq to CF_MIN_3DB_150HZ (0x1) */
 388                        snd_soc_update_bits(codec, tx_mux_ctl_reg,
 389                                            TX_MUX_CTL_CUT_OFF_FREQ_MASK,
 390                                            TX_MUX_CTL_CF_NEG_3DB_150HZ);
 391                }
 392                break;
 393        case SND_SOC_DAPM_POST_PMU:
 394                /* enable HPF */
 395                snd_soc_update_bits(codec, tx_mux_ctl_reg,
 396                                    TX_MUX_CTL_HPF_BP_SEL_MASK,
 397                                    TX_MUX_CTL_HPF_BP_SEL_NO_BYPASS);
 398                /* apply the digital gain after the decimator is enabled */
 399                snd_soc_write(codec, tx_gain_reg[w->shift],
 400                              snd_soc_read(codec, tx_gain_reg[w->shift]));
 401                snd_soc_update_bits(codec, tx_vol_ctl_reg,
 402                                    TX_VOL_CTL_CFG_MUTE_EN_MASK, 0);
 403                break;
 404        case SND_SOC_DAPM_PRE_PMD:
 405                snd_soc_update_bits(codec, tx_vol_ctl_reg,
 406                                    TX_VOL_CTL_CFG_MUTE_EN_MASK,
 407                                    TX_VOL_CTL_CFG_MUTE_EN_ENABLE);
 408                snd_soc_update_bits(codec, tx_mux_ctl_reg,
 409                                    TX_MUX_CTL_HPF_BP_SEL_MASK,
 410                                    TX_MUX_CTL_HPF_BP_SEL_BYPASS);
 411                break;
 412        case SND_SOC_DAPM_POST_PMD:
 413                snd_soc_update_bits(codec, dec_reset_reg, 1 << w->shift,
 414                                    1 << w->shift);
 415                snd_soc_update_bits(codec, dec_reset_reg, 1 << w->shift, 0x0);
 416                snd_soc_update_bits(codec, tx_mux_ctl_reg,
 417                                    TX_MUX_CTL_HPF_BP_SEL_MASK,
 418                                    TX_MUX_CTL_HPF_BP_SEL_BYPASS);
 419                snd_soc_update_bits(codec, tx_vol_ctl_reg,
 420                                    TX_VOL_CTL_CFG_MUTE_EN_MASK, 0);
 421                break;
 422        }
 423
 424        return 0;
 425}
 426
 427static int msm8916_wcd_digital_enable_dmic(struct snd_soc_dapm_widget *w,
 428                                           struct snd_kcontrol *kcontrol,
 429                                           int event)
 430{
 431        struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
 432        unsigned int dmic;
 433        int ret;
 434        /* get dmic number out of widget name */
 435        char *dmic_num = strpbrk(w->name, "12");
 436
 437        if (dmic_num == NULL) {
 438                dev_err(codec->dev, "Invalid DMIC\n");
 439                return -EINVAL;
 440        }
 441        ret = kstrtouint(dmic_num, 10, &dmic);
 442        if (ret < 0 || dmic > 2) {
 443                dev_err(codec->dev, "Invalid DMIC line on the codec\n");
 444                return -EINVAL;
 445        }
 446
 447        switch (event) {
 448        case SND_SOC_DAPM_PRE_PMU:
 449                snd_soc_update_bits(codec, LPASS_CDC_CLK_DMIC_B1_CTL,
 450                                    DMIC_B1_CTL_DMIC0_CLK_SEL_MASK,
 451                                    DMIC_B1_CTL_DMIC0_CLK_SEL_DIV3);
 452                switch (dmic) {
 453                case 1:
 454                        snd_soc_update_bits(codec, LPASS_CDC_TX1_DMIC_CTL,
 455                                            TXN_DMIC_CTL_CLK_SEL_MASK,
 456                                            TXN_DMIC_CTL_CLK_SEL_DIV3);
 457                        break;
 458                case 2:
 459                        snd_soc_update_bits(codec, LPASS_CDC_TX2_DMIC_CTL,
 460                                            TXN_DMIC_CTL_CLK_SEL_MASK,
 461                                            TXN_DMIC_CTL_CLK_SEL_DIV3);
 462                        break;
 463                }
 464                break;
 465        }
 466
 467        return 0;
 468}
 469
 470static const struct snd_soc_dapm_widget msm8916_wcd_digital_dapm_widgets[] = {
 471        /*RX stuff */
 472        SND_SOC_DAPM_AIF_IN("I2S RX1", NULL, 0, SND_SOC_NOPM, 0, 0),
 473        SND_SOC_DAPM_AIF_IN("I2S RX2", NULL, 0, SND_SOC_NOPM, 0, 0),
 474        SND_SOC_DAPM_AIF_IN("I2S RX3", NULL, 0, SND_SOC_NOPM, 0, 0),
 475
 476        SND_SOC_DAPM_OUTPUT("PDM_RX1"),
 477        SND_SOC_DAPM_OUTPUT("PDM_RX2"),
 478        SND_SOC_DAPM_OUTPUT("PDM_RX3"),
 479
 480        SND_SOC_DAPM_INPUT("LPASS_PDM_TX"),
 481
 482        SND_SOC_DAPM_MIXER("RX1 MIX1", SND_SOC_NOPM, 0, 0, NULL, 0),
 483        SND_SOC_DAPM_MIXER("RX2 MIX1", SND_SOC_NOPM, 0, 0, NULL, 0),
 484        SND_SOC_DAPM_MIXER("RX3 MIX1", SND_SOC_NOPM, 0, 0, NULL, 0),
 485
 486        /* Interpolator */
 487        SND_SOC_DAPM_MIXER_E("RX1 INT", LPASS_CDC_CLK_RX_B1_CTL, 0, 0, NULL,
 488                             0, msm8916_wcd_digital_enable_interpolator,
 489                             SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
 490        SND_SOC_DAPM_MIXER_E("RX2 INT", LPASS_CDC_CLK_RX_B1_CTL, 1, 0, NULL,
 491                             0, msm8916_wcd_digital_enable_interpolator,
 492                             SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
 493        SND_SOC_DAPM_MIXER_E("RX3 INT", LPASS_CDC_CLK_RX_B1_CTL, 2, 0, NULL,
 494                             0, msm8916_wcd_digital_enable_interpolator,
 495                             SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
 496        SND_SOC_DAPM_MUX("RX1 MIX1 INP1", SND_SOC_NOPM, 0, 0,
 497                         &rx_mix1_inp1_mux),
 498        SND_SOC_DAPM_MUX("RX1 MIX1 INP2", SND_SOC_NOPM, 0, 0,
 499                         &rx_mix1_inp2_mux),
 500        SND_SOC_DAPM_MUX("RX1 MIX1 INP3", SND_SOC_NOPM, 0, 0,
 501                         &rx_mix1_inp3_mux),
 502        SND_SOC_DAPM_MUX("RX2 MIX1 INP1", SND_SOC_NOPM, 0, 0,
 503                         &rx2_mix1_inp1_mux),
 504        SND_SOC_DAPM_MUX("RX2 MIX1 INP2", SND_SOC_NOPM, 0, 0,
 505                         &rx2_mix1_inp2_mux),
 506        SND_SOC_DAPM_MUX("RX2 MIX1 INP3", SND_SOC_NOPM, 0, 0,
 507                         &rx2_mix1_inp3_mux),
 508        SND_SOC_DAPM_MUX("RX3 MIX1 INP1", SND_SOC_NOPM, 0, 0,
 509                         &rx3_mix1_inp1_mux),
 510        SND_SOC_DAPM_MUX("RX3 MIX1 INP2", SND_SOC_NOPM, 0, 0,
 511                         &rx3_mix1_inp2_mux),
 512        SND_SOC_DAPM_MUX("RX3 MIX1 INP3", SND_SOC_NOPM, 0, 0,
 513                         &rx3_mix1_inp3_mux),
 514
 515        SND_SOC_DAPM_MUX("CIC1 MUX", SND_SOC_NOPM, 0, 0, &cic1_mux),
 516        SND_SOC_DAPM_MUX("CIC2 MUX", SND_SOC_NOPM, 0, 0, &cic2_mux),
 517        /* TX */
 518        SND_SOC_DAPM_MIXER("ADC1", SND_SOC_NOPM, 0, 0, NULL, 0),
 519        SND_SOC_DAPM_MIXER("ADC2", SND_SOC_NOPM, 0, 0, NULL, 0),
 520        SND_SOC_DAPM_MIXER("ADC3", SND_SOC_NOPM, 0, 0, NULL, 0),
 521
 522        SND_SOC_DAPM_MUX_E("DEC1 MUX", LPASS_CDC_CLK_TX_CLK_EN_B1_CTL, 0, 0,
 523                           &dec1_mux, msm8916_wcd_digital_enable_dec,
 524                           SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
 525                           SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
 526        SND_SOC_DAPM_MUX_E("DEC2 MUX", LPASS_CDC_CLK_TX_CLK_EN_B1_CTL, 1, 0,
 527                           &dec2_mux, msm8916_wcd_digital_enable_dec,
 528                           SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
 529                           SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
 530        SND_SOC_DAPM_AIF_OUT("I2S TX1", NULL, 0, SND_SOC_NOPM, 0, 0),
 531        SND_SOC_DAPM_AIF_OUT("I2S TX2", NULL, 0, SND_SOC_NOPM, 0, 0),
 532        SND_SOC_DAPM_AIF_OUT("I2S TX3", NULL, 0, SND_SOC_NOPM, 0, 0),
 533
 534        /* Digital Mic Inputs */
 535        SND_SOC_DAPM_ADC_E("DMIC1", NULL, SND_SOC_NOPM, 0, 0,
 536                           msm8916_wcd_digital_enable_dmic,
 537                           SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
 538        SND_SOC_DAPM_ADC_E("DMIC2", NULL, SND_SOC_NOPM, 0, 0,
 539                           msm8916_wcd_digital_enable_dmic,
 540                           SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
 541        SND_SOC_DAPM_SUPPLY("DMIC_CLK", LPASS_CDC_CLK_DMIC_B1_CTL, 0, 0,
 542                            NULL, 0),
 543        SND_SOC_DAPM_SUPPLY("RX_I2S_CLK", LPASS_CDC_CLK_RX_I2S_CTL,
 544                            4, 0, NULL, 0),
 545        SND_SOC_DAPM_SUPPLY("TX_I2S_CLK", LPASS_CDC_CLK_TX_I2S_CTL, 4, 0,
 546                            NULL, 0),
 547
 548        SND_SOC_DAPM_SUPPLY("MCLK", SND_SOC_NOPM, 0, 0, NULL, 0),
 549        SND_SOC_DAPM_SUPPLY("PDM_CLK", LPASS_CDC_CLK_PDM_CTL, 0, 0, NULL, 0),
 550        /* Connectivity Clock */
 551        SND_SOC_DAPM_SUPPLY_S("CDC_CONN", -2, LPASS_CDC_CLK_OTHR_CTL, 2, 0,
 552                              NULL, 0),
 553        SND_SOC_DAPM_MIC("Digital Mic1", NULL),
 554        SND_SOC_DAPM_MIC("Digital Mic2", NULL),
 555
 556};
 557
 558static int msm8916_wcd_digital_get_clks(struct platform_device *pdev,
 559                                        struct msm8916_wcd_digital_priv *priv)
 560{
 561        struct device *dev = &pdev->dev;
 562
 563        priv->ahbclk = devm_clk_get(dev, "ahbix-clk");
 564        if (IS_ERR(priv->ahbclk)) {
 565                dev_err(dev, "failed to get ahbix clk\n");
 566                return PTR_ERR(priv->ahbclk);
 567        }
 568
 569        priv->mclk = devm_clk_get(dev, "mclk");
 570        if (IS_ERR(priv->mclk)) {
 571                dev_err(dev, "failed to get mclk\n");
 572                return PTR_ERR(priv->mclk);
 573        }
 574
 575        return 0;
 576}
 577
 578static int msm8916_wcd_digital_codec_probe(struct snd_soc_codec *codec)
 579{
 580        struct msm8916_wcd_digital_priv *priv = dev_get_drvdata(codec->dev);
 581
 582        snd_soc_codec_set_drvdata(codec, priv);
 583
 584        return 0;
 585}
 586
 587static int msm8916_wcd_digital_codec_set_sysclk(struct snd_soc_codec *codec,
 588                                                int clk_id, int source,
 589                                                unsigned int freq, int dir)
 590{
 591        struct msm8916_wcd_digital_priv *p = dev_get_drvdata(codec->dev);
 592
 593        return clk_set_rate(p->mclk, freq);
 594}
 595
 596static int msm8916_wcd_digital_hw_params(struct snd_pcm_substream *substream,
 597                                         struct snd_pcm_hw_params *params,
 598                                         struct snd_soc_dai *dai)
 599{
 600        u8 tx_fs_rate;
 601        u8 rx_fs_rate;
 602
 603        switch (params_rate(params)) {
 604        case 8000:
 605                tx_fs_rate = TX_I2S_CTL_TX_I2S_FS_RATE_F_8_KHZ;
 606                rx_fs_rate = RX_I2S_CTL_RX_I2S_FS_RATE_F_8_KHZ;
 607                break;
 608        case 16000:
 609                tx_fs_rate = TX_I2S_CTL_TX_I2S_FS_RATE_F_16_KHZ;
 610                rx_fs_rate = RX_I2S_CTL_RX_I2S_FS_RATE_F_16_KHZ;
 611                break;
 612        case 32000:
 613                tx_fs_rate = TX_I2S_CTL_TX_I2S_FS_RATE_F_32_KHZ;
 614                rx_fs_rate = RX_I2S_CTL_RX_I2S_FS_RATE_F_32_KHZ;
 615                break;
 616        case 48000:
 617                tx_fs_rate = TX_I2S_CTL_TX_I2S_FS_RATE_F_48_KHZ;
 618                rx_fs_rate = RX_I2S_CTL_RX_I2S_FS_RATE_F_48_KHZ;
 619                break;
 620        default:
 621                dev_err(dai->codec->dev, "Invalid sampling rate %d\n",
 622                        params_rate(params));
 623                return -EINVAL;
 624        }
 625
 626        switch (substream->stream) {
 627        case SNDRV_PCM_STREAM_CAPTURE:
 628                snd_soc_update_bits(dai->codec, LPASS_CDC_CLK_TX_I2S_CTL,
 629                                    TX_I2S_CTL_TX_I2S_FS_RATE_MASK, tx_fs_rate);
 630                break;
 631        case SNDRV_PCM_STREAM_PLAYBACK:
 632                snd_soc_update_bits(dai->codec, LPASS_CDC_CLK_RX_I2S_CTL,
 633                                    RX_I2S_CTL_RX_I2S_FS_RATE_MASK, rx_fs_rate);
 634                break;
 635        default:
 636                return -EINVAL;
 637        }
 638
 639        switch (params_format(params)) {
 640        case SNDRV_PCM_FORMAT_S16_LE:
 641                snd_soc_update_bits(dai->codec, LPASS_CDC_CLK_TX_I2S_CTL,
 642                                    TX_I2S_CTL_TX_I2S_MODE_MASK,
 643                                    TX_I2S_CTL_TX_I2S_MODE_16);
 644                snd_soc_update_bits(dai->codec, LPASS_CDC_CLK_RX_I2S_CTL,
 645                                    RX_I2S_CTL_RX_I2S_MODE_MASK,
 646                                    RX_I2S_CTL_RX_I2S_MODE_16);
 647                break;
 648        case SNDRV_PCM_FORMAT_S32_LE:
 649                snd_soc_update_bits(dai->codec, LPASS_CDC_CLK_TX_I2S_CTL,
 650                                    TX_I2S_CTL_TX_I2S_MODE_MASK,
 651                                    TX_I2S_CTL_TX_I2S_MODE_32);
 652                snd_soc_update_bits(dai->codec, LPASS_CDC_CLK_RX_I2S_CTL,
 653                                    RX_I2S_CTL_RX_I2S_MODE_MASK,
 654                                    RX_I2S_CTL_RX_I2S_MODE_32);
 655                break;
 656        default:
 657                dev_err(dai->dev, "%s: wrong format selected\n", __func__);
 658                return -EINVAL;
 659        }
 660
 661        return 0;
 662}
 663
 664static const struct snd_soc_dapm_route msm8916_wcd_digital_audio_map[] = {
 665
 666        {"I2S RX1",  NULL, "AIF1 Playback"},
 667        {"I2S RX2",  NULL, "AIF1 Playback"},
 668        {"I2S RX3",  NULL, "AIF1 Playback"},
 669
 670        {"AIF1 Capture", NULL, "I2S TX1"},
 671        {"AIF1 Capture", NULL, "I2S TX2"},
 672        {"AIF1 Capture", NULL, "I2S TX3"},
 673
 674        {"CIC1 MUX", "DMIC", "DEC1 MUX"},
 675        {"CIC1 MUX", "AMIC", "DEC1 MUX"},
 676        {"CIC2 MUX", "DMIC", "DEC2 MUX"},
 677        {"CIC2 MUX", "AMIC", "DEC2 MUX"},
 678
 679        /* Decimator Inputs */
 680        {"DEC1 MUX", "DMIC1", "DMIC1"},
 681        {"DEC1 MUX", "DMIC2", "DMIC2"},
 682        {"DEC1 MUX", "ADC1", "ADC1"},
 683        {"DEC1 MUX", "ADC2", "ADC2"},
 684        {"DEC1 MUX", "ADC3", "ADC3"},
 685        {"DEC1 MUX", NULL, "CDC_CONN"},
 686
 687        {"DEC2 MUX", "DMIC1", "DMIC1"},
 688        {"DEC2 MUX", "DMIC2", "DMIC2"},
 689        {"DEC2 MUX", "ADC1", "ADC1"},
 690        {"DEC2 MUX", "ADC2", "ADC2"},
 691        {"DEC2 MUX", "ADC3", "ADC3"},
 692        {"DEC2 MUX", NULL, "CDC_CONN"},
 693
 694        {"DMIC1", NULL, "DMIC_CLK"},
 695        {"DMIC2", NULL, "DMIC_CLK"},
 696
 697        {"I2S TX1", NULL, "CIC1 MUX"},
 698        {"I2S TX2", NULL, "CIC2 MUX"},
 699
 700        {"I2S TX1", NULL, "TX_I2S_CLK"},
 701        {"I2S TX2", NULL, "TX_I2S_CLK"},
 702
 703        {"TX_I2S_CLK", NULL, "MCLK"},
 704        {"TX_I2S_CLK", NULL, "PDM_CLK"},
 705
 706        {"ADC1", NULL, "LPASS_PDM_TX"},
 707        {"ADC2", NULL, "LPASS_PDM_TX"},
 708        {"ADC3", NULL, "LPASS_PDM_TX"},
 709
 710        {"I2S RX1", NULL, "RX_I2S_CLK"},
 711        {"I2S RX2", NULL, "RX_I2S_CLK"},
 712        {"I2S RX3", NULL, "RX_I2S_CLK"},
 713
 714        {"RX_I2S_CLK", NULL, "PDM_CLK"},
 715        {"RX_I2S_CLK", NULL, "MCLK"},
 716        {"RX_I2S_CLK", NULL, "CDC_CONN"},
 717
 718        /* RX1 PATH.. */
 719        {"PDM_RX1", NULL, "RX1 INT"},
 720        {"RX1 INT", NULL, "RX1 MIX1"},
 721
 722        {"RX1 MIX1", NULL, "RX1 MIX1 INP1"},
 723        {"RX1 MIX1", NULL, "RX1 MIX1 INP2"},
 724        {"RX1 MIX1", NULL, "RX1 MIX1 INP3"},
 725
 726        {"RX1 MIX1 INP1", "RX1", "I2S RX1"},
 727        {"RX1 MIX1 INP1", "RX2", "I2S RX2"},
 728        {"RX1 MIX1 INP1", "RX3", "I2S RX3"},
 729
 730        {"RX1 MIX1 INP2", "RX1", "I2S RX1"},
 731        {"RX1 MIX1 INP2", "RX2", "I2S RX2"},
 732        {"RX1 MIX1 INP2", "RX3", "I2S RX3"},
 733
 734        {"RX1 MIX1 INP3", "RX1", "I2S RX1"},
 735        {"RX1 MIX1 INP3", "RX2", "I2S RX2"},
 736        {"RX1 MIX1 INP3", "RX3", "I2S RX3"},
 737
 738        /* RX2 PATH */
 739        {"PDM_RX2", NULL, "RX2 INT"},
 740        {"RX2 INT", NULL, "RX2 MIX1"},
 741
 742        {"RX2 MIX1", NULL, "RX2 MIX1 INP1"},
 743        {"RX2 MIX1", NULL, "RX2 MIX1 INP2"},
 744        {"RX2 MIX1", NULL, "RX2 MIX1 INP3"},
 745
 746        {"RX2 MIX1 INP1", "RX1", "I2S RX1"},
 747        {"RX2 MIX1 INP1", "RX2", "I2S RX2"},
 748        {"RX2 MIX1 INP1", "RX3", "I2S RX3"},
 749
 750        {"RX2 MIX1 INP2", "RX1", "I2S RX1"},
 751        {"RX2 MIX1 INP2", "RX2", "I2S RX2"},
 752        {"RX2 MIX1 INP2", "RX3", "I2S RX3"},
 753
 754        {"RX2 MIX1 INP3", "RX1", "I2S RX1"},
 755        {"RX2 MIX1 INP3", "RX2", "I2S RX2"},
 756        {"RX2 MIX1 INP3", "RX3", "I2S RX3"},
 757
 758        /* RX3 PATH */
 759        {"PDM_RX3", NULL, "RX3 INT"},
 760        {"RX3 INT", NULL, "RX3 MIX1"},
 761
 762        {"RX3 MIX1", NULL, "RX3 MIX1 INP1"},
 763        {"RX3 MIX1", NULL, "RX3 MIX1 INP2"},
 764        {"RX3 MIX1", NULL, "RX3 MIX1 INP3"},
 765
 766        {"RX3 MIX1 INP1", "RX1", "I2S RX1"},
 767        {"RX3 MIX1 INP1", "RX2", "I2S RX2"},
 768        {"RX3 MIX1 INP1", "RX3", "I2S RX3"},
 769
 770        {"RX3 MIX1 INP2", "RX1", "I2S RX1"},
 771        {"RX3 MIX1 INP2", "RX2", "I2S RX2"},
 772        {"RX3 MIX1 INP2", "RX3", "I2S RX3"},
 773
 774        {"RX3 MIX1 INP3", "RX1", "I2S RX1"},
 775        {"RX3 MIX1 INP3", "RX2", "I2S RX2"},
 776        {"RX3 MIX1 INP3", "RX3", "I2S RX3"},
 777
 778};
 779
 780static int msm8916_wcd_digital_startup(struct snd_pcm_substream *substream,
 781                                       struct snd_soc_dai *dai)
 782{
 783        struct snd_soc_codec *codec = dai->codec;
 784        struct msm8916_wcd_digital_priv *msm8916_wcd;
 785        unsigned long mclk_rate;
 786
 787        msm8916_wcd = snd_soc_codec_get_drvdata(codec);
 788        snd_soc_update_bits(codec, LPASS_CDC_CLK_MCLK_CTL,
 789                            MCLK_CTL_MCLK_EN_MASK,
 790                            MCLK_CTL_MCLK_EN_ENABLE);
 791        snd_soc_update_bits(codec, LPASS_CDC_CLK_PDM_CTL,
 792                            LPASS_CDC_CLK_PDM_CTL_PDM_CLK_SEL_MASK,
 793                            LPASS_CDC_CLK_PDM_CTL_PDM_CLK_SEL_FB);
 794
 795        mclk_rate = clk_get_rate(msm8916_wcd->mclk);
 796        switch (mclk_rate) {
 797        case 12288000:
 798                snd_soc_update_bits(codec, LPASS_CDC_TOP_CTL,
 799                                    TOP_CTL_DIG_MCLK_FREQ_MASK,
 800                                    TOP_CTL_DIG_MCLK_FREQ_F_12_288MHZ);
 801                break;
 802        case 9600000:
 803                snd_soc_update_bits(codec, LPASS_CDC_TOP_CTL,
 804                                    TOP_CTL_DIG_MCLK_FREQ_MASK,
 805                                    TOP_CTL_DIG_MCLK_FREQ_F_9_6MHZ);
 806                break;
 807        default:
 808                dev_err(codec->dev, "Invalid mclk rate %ld\n", mclk_rate);
 809                break;
 810        }
 811        return 0;
 812}
 813
 814static void msm8916_wcd_digital_shutdown(struct snd_pcm_substream *substream,
 815                                         struct snd_soc_dai *dai)
 816{
 817        snd_soc_update_bits(dai->codec, LPASS_CDC_CLK_PDM_CTL,
 818                            LPASS_CDC_CLK_PDM_CTL_PDM_CLK_SEL_MASK, 0);
 819}
 820
 821static const struct snd_soc_dai_ops msm8916_wcd_digital_dai_ops = {
 822        .startup = msm8916_wcd_digital_startup,
 823        .shutdown = msm8916_wcd_digital_shutdown,
 824        .hw_params = msm8916_wcd_digital_hw_params,
 825};
 826
 827static struct snd_soc_dai_driver msm8916_wcd_digital_dai[] = {
 828        [0] = {
 829               .name = "msm8916_wcd_digital_i2s_rx1",
 830               .id = 0,
 831               .playback = {
 832                            .stream_name = "AIF1 Playback",
 833                            .rates = MSM8916_WCD_DIGITAL_RATES,
 834                            .formats = MSM8916_WCD_DIGITAL_FORMATS,
 835                            .channels_min = 1,
 836                            .channels_max = 3,
 837                            },
 838               .ops = &msm8916_wcd_digital_dai_ops,
 839               },
 840        [1] = {
 841               .name = "msm8916_wcd_digital_i2s_tx1",
 842               .id = 1,
 843               .capture = {
 844                           .stream_name = "AIF1 Capture",
 845                           .rates = MSM8916_WCD_DIGITAL_RATES,
 846                           .formats = MSM8916_WCD_DIGITAL_FORMATS,
 847                           .channels_min = 1,
 848                           .channels_max = 4,
 849                           },
 850               .ops = &msm8916_wcd_digital_dai_ops,
 851               },
 852};
 853
 854static const struct snd_soc_codec_driver msm8916_wcd_digital = {
 855        .probe = msm8916_wcd_digital_codec_probe,
 856        .set_sysclk = msm8916_wcd_digital_codec_set_sysclk,
 857        .component_driver = {
 858                .controls = msm8916_wcd_digital_snd_controls,
 859                .num_controls = ARRAY_SIZE(msm8916_wcd_digital_snd_controls),
 860                .dapm_widgets = msm8916_wcd_digital_dapm_widgets,
 861                .num_dapm_widgets =
 862                                 ARRAY_SIZE(msm8916_wcd_digital_dapm_widgets),
 863                .dapm_routes = msm8916_wcd_digital_audio_map,
 864                .num_dapm_routes = ARRAY_SIZE(msm8916_wcd_digital_audio_map),
 865        },
 866};
 867
 868static const struct regmap_config msm8916_codec_regmap_config = {
 869        .reg_bits = 32,
 870        .reg_stride = 4,
 871        .val_bits = 32,
 872        .max_register = LPASS_CDC_TX2_DMIC_CTL,
 873        .cache_type = REGCACHE_FLAT,
 874};
 875
 876static int msm8916_wcd_digital_probe(struct platform_device *pdev)
 877{
 878        struct msm8916_wcd_digital_priv *priv;
 879        struct device *dev = &pdev->dev;
 880        void __iomem *base;
 881        struct resource *mem_res;
 882        struct regmap *digital_map;
 883        int ret;
 884
 885        priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
 886        if (!priv)
 887                return -ENOMEM;
 888
 889        mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 890        base = devm_ioremap_resource(&pdev->dev, mem_res);
 891        if (IS_ERR(base))
 892                return PTR_ERR(base);
 893
 894        digital_map =
 895            devm_regmap_init_mmio(&pdev->dev, base,
 896                                  &msm8916_codec_regmap_config);
 897        if (IS_ERR(digital_map))
 898                return PTR_ERR(digital_map);
 899
 900        ret = msm8916_wcd_digital_get_clks(pdev, priv);
 901        if (ret < 0)
 902                return ret;
 903
 904        ret = clk_prepare_enable(priv->ahbclk);
 905        if (ret < 0) {
 906                dev_err(dev, "failed to enable ahbclk %d\n", ret);
 907                return ret;
 908        }
 909
 910        ret = clk_prepare_enable(priv->mclk);
 911        if (ret < 0) {
 912                dev_err(dev, "failed to enable mclk %d\n", ret);
 913                return ret;
 914        }
 915
 916        dev_set_drvdata(dev, priv);
 917
 918        return snd_soc_register_codec(dev, &msm8916_wcd_digital,
 919                                      msm8916_wcd_digital_dai,
 920                                      ARRAY_SIZE(msm8916_wcd_digital_dai));
 921}
 922
 923static int msm8916_wcd_digital_remove(struct platform_device *pdev)
 924{
 925        struct msm8916_wcd_digital_priv *priv = dev_get_drvdata(&pdev->dev);
 926
 927        snd_soc_unregister_codec(&pdev->dev);
 928        clk_disable_unprepare(priv->mclk);
 929        clk_disable_unprepare(priv->ahbclk);
 930
 931        return 0;
 932}
 933
 934static const struct of_device_id msm8916_wcd_digital_match_table[] = {
 935        { .compatible = "qcom,msm8916-wcd-digital-codec" },
 936        { }
 937};
 938
 939MODULE_DEVICE_TABLE(of, msm8916_wcd_digital_match_table);
 940
 941static struct platform_driver msm8916_wcd_digital_driver = {
 942        .driver = {
 943                   .name = "msm8916-wcd-digital-codec",
 944                   .of_match_table = msm8916_wcd_digital_match_table,
 945        },
 946        .probe = msm8916_wcd_digital_probe,
 947        .remove = msm8916_wcd_digital_remove,
 948};
 949
 950module_platform_driver(msm8916_wcd_digital_driver);
 951
 952MODULE_AUTHOR("Srinivas Kandagatla <srinivas.kandagatla@linaro.org>");
 953MODULE_DESCRIPTION("MSM8916 WCD Digital Codec driver");
 954MODULE_LICENSE("GPL v2");
 955