linux/sound/soc/codecs/cs42l73.c
<<
>>
Prefs
   1/*
   2 * cs42l73.c  --  CS42L73 ALSA Soc Audio driver
   3 *
   4 * Copyright 2011 Cirrus Logic, Inc.
   5 *
   6 * Authors: Georgi Vlaev, Nucleus Systems Ltd, <joe@nucleusys.com>
   7 *          Brian Austin, Cirrus Logic Inc, <brian.austin@cirrus.com>
   8 *
   9 * This program is free software; you can redistribute it and/or modify
  10 * it under the terms of the GNU General Public License version 2 as
  11 * published by the Free Software Foundation.
  12 *
  13 */
  14
  15#include <linux/module.h>
  16#include <linux/moduleparam.h>
  17#include <linux/kernel.h>
  18#include <linux/init.h>
  19#include <linux/delay.h>
  20#include <linux/pm.h>
  21#include <linux/i2c.h>
  22#include <linux/regmap.h>
  23#include <linux/slab.h>
  24#include <sound/core.h>
  25#include <sound/pcm.h>
  26#include <sound/pcm_params.h>
  27#include <sound/soc.h>
  28#include <sound/soc-dapm.h>
  29#include <sound/initval.h>
  30#include <sound/tlv.h>
  31#include "cs42l73.h"
  32
  33struct sp_config {
  34        u8 spc, mmcc, spfs;
  35        u32 srate;
  36};
  37struct  cs42l73_private {
  38        struct sp_config config[3];
  39        struct regmap *regmap;
  40        u32 sysclk;
  41        u8 mclksel;
  42        u32 mclk;
  43        int shutdwn_delay;
  44};
  45
  46static const struct reg_default cs42l73_reg_defaults[] = {
  47        { 6, 0xF1 },    /* r06  - Power Ctl 1 */
  48        { 7, 0xDF },    /* r07  - Power Ctl 2 */
  49        { 8, 0x3F },    /* r08  - Power Ctl 3 */
  50        { 9, 0x50 },    /* r09  - Charge Pump Freq */
  51        { 10, 0x53 },   /* r0A  - Output Load MicBias Short Detect */
  52        { 11, 0x00 },   /* r0B  - DMIC Master Clock Ctl */
  53        { 12, 0x00 },   /* r0C  - Aux PCM Ctl */
  54        { 13, 0x15 },   /* r0D  - Aux PCM Master Clock Ctl */
  55        { 14, 0x00 },   /* r0E  - Audio PCM Ctl */
  56        { 15, 0x15 },   /* r0F  - Audio PCM Master Clock Ctl */
  57        { 16, 0x00 },   /* r10  - Voice PCM Ctl */
  58        { 17, 0x15 },   /* r11  - Voice PCM Master Clock Ctl */
  59        { 18, 0x00 },   /* r12  - Voice/Aux Sample Rate */
  60        { 19, 0x06 },   /* r13  - Misc I/O Path Ctl */
  61        { 20, 0x00 },   /* r14  - ADC Input Path Ctl */
  62        { 21, 0x00 },   /* r15  - MICA Preamp, PGA Volume */
  63        { 22, 0x00 },   /* r16  - MICB Preamp, PGA Volume */
  64        { 23, 0x00 },   /* r17  - Input Path A Digital Volume */
  65        { 24, 0x00 },   /* r18  - Input Path B Digital Volume */
  66        { 25, 0x00 },   /* r19  - Playback Digital Ctl */
  67        { 26, 0x00 },   /* r1A  - HP/LO Left Digital Volume */
  68        { 27, 0x00 },   /* r1B  - HP/LO Right Digital Volume */
  69        { 28, 0x00 },   /* r1C  - Speakerphone Digital Volume */
  70        { 29, 0x00 },   /* r1D  - Ear/SPKLO Digital Volume */
  71        { 30, 0x00 },   /* r1E  - HP Left Analog Volume */
  72        { 31, 0x00 },   /* r1F  - HP Right Analog Volume */
  73        { 32, 0x00 },   /* r20  - LO Left Analog Volume */
  74        { 33, 0x00 },   /* r21  - LO Right Analog Volume */
  75        { 34, 0x00 },   /* r22  - Stereo Input Path Advisory Volume */
  76        { 35, 0x00 },   /* r23  - Aux PCM Input Advisory Volume */
  77        { 36, 0x00 },   /* r24  - Audio PCM Input Advisory Volume */
  78        { 37, 0x00 },   /* r25  - Voice PCM Input Advisory Volume */
  79        { 38, 0x00 },   /* r26  - Limiter Attack Rate HP/LO */
  80        { 39, 0x7F },   /* r27  - Limter Ctl, Release Rate HP/LO */
  81        { 40, 0x00 },   /* r28  - Limter Threshold HP/LO */
  82        { 41, 0x00 },   /* r29  - Limiter Attack Rate Speakerphone */
  83        { 42, 0x3F },   /* r2A  - Limter Ctl, Release Rate Speakerphone */
  84        { 43, 0x00 },   /* r2B  - Limter Threshold Speakerphone */
  85        { 44, 0x00 },   /* r2C  - Limiter Attack Rate Ear/SPKLO */
  86        { 45, 0x3F },   /* r2D  - Limter Ctl, Release Rate Ear/SPKLO */
  87        { 46, 0x00 },   /* r2E  - Limter Threshold Ear/SPKLO */
  88        { 47, 0x00 },   /* r2F  - ALC Enable, Attack Rate Left/Right */
  89        { 48, 0x3F },   /* r30  - ALC Release Rate Left/Right */
  90        { 49, 0x00 },   /* r31  - ALC Threshold Left/Right */
  91        { 50, 0x00 },   /* r32  - Noise Gate Ctl Left/Right */
  92        { 51, 0x00 },   /* r33  - ALC/NG Misc Ctl */
  93        { 52, 0x18 },   /* r34  - Mixer Ctl */
  94        { 53, 0x3F },   /* r35  - HP/LO Left Mixer Input Path Volume */
  95        { 54, 0x3F },   /* r36  - HP/LO Right Mixer Input Path Volume */
  96        { 55, 0x3F },   /* r37  - HP/LO Left Mixer Aux PCM Volume */
  97        { 56, 0x3F },   /* r38  - HP/LO Right Mixer Aux PCM Volume */
  98        { 57, 0x3F },   /* r39  - HP/LO Left Mixer Audio PCM Volume */
  99        { 58, 0x3F },   /* r3A  - HP/LO Right Mixer Audio PCM Volume */
 100        { 59, 0x3F },   /* r3B  - HP/LO Left Mixer Voice PCM Mono Volume */
 101        { 60, 0x3F },   /* r3C  - HP/LO Right Mixer Voice PCM Mono Volume */
 102        { 61, 0x3F },   /* r3D  - Aux PCM Left Mixer Input Path Volume */
 103        { 62, 0x3F },   /* r3E  - Aux PCM Right Mixer Input Path Volume */
 104        { 63, 0x3F },   /* r3F  - Aux PCM Left Mixer Volume */
 105        { 64, 0x3F },   /* r40  - Aux PCM Left Mixer Volume */
 106        { 65, 0x3F },   /* r41  - Aux PCM Left Mixer Audio PCM L Volume */
 107        { 66, 0x3F },   /* r42  - Aux PCM Right Mixer Audio PCM R Volume */
 108        { 67, 0x3F },   /* r43  - Aux PCM Left Mixer Voice PCM Volume */
 109        { 68, 0x3F },   /* r44  - Aux PCM Right Mixer Voice PCM Volume */
 110        { 69, 0x3F },   /* r45  - Audio PCM Left Input Path Volume */
 111        { 70, 0x3F },   /* r46  - Audio PCM Right Input Path Volume */
 112        { 71, 0x3F },   /* r47  - Audio PCM Left Mixer Aux PCM L Volume */
 113        { 72, 0x3F },   /* r48  - Audio PCM Right Mixer Aux PCM R Volume */
 114        { 73, 0x3F },   /* r49  - Audio PCM Left Mixer Volume */
 115        { 74, 0x3F },   /* r4A  - Audio PCM Right Mixer Volume */
 116        { 75, 0x3F },   /* r4B  - Audio PCM Left Mixer Voice PCM Volume */
 117        { 76, 0x3F },   /* r4C  - Audio PCM Right Mixer Voice PCM Volume */
 118        { 77, 0x3F },   /* r4D  - Voice PCM Left Input Path Volume */
 119        { 78, 0x3F },   /* r4E  - Voice PCM Right Input Path Volume */
 120        { 79, 0x3F },   /* r4F  - Voice PCM Left Mixer Aux PCM L Volume */
 121        { 80, 0x3F },   /* r50  - Voice PCM Right Mixer Aux PCM R Volume */
 122        { 81, 0x3F },   /* r51  - Voice PCM Left Mixer Audio PCM L Volume */
 123        { 82, 0x3F },   /* r52  - Voice PCM Right Mixer Audio PCM R Volume */
 124        { 83, 0x3F },   /* r53  - Voice PCM Left Mixer Voice PCM Volume */
 125        { 84, 0x3F },   /* r54  - Voice PCM Right Mixer Voice PCM Volume */
 126        { 85, 0xAA },   /* r55  - Mono Mixer Ctl */
 127        { 86, 0x3F },   /* r56  - SPK Mono Mixer Input Path Volume */
 128        { 87, 0x3F },   /* r57  - SPK Mono Mixer Aux PCM Mono/L/R Volume */
 129        { 88, 0x3F },   /* r58  - SPK Mono Mixer Audio PCM Mono/L/R Volume */
 130        { 89, 0x3F },   /* r59  - SPK Mono Mixer Voice PCM Mono Volume */
 131        { 90, 0x3F },   /* r5A  - SPKLO Mono Mixer Input Path Mono Volume */
 132        { 91, 0x3F },   /* r5B  - SPKLO Mono Mixer Aux Mono/L/R Volume */
 133        { 92, 0x3F },   /* r5C  - SPKLO Mono Mixer Audio Mono/L/R Volume */
 134        { 93, 0x3F },   /* r5D  - SPKLO Mono Mixer Voice Mono Volume */
 135        { 94, 0x00 },   /* r5E  - Interrupt Mask 1 */
 136        { 95, 0x00 },   /* r5F  - Interrupt Mask 2 */
 137};
 138
 139static bool cs42l73_volatile_register(struct device *dev, unsigned int reg)
 140{
 141        switch (reg) {
 142        case CS42L73_IS1:
 143        case CS42L73_IS2:
 144                return true;
 145        default:
 146                return false;
 147        }
 148}
 149
 150static bool cs42l73_readable_register(struct device *dev, unsigned int reg)
 151{
 152        switch (reg) {
 153        case CS42L73_DEVID_AB:
 154        case CS42L73_DEVID_CD:
 155        case CS42L73_DEVID_E:
 156        case CS42L73_REVID:
 157        case CS42L73_PWRCTL1:
 158        case CS42L73_PWRCTL2:
 159        case CS42L73_PWRCTL3:
 160        case CS42L73_CPFCHC:
 161        case CS42L73_OLMBMSDC:
 162        case CS42L73_DMMCC:
 163        case CS42L73_XSPC:
 164        case CS42L73_XSPMMCC:
 165        case CS42L73_ASPC:
 166        case CS42L73_ASPMMCC:
 167        case CS42L73_VSPC:
 168        case CS42L73_VSPMMCC:
 169        case CS42L73_VXSPFS:
 170        case CS42L73_MIOPC:
 171        case CS42L73_ADCIPC:
 172        case CS42L73_MICAPREPGAAVOL:
 173        case CS42L73_MICBPREPGABVOL:
 174        case CS42L73_IPADVOL:
 175        case CS42L73_IPBDVOL:
 176        case CS42L73_PBDC:
 177        case CS42L73_HLADVOL:
 178        case CS42L73_HLBDVOL:
 179        case CS42L73_SPKDVOL:
 180        case CS42L73_ESLDVOL:
 181        case CS42L73_HPAAVOL:
 182        case CS42L73_HPBAVOL:
 183        case CS42L73_LOAAVOL:
 184        case CS42L73_LOBAVOL:
 185        case CS42L73_STRINV:
 186        case CS42L73_XSPINV:
 187        case CS42L73_ASPINV:
 188        case CS42L73_VSPINV:
 189        case CS42L73_LIMARATEHL:
 190        case CS42L73_LIMRRATEHL:
 191        case CS42L73_LMAXHL:
 192        case CS42L73_LIMARATESPK:
 193        case CS42L73_LIMRRATESPK:
 194        case CS42L73_LMAXSPK:
 195        case CS42L73_LIMARATEESL:
 196        case CS42L73_LIMRRATEESL:
 197        case CS42L73_LMAXESL:
 198        case CS42L73_ALCARATE:
 199        case CS42L73_ALCRRATE:
 200        case CS42L73_ALCMINMAX:
 201        case CS42L73_NGCAB:
 202        case CS42L73_ALCNGMC:
 203        case CS42L73_MIXERCTL:
 204        case CS42L73_HLAIPAA:
 205        case CS42L73_HLBIPBA:
 206        case CS42L73_HLAXSPAA:
 207        case CS42L73_HLBXSPBA:
 208        case CS42L73_HLAASPAA:
 209        case CS42L73_HLBASPBA:
 210        case CS42L73_HLAVSPMA:
 211        case CS42L73_HLBVSPMA:
 212        case CS42L73_XSPAIPAA:
 213        case CS42L73_XSPBIPBA:
 214        case CS42L73_XSPAXSPAA:
 215        case CS42L73_XSPBXSPBA:
 216        case CS42L73_XSPAASPAA:
 217        case CS42L73_XSPAASPBA:
 218        case CS42L73_XSPAVSPMA:
 219        case CS42L73_XSPBVSPMA:
 220        case CS42L73_ASPAIPAA:
 221        case CS42L73_ASPBIPBA:
 222        case CS42L73_ASPAXSPAA:
 223        case CS42L73_ASPBXSPBA:
 224        case CS42L73_ASPAASPAA:
 225        case CS42L73_ASPBASPBA:
 226        case CS42L73_ASPAVSPMA:
 227        case CS42L73_ASPBVSPMA:
 228        case CS42L73_VSPAIPAA:
 229        case CS42L73_VSPBIPBA:
 230        case CS42L73_VSPAXSPAA:
 231        case CS42L73_VSPBXSPBA:
 232        case CS42L73_VSPAASPAA:
 233        case CS42L73_VSPBASPBA:
 234        case CS42L73_VSPAVSPMA:
 235        case CS42L73_VSPBVSPMA:
 236        case CS42L73_MMIXCTL:
 237        case CS42L73_SPKMIPMA:
 238        case CS42L73_SPKMXSPA:
 239        case CS42L73_SPKMASPA:
 240        case CS42L73_SPKMVSPMA:
 241        case CS42L73_ESLMIPMA:
 242        case CS42L73_ESLMXSPA:
 243        case CS42L73_ESLMASPA:
 244        case CS42L73_ESLMVSPMA:
 245        case CS42L73_IM1:
 246        case CS42L73_IM2:
 247                return true;
 248        default:
 249                return false;
 250        }
 251}
 252
 253static const unsigned int hpaloa_tlv[] = {
 254        TLV_DB_RANGE_HEAD(2),
 255        0, 13, TLV_DB_SCALE_ITEM(-7600, 200, 0),
 256        14, 75, TLV_DB_SCALE_ITEM(-4900, 100, 0),
 257};
 258
 259static DECLARE_TLV_DB_SCALE(adc_boost_tlv, 0, 2500, 0);
 260
 261static DECLARE_TLV_DB_SCALE(hl_tlv, -10200, 50, 0);
 262
 263static DECLARE_TLV_DB_SCALE(ipd_tlv, -9600, 100, 0);
 264
 265static DECLARE_TLV_DB_SCALE(micpga_tlv, -600, 50, 0);
 266
 267static const unsigned int limiter_tlv[] = {
 268        TLV_DB_RANGE_HEAD(2),
 269        0, 2, TLV_DB_SCALE_ITEM(-3000, 600, 0),
 270        3, 7, TLV_DB_SCALE_ITEM(-1200, 300, 0),
 271};
 272
 273static const DECLARE_TLV_DB_SCALE(attn_tlv, -6300, 100, 1);
 274
 275static const char * const cs42l73_pgaa_text[] = { "Line A", "Mic 1" };
 276static const char * const cs42l73_pgab_text[] = { "Line B", "Mic 2" };
 277
 278static const struct soc_enum pgaa_enum =
 279        SOC_ENUM_SINGLE(CS42L73_ADCIPC, 3,
 280                ARRAY_SIZE(cs42l73_pgaa_text), cs42l73_pgaa_text);
 281
 282static const struct soc_enum pgab_enum =
 283        SOC_ENUM_SINGLE(CS42L73_ADCIPC, 7,
 284                ARRAY_SIZE(cs42l73_pgab_text), cs42l73_pgab_text);
 285
 286static const struct snd_kcontrol_new pgaa_mux =
 287        SOC_DAPM_ENUM("Left Analog Input Capture Mux", pgaa_enum);
 288
 289static const struct snd_kcontrol_new pgab_mux =
 290        SOC_DAPM_ENUM("Right Analog Input Capture Mux", pgab_enum);
 291
 292static const struct snd_kcontrol_new input_left_mixer[] = {
 293        SOC_DAPM_SINGLE("ADC Left Input", CS42L73_PWRCTL1,
 294                        5, 1, 1),
 295        SOC_DAPM_SINGLE("DMIC Left Input", CS42L73_PWRCTL1,
 296                        4, 1, 1),
 297};
 298
 299static const struct snd_kcontrol_new input_right_mixer[] = {
 300        SOC_DAPM_SINGLE("ADC Right Input", CS42L73_PWRCTL1,
 301                        7, 1, 1),
 302        SOC_DAPM_SINGLE("DMIC Right Input", CS42L73_PWRCTL1,
 303                        6, 1, 1),
 304};
 305
 306static const char * const cs42l73_ng_delay_text[] = {
 307        "50ms", "100ms", "150ms", "200ms" };
 308
 309static const struct soc_enum ng_delay_enum =
 310        SOC_ENUM_SINGLE(CS42L73_NGCAB, 0,
 311                ARRAY_SIZE(cs42l73_ng_delay_text), cs42l73_ng_delay_text);
 312
 313static const char * const charge_pump_freq_text[] = {
 314        "0", "1", "2", "3", "4",
 315        "5", "6", "7", "8", "9",
 316        "10", "11", "12", "13", "14", "15" };
 317
 318static const struct soc_enum charge_pump_enum =
 319        SOC_ENUM_SINGLE(CS42L73_CPFCHC, 4,
 320                ARRAY_SIZE(charge_pump_freq_text), charge_pump_freq_text);
 321
 322static const char * const cs42l73_mono_mix_texts[] = {
 323        "Left", "Right", "Mono Mix"};
 324
 325static const unsigned int cs42l73_mono_mix_values[] = { 0, 1, 2 };
 326
 327static const struct soc_enum spk_asp_enum =
 328        SOC_VALUE_ENUM_SINGLE(CS42L73_MMIXCTL, 6, 1,
 329                              ARRAY_SIZE(cs42l73_mono_mix_texts),
 330                              cs42l73_mono_mix_texts,
 331                              cs42l73_mono_mix_values);
 332
 333static const struct snd_kcontrol_new spk_asp_mixer =
 334        SOC_DAPM_ENUM("Route", spk_asp_enum);
 335
 336static const struct soc_enum spk_xsp_enum =
 337        SOC_VALUE_ENUM_SINGLE(CS42L73_MMIXCTL, 4, 3,
 338                              ARRAY_SIZE(cs42l73_mono_mix_texts),
 339                              cs42l73_mono_mix_texts,
 340                              cs42l73_mono_mix_values);
 341
 342static const struct snd_kcontrol_new spk_xsp_mixer =
 343        SOC_DAPM_ENUM("Route", spk_xsp_enum);
 344
 345static const struct soc_enum esl_asp_enum =
 346        SOC_VALUE_ENUM_SINGLE(CS42L73_MMIXCTL, 2, 5,
 347                              ARRAY_SIZE(cs42l73_mono_mix_texts),
 348                              cs42l73_mono_mix_texts,
 349                              cs42l73_mono_mix_values);
 350
 351static const struct snd_kcontrol_new esl_asp_mixer =
 352        SOC_DAPM_ENUM("Route", esl_asp_enum);
 353
 354static const struct soc_enum esl_xsp_enum =
 355        SOC_VALUE_ENUM_SINGLE(CS42L73_MMIXCTL, 0, 7,
 356                              ARRAY_SIZE(cs42l73_mono_mix_texts),
 357                              cs42l73_mono_mix_texts,
 358                              cs42l73_mono_mix_values);
 359
 360static const struct snd_kcontrol_new esl_xsp_mixer =
 361        SOC_DAPM_ENUM("Route", esl_xsp_enum);
 362
 363static const char * const cs42l73_ip_swap_text[] = {
 364        "Stereo", "Mono A", "Mono B", "Swap A-B"};
 365
 366static const struct soc_enum ip_swap_enum =
 367        SOC_ENUM_SINGLE(CS42L73_MIOPC, 6,
 368                ARRAY_SIZE(cs42l73_ip_swap_text), cs42l73_ip_swap_text);
 369
 370static const char * const cs42l73_spo_mixer_text[] = {"Mono", "Stereo"};
 371
 372static const struct soc_enum vsp_output_mux_enum =
 373        SOC_ENUM_SINGLE(CS42L73_MIXERCTL, 5,
 374                ARRAY_SIZE(cs42l73_spo_mixer_text), cs42l73_spo_mixer_text);
 375
 376static const struct soc_enum xsp_output_mux_enum =
 377        SOC_ENUM_SINGLE(CS42L73_MIXERCTL, 4,
 378                ARRAY_SIZE(cs42l73_spo_mixer_text), cs42l73_spo_mixer_text);
 379
 380static const struct snd_kcontrol_new vsp_output_mux =
 381        SOC_DAPM_ENUM("Route", vsp_output_mux_enum);
 382
 383static const struct snd_kcontrol_new xsp_output_mux =
 384        SOC_DAPM_ENUM("Route", xsp_output_mux_enum);
 385
 386static const struct snd_kcontrol_new hp_amp_ctl =
 387        SOC_DAPM_SINGLE("Switch", CS42L73_PWRCTL3, 0, 1, 1);
 388
 389static const struct snd_kcontrol_new lo_amp_ctl =
 390        SOC_DAPM_SINGLE("Switch", CS42L73_PWRCTL3, 1, 1, 1);
 391
 392static const struct snd_kcontrol_new spk_amp_ctl =
 393        SOC_DAPM_SINGLE("Switch", CS42L73_PWRCTL3, 2, 1, 1);
 394
 395static const struct snd_kcontrol_new spklo_amp_ctl =
 396        SOC_DAPM_SINGLE("Switch", CS42L73_PWRCTL3, 4, 1, 1);
 397
 398static const struct snd_kcontrol_new ear_amp_ctl =
 399        SOC_DAPM_SINGLE("Switch", CS42L73_PWRCTL3, 3, 1, 1);
 400
 401static const struct snd_kcontrol_new cs42l73_snd_controls[] = {
 402        SOC_DOUBLE_R_SX_TLV("Headphone Analog Playback Volume",
 403                        CS42L73_HPAAVOL, CS42L73_HPBAVOL, 0,
 404                        0x41, 0x4B, hpaloa_tlv),
 405
 406        SOC_DOUBLE_R_SX_TLV("LineOut Analog Playback Volume", CS42L73_LOAAVOL,
 407                        CS42L73_LOBAVOL, 0, 0x41, 0x4B, hpaloa_tlv),
 408
 409        SOC_DOUBLE_R_SX_TLV("Input PGA Analog Volume", CS42L73_MICAPREPGAAVOL,
 410                        CS42L73_MICBPREPGABVOL, 5, 0x34,
 411                        0x24, micpga_tlv),
 412
 413        SOC_DOUBLE_R("MIC Preamp Switch", CS42L73_MICAPREPGAAVOL,
 414                        CS42L73_MICBPREPGABVOL, 6, 1, 1),
 415
 416        SOC_DOUBLE_R_SX_TLV("Input Path Digital Volume", CS42L73_IPADVOL,
 417                        CS42L73_IPBDVOL, 0, 0xA0, 0x6C, ipd_tlv),
 418
 419        SOC_DOUBLE_R_SX_TLV("HL Digital Playback Volume",
 420                        CS42L73_HLADVOL, CS42L73_HLBDVOL,
 421                        0, 0x34, 0xE4, hl_tlv),
 422
 423        SOC_SINGLE_TLV("ADC A Boost Volume",
 424                        CS42L73_ADCIPC, 2, 0x01, 1, adc_boost_tlv),
 425
 426        SOC_SINGLE_TLV("ADC B Boost Volume",
 427                       CS42L73_ADCIPC, 6, 0x01, 1, adc_boost_tlv),
 428
 429        SOC_SINGLE_SX_TLV("Speakerphone Digital Volume",
 430                            CS42L73_SPKDVOL, 0, 0x34, 0xE4, hl_tlv),
 431
 432        SOC_SINGLE_SX_TLV("Ear Speaker Digital Volume",
 433                            CS42L73_ESLDVOL, 0, 0x34, 0xE4, hl_tlv),
 434
 435        SOC_DOUBLE_R("Headphone Analog Playback Switch", CS42L73_HPAAVOL,
 436                        CS42L73_HPBAVOL, 7, 1, 1),
 437
 438        SOC_DOUBLE_R("LineOut Analog Playback Switch", CS42L73_LOAAVOL,
 439                        CS42L73_LOBAVOL, 7, 1, 1),
 440        SOC_DOUBLE("Input Path Digital Switch", CS42L73_ADCIPC, 0, 4, 1, 1),
 441        SOC_DOUBLE("HL Digital Playback Switch", CS42L73_PBDC, 0,
 442                        1, 1, 1),
 443        SOC_SINGLE("Speakerphone Digital Playback Switch", CS42L73_PBDC, 2, 1,
 444                        1),
 445        SOC_SINGLE("Ear Speaker Digital Playback Switch", CS42L73_PBDC, 3, 1,
 446                        1),
 447
 448        SOC_SINGLE("PGA Soft-Ramp Switch", CS42L73_MIOPC, 3, 1, 0),
 449        SOC_SINGLE("Analog Zero Cross Switch", CS42L73_MIOPC, 2, 1, 0),
 450        SOC_SINGLE("Digital Soft-Ramp Switch", CS42L73_MIOPC, 1, 1, 0),
 451        SOC_SINGLE("Analog Output Soft-Ramp Switch", CS42L73_MIOPC, 0, 1, 0),
 452
 453        SOC_DOUBLE("ADC Signal Polarity Switch", CS42L73_ADCIPC, 1, 5, 1,
 454                        0),
 455
 456        SOC_SINGLE("HL Limiter Attack Rate", CS42L73_LIMARATEHL, 0, 0x3F,
 457                        0),
 458        SOC_SINGLE("HL Limiter Release Rate", CS42L73_LIMRRATEHL, 0,
 459                        0x3F, 0),
 460
 461
 462        SOC_SINGLE("HL Limiter Switch", CS42L73_LIMRRATEHL, 7, 1, 0),
 463        SOC_SINGLE("HL Limiter All Channels Switch", CS42L73_LIMRRATEHL, 6, 1,
 464                        0),
 465
 466        SOC_SINGLE_TLV("HL Limiter Max Threshold Volume", CS42L73_LMAXHL, 5, 7,
 467                        1, limiter_tlv),
 468
 469        SOC_SINGLE_TLV("HL Limiter Cushion Volume", CS42L73_LMAXHL, 2, 7, 1,
 470                        limiter_tlv),
 471
 472        SOC_SINGLE("SPK Limiter Attack Rate Volume", CS42L73_LIMARATESPK, 0,
 473                        0x3F, 0),
 474        SOC_SINGLE("SPK Limiter Release Rate Volume", CS42L73_LIMRRATESPK, 0,
 475                        0x3F, 0),
 476        SOC_SINGLE("SPK Limiter Switch", CS42L73_LIMRRATESPK, 7, 1, 0),
 477        SOC_SINGLE("SPK Limiter All Channels Switch", CS42L73_LIMRRATESPK,
 478                        6, 1, 0),
 479        SOC_SINGLE_TLV("SPK Limiter Max Threshold Volume", CS42L73_LMAXSPK, 5,
 480                        7, 1, limiter_tlv),
 481
 482        SOC_SINGLE_TLV("SPK Limiter Cushion Volume", CS42L73_LMAXSPK, 2, 7, 1,
 483                        limiter_tlv),
 484
 485        SOC_SINGLE("ESL Limiter Attack Rate Volume", CS42L73_LIMARATEESL, 0,
 486                        0x3F, 0),
 487        SOC_SINGLE("ESL Limiter Release Rate Volume", CS42L73_LIMRRATEESL, 0,
 488                        0x3F, 0),
 489        SOC_SINGLE("ESL Limiter Switch", CS42L73_LIMRRATEESL, 7, 1, 0),
 490        SOC_SINGLE_TLV("ESL Limiter Max Threshold Volume", CS42L73_LMAXESL, 5,
 491                        7, 1, limiter_tlv),
 492
 493        SOC_SINGLE_TLV("ESL Limiter Cushion Volume", CS42L73_LMAXESL, 2, 7, 1,
 494                        limiter_tlv),
 495
 496        SOC_SINGLE("ALC Attack Rate Volume", CS42L73_ALCARATE, 0, 0x3F, 0),
 497        SOC_SINGLE("ALC Release Rate Volume", CS42L73_ALCRRATE, 0, 0x3F, 0),
 498        SOC_DOUBLE("ALC Switch", CS42L73_ALCARATE, 6, 7, 1, 0),
 499        SOC_SINGLE_TLV("ALC Max Threshold Volume", CS42L73_ALCMINMAX, 5, 7, 0,
 500                        limiter_tlv),
 501        SOC_SINGLE_TLV("ALC Min Threshold Volume", CS42L73_ALCMINMAX, 2, 7, 0,
 502                        limiter_tlv),
 503
 504        SOC_DOUBLE("NG Enable Switch", CS42L73_NGCAB, 6, 7, 1, 0),
 505        SOC_SINGLE("NG Boost Switch", CS42L73_NGCAB, 5, 1, 0),
 506        /*
 507            NG Threshold depends on NG_BOOTSAB, which selects
 508            between two threshold scales in decibels.
 509            Set linear values for now ..
 510        */
 511        SOC_SINGLE("NG Threshold", CS42L73_NGCAB, 2, 7, 0),
 512        SOC_ENUM("NG Delay", ng_delay_enum),
 513
 514        SOC_ENUM("Charge Pump Frequency", charge_pump_enum),
 515
 516        SOC_DOUBLE_R_TLV("XSP-IP Volume",
 517                        CS42L73_XSPAIPAA, CS42L73_XSPBIPBA, 0, 0x3F, 1,
 518                        attn_tlv),
 519        SOC_DOUBLE_R_TLV("XSP-XSP Volume",
 520                        CS42L73_XSPAXSPAA, CS42L73_XSPBXSPBA, 0, 0x3F, 1,
 521                        attn_tlv),
 522        SOC_DOUBLE_R_TLV("XSP-ASP Volume",
 523                        CS42L73_XSPAASPAA, CS42L73_XSPAASPBA, 0, 0x3F, 1,
 524                        attn_tlv),
 525        SOC_DOUBLE_R_TLV("XSP-VSP Volume",
 526                        CS42L73_XSPAVSPMA, CS42L73_XSPBVSPMA, 0, 0x3F, 1,
 527                        attn_tlv),
 528
 529        SOC_DOUBLE_R_TLV("ASP-IP Volume",
 530                        CS42L73_ASPAIPAA, CS42L73_ASPBIPBA, 0, 0x3F, 1,
 531                        attn_tlv),
 532        SOC_DOUBLE_R_TLV("ASP-XSP Volume",
 533                        CS42L73_ASPAXSPAA, CS42L73_ASPBXSPBA, 0, 0x3F, 1,
 534                        attn_tlv),
 535        SOC_DOUBLE_R_TLV("ASP-ASP Volume",
 536                        CS42L73_ASPAASPAA, CS42L73_ASPBASPBA, 0, 0x3F, 1,
 537                        attn_tlv),
 538        SOC_DOUBLE_R_TLV("ASP-VSP Volume",
 539                        CS42L73_ASPAVSPMA, CS42L73_ASPBVSPMA, 0, 0x3F, 1,
 540                        attn_tlv),
 541
 542        SOC_DOUBLE_R_TLV("VSP-IP Volume",
 543                        CS42L73_VSPAIPAA, CS42L73_VSPBIPBA, 0, 0x3F, 1,
 544                        attn_tlv),
 545        SOC_DOUBLE_R_TLV("VSP-XSP Volume",
 546                        CS42L73_VSPAXSPAA, CS42L73_VSPBXSPBA, 0, 0x3F, 1,
 547                        attn_tlv),
 548        SOC_DOUBLE_R_TLV("VSP-ASP Volume",
 549                        CS42L73_VSPAASPAA, CS42L73_VSPBASPBA, 0, 0x3F, 1,
 550                        attn_tlv),
 551        SOC_DOUBLE_R_TLV("VSP-VSP Volume",
 552                        CS42L73_VSPAVSPMA, CS42L73_VSPBVSPMA, 0, 0x3F, 1,
 553                        attn_tlv),
 554
 555        SOC_DOUBLE_R_TLV("HL-IP Volume",
 556                        CS42L73_HLAIPAA, CS42L73_HLBIPBA, 0, 0x3F, 1,
 557                        attn_tlv),
 558        SOC_DOUBLE_R_TLV("HL-XSP Volume",
 559                        CS42L73_HLAXSPAA, CS42L73_HLBXSPBA, 0, 0x3F, 1,
 560                        attn_tlv),
 561        SOC_DOUBLE_R_TLV("HL-ASP Volume",
 562                        CS42L73_HLAASPAA, CS42L73_HLBASPBA, 0, 0x3F, 1,
 563                        attn_tlv),
 564        SOC_DOUBLE_R_TLV("HL-VSP Volume",
 565                        CS42L73_HLAVSPMA, CS42L73_HLBVSPMA, 0, 0x3F, 1,
 566                        attn_tlv),
 567
 568        SOC_SINGLE_TLV("SPK-IP Mono Volume",
 569                        CS42L73_SPKMIPMA, 0, 0x3F, 1, attn_tlv),
 570        SOC_SINGLE_TLV("SPK-XSP Mono Volume",
 571                        CS42L73_SPKMXSPA, 0, 0x3F, 1, attn_tlv),
 572        SOC_SINGLE_TLV("SPK-ASP Mono Volume",
 573                        CS42L73_SPKMASPA, 0, 0x3F, 1, attn_tlv),
 574        SOC_SINGLE_TLV("SPK-VSP Mono Volume",
 575                        CS42L73_SPKMVSPMA, 0, 0x3F, 1, attn_tlv),
 576
 577        SOC_SINGLE_TLV("ESL-IP Mono Volume",
 578                        CS42L73_ESLMIPMA, 0, 0x3F, 1, attn_tlv),
 579        SOC_SINGLE_TLV("ESL-XSP Mono Volume",
 580                        CS42L73_ESLMXSPA, 0, 0x3F, 1, attn_tlv),
 581        SOC_SINGLE_TLV("ESL-ASP Mono Volume",
 582                        CS42L73_ESLMASPA, 0, 0x3F, 1, attn_tlv),
 583        SOC_SINGLE_TLV("ESL-VSP Mono Volume",
 584                        CS42L73_ESLMVSPMA, 0, 0x3F, 1, attn_tlv),
 585
 586        SOC_ENUM("IP Digital Swap/Mono Select", ip_swap_enum),
 587
 588        SOC_ENUM("VSPOUT Mono/Stereo Select", vsp_output_mux_enum),
 589        SOC_ENUM("XSPOUT Mono/Stereo Select", xsp_output_mux_enum),
 590};
 591
 592static int cs42l73_spklo_spk_amp_event(struct snd_soc_dapm_widget *w,
 593        struct snd_kcontrol *kcontrol, int event)
 594{
 595        struct snd_soc_codec *codec = w->codec;
 596        struct cs42l73_private *priv = snd_soc_codec_get_drvdata(codec);
 597        switch (event) {
 598        case SND_SOC_DAPM_POST_PMD:
 599                /* 150 ms delay between setting PDN and MCLKDIS */
 600                priv->shutdwn_delay = 150;
 601                break;
 602        default:
 603                pr_err("Invalid event = 0x%x\n", event);
 604        }
 605        return 0;
 606}
 607
 608static int cs42l73_ear_amp_event(struct snd_soc_dapm_widget *w,
 609        struct snd_kcontrol *kcontrol, int event)
 610{
 611        struct snd_soc_codec *codec = w->codec;
 612        struct cs42l73_private *priv = snd_soc_codec_get_drvdata(codec);
 613        switch (event) {
 614        case SND_SOC_DAPM_POST_PMD:
 615                /* 50 ms delay between setting PDN and MCLKDIS */
 616                if (priv->shutdwn_delay < 50)
 617                        priv->shutdwn_delay = 50;
 618                break;
 619        default:
 620                pr_err("Invalid event = 0x%x\n", event);
 621        }
 622        return 0;
 623}
 624
 625
 626static int cs42l73_hp_amp_event(struct snd_soc_dapm_widget *w,
 627        struct snd_kcontrol *kcontrol, int event)
 628{
 629        struct snd_soc_codec *codec = w->codec;
 630        struct cs42l73_private *priv = snd_soc_codec_get_drvdata(codec);
 631        switch (event) {
 632        case SND_SOC_DAPM_POST_PMD:
 633                /* 30 ms delay between setting PDN and MCLKDIS */
 634                if (priv->shutdwn_delay < 30)
 635                        priv->shutdwn_delay = 30;
 636                break;
 637        default:
 638                pr_err("Invalid event = 0x%x\n", event);
 639        }
 640        return 0;
 641}
 642
 643static const struct snd_soc_dapm_widget cs42l73_dapm_widgets[] = {
 644        SND_SOC_DAPM_INPUT("DMICA"),
 645        SND_SOC_DAPM_INPUT("DMICB"),
 646        SND_SOC_DAPM_INPUT("LINEINA"),
 647        SND_SOC_DAPM_INPUT("LINEINB"),
 648        SND_SOC_DAPM_INPUT("MIC1"),
 649        SND_SOC_DAPM_SUPPLY("MIC1 Bias", CS42L73_PWRCTL2, 6, 1, NULL, 0),
 650        SND_SOC_DAPM_INPUT("MIC2"),
 651        SND_SOC_DAPM_SUPPLY("MIC2 Bias", CS42L73_PWRCTL2, 7, 1, NULL, 0),
 652
 653        SND_SOC_DAPM_AIF_OUT("XSPOUTL", NULL,  0,
 654                        CS42L73_PWRCTL2, 1, 1),
 655        SND_SOC_DAPM_AIF_OUT("XSPOUTR", NULL,  0,
 656                        CS42L73_PWRCTL2, 1, 1),
 657        SND_SOC_DAPM_AIF_OUT("ASPOUTL", NULL,  0,
 658                        CS42L73_PWRCTL2, 3, 1),
 659        SND_SOC_DAPM_AIF_OUT("ASPOUTR", NULL,  0,
 660                        CS42L73_PWRCTL2, 3, 1),
 661        SND_SOC_DAPM_AIF_OUT("VSPINOUT", NULL,  0,
 662                        CS42L73_PWRCTL2, 4, 1),
 663
 664        SND_SOC_DAPM_PGA("PGA Left", SND_SOC_NOPM, 0, 0, NULL, 0),
 665        SND_SOC_DAPM_PGA("PGA Right", SND_SOC_NOPM, 0, 0, NULL, 0),
 666
 667        SND_SOC_DAPM_MUX("PGA Left Mux", SND_SOC_NOPM, 0, 0, &pgaa_mux),
 668        SND_SOC_DAPM_MUX("PGA Right Mux", SND_SOC_NOPM, 0, 0, &pgab_mux),
 669
 670        SND_SOC_DAPM_ADC("ADC Left", NULL, CS42L73_PWRCTL1, 7, 1),
 671        SND_SOC_DAPM_ADC("ADC Right", NULL, CS42L73_PWRCTL1, 5, 1),
 672        SND_SOC_DAPM_ADC("DMIC Left", NULL, CS42L73_PWRCTL1, 6, 1),
 673        SND_SOC_DAPM_ADC("DMIC Right", NULL, CS42L73_PWRCTL1, 4, 1),
 674
 675        SND_SOC_DAPM_MIXER_NAMED_CTL("Input Left Capture", SND_SOC_NOPM,
 676                         0, 0, input_left_mixer,
 677                         ARRAY_SIZE(input_left_mixer)),
 678
 679        SND_SOC_DAPM_MIXER_NAMED_CTL("Input Right Capture", SND_SOC_NOPM,
 680                        0, 0, input_right_mixer,
 681                        ARRAY_SIZE(input_right_mixer)),
 682
 683        SND_SOC_DAPM_MIXER("ASPL Output Mixer", SND_SOC_NOPM, 0, 0, NULL, 0),
 684        SND_SOC_DAPM_MIXER("ASPR Output Mixer", SND_SOC_NOPM, 0, 0, NULL, 0),
 685        SND_SOC_DAPM_MIXER("XSPL Output Mixer", SND_SOC_NOPM, 0, 0, NULL, 0),
 686        SND_SOC_DAPM_MIXER("XSPR Output Mixer", SND_SOC_NOPM, 0, 0, NULL, 0),
 687        SND_SOC_DAPM_MIXER("VSP Output Mixer", SND_SOC_NOPM, 0, 0, NULL, 0),
 688
 689        SND_SOC_DAPM_AIF_IN("XSPINL", NULL, 0,
 690                                CS42L73_PWRCTL2, 0, 1),
 691        SND_SOC_DAPM_AIF_IN("XSPINR", NULL, 0,
 692                                CS42L73_PWRCTL2, 0, 1),
 693        SND_SOC_DAPM_AIF_IN("XSPINM", NULL, 0,
 694                                CS42L73_PWRCTL2, 0, 1),
 695
 696        SND_SOC_DAPM_AIF_IN("ASPINL", NULL, 0,
 697                                CS42L73_PWRCTL2, 2, 1),
 698        SND_SOC_DAPM_AIF_IN("ASPINR", NULL, 0,
 699                                CS42L73_PWRCTL2, 2, 1),
 700        SND_SOC_DAPM_AIF_IN("ASPINM", NULL, 0,
 701                                CS42L73_PWRCTL2, 2, 1),
 702
 703        SND_SOC_DAPM_AIF_IN("VSPINOUT", NULL, 0,
 704                                CS42L73_PWRCTL2, 4, 1),
 705
 706        SND_SOC_DAPM_MIXER("HL Left Mixer", SND_SOC_NOPM, 0, 0, NULL, 0),
 707        SND_SOC_DAPM_MIXER("HL Right Mixer", SND_SOC_NOPM, 0, 0, NULL, 0),
 708        SND_SOC_DAPM_MIXER("SPK Mixer", SND_SOC_NOPM, 0, 0, NULL, 0),
 709        SND_SOC_DAPM_MIXER("ESL Mixer", SND_SOC_NOPM, 0, 0, NULL, 0),
 710
 711        SND_SOC_DAPM_MUX("ESL-XSP Mux", SND_SOC_NOPM,
 712                         0, 0, &esl_xsp_mixer),
 713
 714        SND_SOC_DAPM_MUX("ESL-ASP Mux", SND_SOC_NOPM,
 715                         0, 0, &esl_asp_mixer),
 716
 717        SND_SOC_DAPM_MUX("SPK-ASP Mux", SND_SOC_NOPM,
 718                         0, 0, &spk_asp_mixer),
 719
 720        SND_SOC_DAPM_MUX("SPK-XSP Mux", SND_SOC_NOPM,
 721                         0, 0, &spk_xsp_mixer),
 722
 723        SND_SOC_DAPM_PGA("HL Left DAC", SND_SOC_NOPM, 0, 0, NULL, 0),
 724        SND_SOC_DAPM_PGA("HL Right DAC", SND_SOC_NOPM, 0, 0, NULL, 0),
 725        SND_SOC_DAPM_PGA("SPK DAC", SND_SOC_NOPM, 0, 0, NULL, 0),
 726        SND_SOC_DAPM_PGA("ESL DAC", SND_SOC_NOPM, 0, 0, NULL, 0),
 727
 728        SND_SOC_DAPM_SWITCH_E("HP Amp",  CS42L73_PWRCTL3, 0, 1,
 729                            &hp_amp_ctl, cs42l73_hp_amp_event,
 730                        SND_SOC_DAPM_POST_PMD),
 731        SND_SOC_DAPM_SWITCH("LO Amp", CS42L73_PWRCTL3, 1, 1,
 732                            &lo_amp_ctl),
 733        SND_SOC_DAPM_SWITCH_E("SPK Amp", CS42L73_PWRCTL3, 2, 1,
 734                        &spk_amp_ctl, cs42l73_spklo_spk_amp_event,
 735                        SND_SOC_DAPM_POST_PMD),
 736        SND_SOC_DAPM_SWITCH_E("EAR Amp", CS42L73_PWRCTL3, 3, 1,
 737                            &ear_amp_ctl, cs42l73_ear_amp_event,
 738                        SND_SOC_DAPM_POST_PMD),
 739        SND_SOC_DAPM_SWITCH_E("SPKLO Amp", CS42L73_PWRCTL3, 4, 1,
 740                            &spklo_amp_ctl, cs42l73_spklo_spk_amp_event,
 741                        SND_SOC_DAPM_POST_PMD),
 742
 743        SND_SOC_DAPM_OUTPUT("HPOUTA"),
 744        SND_SOC_DAPM_OUTPUT("HPOUTB"),
 745        SND_SOC_DAPM_OUTPUT("LINEOUTA"),
 746        SND_SOC_DAPM_OUTPUT("LINEOUTB"),
 747        SND_SOC_DAPM_OUTPUT("EAROUT"),
 748        SND_SOC_DAPM_OUTPUT("SPKOUT"),
 749        SND_SOC_DAPM_OUTPUT("SPKLINEOUT"),
 750};
 751
 752static const struct snd_soc_dapm_route cs42l73_audio_map[] = {
 753
 754        /* SPKLO EARSPK Paths */
 755        {"EAROUT", NULL, "EAR Amp"},
 756        {"SPKLINEOUT", NULL, "SPKLO Amp"},
 757
 758        {"EAR Amp", "Switch", "ESL DAC"},
 759        {"SPKLO Amp", "Switch", "ESL DAC"},
 760
 761        {"ESL DAC", "ESL-ASP Mono Volume", "ESL Mixer"},
 762        {"ESL DAC", "ESL-XSP Mono Volume", "ESL Mixer"},
 763        {"ESL DAC", "ESL-VSP Mono Volume", "VSPINOUT"},
 764        /* Loopback */
 765        {"ESL DAC", "ESL-IP Mono Volume", "Input Left Capture"},
 766        {"ESL DAC", "ESL-IP Mono Volume", "Input Right Capture"},
 767
 768        {"ESL Mixer", NULL, "ESL-ASP Mux"},
 769        {"ESL Mixer", NULL, "ESL-XSP Mux"},
 770
 771        {"ESL-ASP Mux", "Left", "ASPINL"},
 772        {"ESL-ASP Mux", "Right", "ASPINR"},
 773        {"ESL-ASP Mux", "Mono Mix", "ASPINM"},
 774
 775        {"ESL-XSP Mux", "Left", "XSPINL"},
 776        {"ESL-XSP Mux", "Right", "XSPINR"},
 777        {"ESL-XSP Mux", "Mono Mix", "XSPINM"},
 778
 779        /* Speakerphone Paths */
 780        {"SPKOUT", NULL, "SPK Amp"},
 781        {"SPK Amp", "Switch", "SPK DAC"},
 782
 783        {"SPK DAC", "SPK-ASP Mono Volume", "SPK Mixer"},
 784        {"SPK DAC", "SPK-XSP Mono Volume", "SPK Mixer"},
 785        {"SPK DAC", "SPK-VSP Mono Volume", "VSPINOUT"},
 786        /* Loopback */
 787        {"SPK DAC", "SPK-IP Mono Volume", "Input Left Capture"},
 788        {"SPK DAC", "SPK-IP Mono Volume", "Input Right Capture"},
 789
 790        {"SPK Mixer", NULL, "SPK-ASP Mux"},
 791        {"SPK Mixer", NULL, "SPK-XSP Mux"},
 792
 793        {"SPK-ASP Mux", "Left", "ASPINL"},
 794        {"SPK-ASP Mux", "Mono Mix", "ASPINM"},
 795        {"SPK-ASP Mux", "Right", "ASPINR"},
 796
 797        {"SPK-XSP Mux", "Left", "XSPINL"},
 798        {"SPK-XSP Mux", "Mono Mix", "XSPINM"},
 799        {"SPK-XSP Mux", "Right", "XSPINR"},
 800
 801        /* HP LineOUT Paths */
 802        {"HPOUTA", NULL, "HP Amp"},
 803        {"HPOUTB", NULL, "HP Amp"},
 804        {"LINEOUTA", NULL, "LO Amp"},
 805        {"LINEOUTB", NULL, "LO Amp"},
 806
 807        {"HP Amp", "Switch", "HL Left DAC"},
 808        {"HP Amp", "Switch", "HL Right DAC"},
 809        {"LO Amp", "Switch", "HL Left DAC"},
 810        {"LO Amp", "Switch", "HL Right DAC"},
 811
 812        {"HL Left DAC", "HL-XSP Volume", "HL Left Mixer"},
 813        {"HL Right DAC", "HL-XSP Volume", "HL Right Mixer"},
 814        {"HL Left DAC", "HL-ASP Volume", "HL Left Mixer"},
 815        {"HL Right DAC", "HL-ASP Volume", "HL Right Mixer"},
 816        {"HL Left DAC", "HL-VSP Volume", "HL Left Mixer"},
 817        {"HL Right DAC", "HL-VSP Volume", "HL Right Mixer"},
 818        /* Loopback */
 819        {"HL Left DAC", "HL-IP Volume", "HL Left Mixer"},
 820        {"HL Right DAC", "HL-IP Volume", "HL Right Mixer"},
 821        {"HL Left Mixer", NULL, "Input Left Capture"},
 822        {"HL Right Mixer", NULL, "Input Right Capture"},
 823
 824        {"HL Left Mixer", NULL, "ASPINL"},
 825        {"HL Right Mixer", NULL, "ASPINR"},
 826        {"HL Left Mixer", NULL, "XSPINL"},
 827        {"HL Right Mixer", NULL, "XSPINR"},
 828        {"HL Left Mixer", NULL, "VSPINOUT"},
 829        {"HL Right Mixer", NULL, "VSPINOUT"},
 830
 831        {"ASPINL", NULL, "ASP Playback"},
 832        {"ASPINM", NULL, "ASP Playback"},
 833        {"ASPINR", NULL, "ASP Playback"},
 834        {"XSPINL", NULL, "XSP Playback"},
 835        {"XSPINM", NULL, "XSP Playback"},
 836        {"XSPINR", NULL, "XSP Playback"},
 837        {"VSPINOUT", NULL, "VSP Playback"},
 838
 839        /* Capture Paths */
 840        {"MIC1", NULL, "MIC1 Bias"},
 841        {"PGA Left Mux", "Mic 1", "MIC1"},
 842        {"MIC2", NULL, "MIC2 Bias"},
 843        {"PGA Right Mux", "Mic 2", "MIC2"},
 844
 845        {"PGA Left Mux", "Line A", "LINEINA"},
 846        {"PGA Right Mux", "Line B", "LINEINB"},
 847
 848        {"PGA Left", NULL, "PGA Left Mux"},
 849        {"PGA Right", NULL, "PGA Right Mux"},
 850
 851        {"ADC Left", NULL, "PGA Left"},
 852        {"ADC Right", NULL, "PGA Right"},
 853        {"DMIC Left", NULL, "DMICA"},
 854        {"DMIC Right", NULL, "DMICB"},
 855
 856        {"Input Left Capture", "ADC Left Input", "ADC Left"},
 857        {"Input Right Capture", "ADC Right Input", "ADC Right"},
 858        {"Input Left Capture", "DMIC Left Input", "DMIC Left"},
 859        {"Input Right Capture", "DMIC Right Input", "DMIC Right"},
 860
 861        /* Audio Capture */
 862        {"ASPL Output Mixer", NULL, "Input Left Capture"},
 863        {"ASPR Output Mixer", NULL, "Input Right Capture"},
 864
 865        {"ASPOUTL", "ASP-IP Volume", "ASPL Output Mixer"},
 866        {"ASPOUTR", "ASP-IP Volume", "ASPR Output Mixer"},
 867
 868        /* Auxillary Capture */
 869        {"XSPL Output Mixer", NULL, "Input Left Capture"},
 870        {"XSPR Output Mixer", NULL, "Input Right Capture"},
 871
 872        {"XSPOUTL", "XSP-IP Volume", "XSPL Output Mixer"},
 873        {"XSPOUTR", "XSP-IP Volume", "XSPR Output Mixer"},
 874
 875        {"XSPOUTL", NULL, "XSPL Output Mixer"},
 876        {"XSPOUTR", NULL, "XSPR Output Mixer"},
 877
 878        /* Voice Capture */
 879        {"VSP Output Mixer", NULL, "Input Left Capture"},
 880        {"VSP Output Mixer", NULL, "Input Right Capture"},
 881
 882        {"VSPINOUT", "VSP-IP Volume", "VSP Output Mixer"},
 883
 884        {"VSPINOUT", NULL, "VSP Output Mixer"},
 885
 886        {"ASP Capture", NULL, "ASPOUTL"},
 887        {"ASP Capture", NULL, "ASPOUTR"},
 888        {"XSP Capture", NULL, "XSPOUTL"},
 889        {"XSP Capture", NULL, "XSPOUTR"},
 890        {"VSP Capture", NULL, "VSPINOUT"},
 891};
 892
 893struct cs42l73_mclk_div {
 894        u32 mclk;
 895        u32 srate;
 896        u8 mmcc;
 897};
 898
 899static struct cs42l73_mclk_div cs42l73_mclk_coeffs[] = {
 900        /* MCLK, Sample Rate, xMMCC[5:0] */
 901        {5644800, 11025, 0x30},
 902        {5644800, 22050, 0x20},
 903        {5644800, 44100, 0x10},
 904
 905        {6000000,  8000, 0x39},
 906        {6000000, 11025, 0x33},
 907        {6000000, 12000, 0x31},
 908        {6000000, 16000, 0x29},
 909        {6000000, 22050, 0x23},
 910        {6000000, 24000, 0x21},
 911        {6000000, 32000, 0x19},
 912        {6000000, 44100, 0x13},
 913        {6000000, 48000, 0x11},
 914
 915        {6144000,  8000, 0x38},
 916        {6144000, 12000, 0x30},
 917        {6144000, 16000, 0x28},
 918        {6144000, 24000, 0x20},
 919        {6144000, 32000, 0x18},
 920        {6144000, 48000, 0x10},
 921
 922        {6500000,  8000, 0x3C},
 923        {6500000, 11025, 0x35},
 924        {6500000, 12000, 0x34},
 925        {6500000, 16000, 0x2C},
 926        {6500000, 22050, 0x25},
 927        {6500000, 24000, 0x24},
 928        {6500000, 32000, 0x1C},
 929        {6500000, 44100, 0x15},
 930        {6500000, 48000, 0x14},
 931
 932        {6400000,  8000, 0x3E},
 933        {6400000, 11025, 0x37},
 934        {6400000, 12000, 0x36},
 935        {6400000, 16000, 0x2E},
 936        {6400000, 22050, 0x27},
 937        {6400000, 24000, 0x26},
 938        {6400000, 32000, 0x1E},
 939        {6400000, 44100, 0x17},
 940        {6400000, 48000, 0x16},
 941};
 942
 943struct cs42l73_mclkx_div {
 944        u32 mclkx;
 945        u8 ratio;
 946        u8 mclkdiv;
 947};
 948
 949static struct cs42l73_mclkx_div cs42l73_mclkx_coeffs[] = {
 950        {5644800,  1, 0},       /* 5644800 */
 951        {6000000,  1, 0},       /* 6000000 */
 952        {6144000,  1, 0},       /* 6144000 */
 953        {11289600, 2, 2},       /* 5644800 */
 954        {12288000, 2, 2},       /* 6144000 */
 955        {12000000, 2, 2},       /* 6000000 */
 956        {13000000, 2, 2},       /* 6500000 */
 957        {19200000, 3, 3},       /* 6400000 */
 958        {24000000, 4, 4},       /* 6000000 */
 959        {26000000, 4, 4},       /* 6500000 */
 960        {38400000, 6, 5}        /* 6400000 */
 961};
 962
 963static int cs42l73_get_mclkx_coeff(int mclkx)
 964{
 965        int i;
 966
 967        for (i = 0; i < ARRAY_SIZE(cs42l73_mclkx_coeffs); i++) {
 968                if (cs42l73_mclkx_coeffs[i].mclkx == mclkx)
 969                        return i;
 970        }
 971        return -EINVAL;
 972}
 973
 974static int cs42l73_get_mclk_coeff(int mclk, int srate)
 975{
 976        int i;
 977
 978        for (i = 0; i < ARRAY_SIZE(cs42l73_mclk_coeffs); i++) {
 979                if (cs42l73_mclk_coeffs[i].mclk == mclk &&
 980                    cs42l73_mclk_coeffs[i].srate == srate)
 981                        return i;
 982        }
 983        return -EINVAL;
 984
 985}
 986
 987static int cs42l73_set_mclk(struct snd_soc_dai *dai, unsigned int freq)
 988{
 989        struct snd_soc_codec *codec = dai->codec;
 990        struct cs42l73_private *priv = snd_soc_codec_get_drvdata(codec);
 991
 992        int mclkx_coeff;
 993        u32 mclk = 0;
 994        u8 dmmcc = 0;
 995
 996        /* MCLKX -> MCLK */
 997        mclkx_coeff = cs42l73_get_mclkx_coeff(freq);
 998        if (mclkx_coeff < 0)
 999                return mclkx_coeff;
1000
1001        mclk = cs42l73_mclkx_coeffs[mclkx_coeff].mclkx /
1002                cs42l73_mclkx_coeffs[mclkx_coeff].ratio;
1003
1004        dev_dbg(codec->dev, "MCLK%u %u  <-> internal MCLK %u\n",
1005                 priv->mclksel + 1, cs42l73_mclkx_coeffs[mclkx_coeff].mclkx,
1006                 mclk);
1007
1008        dmmcc = (priv->mclksel << 4) |
1009                (cs42l73_mclkx_coeffs[mclkx_coeff].mclkdiv << 1);
1010
1011        snd_soc_write(codec, CS42L73_DMMCC, dmmcc);
1012
1013        priv->sysclk = mclkx_coeff;
1014        priv->mclk = mclk;
1015
1016        return 0;
1017}
1018
1019static int cs42l73_set_sysclk(struct snd_soc_dai *dai,
1020                              int clk_id, unsigned int freq, int dir)
1021{
1022        struct snd_soc_codec *codec = dai->codec;
1023        struct cs42l73_private *priv = snd_soc_codec_get_drvdata(codec);
1024
1025        switch (clk_id) {
1026        case CS42L73_CLKID_MCLK1:
1027                break;
1028        case CS42L73_CLKID_MCLK2:
1029                break;
1030        default:
1031                return -EINVAL;
1032        }
1033
1034        if ((cs42l73_set_mclk(dai, freq)) < 0) {
1035                dev_err(codec->dev, "Unable to set MCLK for dai %s\n",
1036                        dai->name);
1037                return -EINVAL;
1038        }
1039
1040        priv->mclksel = clk_id;
1041
1042        return 0;
1043}
1044
1045static int cs42l73_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt)
1046{
1047        struct snd_soc_codec *codec = codec_dai->codec;
1048        struct cs42l73_private *priv = snd_soc_codec_get_drvdata(codec);
1049        u8 id = codec_dai->id;
1050        unsigned int inv, format;
1051        u8 spc, mmcc;
1052
1053        spc = snd_soc_read(codec, CS42L73_SPC(id));
1054        mmcc = snd_soc_read(codec, CS42L73_MMCC(id));
1055
1056        switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
1057        case SND_SOC_DAIFMT_CBM_CFM:
1058                mmcc |= MS_MASTER;
1059                break;
1060
1061        case SND_SOC_DAIFMT_CBS_CFS:
1062                mmcc &= ~MS_MASTER;
1063                break;
1064
1065        default:
1066                return -EINVAL;
1067        }
1068
1069        format = (fmt & SND_SOC_DAIFMT_FORMAT_MASK);
1070        inv = (fmt & SND_SOC_DAIFMT_INV_MASK);
1071
1072        switch (format) {
1073        case SND_SOC_DAIFMT_I2S:
1074                spc &= ~SPDIF_PCM;
1075                break;
1076        case SND_SOC_DAIFMT_DSP_A:
1077        case SND_SOC_DAIFMT_DSP_B:
1078                if (mmcc & MS_MASTER) {
1079                        dev_err(codec->dev,
1080                                "PCM format in slave mode only\n");
1081                        return -EINVAL;
1082                }
1083                if (id == CS42L73_ASP) {
1084                        dev_err(codec->dev,
1085                                "PCM format is not supported on ASP port\n");
1086                        return -EINVAL;
1087                }
1088                spc |= SPDIF_PCM;
1089                break;
1090        default:
1091                return -EINVAL;
1092        }
1093
1094        if (spc & SPDIF_PCM) {
1095                /* Clear PCM mode, clear PCM_BIT_ORDER bit for MSB->LSB */
1096                spc &= ~(PCM_MODE_MASK | PCM_BIT_ORDER);
1097                switch (format) {
1098                case SND_SOC_DAIFMT_DSP_B:
1099                        if (inv == SND_SOC_DAIFMT_IB_IF)
1100                                spc |= PCM_MODE0;
1101                        if (inv == SND_SOC_DAIFMT_IB_NF)
1102                                spc |= PCM_MODE1;
1103                break;
1104                case SND_SOC_DAIFMT_DSP_A:
1105                        if (inv == SND_SOC_DAIFMT_IB_IF)
1106                                spc |= PCM_MODE1;
1107                        break;
1108                default:
1109                        return -EINVAL;
1110                }
1111        }
1112
1113        priv->config[id].spc = spc;
1114        priv->config[id].mmcc = mmcc;
1115
1116        return 0;
1117}
1118
1119static u32 cs42l73_asrc_rates[] = {
1120        8000, 11025, 12000, 16000, 22050,
1121        24000, 32000, 44100, 48000
1122};
1123
1124static unsigned int cs42l73_get_xspfs_coeff(u32 rate)
1125{
1126        int i;
1127        for (i = 0; i < ARRAY_SIZE(cs42l73_asrc_rates); i++) {
1128                if (cs42l73_asrc_rates[i] == rate)
1129                        return i + 1;
1130        }
1131        return 0;               /* 0 = Don't know */
1132}
1133
1134static void cs42l73_update_asrc(struct snd_soc_codec *codec, int id, int srate)
1135{
1136        u8 spfs = 0;
1137
1138        if (srate > 0)
1139                spfs = cs42l73_get_xspfs_coeff(srate);
1140
1141        switch (id) {
1142        case CS42L73_XSP:
1143                snd_soc_update_bits(codec, CS42L73_VXSPFS, 0x0f, spfs);
1144        break;
1145        case CS42L73_ASP:
1146                snd_soc_update_bits(codec, CS42L73_ASPC, 0x3c, spfs << 2);
1147        break;
1148        case CS42L73_VSP:
1149                snd_soc_update_bits(codec, CS42L73_VXSPFS, 0xf0, spfs << 4);
1150        break;
1151        default:
1152        break;
1153        }
1154}
1155
1156static int cs42l73_pcm_hw_params(struct snd_pcm_substream *substream,
1157                                 struct snd_pcm_hw_params *params,
1158                                 struct snd_soc_dai *dai)
1159{
1160        struct snd_soc_codec *codec = dai->codec;
1161        struct cs42l73_private *priv = snd_soc_codec_get_drvdata(codec);
1162        int id = dai->id;
1163        int mclk_coeff;
1164        int srate = params_rate(params);
1165
1166        if (priv->config[id].mmcc & MS_MASTER) {
1167                /* CS42L73 Master */
1168                /* MCLK -> srate */
1169                mclk_coeff =
1170                    cs42l73_get_mclk_coeff(priv->mclk, srate);
1171
1172                if (mclk_coeff < 0)
1173                        return -EINVAL;
1174
1175                dev_dbg(codec->dev,
1176                         "DAI[%d]: MCLK %u, srate %u, MMCC[5:0] = %x\n",
1177                         id, priv->mclk, srate,
1178                         cs42l73_mclk_coeffs[mclk_coeff].mmcc);
1179
1180                priv->config[id].mmcc &= 0xC0;
1181                priv->config[id].mmcc |= cs42l73_mclk_coeffs[mclk_coeff].mmcc;
1182                priv->config[id].spc &= 0xFC;
1183                priv->config[id].spc |= MCK_SCLK_MCLK;
1184        } else {
1185                /* CS42L73 Slave */
1186                priv->config[id].spc &= 0xFC;
1187                priv->config[id].spc |= MCK_SCLK_64FS;
1188        }
1189        /* Update ASRCs */
1190        priv->config[id].srate = srate;
1191
1192        snd_soc_write(codec, CS42L73_SPC(id), priv->config[id].spc);
1193        snd_soc_write(codec, CS42L73_MMCC(id), priv->config[id].mmcc);
1194
1195        cs42l73_update_asrc(codec, id, srate);
1196
1197        return 0;
1198}
1199
1200static int cs42l73_set_bias_level(struct snd_soc_codec *codec,
1201                                  enum snd_soc_bias_level level)
1202{
1203        struct cs42l73_private *cs42l73 = snd_soc_codec_get_drvdata(codec);
1204
1205        switch (level) {
1206        case SND_SOC_BIAS_ON:
1207                snd_soc_update_bits(codec, CS42L73_DMMCC, MCLKDIS, 0);
1208                snd_soc_update_bits(codec, CS42L73_PWRCTL1, PDN, 0);
1209                break;
1210
1211        case SND_SOC_BIAS_PREPARE:
1212                break;
1213
1214        case SND_SOC_BIAS_STANDBY:
1215                if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) {
1216                        regcache_cache_only(cs42l73->regmap, false);
1217                        regcache_sync(cs42l73->regmap);
1218                }
1219                snd_soc_update_bits(codec, CS42L73_PWRCTL1, PDN, 1);
1220                break;
1221
1222        case SND_SOC_BIAS_OFF:
1223                snd_soc_update_bits(codec, CS42L73_PWRCTL1, PDN, 1);
1224                if (cs42l73->shutdwn_delay > 0) {
1225                        mdelay(cs42l73->shutdwn_delay);
1226                        cs42l73->shutdwn_delay = 0;
1227                } else {
1228                        mdelay(15); /* Min amount of time requred to power
1229                                     * down.
1230                                     */
1231                }
1232                snd_soc_update_bits(codec, CS42L73_DMMCC, MCLKDIS, 1);
1233                break;
1234        }
1235        codec->dapm.bias_level = level;
1236        return 0;
1237}
1238
1239static int cs42l73_set_tristate(struct snd_soc_dai *dai, int tristate)
1240{
1241        struct snd_soc_codec *codec = dai->codec;
1242        int id = dai->id;
1243
1244        return snd_soc_update_bits(codec, CS42L73_SPC(id),
1245                                        0x7F, tristate << 7);
1246}
1247
1248static struct snd_pcm_hw_constraint_list constraints_12_24 = {
1249        .count  = ARRAY_SIZE(cs42l73_asrc_rates),
1250        .list   = cs42l73_asrc_rates,
1251};
1252
1253static int cs42l73_pcm_startup(struct snd_pcm_substream *substream,
1254                               struct snd_soc_dai *dai)
1255{
1256        snd_pcm_hw_constraint_list(substream->runtime, 0,
1257                                        SNDRV_PCM_HW_PARAM_RATE,
1258                                        &constraints_12_24);
1259        return 0;
1260}
1261
1262/* SNDRV_PCM_RATE_KNOT -> 12000, 24000 Hz, limit with constraint list */
1263#define CS42L73_RATES (SNDRV_PCM_RATE_8000_48000 | SNDRV_PCM_RATE_KNOT)
1264
1265
1266#define CS42L73_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
1267        SNDRV_PCM_FMTBIT_S24_LE)
1268
1269static const struct snd_soc_dai_ops cs42l73_ops = {
1270        .startup = cs42l73_pcm_startup,
1271        .hw_params = cs42l73_pcm_hw_params,
1272        .set_fmt = cs42l73_set_dai_fmt,
1273        .set_sysclk = cs42l73_set_sysclk,
1274        .set_tristate = cs42l73_set_tristate,
1275};
1276
1277static struct snd_soc_dai_driver cs42l73_dai[] = {
1278        {
1279                .name = "cs42l73-xsp",
1280                .id = CS42L73_XSP,
1281                .playback = {
1282                        .stream_name = "XSP Playback",
1283                        .channels_min = 1,
1284                        .channels_max = 2,
1285                        .rates = CS42L73_RATES,
1286                        .formats = CS42L73_FORMATS,
1287                },
1288                .capture = {
1289                        .stream_name = "XSP Capture",
1290                        .channels_min = 1,
1291                        .channels_max = 2,
1292                        .rates = CS42L73_RATES,
1293                        .formats = CS42L73_FORMATS,
1294                },
1295                .ops = &cs42l73_ops,
1296                .symmetric_rates = 1,
1297         },
1298        {
1299                .name = "cs42l73-asp",
1300                .id = CS42L73_ASP,
1301                .playback = {
1302                        .stream_name = "ASP Playback",
1303                        .channels_min = 2,
1304                        .channels_max = 2,
1305                        .rates = CS42L73_RATES,
1306                        .formats = CS42L73_FORMATS,
1307                },
1308                .capture = {
1309                        .stream_name = "ASP Capture",
1310                        .channels_min = 2,
1311                        .channels_max = 2,
1312                        .rates = CS42L73_RATES,
1313                        .formats = CS42L73_FORMATS,
1314                },
1315                .ops = &cs42l73_ops,
1316                .symmetric_rates = 1,
1317         },
1318        {
1319                .name = "cs42l73-vsp",
1320                .id = CS42L73_VSP,
1321                .playback = {
1322                        .stream_name = "VSP Playback",
1323                        .channels_min = 1,
1324                        .channels_max = 2,
1325                        .rates = CS42L73_RATES,
1326                        .formats = CS42L73_FORMATS,
1327                },
1328                .capture = {
1329                        .stream_name = "VSP Capture",
1330                        .channels_min = 1,
1331                        .channels_max = 2,
1332                        .rates = CS42L73_RATES,
1333                        .formats = CS42L73_FORMATS,
1334                },
1335                .ops = &cs42l73_ops,
1336                .symmetric_rates = 1,
1337         }
1338};
1339
1340static int cs42l73_suspend(struct snd_soc_codec *codec)
1341{
1342        cs42l73_set_bias_level(codec, SND_SOC_BIAS_OFF);
1343
1344        return 0;
1345}
1346
1347static int cs42l73_resume(struct snd_soc_codec *codec)
1348{
1349        cs42l73_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
1350        return 0;
1351}
1352
1353static int cs42l73_probe(struct snd_soc_codec *codec)
1354{
1355        int ret;
1356        struct cs42l73_private *cs42l73 = snd_soc_codec_get_drvdata(codec);
1357
1358        codec->control_data = cs42l73->regmap;
1359
1360        ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_REGMAP);
1361        if (ret < 0) {
1362                dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
1363                return ret;
1364        }
1365
1366        regcache_cache_only(cs42l73->regmap, true);
1367
1368        cs42l73_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
1369
1370        cs42l73->mclksel = CS42L73_CLKID_MCLK1; /* MCLK1 as master clk */
1371        cs42l73->mclk = 0;
1372
1373        return ret;
1374}
1375
1376static int cs42l73_remove(struct snd_soc_codec *codec)
1377{
1378        cs42l73_set_bias_level(codec, SND_SOC_BIAS_OFF);
1379        return 0;
1380}
1381
1382static struct snd_soc_codec_driver soc_codec_dev_cs42l73 = {
1383        .probe = cs42l73_probe,
1384        .remove = cs42l73_remove,
1385        .suspend = cs42l73_suspend,
1386        .resume = cs42l73_resume,
1387        .set_bias_level = cs42l73_set_bias_level,
1388
1389        .dapm_widgets = cs42l73_dapm_widgets,
1390        .num_dapm_widgets = ARRAY_SIZE(cs42l73_dapm_widgets),
1391        .dapm_routes = cs42l73_audio_map,
1392        .num_dapm_routes = ARRAY_SIZE(cs42l73_audio_map),
1393
1394        .controls = cs42l73_snd_controls,
1395        .num_controls = ARRAY_SIZE(cs42l73_snd_controls),
1396};
1397
1398static struct regmap_config cs42l73_regmap = {
1399        .reg_bits = 8,
1400        .val_bits = 8,
1401
1402        .max_register = CS42L73_MAX_REGISTER,
1403        .reg_defaults = cs42l73_reg_defaults,
1404        .num_reg_defaults = ARRAY_SIZE(cs42l73_reg_defaults),
1405        .volatile_reg = cs42l73_volatile_register,
1406        .readable_reg = cs42l73_readable_register,
1407        .cache_type = REGCACHE_RBTREE,
1408};
1409
1410static int cs42l73_i2c_probe(struct i2c_client *i2c_client,
1411                             const struct i2c_device_id *id)
1412{
1413        struct cs42l73_private *cs42l73;
1414        int ret;
1415        unsigned int devid = 0;
1416        unsigned int reg;
1417
1418        cs42l73 = devm_kzalloc(&i2c_client->dev, sizeof(struct cs42l73_private),
1419                               GFP_KERNEL);
1420        if (!cs42l73) {
1421                dev_err(&i2c_client->dev, "could not allocate codec\n");
1422                return -ENOMEM;
1423        }
1424
1425        i2c_set_clientdata(i2c_client, cs42l73);
1426
1427        cs42l73->regmap = devm_regmap_init_i2c(i2c_client, &cs42l73_regmap);
1428        if (IS_ERR(cs42l73->regmap)) {
1429                ret = PTR_ERR(cs42l73->regmap);
1430                dev_err(&i2c_client->dev, "regmap_init() failed: %d\n", ret);
1431                return ret;
1432        }
1433        /* initialize codec */
1434        ret = regmap_read(cs42l73->regmap, CS42L73_DEVID_AB, &reg);
1435        devid = (reg & 0xFF) << 12;
1436
1437        ret = regmap_read(cs42l73->regmap, CS42L73_DEVID_CD, &reg);
1438        devid |= (reg & 0xFF) << 4;
1439
1440        ret = regmap_read(cs42l73->regmap, CS42L73_DEVID_E, &reg);
1441        devid |= (reg & 0xF0) >> 4;
1442
1443
1444        if (devid != CS42L73_DEVID) {
1445                ret = -ENODEV;
1446                dev_err(&i2c_client->dev,
1447                        "CS42L73 Device ID (%X). Expected %X\n",
1448                        devid, CS42L73_DEVID);
1449                return ret;
1450        }
1451
1452        ret = regmap_read(cs42l73->regmap, CS42L73_REVID, &reg);
1453        if (ret < 0) {
1454                dev_err(&i2c_client->dev, "Get Revision ID failed\n");
1455                return ret;;
1456        }
1457
1458        dev_info(&i2c_client->dev,
1459                 "Cirrus Logic CS42L73, Revision: %02X\n", reg & 0xFF);
1460
1461        regcache_cache_only(cs42l73->regmap, true);
1462
1463        ret =  snd_soc_register_codec(&i2c_client->dev,
1464                        &soc_codec_dev_cs42l73, cs42l73_dai,
1465                        ARRAY_SIZE(cs42l73_dai));
1466        if (ret < 0)
1467                return ret;
1468        return 0;
1469}
1470
1471static int cs42l73_i2c_remove(struct i2c_client *client)
1472{
1473        snd_soc_unregister_codec(&client->dev);
1474        return 0;
1475}
1476
1477static const struct i2c_device_id cs42l73_id[] = {
1478        {"cs42l73", 0},
1479        {}
1480};
1481
1482MODULE_DEVICE_TABLE(i2c, cs42l73_id);
1483
1484static struct i2c_driver cs42l73_i2c_driver = {
1485        .driver = {
1486                   .name = "cs42l73",
1487                   .owner = THIS_MODULE,
1488                   },
1489        .id_table = cs42l73_id,
1490        .probe = cs42l73_i2c_probe,
1491        .remove = cs42l73_i2c_remove,
1492
1493};
1494
1495module_i2c_driver(cs42l73_i2c_driver);
1496
1497MODULE_DESCRIPTION("ASoC CS42L73 driver");
1498MODULE_AUTHOR("Georgi Vlaev, Nucleus Systems Ltd, <joe@nucleusys.com>");
1499MODULE_AUTHOR("Brian Austin, Cirrus Logic Inc, <brian.austin@cirrus.com>");
1500MODULE_LICENSE("GPL");
1501