linux/sound/soc/codecs/cs42l52.c
<<
>>
Prefs
   1/*
   2 * cs42l52.c -- CS42L52 ALSA SoC audio driver
   3 *
   4 * Copyright 2012 CirrusLogic, Inc.
   5 *
   6 * Author: Georgi Vlaev <joe@nucleusys.com>
   7 * Author: Brian Austin <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/of_gpio.h>
  21#include <linux/pm.h>
  22#include <linux/i2c.h>
  23#include <linux/input.h>
  24#include <linux/regmap.h>
  25#include <linux/slab.h>
  26#include <linux/workqueue.h>
  27#include <linux/platform_device.h>
  28#include <sound/core.h>
  29#include <sound/pcm.h>
  30#include <sound/pcm_params.h>
  31#include <sound/soc.h>
  32#include <sound/soc-dapm.h>
  33#include <sound/initval.h>
  34#include <sound/tlv.h>
  35#include <sound/cs42l52.h>
  36#include "cs42l52.h"
  37
  38struct sp_config {
  39        u8 spc, format, spfs;
  40        u32 srate;
  41};
  42
  43struct  cs42l52_private {
  44        struct regmap *regmap;
  45        struct snd_soc_codec *codec;
  46        struct device *dev;
  47        struct sp_config config;
  48        struct cs42l52_platform_data pdata;
  49        u32 sysclk;
  50        u8 mclksel;
  51        u32 mclk;
  52        u8 flags;
  53        struct input_dev *beep;
  54        struct work_struct beep_work;
  55        int beep_rate;
  56};
  57
  58static const struct reg_default cs42l52_reg_defaults[] = {
  59        { CS42L52_PWRCTL1, 0x9F },      /* r02 PWRCTL 1 */
  60        { CS42L52_PWRCTL2, 0x07 },      /* r03 PWRCTL 2 */
  61        { CS42L52_PWRCTL3, 0xFF },      /* r04 PWRCTL 3 */
  62        { CS42L52_CLK_CTL, 0xA0 },      /* r05 Clocking Ctl */
  63        { CS42L52_IFACE_CTL1, 0x00 },   /* r06 Interface Ctl 1 */
  64        { CS42L52_ADC_PGA_A, 0x80 },    /* r08 Input A Select */
  65        { CS42L52_ADC_PGA_B, 0x80 },    /* r09 Input B Select */
  66        { CS42L52_ANALOG_HPF_CTL, 0xA5 },       /* r0A Analog HPF Ctl */
  67        { CS42L52_ADC_HPF_FREQ, 0x00 }, /* r0B ADC HPF Corner Freq */
  68        { CS42L52_ADC_MISC_CTL, 0x00 }, /* r0C Misc. ADC Ctl */
  69        { CS42L52_PB_CTL1, 0x60 },      /* r0D Playback Ctl 1 */
  70        { CS42L52_MISC_CTL, 0x02 },     /* r0E Misc. Ctl */
  71        { CS42L52_PB_CTL2, 0x00 },      /* r0F Playback Ctl 2 */
  72        { CS42L52_MICA_CTL, 0x00 },     /* r10 MICA Amp Ctl */
  73        { CS42L52_MICB_CTL, 0x00 },     /* r11 MICB Amp Ctl */
  74        { CS42L52_PGAA_CTL, 0x00 },     /* r12 PGAA Vol, Misc. */
  75        { CS42L52_PGAB_CTL, 0x00 },     /* r13 PGAB Vol, Misc. */
  76        { CS42L52_PASSTHRUA_VOL, 0x00 },        /* r14 Bypass A Vol */
  77        { CS42L52_PASSTHRUB_VOL, 0x00 },        /* r15 Bypass B Vol */
  78        { CS42L52_ADCA_VOL, 0x00 },     /* r16 ADCA Volume */
  79        { CS42L52_ADCB_VOL, 0x00 },     /* r17 ADCB Volume */
  80        { CS42L52_ADCA_MIXER_VOL, 0x80 },       /* r18 ADCA Mixer Volume */
  81        { CS42L52_ADCB_MIXER_VOL, 0x80 },       /* r19 ADCB Mixer Volume */
  82        { CS42L52_PCMA_MIXER_VOL, 0x00 },       /* r1A PCMA Mixer Volume */
  83        { CS42L52_PCMB_MIXER_VOL, 0x00 },       /* r1B PCMB Mixer Volume */
  84        { CS42L52_BEEP_FREQ, 0x00 },    /* r1C Beep Freq on Time */
  85        { CS42L52_BEEP_VOL, 0x00 },     /* r1D Beep Volume off Time */
  86        { CS42L52_BEEP_TONE_CTL, 0x00 },        /* r1E Beep Tone Cfg. */
  87        { CS42L52_TONE_CTL, 0x00 },     /* r1F Tone Ctl */
  88        { CS42L52_MASTERA_VOL, 0x00 },  /* r20 Master A Volume */
  89        { CS42L52_MASTERB_VOL, 0x00 },  /* r21 Master B Volume */
  90        { CS42L52_HPA_VOL, 0x00 },      /* r22 Headphone A Volume */
  91        { CS42L52_HPB_VOL, 0x00 },      /* r23 Headphone B Volume */
  92        { CS42L52_SPKA_VOL, 0x00 },     /* r24 Speaker A Volume */
  93        { CS42L52_SPKB_VOL, 0x00 },     /* r25 Speaker B Volume */
  94        { CS42L52_ADC_PCM_MIXER, 0x00 },        /* r26 Channel Mixer and Swap */
  95        { CS42L52_LIMITER_CTL1, 0x00 }, /* r27 Limit Ctl 1 Thresholds */
  96        { CS42L52_LIMITER_CTL2, 0x7F }, /* r28 Limit Ctl 2 Release Rate */
  97        { CS42L52_LIMITER_AT_RATE, 0xC0 },      /* r29 Limiter Attack Rate */
  98        { CS42L52_ALC_CTL, 0x00 },      /* r2A ALC Ctl 1 Attack Rate */
  99        { CS42L52_ALC_RATE, 0x3F },     /* r2B ALC Release Rate */
 100        { CS42L52_ALC_THRESHOLD, 0x3f },        /* r2C ALC Thresholds */
 101        { CS42L52_NOISE_GATE_CTL, 0x00 },       /* r2D Noise Gate Ctl */
 102        { CS42L52_CLK_STATUS, 0x00 },   /* r2E Overflow and Clock Status */
 103        { CS42L52_BATT_COMPEN, 0x00 },  /* r2F battery Compensation */
 104        { CS42L52_BATT_LEVEL, 0x00 },   /* r30 VP Battery Level */
 105        { CS42L52_SPK_STATUS, 0x00 },   /* r31 Speaker Status */
 106        { CS42L52_TEM_CTL, 0x3B },      /* r32 Temp Ctl */
 107        { CS42L52_THE_FOLDBACK, 0x00 }, /* r33 Foldback */
 108};
 109
 110static bool cs42l52_readable_register(struct device *dev, unsigned int reg)
 111{
 112        switch (reg) {
 113        case CS42L52_CHIP ... CS42L52_CHARGE_PUMP:
 114                return true;
 115        default:
 116                return false;
 117        }
 118}
 119
 120static bool cs42l52_volatile_register(struct device *dev, unsigned int reg)
 121{
 122        switch (reg) {
 123        case CS42L52_IFACE_CTL2:
 124        case CS42L52_CLK_STATUS:
 125        case CS42L52_BATT_LEVEL:
 126        case CS42L52_SPK_STATUS:
 127        case CS42L52_CHARGE_PUMP:
 128                return true;
 129        default:
 130                return false;
 131        }
 132}
 133
 134static DECLARE_TLV_DB_SCALE(hl_tlv, -10200, 50, 0);
 135
 136static DECLARE_TLV_DB_SCALE(hpd_tlv, -9600, 50, 1);
 137
 138static DECLARE_TLV_DB_SCALE(ipd_tlv, -9600, 100, 0);
 139
 140static DECLARE_TLV_DB_SCALE(mic_tlv, 1600, 100, 0);
 141
 142static DECLARE_TLV_DB_SCALE(pga_tlv, -600, 50, 0);
 143
 144static DECLARE_TLV_DB_SCALE(mix_tlv, -50, 50, 0);
 145
 146static DECLARE_TLV_DB_SCALE(beep_tlv, -56, 200, 0);
 147
 148static const DECLARE_TLV_DB_RANGE(limiter_tlv,
 149        0, 2, TLV_DB_SCALE_ITEM(-3000, 600, 0),
 150        3, 7, TLV_DB_SCALE_ITEM(-1200, 300, 0)
 151);
 152
 153static const char * const cs42l52_adca_text[] = {
 154        "Input1A", "Input2A", "Input3A", "Input4A", "PGA Input Left"};
 155
 156static const char * const cs42l52_adcb_text[] = {
 157        "Input1B", "Input2B", "Input3B", "Input4B", "PGA Input Right"};
 158
 159static SOC_ENUM_SINGLE_DECL(adca_enum,
 160                            CS42L52_ADC_PGA_A, 5, cs42l52_adca_text);
 161
 162static SOC_ENUM_SINGLE_DECL(adcb_enum,
 163                            CS42L52_ADC_PGA_B, 5, cs42l52_adcb_text);
 164
 165static const struct snd_kcontrol_new adca_mux =
 166        SOC_DAPM_ENUM("Left ADC Input Capture Mux", adca_enum);
 167
 168static const struct snd_kcontrol_new adcb_mux =
 169        SOC_DAPM_ENUM("Right ADC Input Capture Mux", adcb_enum);
 170
 171static const char * const mic_bias_level_text[] = {
 172        "0.5 +VA", "0.6 +VA", "0.7 +VA",
 173        "0.8 +VA", "0.83 +VA", "0.91 +VA"
 174};
 175
 176static SOC_ENUM_SINGLE_DECL(mic_bias_level_enum,
 177                            CS42L52_IFACE_CTL2, 0, mic_bias_level_text);
 178
 179static const char * const cs42l52_mic_text[] = { "MIC1", "MIC2" };
 180
 181static SOC_ENUM_SINGLE_DECL(mica_enum,
 182                            CS42L52_MICA_CTL, 5, cs42l52_mic_text);
 183
 184static SOC_ENUM_SINGLE_DECL(micb_enum,
 185                            CS42L52_MICB_CTL, 5, cs42l52_mic_text);
 186
 187static const char * const digital_output_mux_text[] = {"ADC", "DSP"};
 188
 189static SOC_ENUM_SINGLE_DECL(digital_output_mux_enum,
 190                            CS42L52_ADC_MISC_CTL, 6,
 191                            digital_output_mux_text);
 192
 193static const struct snd_kcontrol_new digital_output_mux =
 194        SOC_DAPM_ENUM("Digital Output Mux", digital_output_mux_enum);
 195
 196static const char * const hp_gain_num_text[] = {
 197        "0.3959", "0.4571", "0.5111", "0.6047",
 198        "0.7099", "0.8399", "1.000", "1.1430"
 199};
 200
 201static SOC_ENUM_SINGLE_DECL(hp_gain_enum,
 202                            CS42L52_PB_CTL1, 5,
 203                            hp_gain_num_text);
 204
 205static const char * const beep_pitch_text[] = {
 206        "C4", "C5", "D5", "E5", "F5", "G5", "A5", "B5",
 207        "C6", "D6", "E6", "F6", "G6", "A6", "B6", "C7"
 208};
 209
 210static SOC_ENUM_SINGLE_DECL(beep_pitch_enum,
 211                            CS42L52_BEEP_FREQ, 4,
 212                            beep_pitch_text);
 213
 214static const char * const beep_ontime_text[] = {
 215        "86 ms", "430 ms", "780 ms", "1.20 s", "1.50 s",
 216        "1.80 s", "2.20 s", "2.50 s", "2.80 s", "3.20 s",
 217        "3.50 s", "3.80 s", "4.20 s", "4.50 s", "4.80 s", "5.20 s"
 218};
 219
 220static SOC_ENUM_SINGLE_DECL(beep_ontime_enum,
 221                            CS42L52_BEEP_FREQ, 0,
 222                            beep_ontime_text);
 223
 224static const char * const beep_offtime_text[] = {
 225        "1.23 s", "2.58 s", "3.90 s", "5.20 s",
 226        "6.60 s", "8.05 s", "9.35 s", "10.80 s"
 227};
 228
 229static SOC_ENUM_SINGLE_DECL(beep_offtime_enum,
 230                            CS42L52_BEEP_VOL, 5,
 231                            beep_offtime_text);
 232
 233static const char * const beep_config_text[] = {
 234        "Off", "Single", "Multiple", "Continuous"
 235};
 236
 237static SOC_ENUM_SINGLE_DECL(beep_config_enum,
 238                            CS42L52_BEEP_TONE_CTL, 6,
 239                            beep_config_text);
 240
 241static const char * const beep_bass_text[] = {
 242        "50 Hz", "100 Hz", "200 Hz", "250 Hz"
 243};
 244
 245static SOC_ENUM_SINGLE_DECL(beep_bass_enum,
 246                            CS42L52_BEEP_TONE_CTL, 1,
 247                            beep_bass_text);
 248
 249static const char * const beep_treble_text[] = {
 250        "5 kHz", "7 kHz", "10 kHz", " 15 kHz"
 251};
 252
 253static SOC_ENUM_SINGLE_DECL(beep_treble_enum,
 254                            CS42L52_BEEP_TONE_CTL, 3,
 255                            beep_treble_text);
 256
 257static const char * const ng_threshold_text[] = {
 258        "-34dB", "-37dB", "-40dB", "-43dB",
 259        "-46dB", "-52dB", "-58dB", "-64dB"
 260};
 261
 262static SOC_ENUM_SINGLE_DECL(ng_threshold_enum,
 263                            CS42L52_NOISE_GATE_CTL, 2,
 264                            ng_threshold_text);
 265
 266static const char * const cs42l52_ng_delay_text[] = {
 267        "50ms", "100ms", "150ms", "200ms"};
 268
 269static SOC_ENUM_SINGLE_DECL(ng_delay_enum,
 270                            CS42L52_NOISE_GATE_CTL, 0,
 271                            cs42l52_ng_delay_text);
 272
 273static const char * const cs42l52_ng_type_text[] = {
 274        "Apply Specific", "Apply All"
 275};
 276
 277static SOC_ENUM_SINGLE_DECL(ng_type_enum,
 278                            CS42L52_NOISE_GATE_CTL, 6,
 279                            cs42l52_ng_type_text);
 280
 281static const char * const left_swap_text[] = {
 282        "Left", "LR 2", "Right"};
 283
 284static const char * const right_swap_text[] = {
 285        "Right", "LR 2", "Left"};
 286
 287static const unsigned int swap_values[] = { 0, 1, 3 };
 288
 289static const struct soc_enum adca_swap_enum =
 290        SOC_VALUE_ENUM_SINGLE(CS42L52_ADC_PCM_MIXER, 2, 3,
 291                              ARRAY_SIZE(left_swap_text),
 292                              left_swap_text,
 293                              swap_values);
 294
 295static const struct snd_kcontrol_new adca_mixer =
 296        SOC_DAPM_ENUM("Route", adca_swap_enum);
 297
 298static const struct soc_enum pcma_swap_enum =
 299        SOC_VALUE_ENUM_SINGLE(CS42L52_ADC_PCM_MIXER, 6, 3,
 300                              ARRAY_SIZE(left_swap_text),
 301                              left_swap_text,
 302                              swap_values);
 303
 304static const struct snd_kcontrol_new pcma_mixer =
 305        SOC_DAPM_ENUM("Route", pcma_swap_enum);
 306
 307static const struct soc_enum adcb_swap_enum =
 308        SOC_VALUE_ENUM_SINGLE(CS42L52_ADC_PCM_MIXER, 0, 3,
 309                              ARRAY_SIZE(right_swap_text),
 310                              right_swap_text,
 311                              swap_values);
 312
 313static const struct snd_kcontrol_new adcb_mixer =
 314        SOC_DAPM_ENUM("Route", adcb_swap_enum);
 315
 316static const struct soc_enum pcmb_swap_enum =
 317        SOC_VALUE_ENUM_SINGLE(CS42L52_ADC_PCM_MIXER, 4, 3,
 318                              ARRAY_SIZE(right_swap_text),
 319                              right_swap_text,
 320                              swap_values);
 321
 322static const struct snd_kcontrol_new pcmb_mixer =
 323        SOC_DAPM_ENUM("Route", pcmb_swap_enum);
 324
 325
 326static const struct snd_kcontrol_new passthrul_ctl =
 327        SOC_DAPM_SINGLE("Switch", CS42L52_MISC_CTL, 6, 1, 0);
 328
 329static const struct snd_kcontrol_new passthrur_ctl =
 330        SOC_DAPM_SINGLE("Switch", CS42L52_MISC_CTL, 7, 1, 0);
 331
 332static const struct snd_kcontrol_new spkl_ctl =
 333        SOC_DAPM_SINGLE("Switch", CS42L52_PWRCTL3, 0, 1, 1);
 334
 335static const struct snd_kcontrol_new spkr_ctl =
 336        SOC_DAPM_SINGLE("Switch", CS42L52_PWRCTL3, 2, 1, 1);
 337
 338static const struct snd_kcontrol_new hpl_ctl =
 339        SOC_DAPM_SINGLE("Switch", CS42L52_PWRCTL3, 4, 1, 1);
 340
 341static const struct snd_kcontrol_new hpr_ctl =
 342        SOC_DAPM_SINGLE("Switch", CS42L52_PWRCTL3, 6, 1, 1);
 343
 344static const struct snd_kcontrol_new cs42l52_snd_controls[] = {
 345
 346        SOC_DOUBLE_R_SX_TLV("Master Volume", CS42L52_MASTERA_VOL,
 347                              CS42L52_MASTERB_VOL, 0, 0x34, 0xE4, hl_tlv),
 348
 349        SOC_DOUBLE_R_SX_TLV("Headphone Volume", CS42L52_HPA_VOL,
 350                              CS42L52_HPB_VOL, 0, 0x34, 0xC0, hpd_tlv),
 351
 352        SOC_ENUM("Headphone Analog Gain", hp_gain_enum),
 353
 354        SOC_DOUBLE_R_SX_TLV("Speaker Volume", CS42L52_SPKA_VOL,
 355                              CS42L52_SPKB_VOL, 0, 0x40, 0xC0, hl_tlv),
 356
 357        SOC_DOUBLE_R_SX_TLV("Bypass Volume", CS42L52_PASSTHRUA_VOL,
 358                              CS42L52_PASSTHRUB_VOL, 0, 0x88, 0x90, pga_tlv),
 359
 360        SOC_DOUBLE("Bypass Mute", CS42L52_MISC_CTL, 4, 5, 1, 0),
 361
 362        SOC_DOUBLE_R_TLV("MIC Gain Volume", CS42L52_MICA_CTL,
 363                              CS42L52_MICB_CTL, 0, 0x10, 0, mic_tlv),
 364
 365        SOC_ENUM("MIC Bias Level", mic_bias_level_enum),
 366
 367        SOC_DOUBLE_R_SX_TLV("ADC Volume", CS42L52_ADCA_VOL,
 368                              CS42L52_ADCB_VOL, 0, 0xA0, 0x78, ipd_tlv),
 369        SOC_DOUBLE_R_SX_TLV("ADC Mixer Volume",
 370                             CS42L52_ADCA_MIXER_VOL, CS42L52_ADCB_MIXER_VOL,
 371                                0, 0x19, 0x7F, ipd_tlv),
 372
 373        SOC_DOUBLE("ADC Switch", CS42L52_ADC_MISC_CTL, 0, 1, 1, 0),
 374
 375        SOC_DOUBLE_R("ADC Mixer Switch", CS42L52_ADCA_MIXER_VOL,
 376                     CS42L52_ADCB_MIXER_VOL, 7, 1, 1),
 377
 378        SOC_DOUBLE_R_SX_TLV("PGA Volume", CS42L52_PGAA_CTL,
 379                            CS42L52_PGAB_CTL, 0, 0x28, 0x24, pga_tlv),
 380
 381        SOC_DOUBLE_R_SX_TLV("PCM Mixer Volume",
 382                            CS42L52_PCMA_MIXER_VOL, CS42L52_PCMB_MIXER_VOL,
 383                                0, 0x19, 0x7f, mix_tlv),
 384        SOC_DOUBLE_R("PCM Mixer Switch",
 385                     CS42L52_PCMA_MIXER_VOL, CS42L52_PCMB_MIXER_VOL, 7, 1, 1),
 386
 387        SOC_ENUM("Beep Config", beep_config_enum),
 388        SOC_ENUM("Beep Pitch", beep_pitch_enum),
 389        SOC_ENUM("Beep on Time", beep_ontime_enum),
 390        SOC_ENUM("Beep off Time", beep_offtime_enum),
 391        SOC_SINGLE_SX_TLV("Beep Volume", CS42L52_BEEP_VOL,
 392                        0, 0x07, 0x1f, beep_tlv),
 393        SOC_SINGLE("Beep Mixer Switch", CS42L52_BEEP_TONE_CTL, 5, 1, 1),
 394        SOC_ENUM("Beep Treble Corner Freq", beep_treble_enum),
 395        SOC_ENUM("Beep Bass Corner Freq", beep_bass_enum),
 396
 397        SOC_SINGLE("Tone Control Switch", CS42L52_BEEP_TONE_CTL, 0, 1, 1),
 398        SOC_SINGLE_TLV("Treble Gain Volume",
 399                            CS42L52_TONE_CTL, 4, 15, 1, hl_tlv),
 400        SOC_SINGLE_TLV("Bass Gain Volume",
 401                            CS42L52_TONE_CTL, 0, 15, 1, hl_tlv),
 402
 403        /* Limiter */
 404        SOC_SINGLE_TLV("Limiter Max Threshold Volume",
 405                       CS42L52_LIMITER_CTL1, 5, 7, 0, limiter_tlv),
 406        SOC_SINGLE_TLV("Limiter Cushion Threshold Volume",
 407                       CS42L52_LIMITER_CTL1, 2, 7, 0, limiter_tlv),
 408        SOC_SINGLE_TLV("Limiter Release Rate Volume",
 409                       CS42L52_LIMITER_CTL2, 0, 63, 0, limiter_tlv),
 410        SOC_SINGLE_TLV("Limiter Attack Rate Volume",
 411                       CS42L52_LIMITER_AT_RATE, 0, 63, 0, limiter_tlv),
 412
 413        SOC_SINGLE("Limiter SR Switch", CS42L52_LIMITER_CTL1, 1, 1, 0),
 414        SOC_SINGLE("Limiter ZC Switch", CS42L52_LIMITER_CTL1, 0, 1, 0),
 415        SOC_SINGLE("Limiter Switch", CS42L52_LIMITER_CTL2, 7, 1, 0),
 416
 417        /* ALC */
 418        SOC_SINGLE_TLV("ALC Attack Rate Volume", CS42L52_ALC_CTL,
 419                       0, 63, 0, limiter_tlv),
 420        SOC_SINGLE_TLV("ALC Release Rate Volume", CS42L52_ALC_RATE,
 421                       0, 63, 0, limiter_tlv),
 422        SOC_SINGLE_TLV("ALC Max Threshold Volume", CS42L52_ALC_THRESHOLD,
 423                       5, 7, 0, limiter_tlv),
 424        SOC_SINGLE_TLV("ALC Min Threshold Volume", CS42L52_ALC_THRESHOLD,
 425                       2, 7, 0, limiter_tlv),
 426
 427        SOC_DOUBLE_R("ALC SR Capture Switch", CS42L52_PGAA_CTL,
 428                     CS42L52_PGAB_CTL, 7, 1, 1),
 429        SOC_DOUBLE_R("ALC ZC Capture Switch", CS42L52_PGAA_CTL,
 430                     CS42L52_PGAB_CTL, 6, 1, 1),
 431        SOC_DOUBLE("ALC Capture Switch", CS42L52_ALC_CTL, 6, 7, 1, 0),
 432
 433        /* Noise gate */
 434        SOC_ENUM("NG Type Switch", ng_type_enum),
 435        SOC_SINGLE("NG Enable Switch", CS42L52_NOISE_GATE_CTL, 6, 1, 0),
 436        SOC_SINGLE("NG Boost Switch", CS42L52_NOISE_GATE_CTL, 5, 1, 1),
 437        SOC_ENUM("NG Threshold", ng_threshold_enum),
 438        SOC_ENUM("NG Delay", ng_delay_enum),
 439
 440        SOC_DOUBLE("HPF Switch", CS42L52_ANALOG_HPF_CTL, 5, 7, 1, 0),
 441
 442        SOC_DOUBLE("Analog SR Switch", CS42L52_ANALOG_HPF_CTL, 1, 3, 1, 1),
 443        SOC_DOUBLE("Analog ZC Switch", CS42L52_ANALOG_HPF_CTL, 0, 2, 1, 1),
 444        SOC_SINGLE("Digital SR Switch", CS42L52_MISC_CTL, 1, 1, 0),
 445        SOC_SINGLE("Digital ZC Switch", CS42L52_MISC_CTL, 0, 1, 0),
 446        SOC_SINGLE("Deemphasis Switch", CS42L52_MISC_CTL, 2, 1, 0),
 447
 448        SOC_SINGLE("Batt Compensation Switch", CS42L52_BATT_COMPEN, 7, 1, 0),
 449        SOC_SINGLE("Batt VP Monitor Switch", CS42L52_BATT_COMPEN, 6, 1, 0),
 450        SOC_SINGLE("Batt VP ref", CS42L52_BATT_COMPEN, 0, 0x0f, 0),
 451
 452        SOC_SINGLE("PGA AIN1L Switch", CS42L52_ADC_PGA_A, 0, 1, 0),
 453        SOC_SINGLE("PGA AIN1R Switch", CS42L52_ADC_PGA_B, 0, 1, 0),
 454        SOC_SINGLE("PGA AIN2L Switch", CS42L52_ADC_PGA_A, 1, 1, 0),
 455        SOC_SINGLE("PGA AIN2R Switch", CS42L52_ADC_PGA_B, 1, 1, 0),
 456
 457        SOC_SINGLE("PGA AIN3L Switch", CS42L52_ADC_PGA_A, 2, 1, 0),
 458        SOC_SINGLE("PGA AIN3R Switch", CS42L52_ADC_PGA_B, 2, 1, 0),
 459
 460        SOC_SINGLE("PGA AIN4L Switch", CS42L52_ADC_PGA_A, 3, 1, 0),
 461        SOC_SINGLE("PGA AIN4R Switch", CS42L52_ADC_PGA_B, 3, 1, 0),
 462
 463        SOC_SINGLE("PGA MICA Switch", CS42L52_ADC_PGA_A, 4, 1, 0),
 464        SOC_SINGLE("PGA MICB Switch", CS42L52_ADC_PGA_B, 4, 1, 0),
 465
 466};
 467
 468static const struct snd_kcontrol_new cs42l52_mica_controls[] = {
 469        SOC_ENUM("MICA Select", mica_enum),
 470};
 471
 472static const struct snd_kcontrol_new cs42l52_micb_controls[] = {
 473        SOC_ENUM("MICB Select", micb_enum),
 474};
 475
 476static int cs42l52_add_mic_controls(struct snd_soc_codec *codec)
 477{
 478        struct cs42l52_private *cs42l52 = snd_soc_codec_get_drvdata(codec);
 479        struct cs42l52_platform_data *pdata = &cs42l52->pdata;
 480
 481        if (!pdata->mica_diff_cfg)
 482                snd_soc_add_codec_controls(codec, cs42l52_mica_controls,
 483                                     ARRAY_SIZE(cs42l52_mica_controls));
 484
 485        if (!pdata->micb_diff_cfg)
 486                snd_soc_add_codec_controls(codec, cs42l52_micb_controls,
 487                                     ARRAY_SIZE(cs42l52_micb_controls));
 488
 489        return 0;
 490}
 491
 492static const struct snd_soc_dapm_widget cs42l52_dapm_widgets[] = {
 493
 494        SND_SOC_DAPM_INPUT("AIN1L"),
 495        SND_SOC_DAPM_INPUT("AIN1R"),
 496        SND_SOC_DAPM_INPUT("AIN2L"),
 497        SND_SOC_DAPM_INPUT("AIN2R"),
 498        SND_SOC_DAPM_INPUT("AIN3L"),
 499        SND_SOC_DAPM_INPUT("AIN3R"),
 500        SND_SOC_DAPM_INPUT("AIN4L"),
 501        SND_SOC_DAPM_INPUT("AIN4R"),
 502        SND_SOC_DAPM_INPUT("MICA"),
 503        SND_SOC_DAPM_INPUT("MICB"),
 504        SND_SOC_DAPM_SIGGEN("Beep"),
 505
 506        SND_SOC_DAPM_AIF_OUT("AIFOUTL", NULL,  0,
 507                        SND_SOC_NOPM, 0, 0),
 508        SND_SOC_DAPM_AIF_OUT("AIFOUTR", NULL,  0,
 509                        SND_SOC_NOPM, 0, 0),
 510
 511        SND_SOC_DAPM_ADC("ADC Left", NULL, CS42L52_PWRCTL1, 1, 1),
 512        SND_SOC_DAPM_ADC("ADC Right", NULL, CS42L52_PWRCTL1, 2, 1),
 513        SND_SOC_DAPM_PGA("PGA Left", CS42L52_PWRCTL1, 3, 1, NULL, 0),
 514        SND_SOC_DAPM_PGA("PGA Right", CS42L52_PWRCTL1, 4, 1, NULL, 0),
 515
 516        SND_SOC_DAPM_MUX("ADC Left Mux", SND_SOC_NOPM, 0, 0, &adca_mux),
 517        SND_SOC_DAPM_MUX("ADC Right Mux", SND_SOC_NOPM, 0, 0, &adcb_mux),
 518
 519        SND_SOC_DAPM_MUX("ADC Left Swap", SND_SOC_NOPM,
 520                         0, 0, &adca_mixer),
 521        SND_SOC_DAPM_MUX("ADC Right Swap", SND_SOC_NOPM,
 522                         0, 0, &adcb_mixer),
 523
 524        SND_SOC_DAPM_MUX("Output Mux", SND_SOC_NOPM,
 525                         0, 0, &digital_output_mux),
 526
 527        SND_SOC_DAPM_PGA("PGA MICA", CS42L52_PWRCTL2, 1, 1, NULL, 0),
 528        SND_SOC_DAPM_PGA("PGA MICB", CS42L52_PWRCTL2, 2, 1, NULL, 0),
 529
 530        SND_SOC_DAPM_SUPPLY("Mic Bias", CS42L52_PWRCTL2, 0, 1, NULL, 0),
 531        SND_SOC_DAPM_SUPPLY("Charge Pump", CS42L52_PWRCTL1, 7, 1, NULL, 0),
 532
 533        SND_SOC_DAPM_AIF_IN("AIFINL", NULL,  0,
 534                        SND_SOC_NOPM, 0, 0),
 535        SND_SOC_DAPM_AIF_IN("AIFINR", NULL,  0,
 536                        SND_SOC_NOPM, 0, 0),
 537
 538        SND_SOC_DAPM_DAC("DAC Left", NULL, SND_SOC_NOPM, 0, 0),
 539        SND_SOC_DAPM_DAC("DAC Right", NULL, SND_SOC_NOPM, 0, 0),
 540
 541        SND_SOC_DAPM_SWITCH("Bypass Left", CS42L52_MISC_CTL,
 542                            6, 0, &passthrul_ctl),
 543        SND_SOC_DAPM_SWITCH("Bypass Right", CS42L52_MISC_CTL,
 544                            7, 0, &passthrur_ctl),
 545
 546        SND_SOC_DAPM_MUX("PCM Left Swap", SND_SOC_NOPM,
 547                         0, 0, &pcma_mixer),
 548        SND_SOC_DAPM_MUX("PCM Right Swap", SND_SOC_NOPM,
 549                         0, 0, &pcmb_mixer),
 550
 551        SND_SOC_DAPM_SWITCH("HP Left Amp", SND_SOC_NOPM, 0, 0, &hpl_ctl),
 552        SND_SOC_DAPM_SWITCH("HP Right Amp", SND_SOC_NOPM, 0, 0, &hpr_ctl),
 553
 554        SND_SOC_DAPM_SWITCH("SPK Left Amp", SND_SOC_NOPM, 0, 0, &spkl_ctl),
 555        SND_SOC_DAPM_SWITCH("SPK Right Amp", SND_SOC_NOPM, 0, 0, &spkr_ctl),
 556
 557        SND_SOC_DAPM_OUTPUT("HPOUTA"),
 558        SND_SOC_DAPM_OUTPUT("HPOUTB"),
 559        SND_SOC_DAPM_OUTPUT("SPKOUTA"),
 560        SND_SOC_DAPM_OUTPUT("SPKOUTB"),
 561
 562};
 563
 564static const struct snd_soc_dapm_route cs42l52_audio_map[] = {
 565
 566        {"Capture", NULL, "AIFOUTL"},
 567        {"Capture", NULL, "AIFOUTL"},
 568
 569        {"AIFOUTL", NULL, "Output Mux"},
 570        {"AIFOUTR", NULL, "Output Mux"},
 571
 572        {"Output Mux", "ADC", "ADC Left"},
 573        {"Output Mux", "ADC", "ADC Right"},
 574
 575        {"ADC Left", NULL, "Charge Pump"},
 576        {"ADC Right", NULL, "Charge Pump"},
 577
 578        {"Charge Pump", NULL, "ADC Left Mux"},
 579        {"Charge Pump", NULL, "ADC Right Mux"},
 580
 581        {"ADC Left Mux", "Input1A", "AIN1L"},
 582        {"ADC Right Mux", "Input1B", "AIN1R"},
 583        {"ADC Left Mux", "Input2A", "AIN2L"},
 584        {"ADC Right Mux", "Input2B", "AIN2R"},
 585        {"ADC Left Mux", "Input3A", "AIN3L"},
 586        {"ADC Right Mux", "Input3B", "AIN3R"},
 587        {"ADC Left Mux", "Input4A", "AIN4L"},
 588        {"ADC Right Mux", "Input4B", "AIN4R"},
 589        {"ADC Left Mux", "PGA Input Left", "PGA Left"},
 590        {"ADC Right Mux", "PGA Input Right" , "PGA Right"},
 591
 592        {"PGA Left", "Switch", "AIN1L"},
 593        {"PGA Right", "Switch", "AIN1R"},
 594        {"PGA Left", "Switch", "AIN2L"},
 595        {"PGA Right", "Switch", "AIN2R"},
 596        {"PGA Left", "Switch", "AIN3L"},
 597        {"PGA Right", "Switch", "AIN3R"},
 598        {"PGA Left", "Switch", "AIN4L"},
 599        {"PGA Right", "Switch", "AIN4R"},
 600
 601        {"PGA Left", "Switch", "PGA MICA"},
 602        {"PGA MICA", NULL, "MICA"},
 603
 604        {"PGA Right", "Switch", "PGA MICB"},
 605        {"PGA MICB", NULL, "MICB"},
 606
 607        {"HPOUTA", NULL, "HP Left Amp"},
 608        {"HPOUTB", NULL, "HP Right Amp"},
 609        {"HP Left Amp", NULL, "Bypass Left"},
 610        {"HP Right Amp", NULL, "Bypass Right"},
 611        {"Bypass Left", "Switch", "PGA Left"},
 612        {"Bypass Right", "Switch", "PGA Right"},
 613        {"HP Left Amp", "Switch", "DAC Left"},
 614        {"HP Right Amp", "Switch", "DAC Right"},
 615
 616        {"SPKOUTA", NULL, "SPK Left Amp"},
 617        {"SPKOUTB", NULL, "SPK Right Amp"},
 618
 619        {"SPK Left Amp", NULL, "Beep"},
 620        {"SPK Right Amp", NULL, "Beep"},
 621        {"SPK Left Amp", "Switch", "Playback"},
 622        {"SPK Right Amp", "Switch", "Playback"},
 623
 624        {"DAC Left", NULL, "Beep"},
 625        {"DAC Right", NULL, "Beep"},
 626        {"DAC Left", NULL, "Playback"},
 627        {"DAC Right", NULL, "Playback"},
 628
 629        {"Output Mux", "DSP", "Playback"},
 630        {"Output Mux", "DSP", "Playback"},
 631
 632        {"AIFINL", NULL, "Playback"},
 633        {"AIFINR", NULL, "Playback"},
 634
 635};
 636
 637struct cs42l52_clk_para {
 638        u32 mclk;
 639        u32 rate;
 640        u8 speed;
 641        u8 group;
 642        u8 videoclk;
 643        u8 ratio;
 644        u8 mclkdiv2;
 645};
 646
 647static const struct cs42l52_clk_para clk_map_table[] = {
 648        /*8k*/
 649        {12288000, 8000, CLK_QS_MODE, CLK_32K, CLK_NO_27M, CLK_R_128, 0},
 650        {18432000, 8000, CLK_QS_MODE, CLK_32K, CLK_NO_27M, CLK_R_128, 0},
 651        {12000000, 8000, CLK_QS_MODE, CLK_32K, CLK_NO_27M, CLK_R_125, 0},
 652        {24000000, 8000, CLK_QS_MODE, CLK_32K, CLK_NO_27M, CLK_R_125, 1},
 653        {27000000, 8000, CLK_QS_MODE, CLK_32K, CLK_27M_MCLK, CLK_R_125, 0},
 654
 655        /*11.025k*/
 656        {11289600, 11025, CLK_QS_MODE, CLK_NO_32K, CLK_NO_27M, CLK_R_128, 0},
 657        {16934400, 11025, CLK_QS_MODE, CLK_NO_32K, CLK_NO_27M, CLK_R_128, 0},
 658
 659        /*16k*/
 660        {12288000, 16000, CLK_HS_MODE, CLK_32K, CLK_NO_27M, CLK_R_128, 0},
 661        {18432000, 16000, CLK_HS_MODE, CLK_32K, CLK_NO_27M, CLK_R_128, 0},
 662        {12000000, 16000, CLK_HS_MODE, CLK_32K, CLK_NO_27M, CLK_R_125, 0},
 663        {24000000, 16000, CLK_HS_MODE, CLK_32K, CLK_NO_27M, CLK_R_125, 1},
 664        {27000000, 16000, CLK_HS_MODE, CLK_32K, CLK_27M_MCLK, CLK_R_125, 1},
 665
 666        /*22.05k*/
 667        {11289600, 22050, CLK_HS_MODE, CLK_NO_32K, CLK_NO_27M, CLK_R_128, 0},
 668        {16934400, 22050, CLK_HS_MODE, CLK_NO_32K, CLK_NO_27M, CLK_R_128, 0},
 669
 670        /* 32k */
 671        {12288000, 32000, CLK_SS_MODE, CLK_32K, CLK_NO_27M, CLK_R_128, 0},
 672        {18432000, 32000, CLK_SS_MODE, CLK_32K, CLK_NO_27M, CLK_R_128, 0},
 673        {12000000, 32000, CLK_SS_MODE, CLK_32K, CLK_NO_27M, CLK_R_125, 0},
 674        {24000000, 32000, CLK_SS_MODE, CLK_32K, CLK_NO_27M, CLK_R_125, 1},
 675        {27000000, 32000, CLK_SS_MODE, CLK_32K, CLK_27M_MCLK, CLK_R_125, 0},
 676
 677        /* 44.1k */
 678        {11289600, 44100, CLK_SS_MODE, CLK_NO_32K, CLK_NO_27M, CLK_R_128, 0},
 679        {16934400, 44100, CLK_SS_MODE, CLK_NO_32K, CLK_NO_27M, CLK_R_128, 0},
 680
 681        /* 48k */
 682        {12288000, 48000, CLK_SS_MODE, CLK_NO_32K, CLK_NO_27M, CLK_R_128, 0},
 683        {18432000, 48000, CLK_SS_MODE, CLK_NO_32K, CLK_NO_27M, CLK_R_128, 0},
 684        {12000000, 48000, CLK_SS_MODE, CLK_NO_32K, CLK_NO_27M, CLK_R_125, 0},
 685        {24000000, 48000, CLK_SS_MODE, CLK_NO_32K, CLK_NO_27M, CLK_R_125, 1},
 686        {27000000, 48000, CLK_SS_MODE, CLK_NO_32K, CLK_27M_MCLK, CLK_R_125, 1},
 687
 688        /* 88.2k */
 689        {11289600, 88200, CLK_DS_MODE, CLK_NO_32K, CLK_NO_27M, CLK_R_128, 0},
 690        {16934400, 88200, CLK_DS_MODE, CLK_NO_32K, CLK_NO_27M, CLK_R_128, 0},
 691
 692        /* 96k */
 693        {12288000, 96000, CLK_DS_MODE, CLK_NO_32K, CLK_NO_27M, CLK_R_128, 0},
 694        {18432000, 96000, CLK_DS_MODE, CLK_NO_32K, CLK_NO_27M, CLK_R_128, 0},
 695        {12000000, 96000, CLK_DS_MODE, CLK_NO_32K, CLK_NO_27M, CLK_R_125, 0},
 696        {24000000, 96000, CLK_DS_MODE, CLK_NO_32K, CLK_NO_27M, CLK_R_125, 1},
 697};
 698
 699static int cs42l52_get_clk(int mclk, int rate)
 700{
 701        int i, ret = -EINVAL;
 702        u_int mclk1, mclk2 = 0;
 703
 704        for (i = 0; i < ARRAY_SIZE(clk_map_table); i++) {
 705                if (clk_map_table[i].rate == rate) {
 706                        mclk1 = clk_map_table[i].mclk;
 707                        if (abs(mclk - mclk1) < abs(mclk - mclk2)) {
 708                                mclk2 = mclk1;
 709                                ret = i;
 710                        }
 711                }
 712        }
 713        return ret;
 714}
 715
 716static int cs42l52_set_sysclk(struct snd_soc_dai *codec_dai,
 717                        int clk_id, unsigned int freq, int dir)
 718{
 719        struct snd_soc_codec *codec = codec_dai->codec;
 720        struct cs42l52_private *cs42l52 = snd_soc_codec_get_drvdata(codec);
 721
 722        if ((freq >= CS42L52_MIN_CLK) && (freq <= CS42L52_MAX_CLK)) {
 723                cs42l52->sysclk = freq;
 724        } else {
 725                dev_err(codec->dev, "Invalid freq parameter\n");
 726                return -EINVAL;
 727        }
 728        return 0;
 729}
 730
 731static int cs42l52_set_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt)
 732{
 733        struct snd_soc_codec *codec = codec_dai->codec;
 734        struct cs42l52_private *cs42l52 = snd_soc_codec_get_drvdata(codec);
 735        u8 iface = 0;
 736
 737        switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
 738        case SND_SOC_DAIFMT_CBM_CFM:
 739                iface = CS42L52_IFACE_CTL1_MASTER;
 740                break;
 741        case SND_SOC_DAIFMT_CBS_CFS:
 742                iface = CS42L52_IFACE_CTL1_SLAVE;
 743                break;
 744        default:
 745                return -EINVAL;
 746        }
 747
 748         /* interface format */
 749        switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
 750        case SND_SOC_DAIFMT_I2S:
 751                iface |= CS42L52_IFACE_CTL1_ADC_FMT_I2S |
 752                                CS42L52_IFACE_CTL1_DAC_FMT_I2S;
 753                break;
 754        case SND_SOC_DAIFMT_RIGHT_J:
 755                iface |= CS42L52_IFACE_CTL1_DAC_FMT_RIGHT_J;
 756                break;
 757        case SND_SOC_DAIFMT_LEFT_J:
 758                iface |= CS42L52_IFACE_CTL1_ADC_FMT_LEFT_J |
 759                                CS42L52_IFACE_CTL1_DAC_FMT_LEFT_J;
 760                break;
 761        case SND_SOC_DAIFMT_DSP_A:
 762                iface |= CS42L52_IFACE_CTL1_DSP_MODE_EN;
 763                break;
 764        case SND_SOC_DAIFMT_DSP_B:
 765                break;
 766        default:
 767                return -EINVAL;
 768        }
 769
 770        /* clock inversion */
 771        switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
 772        case SND_SOC_DAIFMT_NB_NF:
 773                break;
 774        case SND_SOC_DAIFMT_IB_IF:
 775                iface |= CS42L52_IFACE_CTL1_INV_SCLK;
 776                break;
 777        case SND_SOC_DAIFMT_IB_NF:
 778                iface |= CS42L52_IFACE_CTL1_INV_SCLK;
 779                break;
 780        case SND_SOC_DAIFMT_NB_IF:
 781                break;
 782        default:
 783                return -EINVAL;
 784        }
 785        cs42l52->config.format = iface;
 786        snd_soc_write(codec, CS42L52_IFACE_CTL1, cs42l52->config.format);
 787
 788        return 0;
 789}
 790
 791static int cs42l52_digital_mute(struct snd_soc_dai *dai, int mute)
 792{
 793        struct snd_soc_codec *codec = dai->codec;
 794
 795        if (mute)
 796                snd_soc_update_bits(codec, CS42L52_PB_CTL1,
 797                                    CS42L52_PB_CTL1_MUTE_MASK,
 798                                CS42L52_PB_CTL1_MUTE);
 799        else
 800                snd_soc_update_bits(codec, CS42L52_PB_CTL1,
 801                                    CS42L52_PB_CTL1_MUTE_MASK,
 802                                CS42L52_PB_CTL1_UNMUTE);
 803
 804        return 0;
 805}
 806
 807static int cs42l52_pcm_hw_params(struct snd_pcm_substream *substream,
 808                                     struct snd_pcm_hw_params *params,
 809                                     struct snd_soc_dai *dai)
 810{
 811        struct snd_soc_codec *codec = dai->codec;
 812        struct cs42l52_private *cs42l52 = snd_soc_codec_get_drvdata(codec);
 813        u32 clk = 0;
 814        int index;
 815
 816        index = cs42l52_get_clk(cs42l52->sysclk, params_rate(params));
 817        if (index >= 0) {
 818                cs42l52->sysclk = clk_map_table[index].mclk;
 819
 820                clk |= (clk_map_table[index].speed << CLK_SPEED_SHIFT) |
 821                (clk_map_table[index].group << CLK_32K_SR_SHIFT) |
 822                (clk_map_table[index].videoclk << CLK_27M_MCLK_SHIFT) |
 823                (clk_map_table[index].ratio << CLK_RATIO_SHIFT) |
 824                clk_map_table[index].mclkdiv2;
 825
 826                snd_soc_write(codec, CS42L52_CLK_CTL, clk);
 827        } else {
 828                dev_err(codec->dev, "can't get correct mclk\n");
 829                return -EINVAL;
 830        }
 831
 832        return 0;
 833}
 834
 835static int cs42l52_set_bias_level(struct snd_soc_codec *codec,
 836                                        enum snd_soc_bias_level level)
 837{
 838        struct cs42l52_private *cs42l52 = snd_soc_codec_get_drvdata(codec);
 839
 840        switch (level) {
 841        case SND_SOC_BIAS_ON:
 842                break;
 843        case SND_SOC_BIAS_PREPARE:
 844                snd_soc_update_bits(codec, CS42L52_PWRCTL1,
 845                                    CS42L52_PWRCTL1_PDN_CODEC, 0);
 846                break;
 847        case SND_SOC_BIAS_STANDBY:
 848                if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_OFF) {
 849                        regcache_cache_only(cs42l52->regmap, false);
 850                        regcache_sync(cs42l52->regmap);
 851                }
 852                snd_soc_write(codec, CS42L52_PWRCTL1, CS42L52_PWRCTL1_PDN_ALL);
 853                break;
 854        case SND_SOC_BIAS_OFF:
 855                snd_soc_write(codec, CS42L52_PWRCTL1, CS42L52_PWRCTL1_PDN_ALL);
 856                regcache_cache_only(cs42l52->regmap, true);
 857                break;
 858        }
 859
 860        return 0;
 861}
 862
 863#define CS42L52_RATES (SNDRV_PCM_RATE_8000_96000)
 864
 865#define CS42L52_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_U16_LE | \
 866                        SNDRV_PCM_FMTBIT_S18_3LE | SNDRV_PCM_FMTBIT_U18_3LE | \
 867                        SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_U20_3LE | \
 868                        SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_U24_LE)
 869
 870static const struct snd_soc_dai_ops cs42l52_ops = {
 871        .hw_params      = cs42l52_pcm_hw_params,
 872        .digital_mute   = cs42l52_digital_mute,
 873        .set_fmt        = cs42l52_set_fmt,
 874        .set_sysclk     = cs42l52_set_sysclk,
 875};
 876
 877static struct snd_soc_dai_driver cs42l52_dai = {
 878                .name = "cs42l52",
 879                .playback = {
 880                        .stream_name = "Playback",
 881                        .channels_min = 1,
 882                        .channels_max = 2,
 883                        .rates = CS42L52_RATES,
 884                        .formats = CS42L52_FORMATS,
 885                },
 886                .capture = {
 887                        .stream_name = "Capture",
 888                        .channels_min = 1,
 889                        .channels_max = 2,
 890                        .rates = CS42L52_RATES,
 891                        .formats = CS42L52_FORMATS,
 892                },
 893                .ops = &cs42l52_ops,
 894};
 895
 896static int beep_rates[] = {
 897        261, 522, 585, 667, 706, 774, 889, 1000,
 898        1043, 1200, 1333, 1412, 1600, 1714, 2000, 2182
 899};
 900
 901static void cs42l52_beep_work(struct work_struct *work)
 902{
 903        struct cs42l52_private *cs42l52 =
 904                container_of(work, struct cs42l52_private, beep_work);
 905        struct snd_soc_codec *codec = cs42l52->codec;
 906        struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec);
 907        int i;
 908        int val = 0;
 909        int best = 0;
 910
 911        if (cs42l52->beep_rate) {
 912                for (i = 0; i < ARRAY_SIZE(beep_rates); i++) {
 913                        if (abs(cs42l52->beep_rate - beep_rates[i]) <
 914                            abs(cs42l52->beep_rate - beep_rates[best]))
 915                                best = i;
 916                }
 917
 918                dev_dbg(codec->dev, "Set beep rate %dHz for requested %dHz\n",
 919                        beep_rates[best], cs42l52->beep_rate);
 920
 921                val = (best << CS42L52_BEEP_RATE_SHIFT);
 922
 923                snd_soc_dapm_enable_pin(dapm, "Beep");
 924        } else {
 925                dev_dbg(codec->dev, "Disabling beep\n");
 926                snd_soc_dapm_disable_pin(dapm, "Beep");
 927        }
 928
 929        snd_soc_update_bits(codec, CS42L52_BEEP_FREQ,
 930                            CS42L52_BEEP_RATE_MASK, val);
 931
 932        snd_soc_dapm_sync(dapm);
 933}
 934
 935/* For usability define a way of injecting beep events for the device -
 936 * many systems will not have a keyboard.
 937 */
 938static int cs42l52_beep_event(struct input_dev *dev, unsigned int type,
 939                             unsigned int code, int hz)
 940{
 941        struct snd_soc_codec *codec = input_get_drvdata(dev);
 942        struct cs42l52_private *cs42l52 = snd_soc_codec_get_drvdata(codec);
 943
 944        dev_dbg(codec->dev, "Beep event %x %x\n", code, hz);
 945
 946        switch (code) {
 947        case SND_BELL:
 948                if (hz)
 949                        hz = 261;
 950        case SND_TONE:
 951                break;
 952        default:
 953                return -1;
 954        }
 955
 956        /* Kick the beep from a workqueue */
 957        cs42l52->beep_rate = hz;
 958        schedule_work(&cs42l52->beep_work);
 959        return 0;
 960}
 961
 962static ssize_t cs42l52_beep_set(struct device *dev,
 963                               struct device_attribute *attr,
 964                               const char *buf, size_t count)
 965{
 966        struct cs42l52_private *cs42l52 = dev_get_drvdata(dev);
 967        long int time;
 968        int ret;
 969
 970        ret = kstrtol(buf, 10, &time);
 971        if (ret != 0)
 972                return ret;
 973
 974        input_event(cs42l52->beep, EV_SND, SND_TONE, time);
 975
 976        return count;
 977}
 978
 979static DEVICE_ATTR(beep, 0200, NULL, cs42l52_beep_set);
 980
 981static void cs42l52_init_beep(struct snd_soc_codec *codec)
 982{
 983        struct cs42l52_private *cs42l52 = snd_soc_codec_get_drvdata(codec);
 984        int ret;
 985
 986        cs42l52->beep = devm_input_allocate_device(codec->dev);
 987        if (!cs42l52->beep) {
 988                dev_err(codec->dev, "Failed to allocate beep device\n");
 989                return;
 990        }
 991
 992        INIT_WORK(&cs42l52->beep_work, cs42l52_beep_work);
 993        cs42l52->beep_rate = 0;
 994
 995        cs42l52->beep->name = "CS42L52 Beep Generator";
 996        cs42l52->beep->phys = dev_name(codec->dev);
 997        cs42l52->beep->id.bustype = BUS_I2C;
 998
 999        cs42l52->beep->evbit[0] = BIT_MASK(EV_SND);
1000        cs42l52->beep->sndbit[0] = BIT_MASK(SND_BELL) | BIT_MASK(SND_TONE);
1001        cs42l52->beep->event = cs42l52_beep_event;
1002        cs42l52->beep->dev.parent = codec->dev;
1003        input_set_drvdata(cs42l52->beep, codec);
1004
1005        ret = input_register_device(cs42l52->beep);
1006        if (ret != 0) {
1007                cs42l52->beep = NULL;
1008                dev_err(codec->dev, "Failed to register beep device\n");
1009        }
1010
1011        ret = device_create_file(codec->dev, &dev_attr_beep);
1012        if (ret != 0) {
1013                dev_err(codec->dev, "Failed to create keyclick file: %d\n",
1014                        ret);
1015        }
1016}
1017
1018static void cs42l52_free_beep(struct snd_soc_codec *codec)
1019{
1020        struct cs42l52_private *cs42l52 = snd_soc_codec_get_drvdata(codec);
1021
1022        device_remove_file(codec->dev, &dev_attr_beep);
1023        cancel_work_sync(&cs42l52->beep_work);
1024        cs42l52->beep = NULL;
1025
1026        snd_soc_update_bits(codec, CS42L52_BEEP_TONE_CTL,
1027                            CS42L52_BEEP_EN_MASK, 0);
1028}
1029
1030static int cs42l52_probe(struct snd_soc_codec *codec)
1031{
1032        struct cs42l52_private *cs42l52 = snd_soc_codec_get_drvdata(codec);
1033
1034        regcache_cache_only(cs42l52->regmap, true);
1035
1036        cs42l52_add_mic_controls(codec);
1037
1038        cs42l52_init_beep(codec);
1039
1040        cs42l52->sysclk = CS42L52_DEFAULT_CLK;
1041        cs42l52->config.format = CS42L52_DEFAULT_FORMAT;
1042
1043        return 0;
1044}
1045
1046static int cs42l52_remove(struct snd_soc_codec *codec)
1047{
1048        cs42l52_free_beep(codec);
1049
1050        return 0;
1051}
1052
1053static const struct snd_soc_codec_driver soc_codec_dev_cs42l52 = {
1054        .probe = cs42l52_probe,
1055        .remove = cs42l52_remove,
1056        .set_bias_level = cs42l52_set_bias_level,
1057        .suspend_bias_off = true,
1058
1059        .component_driver = {
1060                .controls               = cs42l52_snd_controls,
1061                .num_controls           = ARRAY_SIZE(cs42l52_snd_controls),
1062                .dapm_widgets           = cs42l52_dapm_widgets,
1063                .num_dapm_widgets       = ARRAY_SIZE(cs42l52_dapm_widgets),
1064                .dapm_routes            = cs42l52_audio_map,
1065                .num_dapm_routes        = ARRAY_SIZE(cs42l52_audio_map),
1066        },
1067};
1068
1069/* Current and threshold powerup sequence Pg37 */
1070static const struct reg_sequence cs42l52_threshold_patch[] = {
1071
1072        { 0x00, 0x99 },
1073        { 0x3E, 0xBA },
1074        { 0x47, 0x80 },
1075        { 0x32, 0xBB },
1076        { 0x32, 0x3B },
1077        { 0x00, 0x00 },
1078
1079};
1080
1081static const struct regmap_config cs42l52_regmap = {
1082        .reg_bits = 8,
1083        .val_bits = 8,
1084
1085        .max_register = CS42L52_MAX_REGISTER,
1086        .reg_defaults = cs42l52_reg_defaults,
1087        .num_reg_defaults = ARRAY_SIZE(cs42l52_reg_defaults),
1088        .readable_reg = cs42l52_readable_register,
1089        .volatile_reg = cs42l52_volatile_register,
1090        .cache_type = REGCACHE_RBTREE,
1091};
1092
1093static int cs42l52_i2c_probe(struct i2c_client *i2c_client,
1094                             const struct i2c_device_id *id)
1095{
1096        struct cs42l52_private *cs42l52;
1097        struct cs42l52_platform_data *pdata = dev_get_platdata(&i2c_client->dev);
1098        int ret;
1099        unsigned int devid = 0;
1100        unsigned int reg;
1101        u32 val32;
1102
1103        cs42l52 = devm_kzalloc(&i2c_client->dev, sizeof(*cs42l52), GFP_KERNEL);
1104        if (cs42l52 == NULL)
1105                return -ENOMEM;
1106        cs42l52->dev = &i2c_client->dev;
1107
1108        cs42l52->regmap = devm_regmap_init_i2c(i2c_client, &cs42l52_regmap);
1109        if (IS_ERR(cs42l52->regmap)) {
1110                ret = PTR_ERR(cs42l52->regmap);
1111                dev_err(&i2c_client->dev, "regmap_init() failed: %d\n", ret);
1112                return ret;
1113        }
1114        if (pdata) {
1115                cs42l52->pdata = *pdata;
1116        } else {
1117                pdata = devm_kzalloc(&i2c_client->dev, sizeof(*pdata),
1118                                     GFP_KERNEL);
1119                if (!pdata)
1120                        return -ENOMEM;
1121
1122                if (i2c_client->dev.of_node) {
1123                        if (of_property_read_bool(i2c_client->dev.of_node,
1124                                "cirrus,mica-differential-cfg"))
1125                                pdata->mica_diff_cfg = true;
1126
1127                        if (of_property_read_bool(i2c_client->dev.of_node,
1128                                "cirrus,micb-differential-cfg"))
1129                                pdata->micb_diff_cfg = true;
1130
1131                        if (of_property_read_u32(i2c_client->dev.of_node,
1132                                "cirrus,micbias-lvl", &val32) >= 0)
1133                                pdata->micbias_lvl = val32;
1134
1135                        if (of_property_read_u32(i2c_client->dev.of_node,
1136                                "cirrus,chgfreq-divisor", &val32) >= 0)
1137                                pdata->chgfreq = val32;
1138
1139                        pdata->reset_gpio =
1140                                of_get_named_gpio(i2c_client->dev.of_node,
1141                                                "cirrus,reset-gpio", 0);
1142                }
1143                cs42l52->pdata = *pdata;
1144        }
1145
1146        if (cs42l52->pdata.reset_gpio) {
1147                ret = devm_gpio_request_one(&i2c_client->dev,
1148                                            cs42l52->pdata.reset_gpio,
1149                                            GPIOF_OUT_INIT_HIGH,
1150                                            "CS42L52 /RST");
1151                if (ret < 0) {
1152                        dev_err(&i2c_client->dev, "Failed to request /RST %d: %d\n",
1153                                cs42l52->pdata.reset_gpio, ret);
1154                        return ret;
1155                }
1156                gpio_set_value_cansleep(cs42l52->pdata.reset_gpio, 0);
1157                gpio_set_value_cansleep(cs42l52->pdata.reset_gpio, 1);
1158        }
1159
1160        i2c_set_clientdata(i2c_client, cs42l52);
1161
1162        ret = regmap_register_patch(cs42l52->regmap, cs42l52_threshold_patch,
1163                                    ARRAY_SIZE(cs42l52_threshold_patch));
1164        if (ret != 0)
1165                dev_warn(cs42l52->dev, "Failed to apply regmap patch: %d\n",
1166                         ret);
1167
1168        ret = regmap_read(cs42l52->regmap, CS42L52_CHIP, &reg);
1169        devid = reg & CS42L52_CHIP_ID_MASK;
1170        if (devid != CS42L52_CHIP_ID) {
1171                ret = -ENODEV;
1172                dev_err(&i2c_client->dev,
1173                        "CS42L52 Device ID (%X). Expected %X\n",
1174                        devid, CS42L52_CHIP_ID);
1175                return ret;
1176        }
1177
1178        dev_info(&i2c_client->dev, "Cirrus Logic CS42L52, Revision: %02X\n",
1179                 reg & CS42L52_CHIP_REV_MASK);
1180
1181        /* Set Platform Data */
1182        if (cs42l52->pdata.mica_diff_cfg)
1183                regmap_update_bits(cs42l52->regmap, CS42L52_MICA_CTL,
1184                                   CS42L52_MIC_CTL_TYPE_MASK,
1185                                cs42l52->pdata.mica_diff_cfg <<
1186                                CS42L52_MIC_CTL_TYPE_SHIFT);
1187
1188        if (cs42l52->pdata.micb_diff_cfg)
1189                regmap_update_bits(cs42l52->regmap, CS42L52_MICB_CTL,
1190                                   CS42L52_MIC_CTL_TYPE_MASK,
1191                                cs42l52->pdata.micb_diff_cfg <<
1192                                CS42L52_MIC_CTL_TYPE_SHIFT);
1193
1194        if (cs42l52->pdata.chgfreq)
1195                regmap_update_bits(cs42l52->regmap, CS42L52_CHARGE_PUMP,
1196                                   CS42L52_CHARGE_PUMP_MASK,
1197                                cs42l52->pdata.chgfreq <<
1198                                CS42L52_CHARGE_PUMP_SHIFT);
1199
1200        if (cs42l52->pdata.micbias_lvl)
1201                regmap_update_bits(cs42l52->regmap, CS42L52_IFACE_CTL2,
1202                                   CS42L52_IFACE_CTL2_BIAS_LVL,
1203                                cs42l52->pdata.micbias_lvl);
1204
1205        ret =  snd_soc_register_codec(&i2c_client->dev,
1206                        &soc_codec_dev_cs42l52, &cs42l52_dai, 1);
1207        if (ret < 0)
1208                return ret;
1209        return 0;
1210}
1211
1212static int cs42l52_i2c_remove(struct i2c_client *client)
1213{
1214        snd_soc_unregister_codec(&client->dev);
1215        return 0;
1216}
1217
1218static const struct of_device_id cs42l52_of_match[] = {
1219        { .compatible = "cirrus,cs42l52", },
1220        {},
1221};
1222MODULE_DEVICE_TABLE(of, cs42l52_of_match);
1223
1224
1225static const struct i2c_device_id cs42l52_id[] = {
1226        { "cs42l52", 0 },
1227        { }
1228};
1229MODULE_DEVICE_TABLE(i2c, cs42l52_id);
1230
1231static struct i2c_driver cs42l52_i2c_driver = {
1232        .driver = {
1233                .name = "cs42l52",
1234                .of_match_table = cs42l52_of_match,
1235        },
1236        .id_table = cs42l52_id,
1237        .probe =    cs42l52_i2c_probe,
1238        .remove =   cs42l52_i2c_remove,
1239};
1240
1241module_i2c_driver(cs42l52_i2c_driver);
1242
1243MODULE_DESCRIPTION("ASoC CS42L52 driver");
1244MODULE_AUTHOR("Georgi Vlaev, Nucleus Systems Ltd, <joe@nucleusys.com>");
1245MODULE_AUTHOR("Brian Austin, Cirrus Logic Inc, <brian.austin@cirrus.com>");
1246MODULE_LICENSE("GPL");
1247