File Index
Files and directories
Sign in
FILE

cs42l52.c

File preview with syntax highlighting.

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