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_S24_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};
 221static const char *const rx_mix2_text[] = { "ZERO", "IIR1", "IIR2" };
 222static const char *const adc2_mux_text[] = { "ZERO", "INP2", "INP3" };
 223
 224/* RX1 MIX1 */
 225static const struct soc_enum rx_mix1_inp_enum[] = {
 226        SOC_ENUM_SINGLE(LPASS_CDC_CONN_RX1_B1_CTL, 0, 6, rx_mix1_text),
 227        SOC_ENUM_SINGLE(LPASS_CDC_CONN_RX1_B1_CTL, 3, 6, rx_mix1_text),
 228        SOC_ENUM_SINGLE(LPASS_CDC_CONN_RX1_B2_CTL, 0, 6, rx_mix1_text),
 229};
 230
 231/* RX1 MIX2 */
 232static const struct soc_enum rx_mix2_inp1_chain_enum = SOC_ENUM_SINGLE(
 233                                LPASS_CDC_CONN_RX1_B3_CTL, 0, 3, rx_mix2_text);
 234
 235/* RX2 MIX1 */
 236static const struct soc_enum rx2_mix1_inp_enum[] = {
 237        SOC_ENUM_SINGLE(LPASS_CDC_CONN_RX2_B1_CTL, 0, 6, rx_mix1_text),
 238        SOC_ENUM_SINGLE(LPASS_CDC_CONN_RX2_B1_CTL, 3, 6, rx_mix1_text),
 239        SOC_ENUM_SINGLE(LPASS_CDC_CONN_RX2_B1_CTL, 0, 6, rx_mix1_text),
 240};
 241
 242/* RX2 MIX2 */
 243static const struct soc_enum rx2_mix2_inp1_chain_enum = SOC_ENUM_SINGLE(
 244                                LPASS_CDC_CONN_RX2_B3_CTL, 0, 3, rx_mix2_text);
 245
 246/* RX3 MIX1 */
 247static const struct soc_enum rx3_mix1_inp_enum[] = {
 248        SOC_ENUM_SINGLE(LPASS_CDC_CONN_RX3_B1_CTL, 0, 6, rx_mix1_text),
 249        SOC_ENUM_SINGLE(LPASS_CDC_CONN_RX3_B1_CTL, 3, 6, rx_mix1_text),
 250        SOC_ENUM_SINGLE(LPASS_CDC_CONN_RX3_B1_CTL, 0, 6, rx_mix1_text),
 251};
 252
 253/* DEC */
 254static const struct soc_enum dec1_mux_enum = SOC_ENUM_SINGLE(
 255                                LPASS_CDC_CONN_TX_B1_CTL, 0, 6, dec_mux_text);
 256static const struct soc_enum dec2_mux_enum = SOC_ENUM_SINGLE(
 257                                LPASS_CDC_CONN_TX_B1_CTL, 3, 6, dec_mux_text);
 258
 259/* RDAC2 MUX */
 260static const struct snd_kcontrol_new dec1_mux = SOC_DAPM_ENUM(
 261                                "DEC1 MUX Mux", dec1_mux_enum);
 262static const struct snd_kcontrol_new dec2_mux = SOC_DAPM_ENUM(
 263                                "DEC2 MUX Mux", dec2_mux_enum);
 264static const struct snd_kcontrol_new rx_mix1_inp1_mux = SOC_DAPM_ENUM(
 265                                "RX1 MIX1 INP1 Mux", rx_mix1_inp_enum[0]);
 266static const struct snd_kcontrol_new rx_mix1_inp2_mux = SOC_DAPM_ENUM(
 267                                "RX1 MIX1 INP2 Mux", rx_mix1_inp_enum[1]);
 268static const struct snd_kcontrol_new rx_mix1_inp3_mux = SOC_DAPM_ENUM(
 269                                "RX1 MIX1 INP3 Mux", rx_mix1_inp_enum[2]);
 270static const struct snd_kcontrol_new rx2_mix1_inp1_mux = SOC_DAPM_ENUM(
 271                                "RX2 MIX1 INP1 Mux", rx2_mix1_inp_enum[0]);
 272static const struct snd_kcontrol_new rx2_mix1_inp2_mux = SOC_DAPM_ENUM(
 273                                "RX2 MIX1 INP2 Mux", rx2_mix1_inp_enum[1]);
 274static const struct snd_kcontrol_new rx2_mix1_inp3_mux = SOC_DAPM_ENUM(
 275                                "RX2 MIX1 INP3 Mux", rx2_mix1_inp_enum[2]);
 276static const struct snd_kcontrol_new rx3_mix1_inp1_mux = SOC_DAPM_ENUM(
 277                                "RX3 MIX1 INP1 Mux", rx3_mix1_inp_enum[0]);
 278static const struct snd_kcontrol_new rx3_mix1_inp2_mux = SOC_DAPM_ENUM(
 279                                "RX3 MIX1 INP2 Mux", rx3_mix1_inp_enum[1]);
 280static const struct snd_kcontrol_new rx3_mix1_inp3_mux = SOC_DAPM_ENUM(
 281                                "RX3 MIX1 INP3 Mux", rx3_mix1_inp_enum[2]);
 282
 283/* Digital Gain control -38.4 dB to +38.4 dB in 0.3 dB steps */
 284static const DECLARE_TLV_DB_SCALE(digital_gain, -3840, 30, 0);
 285
 286/* Cutoff Freq for High Pass Filter at -3dB */
 287static const char * const hpf_cutoff_text[] = {
 288        "4Hz", "75Hz", "150Hz",
 289};
 290
 291static SOC_ENUM_SINGLE_DECL(tx1_hpf_cutoff_enum, LPASS_CDC_TX1_MUX_CTL, 4,
 292                            hpf_cutoff_text);
 293static SOC_ENUM_SINGLE_DECL(tx2_hpf_cutoff_enum, LPASS_CDC_TX2_MUX_CTL, 4,
 294                            hpf_cutoff_text);
 295
 296/* cut off for dc blocker inside rx chain */
 297static const char * const dc_blocker_cutoff_text[] = {
 298        "4Hz", "75Hz", "150Hz",
 299};
 300
 301static SOC_ENUM_SINGLE_DECL(rx1_dcb_cutoff_enum, LPASS_CDC_RX1_B4_CTL, 0,
 302                            dc_blocker_cutoff_text);
 303static SOC_ENUM_SINGLE_DECL(rx2_dcb_cutoff_enum, LPASS_CDC_RX2_B4_CTL, 0,
 304                            dc_blocker_cutoff_text);
 305static SOC_ENUM_SINGLE_DECL(rx3_dcb_cutoff_enum, LPASS_CDC_RX3_B4_CTL, 0,
 306                            dc_blocker_cutoff_text);
 307
 308static const struct snd_kcontrol_new msm8916_wcd_digital_snd_controls[] = {
 309        SOC_SINGLE_S8_TLV("RX1 Digital Volume", LPASS_CDC_RX1_VOL_CTL_B2_CTL,
 310                          -128, 127, digital_gain),
 311        SOC_SINGLE_S8_TLV("RX2 Digital Volume", LPASS_CDC_RX2_VOL_CTL_B2_CTL,
 312                          -128, 127, digital_gain),
 313        SOC_SINGLE_S8_TLV("RX3 Digital Volume", LPASS_CDC_RX3_VOL_CTL_B2_CTL,
 314                          -128, 127, digital_gain),
 315        SOC_SINGLE_S8_TLV("TX1 Digital Volume", LPASS_CDC_TX1_VOL_CTL_GAIN,
 316                          -128, 127, digital_gain),
 317        SOC_SINGLE_S8_TLV("TX2 Digital Volume", LPASS_CDC_TX2_VOL_CTL_GAIN,
 318                          -128, 127, digital_gain),
 319        SOC_ENUM("TX1 HPF Cutoff", tx1_hpf_cutoff_enum),
 320        SOC_ENUM("TX2 HPF Cutoff", tx2_hpf_cutoff_enum),
 321        SOC_SINGLE("TX1 HPF Switch", LPASS_CDC_TX1_MUX_CTL, 3, 1, 0),
 322        SOC_SINGLE("TX2 HPF Switch", LPASS_CDC_TX2_MUX_CTL, 3, 1, 0),
 323        SOC_ENUM("RX1 DCB Cutoff", rx1_dcb_cutoff_enum),
 324        SOC_ENUM("RX2 DCB Cutoff", rx2_dcb_cutoff_enum),
 325        SOC_ENUM("RX3 DCB Cutoff", rx3_dcb_cutoff_enum),
 326        SOC_SINGLE("RX1 DCB Switch", LPASS_CDC_RX1_B5_CTL, 2, 1, 0),
 327        SOC_SINGLE("RX2 DCB Switch", LPASS_CDC_RX2_B5_CTL, 2, 1, 0),
 328        SOC_SINGLE("RX3 DCB Switch", LPASS_CDC_RX3_B5_CTL, 2, 1, 0),
 329        SOC_SINGLE("RX1 Mute Switch", LPASS_CDC_RX1_B6_CTL, 0, 1, 0),
 330        SOC_SINGLE("RX2 Mute Switch", LPASS_CDC_RX2_B6_CTL, 0, 1, 0),
 331        SOC_SINGLE("RX3 Mute Switch", LPASS_CDC_RX3_B6_CTL, 0, 1, 0),
 332};
 333
 334static int msm8916_wcd_digital_enable_interpolator(
 335                                                struct snd_soc_dapm_widget *w,
 336                                                struct snd_kcontrol *kcontrol,
 337                                                int event)
 338{
 339        struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
 340
 341        switch (event) {
 342        case SND_SOC_DAPM_POST_PMU:
 343                /* apply the digital gain after the interpolator is enabled */
 344                usleep_range(10000, 10100);
 345                snd_soc_write(codec, rx_gain_reg[w->shift],
 346                              snd_soc_read(codec, rx_gain_reg[w->shift]));
 347                break;
 348        }
 349        return 0;
 350}
 351
 352static int msm8916_wcd_digital_enable_dec(struct snd_soc_dapm_widget *w,
 353                                          struct snd_kcontrol *kcontrol,
 354                                          int event)
 355{
 356        struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
 357        unsigned int decimator = w->shift + 1;
 358        u16 dec_reset_reg, tx_vol_ctl_reg, tx_mux_ctl_reg;
 359        u8 dec_hpf_cut_of_freq;
 360
 361        dec_reset_reg = LPASS_CDC_CLK_TX_RESET_B1_CTL;
 362        tx_vol_ctl_reg = LPASS_CDC_TX1_VOL_CTL_CFG + 32 * (decimator - 1);
 363        tx_mux_ctl_reg = LPASS_CDC_TX1_MUX_CTL + 32 * (decimator - 1);
 364
 365        switch (event) {
 366        case SND_SOC_DAPM_PRE_PMU:
 367                /* Enable TX digital mute */
 368                snd_soc_update_bits(codec, tx_vol_ctl_reg,
 369                                    TX_VOL_CTL_CFG_MUTE_EN_MASK,
 370                                    TX_VOL_CTL_CFG_MUTE_EN_ENABLE);
 371                dec_hpf_cut_of_freq = snd_soc_read(codec, tx_mux_ctl_reg) &
 372                                        TX_MUX_CTL_CUT_OFF_FREQ_MASK;
 373                dec_hpf_cut_of_freq >>= TX_MUX_CTL_CUT_OFF_FREQ_SHIFT;
 374                if (dec_hpf_cut_of_freq != TX_MUX_CTL_CF_NEG_3DB_150HZ) {
 375                        /* set cut of freq to CF_MIN_3DB_150HZ (0x1) */
 376                        snd_soc_update_bits(codec, tx_mux_ctl_reg,
 377                                            TX_MUX_CTL_CUT_OFF_FREQ_MASK,
 378                                            TX_MUX_CTL_CF_NEG_3DB_150HZ);
 379                }
 380                break;
 381        case SND_SOC_DAPM_POST_PMU:
 382                /* enable HPF */
 383                snd_soc_update_bits(codec, tx_mux_ctl_reg,
 384                                    TX_MUX_CTL_HPF_BP_SEL_MASK,
 385                                    TX_MUX_CTL_HPF_BP_SEL_NO_BYPASS);
 386                /* apply the digital gain after the decimator is enabled */
 387                snd_soc_write(codec, tx_gain_reg[w->shift],
 388                              snd_soc_read(codec, tx_gain_reg[w->shift]));
 389                snd_soc_update_bits(codec, tx_vol_ctl_reg,
 390                                    TX_VOL_CTL_CFG_MUTE_EN_MASK, 0);
 391                break;
 392        case SND_SOC_DAPM_PRE_PMD:
 393                snd_soc_update_bits(codec, tx_vol_ctl_reg,
 394                                    TX_VOL_CTL_CFG_MUTE_EN_MASK,
 395                                    TX_VOL_CTL_CFG_MUTE_EN_ENABLE);
 396                snd_soc_update_bits(codec, tx_mux_ctl_reg,
 397                                    TX_MUX_CTL_HPF_BP_SEL_MASK,
 398                                    TX_MUX_CTL_HPF_BP_SEL_BYPASS);
 399                break;
 400        case SND_SOC_DAPM_POST_PMD:
 401                snd_soc_update_bits(codec, dec_reset_reg, 1 << w->shift,
 402                                    1 << w->shift);
 403                snd_soc_update_bits(codec, dec_reset_reg, 1 << w->shift, 0x0);
 404                snd_soc_update_bits(codec, tx_mux_ctl_reg,
 405                                    TX_MUX_CTL_HPF_BP_SEL_MASK,
 406                                    TX_MUX_CTL_HPF_BP_SEL_BYPASS);
 407                snd_soc_update_bits(codec, tx_vol_ctl_reg,
 408                                    TX_VOL_CTL_CFG_MUTE_EN_MASK, 0);
 409                break;
 410        }
 411
 412        return 0;
 413}
 414
 415static int msm8916_wcd_digital_enable_dmic(struct snd_soc_dapm_widget *w,
 416                                           struct snd_kcontrol *kcontrol,
 417                                           int event)
 418{
 419        struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
 420        unsigned int dmic;
 421        int ret;
 422        /* get dmic number out of widget name */
 423        char *dmic_num = strpbrk(w->name, "12");
 424
 425        if (dmic_num == NULL) {
 426                dev_err(codec->dev, "Invalid DMIC\n");
 427                return -EINVAL;
 428        }
 429        ret = kstrtouint(dmic_num, 10, &dmic);
 430        if (ret < 0 || dmic > 2) {
 431                dev_err(codec->dev, "Invalid DMIC line on the codec\n");
 432                return -EINVAL;
 433        }
 434
 435        switch (event) {
 436        case SND_SOC_DAPM_PRE_PMU:
 437                snd_soc_update_bits(codec, LPASS_CDC_CLK_DMIC_B1_CTL,
 438                                    DMIC_B1_CTL_DMIC0_CLK_SEL_MASK,
 439                                    DMIC_B1_CTL_DMIC0_CLK_SEL_DIV3);
 440                switch (dmic) {
 441                case 1:
 442                        snd_soc_update_bits(codec, LPASS_CDC_TX1_DMIC_CTL,
 443                                            TXN_DMIC_CTL_CLK_SEL_MASK,
 444                                            TXN_DMIC_CTL_CLK_SEL_DIV3);
 445                        break;
 446                case 2:
 447                        snd_soc_update_bits(codec, LPASS_CDC_TX2_DMIC_CTL,
 448                                            TXN_DMIC_CTL_CLK_SEL_MASK,
 449                                            TXN_DMIC_CTL_CLK_SEL_DIV3);
 450                        break;
 451                }
 452                break;
 453        }
 454
 455        return 0;
 456}
 457
 458static const struct snd_soc_dapm_widget msm8916_wcd_digital_dapm_widgets[] = {
 459        /*RX stuff */
 460        SND_SOC_DAPM_AIF_IN("I2S RX1", NULL, 0, SND_SOC_NOPM, 0, 0),
 461        SND_SOC_DAPM_AIF_IN("I2S RX2", NULL, 0, SND_SOC_NOPM, 0, 0),
 462        SND_SOC_DAPM_AIF_IN("I2S RX3", NULL, 0, SND_SOC_NOPM, 0, 0),
 463
 464        SND_SOC_DAPM_OUTPUT("PDM_RX1"),
 465        SND_SOC_DAPM_OUTPUT("PDM_RX2"),
 466        SND_SOC_DAPM_OUTPUT("PDM_RX3"),
 467
 468        SND_SOC_DAPM_INPUT("LPASS_PDM_TX"),
 469
 470        SND_SOC_DAPM_MIXER("RX1 MIX1", SND_SOC_NOPM, 0, 0, NULL, 0),
 471        SND_SOC_DAPM_MIXER("RX2 MIX1", SND_SOC_NOPM, 0, 0, NULL, 0),
 472        SND_SOC_DAPM_MIXER("RX3 MIX1", SND_SOC_NOPM, 0, 0, NULL, 0),
 473
 474        /* Interpolator */
 475        SND_SOC_DAPM_MIXER_E("RX1 INT", LPASS_CDC_CLK_RX_B1_CTL, 0, 0, NULL,
 476                             0, msm8916_wcd_digital_enable_interpolator,
 477                             SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
 478        SND_SOC_DAPM_MIXER_E("RX2 INT", LPASS_CDC_CLK_RX_B1_CTL, 1, 0, NULL,
 479                             0, msm8916_wcd_digital_enable_interpolator,
 480                             SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
 481        SND_SOC_DAPM_MIXER_E("RX3 INT", LPASS_CDC_CLK_RX_B1_CTL, 2, 0, NULL,
 482                             0, msm8916_wcd_digital_enable_interpolator,
 483                             SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
 484        SND_SOC_DAPM_MUX("RX1 MIX1 INP1", SND_SOC_NOPM, 0, 0,
 485                         &rx_mix1_inp1_mux),
 486        SND_SOC_DAPM_MUX("RX1 MIX1 INP2", SND_SOC_NOPM, 0, 0,
 487                         &rx_mix1_inp2_mux),
 488        SND_SOC_DAPM_MUX("RX1 MIX1 INP3", SND_SOC_NOPM, 0, 0,
 489                         &rx_mix1_inp3_mux),
 490        SND_SOC_DAPM_MUX("RX2 MIX1 INP1", SND_SOC_NOPM, 0, 0,
 491                         &rx2_mix1_inp1_mux),
 492        SND_SOC_DAPM_MUX("RX2 MIX1 INP2", SND_SOC_NOPM, 0, 0,
 493                         &rx2_mix1_inp2_mux),
 494        SND_SOC_DAPM_MUX("RX2 MIX1 INP3", SND_SOC_NOPM, 0, 0,
 495                         &rx2_mix1_inp3_mux),
 496        SND_SOC_DAPM_MUX("RX3 MIX1 INP1", SND_SOC_NOPM, 0, 0,
 497                         &rx3_mix1_inp1_mux),
 498        SND_SOC_DAPM_MUX("RX3 MIX1 INP2", SND_SOC_NOPM, 0, 0,
 499                         &rx3_mix1_inp2_mux),
 500        SND_SOC_DAPM_MUX("RX3 MIX1 INP3", SND_SOC_NOPM, 0, 0,
 501                         &rx3_mix1_inp3_mux),
 502
 503        /* TX */
 504        SND_SOC_DAPM_MIXER("ADC1", SND_SOC_NOPM, 0, 0, NULL, 0),
 505        SND_SOC_DAPM_MIXER("ADC2", SND_SOC_NOPM, 0, 0, NULL, 0),
 506        SND_SOC_DAPM_MIXER("ADC3", SND_SOC_NOPM, 0, 0, NULL, 0),
 507
 508        SND_SOC_DAPM_MUX_E("DEC1 MUX", LPASS_CDC_CLK_TX_CLK_EN_B1_CTL, 0, 0,
 509                           &dec1_mux, msm8916_wcd_digital_enable_dec,
 510                           SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
 511                           SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
 512        SND_SOC_DAPM_MUX_E("DEC2 MUX", LPASS_CDC_CLK_TX_CLK_EN_B1_CTL, 1, 0,
 513                           &dec2_mux, msm8916_wcd_digital_enable_dec,
 514                           SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
 515                           SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
 516        SND_SOC_DAPM_AIF_OUT("I2S TX1", NULL, 0, SND_SOC_NOPM, 0, 0),
 517        SND_SOC_DAPM_AIF_OUT("I2S TX2", NULL, 0, SND_SOC_NOPM, 0, 0),
 518        SND_SOC_DAPM_AIF_OUT("I2S TX3", NULL, 0, SND_SOC_NOPM, 0, 0),
 519
 520        /* Digital Mic Inputs */
 521        SND_SOC_DAPM_ADC_E("DMIC1", NULL, SND_SOC_NOPM, 0, 0,
 522                           msm8916_wcd_digital_enable_dmic,
 523                           SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
 524        SND_SOC_DAPM_ADC_E("DMIC2", NULL, SND_SOC_NOPM, 0, 0,
 525                           msm8916_wcd_digital_enable_dmic,
 526                           SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
 527        SND_SOC_DAPM_SUPPLY("DMIC_CLK", LPASS_CDC_CLK_DMIC_B1_CTL, 0, 0,
 528                            NULL, 0),
 529        SND_SOC_DAPM_SUPPLY("RX_I2S_CLK", LPASS_CDC_CLK_RX_I2S_CTL,
 530                            4, 0, NULL, 0),
 531        SND_SOC_DAPM_SUPPLY("TX_I2S_CLK", LPASS_CDC_CLK_TX_I2S_CTL, 4, 0,
 532                            NULL, 0),
 533
 534        SND_SOC_DAPM_SUPPLY("MCLK", SND_SOC_NOPM, 0, 0, NULL, 0),
 535        SND_SOC_DAPM_SUPPLY("PDM_CLK", LPASS_CDC_CLK_PDM_CTL, 0, 0, NULL, 0),
 536        /* Connectivity Clock */
 537        SND_SOC_DAPM_SUPPLY_S("CDC_CONN", -2, LPASS_CDC_CLK_OTHR_CTL, 2, 0,
 538                              NULL, 0),
 539
 540};
 541
 542static int msm8916_wcd_digital_get_clks(struct platform_device *pdev,
 543                                        struct msm8916_wcd_digital_priv *priv)
 544{
 545        struct device *dev = &pdev->dev;
 546
 547        priv->ahbclk = devm_clk_get(dev, "ahbix-clk");
 548        if (IS_ERR(priv->ahbclk)) {
 549                dev_err(dev, "failed to get ahbix clk\n");
 550                return PTR_ERR(priv->ahbclk);
 551        }
 552
 553        priv->mclk = devm_clk_get(dev, "mclk");
 554        if (IS_ERR(priv->mclk)) {
 555                dev_err(dev, "failed to get mclk\n");
 556                return PTR_ERR(priv->mclk);
 557        }
 558
 559        return 0;
 560}
 561
 562static int msm8916_wcd_digital_codec_probe(struct snd_soc_codec *codec)
 563{
 564        struct msm8916_wcd_digital_priv *priv = dev_get_drvdata(codec->dev);
 565
 566        snd_soc_codec_set_drvdata(codec, priv);
 567
 568        return 0;
 569}
 570
 571static int msm8916_wcd_digital_hw_params(struct snd_pcm_substream *substream,
 572                                         struct snd_pcm_hw_params *params,
 573                                         struct snd_soc_dai *dai)
 574{
 575        u8 tx_fs_rate;
 576        u8 rx_fs_rate;
 577
 578        switch (params_rate(params)) {
 579        case 8000:
 580                tx_fs_rate = TX_I2S_CTL_TX_I2S_FS_RATE_F_8_KHZ;
 581                rx_fs_rate = RX_I2S_CTL_RX_I2S_FS_RATE_F_8_KHZ;
 582                break;
 583        case 16000:
 584                tx_fs_rate = TX_I2S_CTL_TX_I2S_FS_RATE_F_16_KHZ;
 585                rx_fs_rate = RX_I2S_CTL_RX_I2S_FS_RATE_F_16_KHZ;
 586                break;
 587        case 32000:
 588                tx_fs_rate = TX_I2S_CTL_TX_I2S_FS_RATE_F_32_KHZ;
 589                rx_fs_rate = RX_I2S_CTL_RX_I2S_FS_RATE_F_32_KHZ;
 590                break;
 591        case 48000:
 592                tx_fs_rate = TX_I2S_CTL_TX_I2S_FS_RATE_F_48_KHZ;
 593                rx_fs_rate = RX_I2S_CTL_RX_I2S_FS_RATE_F_48_KHZ;
 594                break;
 595        default:
 596                dev_err(dai->codec->dev, "Invalid sampling rate %d\n",
 597                        params_rate(params));
 598                return -EINVAL;
 599        }
 600
 601        switch (substream->stream) {
 602        case SNDRV_PCM_STREAM_CAPTURE:
 603                snd_soc_update_bits(dai->codec, LPASS_CDC_CLK_TX_I2S_CTL,
 604                                    TX_I2S_CTL_TX_I2S_FS_RATE_MASK, tx_fs_rate);
 605                break;
 606        case SNDRV_PCM_STREAM_PLAYBACK:
 607                snd_soc_update_bits(dai->codec, LPASS_CDC_CLK_RX_I2S_CTL,
 608                                    RX_I2S_CTL_RX_I2S_FS_RATE_MASK, rx_fs_rate);
 609                break;
 610        default:
 611                return -EINVAL;
 612        }
 613
 614        switch (params_format(params)) {
 615        case SNDRV_PCM_FORMAT_S16_LE:
 616                snd_soc_update_bits(dai->codec, LPASS_CDC_CLK_TX_I2S_CTL,
 617                                    TX_I2S_CTL_TX_I2S_MODE_MASK,
 618                                    TX_I2S_CTL_TX_I2S_MODE_16);
 619                snd_soc_update_bits(dai->codec, LPASS_CDC_CLK_RX_I2S_CTL,
 620                                    RX_I2S_CTL_RX_I2S_MODE_MASK,
 621                                    RX_I2S_CTL_RX_I2S_MODE_16);
 622                break;
 623        case SNDRV_PCM_FORMAT_S24_LE:
 624                snd_soc_update_bits(dai->codec, LPASS_CDC_CLK_TX_I2S_CTL,
 625                                    TX_I2S_CTL_TX_I2S_MODE_MASK,
 626                                    TX_I2S_CTL_TX_I2S_MODE_32);
 627                snd_soc_update_bits(dai->codec, LPASS_CDC_CLK_RX_I2S_CTL,
 628                                    RX_I2S_CTL_RX_I2S_MODE_MASK,
 629                                    RX_I2S_CTL_RX_I2S_MODE_32);
 630                break;
 631        default:
 632                dev_err(dai->dev, "%s: wrong format selected\n", __func__);
 633                return -EINVAL;
 634        }
 635
 636        return 0;
 637}
 638
 639static const struct snd_soc_dapm_route msm8916_wcd_digital_audio_map[] = {
 640
 641        {"I2S RX1",  NULL, "AIF1 Playback"},
 642        {"I2S RX2",  NULL, "AIF1 Playback"},
 643        {"I2S RX3",  NULL, "AIF1 Playback"},
 644
 645        {"AIF1 Capture", NULL, "I2S TX1"},
 646        {"AIF1 Capture", NULL, "I2S TX2"},
 647        {"AIF1 Capture", NULL, "I2S TX3"},
 648
 649        /* Decimator Inputs */
 650        {"DEC1 MUX", "DMIC1", "DMIC1"},
 651        {"DEC1 MUX", "DMIC2", "DMIC2"},
 652        {"DEC1 MUX", "ADC1", "ADC1"},
 653        {"DEC1 MUX", "ADC2", "ADC2"},
 654        {"DEC1 MUX", "ADC3", "ADC3"},
 655        {"DEC1 MUX", NULL, "CDC_CONN"},
 656
 657        {"DEC2 MUX", "DMIC1", "DMIC1"},
 658        {"DEC2 MUX", "DMIC2", "DMIC2"},
 659        {"DEC2 MUX", "ADC1", "ADC1"},
 660        {"DEC2 MUX", "ADC2", "ADC2"},
 661        {"DEC2 MUX", "ADC3", "ADC3"},
 662        {"DEC2 MUX", NULL, "CDC_CONN"},
 663
 664        {"DMIC1", NULL, "DMIC_CLK"},
 665        {"DMIC2", NULL, "DMIC_CLK"},
 666
 667        {"I2S TX1", NULL, "DEC1 MUX"},
 668        {"I2S TX2", NULL, "DEC2 MUX"},
 669
 670        {"I2S TX1", NULL, "TX_I2S_CLK"},
 671        {"I2S TX2", NULL, "TX_I2S_CLK"},
 672
 673        {"TX_I2S_CLK", NULL, "MCLK"},
 674        {"TX_I2S_CLK", NULL, "PDM_CLK"},
 675
 676        {"ADC1", NULL, "LPASS_PDM_TX"},
 677        {"ADC2", NULL, "LPASS_PDM_TX"},
 678        {"ADC3", NULL, "LPASS_PDM_TX"},
 679
 680        {"I2S RX1", NULL, "RX_I2S_CLK"},
 681        {"I2S RX2", NULL, "RX_I2S_CLK"},
 682        {"I2S RX3", NULL, "RX_I2S_CLK"},
 683
 684        {"RX_I2S_CLK", NULL, "PDM_CLK"},
 685        {"RX_I2S_CLK", NULL, "MCLK"},
 686        {"RX_I2S_CLK", NULL, "CDC_CONN"},
 687
 688        /* RX1 PATH.. */
 689        {"PDM_RX1", NULL, "RX1 INT"},
 690        {"RX1 INT", NULL, "RX1 MIX1"},
 691
 692        {"RX1 MIX1", NULL, "RX1 MIX1 INP1"},
 693        {"RX1 MIX1", NULL, "RX1 MIX1 INP2"},
 694        {"RX1 MIX1", NULL, "RX1 MIX1 INP3"},
 695
 696        {"RX1 MIX1 INP1", "RX1", "I2S RX1"},
 697        {"RX1 MIX1 INP1", "RX2", "I2S RX2"},
 698        {"RX1 MIX1 INP1", "RX3", "I2S RX3"},
 699
 700        {"RX1 MIX1 INP2", "RX1", "I2S RX1"},
 701        {"RX1 MIX1 INP2", "RX2", "I2S RX2"},
 702        {"RX1 MIX1 INP2", "RX3", "I2S RX3"},
 703
 704        {"RX1 MIX1 INP3", "RX1", "I2S RX1"},
 705        {"RX1 MIX1 INP3", "RX2", "I2S RX2"},
 706        {"RX1 MIX1 INP3", "RX3", "I2S RX3"},
 707
 708        /* RX2 PATH */
 709        {"PDM_RX2", NULL, "RX2 INT"},
 710        {"RX2 INT", NULL, "RX2 MIX1"},
 711
 712        {"RX2 MIX1", NULL, "RX2 MIX1 INP1"},
 713        {"RX2 MIX1", NULL, "RX2 MIX1 INP2"},
 714        {"RX2 MIX1", NULL, "RX2 MIX1 INP3"},
 715
 716        {"RX2 MIX1 INP1", "RX1", "I2S RX1"},
 717        {"RX2 MIX1 INP1", "RX2", "I2S RX2"},
 718        {"RX2 MIX1 INP1", "RX3", "I2S RX3"},
 719
 720        {"RX2 MIX1 INP2", "RX1", "I2S RX1"},
 721        {"RX2 MIX1 INP2", "RX2", "I2S RX2"},
 722        {"RX2 MIX1 INP2", "RX3", "I2S RX3"},
 723
 724        {"RX2 MIX1 INP3", "RX1", "I2S RX1"},
 725        {"RX2 MIX1 INP3", "RX2", "I2S RX2"},
 726        {"RX2 MIX1 INP3", "RX3", "I2S RX3"},
 727
 728        /* RX3 PATH */
 729        {"PDM_RX3", NULL, "RX3 INT"},
 730        {"RX3 INT", NULL, "RX3 MIX1"},
 731
 732        {"RX3 MIX1", NULL, "RX3 MIX1 INP1"},
 733        {"RX3 MIX1", NULL, "RX3 MIX1 INP2"},
 734        {"RX3 MIX1", NULL, "RX3 MIX1 INP3"},
 735
 736        {"RX3 MIX1 INP1", "RX1", "I2S RX1"},
 737        {"RX3 MIX1 INP1", "RX2", "I2S RX2"},
 738        {"RX3 MIX1 INP1", "RX3", "I2S RX3"},
 739
 740        {"RX3 MIX1 INP2", "RX1", "I2S RX1"},
 741        {"RX3 MIX1 INP2", "RX2", "I2S RX2"},
 742        {"RX3 MIX1 INP2", "RX3", "I2S RX3"},
 743
 744        {"RX3 MIX1 INP3", "RX1", "I2S RX1"},
 745        {"RX3 MIX1 INP3", "RX2", "I2S RX2"},
 746        {"RX3 MIX1 INP3", "RX3", "I2S RX3"},
 747
 748};
 749
 750static int msm8916_wcd_digital_startup(struct snd_pcm_substream *substream,
 751                                       struct snd_soc_dai *dai)
 752{
 753        struct snd_soc_codec *codec = dai->codec;
 754        struct msm8916_wcd_digital_priv *msm8916_wcd;
 755        unsigned long mclk_rate;
 756
 757        msm8916_wcd = snd_soc_codec_get_drvdata(codec);
 758        snd_soc_update_bits(codec, LPASS_CDC_CLK_MCLK_CTL,
 759                            MCLK_CTL_MCLK_EN_MASK,
 760                            MCLK_CTL_MCLK_EN_ENABLE);
 761        snd_soc_update_bits(codec, LPASS_CDC_CLK_PDM_CTL,
 762                            LPASS_CDC_CLK_PDM_CTL_PDM_CLK_SEL_MASK,
 763                            LPASS_CDC_CLK_PDM_CTL_PDM_CLK_SEL_FB);
 764
 765        mclk_rate = clk_get_rate(msm8916_wcd->mclk);
 766        switch (mclk_rate) {
 767        case 12288000:
 768                snd_soc_update_bits(codec, LPASS_CDC_TOP_CTL,
 769                                    TOP_CTL_DIG_MCLK_FREQ_MASK,
 770                                    TOP_CTL_DIG_MCLK_FREQ_F_12_288MHZ);
 771                break;
 772        case 9600000:
 773                snd_soc_update_bits(codec, LPASS_CDC_TOP_CTL,
 774                                    TOP_CTL_DIG_MCLK_FREQ_MASK,
 775                                    TOP_CTL_DIG_MCLK_FREQ_F_9_6MHZ);
 776                break;
 777        default:
 778                dev_err(codec->dev, "Invalid mclk rate %ld\n", mclk_rate);
 779                break;
 780        }
 781        return 0;
 782}
 783
 784static void msm8916_wcd_digital_shutdown(struct snd_pcm_substream *substream,
 785                                         struct snd_soc_dai *dai)
 786{
 787        snd_soc_update_bits(dai->codec, LPASS_CDC_CLK_PDM_CTL,
 788                            LPASS_CDC_CLK_PDM_CTL_PDM_CLK_SEL_MASK, 0);
 789}
 790
 791static struct snd_soc_dai_ops msm8916_wcd_digital_dai_ops = {
 792        .startup = msm8916_wcd_digital_startup,
 793        .shutdown = msm8916_wcd_digital_shutdown,
 794        .hw_params = msm8916_wcd_digital_hw_params,
 795};
 796
 797static struct snd_soc_dai_driver msm8916_wcd_digital_dai[] = {
 798        [0] = {
 799               .name = "msm8916_wcd_digital_i2s_rx1",
 800               .id = 0,
 801               .playback = {
 802                            .stream_name = "AIF1 Playback",
 803                            .rates = MSM8916_WCD_DIGITAL_RATES,
 804                            .formats = MSM8916_WCD_DIGITAL_FORMATS,
 805                            .channels_min = 1,
 806                            .channels_max = 3,
 807                            },
 808               .ops = &msm8916_wcd_digital_dai_ops,
 809               },
 810        [1] = {
 811               .name = "msm8916_wcd_digital_i2s_tx1",
 812               .id = 1,
 813               .capture = {
 814                           .stream_name = "AIF1 Capture",
 815                           .rates = MSM8916_WCD_DIGITAL_RATES,
 816                           .formats = MSM8916_WCD_DIGITAL_FORMATS,
 817                           .channels_min = 1,
 818                           .channels_max = 4,
 819                           },
 820               .ops = &msm8916_wcd_digital_dai_ops,
 821               },
 822};
 823
 824static struct snd_soc_codec_driver msm8916_wcd_digital = {
 825        .probe = msm8916_wcd_digital_codec_probe,
 826        .component_driver = {
 827                .controls = msm8916_wcd_digital_snd_controls,
 828                .num_controls = ARRAY_SIZE(msm8916_wcd_digital_snd_controls),
 829                .dapm_widgets = msm8916_wcd_digital_dapm_widgets,
 830                .num_dapm_widgets =
 831                                 ARRAY_SIZE(msm8916_wcd_digital_dapm_widgets),
 832                .dapm_routes = msm8916_wcd_digital_audio_map,
 833                .num_dapm_routes = ARRAY_SIZE(msm8916_wcd_digital_audio_map),
 834        },
 835};
 836
 837static const struct regmap_config msm8916_codec_regmap_config = {
 838        .reg_bits = 32,
 839        .reg_stride = 4,
 840        .val_bits = 32,
 841        .max_register = LPASS_CDC_TX2_DMIC_CTL,
 842        .cache_type = REGCACHE_FLAT,
 843};
 844
 845static int msm8916_wcd_digital_probe(struct platform_device *pdev)
 846{
 847        struct msm8916_wcd_digital_priv *priv;
 848        struct device *dev = &pdev->dev;
 849        void __iomem *base;
 850        struct resource *mem_res;
 851        struct regmap *digital_map;
 852        int ret;
 853
 854        priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
 855        if (!priv)
 856                return -ENOMEM;
 857
 858        mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 859        base = devm_ioremap_resource(&pdev->dev, mem_res);
 860        if (IS_ERR(base))
 861                return PTR_ERR(base);
 862
 863        digital_map =
 864            devm_regmap_init_mmio(&pdev->dev, base,
 865                                  &msm8916_codec_regmap_config);
 866        if (IS_ERR(digital_map))
 867                return PTR_ERR(digital_map);
 868
 869        ret = msm8916_wcd_digital_get_clks(pdev, priv);
 870        if (ret < 0)
 871                return ret;
 872
 873        ret = clk_prepare_enable(priv->ahbclk);
 874        if (ret < 0) {
 875                dev_err(dev, "failed to enable ahbclk %d\n", ret);
 876                return ret;
 877        }
 878
 879        ret = clk_prepare_enable(priv->mclk);
 880        if (ret < 0) {
 881                dev_err(dev, "failed to enable mclk %d\n", ret);
 882                return ret;
 883        }
 884
 885        dev_set_drvdata(dev, priv);
 886
 887        return snd_soc_register_codec(dev, &msm8916_wcd_digital,
 888                                      msm8916_wcd_digital_dai,
 889                                      ARRAY_SIZE(msm8916_wcd_digital_dai));
 890}
 891
 892static int msm8916_wcd_digital_remove(struct platform_device *pdev)
 893{
 894        struct msm8916_wcd_digital_priv *priv = dev_get_drvdata(&pdev->dev);
 895
 896        snd_soc_unregister_codec(&pdev->dev);
 897        clk_disable_unprepare(priv->mclk);
 898        clk_disable_unprepare(priv->ahbclk);
 899
 900        return 0;
 901}
 902
 903static const struct of_device_id msm8916_wcd_digital_match_table[] = {
 904        { .compatible = "qcom,msm8916-wcd-digital-codec" },
 905        { }
 906};
 907
 908MODULE_DEVICE_TABLE(of, msm8916_wcd_digital_match_table);
 909
 910static struct platform_driver msm8916_wcd_digital_driver = {
 911        .driver = {
 912                   .name = "msm8916-wcd-digital-codec",
 913                   .of_match_table = msm8916_wcd_digital_match_table,
 914        },
 915        .probe = msm8916_wcd_digital_probe,
 916        .remove = msm8916_wcd_digital_remove,
 917};
 918
 919module_platform_driver(msm8916_wcd_digital_driver);
 920
 921MODULE_AUTHOR("Srinivas Kandagatla <srinivas.kandagatla@linaro.org>");
 922MODULE_DESCRIPTION("MSM8916 WCD Digital Codec driver");
 923MODULE_LICENSE("GPL v2");
 924