1 /* 2 * cs42l51.c 3 * 4 * ASoC Driver for Cirrus Logic CS42L51 codecs 5 * 6 * Copyright (c) 2010 Arnaud Patard <apatard@mandriva.com> 7 * 8 * Based on cs4270.c - Copyright (c) Freescale Semiconductor 9 * 10 * This program is free software; you can redistribute it and/or modify 11 * it under the terms of the GNU General Public License version 2 as 12 * published by the Free Software Foundation. 13 * 14 * This program is distributed in the hope that it will be useful, 15 * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 * GNU General Public License for more details. 18 * 19 * For now: 20 * - Only I2C is support. Not SPI 21 * - master mode *NOT* supported 22 */ 23 24 #include <linux/module.h> 25 #include <linux/slab.h> 26 #include <sound/core.h> 27 #include <sound/soc.h> 28 #include <sound/tlv.h> 29 #include <sound/initval.h> 30 #include <sound/pcm_params.h> 31 #include <sound/pcm.h> 32 #include <linux/i2c.h> 33 34 #include "cs42l51.h" 35 36 enum master_slave_mode { 37 MODE_SLAVE, 38 MODE_SLAVE_AUTO, 39 MODE_MASTER, 40 }; 41 42 struct cs42l51_private { 43 enum snd_soc_control_type control_type; 44 unsigned int mclk; 45 unsigned int audio_mode; /* The mode (I2S or left-justified) */ 46 enum master_slave_mode func; 47 }; 48 49 #define CS42L51_FORMATS ( \ 50 SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S16_BE | \ 51 SNDRV_PCM_FMTBIT_S18_3LE | SNDRV_PCM_FMTBIT_S18_3BE | \ 52 SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S20_3BE | \ 53 SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S24_BE) 54 55 static int cs42l51_fill_cache(struct snd_soc_codec *codec) 56 { 57 u8 *cache = codec->reg_cache + 1; 58 struct i2c_client *i2c_client = to_i2c_client(codec->dev); 59 s32 length; 60 61 length = i2c_smbus_read_i2c_block_data(i2c_client, 62 CS42L51_FIRSTREG | 0x80, CS42L51_NUMREGS, cache); 63 if (length != CS42L51_NUMREGS) { 64 dev_err(&i2c_client->dev, 65 "I2C read failure, addr=0x%x (ret=%d vs %d)\n", 66 i2c_client->addr, length, CS42L51_NUMREGS); 67 return -EIO; 68 } 69 70 return 0; 71 } 72 73 static int cs42l51_get_chan_mix(struct snd_kcontrol *kcontrol, 74 struct snd_ctl_elem_value *ucontrol) 75 { 76 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); 77 unsigned long value = snd_soc_read(codec, CS42L51_PCM_MIXER)&3; 78 79 switch (value) { 80 default: 81 case 0: 82 ucontrol->value.integer.value[0] = 0; 83 break; 84 /* same value : (L+R)/2 and (R+L)/2 */ 85 case 1: 86 case 2: 87 ucontrol->value.integer.value[0] = 1; 88 break; 89 case 3: 90 ucontrol->value.integer.value[0] = 2; 91 break; 92 } 93 94 return 0; 95 } 96 97 #define CHAN_MIX_NORMAL 0x00 98 #define CHAN_MIX_BOTH 0x55 99 #define CHAN_MIX_SWAP 0xFF 100 101 static int cs42l51_set_chan_mix(struct snd_kcontrol *kcontrol, 102 struct snd_ctl_elem_value *ucontrol) 103 { 104 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); 105 unsigned char val; 106 107 switch (ucontrol->value.integer.value[0]) { 108 default: 109 case 0: 110 val = CHAN_MIX_NORMAL; 111 break; 112 case 1: 113 val = CHAN_MIX_BOTH; 114 break; 115 case 2: 116 val = CHAN_MIX_SWAP; 117 break; 118 } 119 120 snd_soc_write(codec, CS42L51_PCM_MIXER, val); 121 122 return 1; 123 } 124 125 static const DECLARE_TLV_DB_SCALE(adc_pcm_tlv, -5150, 50, 0); 126 static const DECLARE_TLV_DB_SCALE(tone_tlv, -1050, 150, 0); 127 /* This is a lie. after -102 db, it stays at -102 */ 128 /* maybe a range would be better */ 129 static const DECLARE_TLV_DB_SCALE(aout_tlv, -11550, 50, 0); 130 131 static const DECLARE_TLV_DB_SCALE(boost_tlv, 1600, 1600, 0); 132 static const char *chan_mix[] = { 133 "L R", 134 "L+R", 135 "R L", 136 }; 137 138 static const struct soc_enum cs42l51_chan_mix = 139 SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(chan_mix), chan_mix); 140 141 static const struct snd_kcontrol_new cs42l51_snd_controls[] = { 142 SOC_DOUBLE_R_SX_TLV("PCM Playback Volume", 143 CS42L51_PCMA_VOL, CS42L51_PCMB_VOL, 144 6, 0x19, 0x7F, adc_pcm_tlv), 145 SOC_DOUBLE_R("PCM Playback Switch", 146 CS42L51_PCMA_VOL, CS42L51_PCMB_VOL, 7, 1, 1), 147 SOC_DOUBLE_R_SX_TLV("Analog Playback Volume", 148 CS42L51_AOUTA_VOL, CS42L51_AOUTB_VOL, 149 0, 0x34, 0xE4, aout_tlv), 150 SOC_DOUBLE_R_SX_TLV("ADC Mixer Volume", 151 CS42L51_ADCA_VOL, CS42L51_ADCB_VOL, 152 6, 0x19, 0x7F, adc_pcm_tlv), 153 SOC_DOUBLE_R("ADC Mixer Switch", 154 CS42L51_ADCA_VOL, CS42L51_ADCB_VOL, 7, 1, 1), 155 SOC_SINGLE("Playback Deemphasis Switch", CS42L51_DAC_CTL, 3, 1, 0), 156 SOC_SINGLE("Auto-Mute Switch", CS42L51_DAC_CTL, 2, 1, 0), 157 SOC_SINGLE("Soft Ramp Switch", CS42L51_DAC_CTL, 1, 1, 0), 158 SOC_SINGLE("Zero Cross Switch", CS42L51_DAC_CTL, 0, 0, 0), 159 SOC_DOUBLE_TLV("Mic Boost Volume", 160 CS42L51_MIC_CTL, 0, 1, 1, 0, boost_tlv), 161 SOC_SINGLE_TLV("Bass Volume", CS42L51_TONE_CTL, 0, 0xf, 1, tone_tlv), 162 SOC_SINGLE_TLV("Treble Volume", CS42L51_TONE_CTL, 4, 0xf, 1, tone_tlv), 163 SOC_ENUM_EXT("PCM channel mixer", 164 cs42l51_chan_mix, 165 cs42l51_get_chan_mix, cs42l51_set_chan_mix), 166 }; 167 168 /* 169 * to power down, one must: 170 * 1.) Enable the PDN bit 171 * 2.) enable power-down for the select channels 172 * 3.) disable the PDN bit. 173 */ 174 static int cs42l51_pdn_event(struct snd_soc_dapm_widget *w, 175 struct snd_kcontrol *kcontrol, int event) 176 { 177 switch (event) { 178 case SND_SOC_DAPM_PRE_PMD: 179 snd_soc_update_bits(w->codec, CS42L51_POWER_CTL1, 180 CS42L51_POWER_CTL1_PDN, 181 CS42L51_POWER_CTL1_PDN); 182 break; 183 default: 184 case SND_SOC_DAPM_POST_PMD: 185 snd_soc_update_bits(w->codec, CS42L51_POWER_CTL1, 186 CS42L51_POWER_CTL1_PDN, 0); 187 break; 188 } 189 190 return 0; 191 } 192 193 static const char *cs42l51_dac_names[] = {"Direct PCM", 194 "DSP PCM", "ADC"}; 195 static const struct soc_enum cs42l51_dac_mux_enum = 196 SOC_ENUM_SINGLE(CS42L51_DAC_CTL, 6, 3, cs42l51_dac_names); 197 static const struct snd_kcontrol_new cs42l51_dac_mux_controls = 198 SOC_DAPM_ENUM("Route", cs42l51_dac_mux_enum); 199 200 static const char *cs42l51_adcl_names[] = {"AIN1 Left", "AIN2 Left", 201 "MIC Left", "MIC+preamp Left"}; 202 static const struct soc_enum cs42l51_adcl_mux_enum = 203 SOC_ENUM_SINGLE(CS42L51_ADC_INPUT, 4, 4, cs42l51_adcl_names); 204 static const struct snd_kcontrol_new cs42l51_adcl_mux_controls = 205 SOC_DAPM_ENUM("Route", cs42l51_adcl_mux_enum); 206 207 static const char *cs42l51_adcr_names[] = {"AIN1 Right", "AIN2 Right", 208 "MIC Right", "MIC+preamp Right"}; 209 static const struct soc_enum cs42l51_adcr_mux_enum = 210 SOC_ENUM_SINGLE(CS42L51_ADC_INPUT, 6, 4, cs42l51_adcr_names); 211 static const struct snd_kcontrol_new cs42l51_adcr_mux_controls = 212 SOC_DAPM_ENUM("Route", cs42l51_adcr_mux_enum); 213 214 static const struct snd_soc_dapm_widget cs42l51_dapm_widgets[] = { 215 SND_SOC_DAPM_MICBIAS("Mic Bias", CS42L51_MIC_POWER_CTL, 1, 1), 216 SND_SOC_DAPM_PGA_E("Left PGA", CS42L51_POWER_CTL1, 3, 1, NULL, 0, 217 cs42l51_pdn_event, SND_SOC_DAPM_PRE_POST_PMD), 218 SND_SOC_DAPM_PGA_E("Right PGA", CS42L51_POWER_CTL1, 4, 1, NULL, 0, 219 cs42l51_pdn_event, SND_SOC_DAPM_PRE_POST_PMD), 220 SND_SOC_DAPM_ADC_E("Left ADC", "Left HiFi Capture", 221 CS42L51_POWER_CTL1, 1, 1, 222 cs42l51_pdn_event, SND_SOC_DAPM_PRE_POST_PMD), 223 SND_SOC_DAPM_ADC_E("Right ADC", "Right HiFi Capture", 224 CS42L51_POWER_CTL1, 2, 1, 225 cs42l51_pdn_event, SND_SOC_DAPM_PRE_POST_PMD), 226 SND_SOC_DAPM_DAC_E("Left DAC", "Left HiFi Playback", 227 CS42L51_POWER_CTL1, 5, 1, 228 cs42l51_pdn_event, SND_SOC_DAPM_PRE_POST_PMD), 229 SND_SOC_DAPM_DAC_E("Right DAC", "Right HiFi Playback", 230 CS42L51_POWER_CTL1, 6, 1, 231 cs42l51_pdn_event, SND_SOC_DAPM_PRE_POST_PMD), 232 233 /* analog/mic */ 234 SND_SOC_DAPM_INPUT("AIN1L"), 235 SND_SOC_DAPM_INPUT("AIN1R"), 236 SND_SOC_DAPM_INPUT("AIN2L"), 237 SND_SOC_DAPM_INPUT("AIN2R"), 238 SND_SOC_DAPM_INPUT("MICL"), 239 SND_SOC_DAPM_INPUT("MICR"), 240 241 SND_SOC_DAPM_MIXER("Mic Preamp Left", 242 CS42L51_MIC_POWER_CTL, 2, 1, NULL, 0), 243 SND_SOC_DAPM_MIXER("Mic Preamp Right", 244 CS42L51_MIC_POWER_CTL, 3, 1, NULL, 0), 245 246 /* HP */ 247 SND_SOC_DAPM_OUTPUT("HPL"), 248 SND_SOC_DAPM_OUTPUT("HPR"), 249 250 /* mux */ 251 SND_SOC_DAPM_MUX("DAC Mux", SND_SOC_NOPM, 0, 0, 252 &cs42l51_dac_mux_controls), 253 SND_SOC_DAPM_MUX("PGA-ADC Mux Left", SND_SOC_NOPM, 0, 0, 254 &cs42l51_adcl_mux_controls), 255 SND_SOC_DAPM_MUX("PGA-ADC Mux Right", SND_SOC_NOPM, 0, 0, 256 &cs42l51_adcr_mux_controls), 257 }; 258 259 static const struct snd_soc_dapm_route cs42l51_routes[] = { 260 {"HPL", NULL, "Left DAC"}, 261 {"HPR", NULL, "Right DAC"}, 262 263 {"Left ADC", NULL, "Left PGA"}, 264 {"Right ADC", NULL, "Right PGA"}, 265 266 {"Mic Preamp Left", NULL, "MICL"}, 267 {"Mic Preamp Right", NULL, "MICR"}, 268 269 {"PGA-ADC Mux Left", "AIN1 Left", "AIN1L" }, 270 {"PGA-ADC Mux Left", "AIN2 Left", "AIN2L" }, 271 {"PGA-ADC Mux Left", "MIC Left", "MICL" }, 272 {"PGA-ADC Mux Left", "MIC+preamp Left", "Mic Preamp Left" }, 273 {"PGA-ADC Mux Right", "AIN1 Right", "AIN1R" }, 274 {"PGA-ADC Mux Right", "AIN2 Right", "AIN2R" }, 275 {"PGA-ADC Mux Right", "MIC Right", "MICR" }, 276 {"PGA-ADC Mux Right", "MIC+preamp Right", "Mic Preamp Right" }, 277 278 {"Left PGA", NULL, "PGA-ADC Mux Left"}, 279 {"Right PGA", NULL, "PGA-ADC Mux Right"}, 280 }; 281 282 static int cs42l51_set_dai_fmt(struct snd_soc_dai *codec_dai, 283 unsigned int format) 284 { 285 struct snd_soc_codec *codec = codec_dai->codec; 286 struct cs42l51_private *cs42l51 = snd_soc_codec_get_drvdata(codec); 287 288 switch (format & SND_SOC_DAIFMT_FORMAT_MASK) { 289 case SND_SOC_DAIFMT_I2S: 290 case SND_SOC_DAIFMT_LEFT_J: 291 case SND_SOC_DAIFMT_RIGHT_J: 292 cs42l51->audio_mode = format & SND_SOC_DAIFMT_FORMAT_MASK; 293 break; 294 default: 295 dev_err(codec->dev, "invalid DAI format\n"); 296 return -EINVAL; 297 } 298 299 switch (format & SND_SOC_DAIFMT_MASTER_MASK) { 300 case SND_SOC_DAIFMT_CBM_CFM: 301 cs42l51->func = MODE_MASTER; 302 break; 303 case SND_SOC_DAIFMT_CBS_CFS: 304 cs42l51->func = MODE_SLAVE_AUTO; 305 break; 306 default: 307 dev_err(codec->dev, "Unknown master/slave configuration\n"); 308 return -EINVAL; 309 } 310 311 return 0; 312 } 313 314 struct cs42l51_ratios { 315 unsigned int ratio; 316 unsigned char speed_mode; 317 unsigned char mclk; 318 }; 319 320 static struct cs42l51_ratios slave_ratios[] = { 321 { 512, CS42L51_QSM_MODE, 0 }, { 768, CS42L51_QSM_MODE, 0 }, 322 { 1024, CS42L51_QSM_MODE, 0 }, { 1536, CS42L51_QSM_MODE, 0 }, 323 { 2048, CS42L51_QSM_MODE, 0 }, { 3072, CS42L51_QSM_MODE, 0 }, 324 { 256, CS42L51_HSM_MODE, 0 }, { 384, CS42L51_HSM_MODE, 0 }, 325 { 512, CS42L51_HSM_MODE, 0 }, { 768, CS42L51_HSM_MODE, 0 }, 326 { 1024, CS42L51_HSM_MODE, 0 }, { 1536, CS42L51_HSM_MODE, 0 }, 327 { 128, CS42L51_SSM_MODE, 0 }, { 192, CS42L51_SSM_MODE, 0 }, 328 { 256, CS42L51_SSM_MODE, 0 }, { 384, CS42L51_SSM_MODE, 0 }, 329 { 512, CS42L51_SSM_MODE, 0 }, { 768, CS42L51_SSM_MODE, 0 }, 330 { 128, CS42L51_DSM_MODE, 0 }, { 192, CS42L51_DSM_MODE, 0 }, 331 { 256, CS42L51_DSM_MODE, 0 }, { 384, CS42L51_DSM_MODE, 0 }, 332 }; 333 334 static struct cs42l51_ratios slave_auto_ratios[] = { 335 { 1024, CS42L51_QSM_MODE, 0 }, { 1536, CS42L51_QSM_MODE, 0 }, 336 { 2048, CS42L51_QSM_MODE, 1 }, { 3072, CS42L51_QSM_MODE, 1 }, 337 { 512, CS42L51_HSM_MODE, 0 }, { 768, CS42L51_HSM_MODE, 0 }, 338 { 1024, CS42L51_HSM_MODE, 1 }, { 1536, CS42L51_HSM_MODE, 1 }, 339 { 256, CS42L51_SSM_MODE, 0 }, { 384, CS42L51_SSM_MODE, 0 }, 340 { 512, CS42L51_SSM_MODE, 1 }, { 768, CS42L51_SSM_MODE, 1 }, 341 { 128, CS42L51_DSM_MODE, 0 }, { 192, CS42L51_DSM_MODE, 0 }, 342 { 256, CS42L51_DSM_MODE, 1 }, { 384, CS42L51_DSM_MODE, 1 }, 343 }; 344 345 static int cs42l51_set_dai_sysclk(struct snd_soc_dai *codec_dai, 346 int clk_id, unsigned int freq, int dir) 347 { 348 struct snd_soc_codec *codec = codec_dai->codec; 349 struct cs42l51_private *cs42l51 = snd_soc_codec_get_drvdata(codec); 350 351 cs42l51->mclk = freq; 352 return 0; 353 } 354 355 static int cs42l51_hw_params(struct snd_pcm_substream *substream, 356 struct snd_pcm_hw_params *params, 357 struct snd_soc_dai *dai) 358 { 359 struct snd_soc_codec *codec = dai->codec; 360 struct cs42l51_private *cs42l51 = snd_soc_codec_get_drvdata(codec); 361 int ret; 362 unsigned int i; 363 unsigned int rate; 364 unsigned int ratio; 365 struct cs42l51_ratios *ratios = NULL; 366 int nr_ratios = 0; 367 int intf_ctl, power_ctl, fmt; 368 369 switch (cs42l51->func) { 370 case MODE_MASTER: 371 return -EINVAL; 372 case MODE_SLAVE: 373 ratios = slave_ratios; 374 nr_ratios = ARRAY_SIZE(slave_ratios); 375 break; 376 case MODE_SLAVE_AUTO: 377 ratios = slave_auto_ratios; 378 nr_ratios = ARRAY_SIZE(slave_auto_ratios); 379 break; 380 } 381 382 /* Figure out which MCLK/LRCK ratio to use */ 383 rate = params_rate(params); /* Sampling rate, in Hz */ 384 ratio = cs42l51->mclk / rate; /* MCLK/LRCK ratio */ 385 for (i = 0; i < nr_ratios; i++) { 386 if (ratios[i].ratio == ratio) 387 break; 388 } 389 390 if (i == nr_ratios) { 391 /* We did not find a matching ratio */ 392 dev_err(codec->dev, "could not find matching ratio\n"); 393 return -EINVAL; 394 } 395 396 intf_ctl = snd_soc_read(codec, CS42L51_INTF_CTL); 397 power_ctl = snd_soc_read(codec, CS42L51_MIC_POWER_CTL); 398 399 intf_ctl &= ~(CS42L51_INTF_CTL_MASTER | CS42L51_INTF_CTL_ADC_I2S 400 | CS42L51_INTF_CTL_DAC_FORMAT(7)); 401 power_ctl &= ~(CS42L51_MIC_POWER_CTL_SPEED(3) 402 | CS42L51_MIC_POWER_CTL_MCLK_DIV2); 403 404 switch (cs42l51->func) { 405 case MODE_MASTER: 406 intf_ctl |= CS42L51_INTF_CTL_MASTER; 407 power_ctl |= CS42L51_MIC_POWER_CTL_SPEED(ratios[i].speed_mode); 408 break; 409 case MODE_SLAVE: 410 power_ctl |= CS42L51_MIC_POWER_CTL_SPEED(ratios[i].speed_mode); 411 break; 412 case MODE_SLAVE_AUTO: 413 power_ctl |= CS42L51_MIC_POWER_CTL_AUTO; 414 break; 415 } 416 417 switch (cs42l51->audio_mode) { 418 case SND_SOC_DAIFMT_I2S: 419 intf_ctl |= CS42L51_INTF_CTL_ADC_I2S; 420 intf_ctl |= CS42L51_INTF_CTL_DAC_FORMAT(CS42L51_DAC_DIF_I2S); 421 break; 422 case SND_SOC_DAIFMT_LEFT_J: 423 intf_ctl |= CS42L51_INTF_CTL_DAC_FORMAT(CS42L51_DAC_DIF_LJ24); 424 break; 425 case SND_SOC_DAIFMT_RIGHT_J: 426 switch (params_format(params)) { 427 case SNDRV_PCM_FORMAT_S16_LE: 428 case SNDRV_PCM_FORMAT_S16_BE: 429 fmt = CS42L51_DAC_DIF_RJ16; 430 break; 431 case SNDRV_PCM_FORMAT_S18_3LE: 432 case SNDRV_PCM_FORMAT_S18_3BE: 433 fmt = CS42L51_DAC_DIF_RJ18; 434 break; 435 case SNDRV_PCM_FORMAT_S20_3LE: 436 case SNDRV_PCM_FORMAT_S20_3BE: 437 fmt = CS42L51_DAC_DIF_RJ20; 438 break; 439 case SNDRV_PCM_FORMAT_S24_LE: 440 case SNDRV_PCM_FORMAT_S24_BE: 441 fmt = CS42L51_DAC_DIF_RJ24; 442 break; 443 default: 444 dev_err(codec->dev, "unknown format\n"); 445 return -EINVAL; 446 } 447 intf_ctl |= CS42L51_INTF_CTL_DAC_FORMAT(fmt); 448 break; 449 default: 450 dev_err(codec->dev, "unknown format\n"); 451 return -EINVAL; 452 } 453 454 if (ratios[i].mclk) 455 power_ctl |= CS42L51_MIC_POWER_CTL_MCLK_DIV2; 456 457 ret = snd_soc_write(codec, CS42L51_INTF_CTL, intf_ctl); 458 if (ret < 0) 459 return ret; 460 461 ret = snd_soc_write(codec, CS42L51_MIC_POWER_CTL, power_ctl); 462 if (ret < 0) 463 return ret; 464 465 return 0; 466 } 467 468 static int cs42l51_dai_mute(struct snd_soc_dai *dai, int mute) 469 { 470 struct snd_soc_codec *codec = dai->codec; 471 int reg; 472 int mask = CS42L51_DAC_OUT_CTL_DACA_MUTE|CS42L51_DAC_OUT_CTL_DACB_MUTE; 473 474 reg = snd_soc_read(codec, CS42L51_DAC_OUT_CTL); 475 476 if (mute) 477 reg |= mask; 478 else 479 reg &= ~mask; 480 481 return snd_soc_write(codec, CS42L51_DAC_OUT_CTL, reg); 482 } 483 484 static const struct snd_soc_dai_ops cs42l51_dai_ops = { 485 .hw_params = cs42l51_hw_params, 486 .set_sysclk = cs42l51_set_dai_sysclk, 487 .set_fmt = cs42l51_set_dai_fmt, 488 .digital_mute = cs42l51_dai_mute, 489 }; 490 491 static struct snd_soc_dai_driver cs42l51_dai = { 492 .name = "cs42l51-hifi", 493 .playback = { 494 .stream_name = "Playback", 495 .channels_min = 1, 496 .channels_max = 2, 497 .rates = SNDRV_PCM_RATE_8000_96000, 498 .formats = CS42L51_FORMATS, 499 }, 500 .capture = { 501 .stream_name = "Capture", 502 .channels_min = 1, 503 .channels_max = 2, 504 .rates = SNDRV_PCM_RATE_8000_96000, 505 .formats = CS42L51_FORMATS, 506 }, 507 .ops = &cs42l51_dai_ops, 508 }; 509 510 static int cs42l51_probe(struct snd_soc_codec *codec) 511 { 512 struct cs42l51_private *cs42l51 = snd_soc_codec_get_drvdata(codec); 513 int ret, reg; 514 515 ret = cs42l51_fill_cache(codec); 516 if (ret < 0) { 517 dev_err(codec->dev, "failed to fill register cache\n"); 518 return ret; 519 } 520 521 ret = snd_soc_codec_set_cache_io(codec, 8, 8, cs42l51->control_type); 522 if (ret < 0) { 523 dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); 524 return ret; 525 } 526 527 /* 528 * DAC configuration 529 * - Use signal processor 530 * - auto mute 531 * - vol changes immediate 532 * - no de-emphasize 533 */ 534 reg = CS42L51_DAC_CTL_DATA_SEL(1) 535 | CS42L51_DAC_CTL_AMUTE | CS42L51_DAC_CTL_DACSZ(0); 536 ret = snd_soc_write(codec, CS42L51_DAC_CTL, reg); 537 if (ret < 0) 538 return ret; 539 540 return 0; 541 } 542 543 static struct snd_soc_codec_driver soc_codec_device_cs42l51 = { 544 .probe = cs42l51_probe, 545 .reg_cache_size = CS42L51_NUMREGS + 1, 546 .reg_word_size = sizeof(u8), 547 548 .controls = cs42l51_snd_controls, 549 .num_controls = ARRAY_SIZE(cs42l51_snd_controls), 550 .dapm_widgets = cs42l51_dapm_widgets, 551 .num_dapm_widgets = ARRAY_SIZE(cs42l51_dapm_widgets), 552 .dapm_routes = cs42l51_routes, 553 .num_dapm_routes = ARRAY_SIZE(cs42l51_routes), 554 }; 555 556 static int cs42l51_i2c_probe(struct i2c_client *i2c_client, 557 const struct i2c_device_id *id) 558 { 559 struct cs42l51_private *cs42l51; 560 int ret; 561 562 /* Verify that we have a CS42L51 */ 563 ret = i2c_smbus_read_byte_data(i2c_client, CS42L51_CHIP_REV_ID); 564 if (ret < 0) { 565 dev_err(&i2c_client->dev, "failed to read I2C\n"); 566 goto error; 567 } 568 569 if ((ret != CS42L51_MK_CHIP_REV(CS42L51_CHIP_ID, CS42L51_CHIP_REV_A)) && 570 (ret != CS42L51_MK_CHIP_REV(CS42L51_CHIP_ID, CS42L51_CHIP_REV_B))) { 571 dev_err(&i2c_client->dev, "Invalid chip id\n"); 572 ret = -ENODEV; 573 goto error; 574 } 575 576 dev_info(&i2c_client->dev, "found device cs42l51 rev %d\n", 577 ret & 7); 578 579 cs42l51 = devm_kzalloc(&i2c_client->dev, sizeof(struct cs42l51_private), 580 GFP_KERNEL); 581 if (!cs42l51) { 582 dev_err(&i2c_client->dev, "could not allocate codec\n"); 583 return -ENOMEM; 584 } 585 586 i2c_set_clientdata(i2c_client, cs42l51); 587 cs42l51->control_type = SND_SOC_I2C; 588 589 ret = snd_soc_register_codec(&i2c_client->dev, 590 &soc_codec_device_cs42l51, &cs42l51_dai, 1); 591 error: 592 return ret; 593 } 594 595 static int cs42l51_i2c_remove(struct i2c_client *client) 596 { 597 snd_soc_unregister_codec(&client->dev); 598 return 0; 599 } 600 601 static const struct i2c_device_id cs42l51_id[] = { 602 {"cs42l51", 0}, 603 {} 604 }; 605 MODULE_DEVICE_TABLE(i2c, cs42l51_id); 606 607 static struct i2c_driver cs42l51_i2c_driver = { 608 .driver = { 609 .name = "cs42l51-codec", 610 .owner = THIS_MODULE, 611 }, 612 .id_table = cs42l51_id, 613 .probe = cs42l51_i2c_probe, 614 .remove = cs42l51_i2c_remove, 615 }; 616 617 static int __init cs42l51_init(void) 618 { 619 int ret; 620 621 ret = i2c_add_driver(&cs42l51_i2c_driver); 622 if (ret != 0) { 623 printk(KERN_ERR "%s: can't add i2c driver\n", __func__); 624 return ret; 625 } 626 return 0; 627 } 628 module_init(cs42l51_init); 629 630 static void __exit cs42l51_exit(void) 631 { 632 i2c_del_driver(&cs42l51_i2c_driver); 633 } 634 module_exit(cs42l51_exit); 635 636 MODULE_AUTHOR("Arnaud Patard <arnaud.patard@rtp-net.org>"); 637 MODULE_DESCRIPTION("Cirrus Logic CS42L51 ALSA SoC Codec Driver"); 638 MODULE_LICENSE("GPL"); 639