1 /* 2 * File: sound/soc/codecs/ssm2602.c 3 * Author: Cliff Cai <Cliff.Cai@analog.com> 4 * 5 * Created: Tue June 06 2008 6 * Description: Driver for ssm2602 sound chip 7 * 8 * Modified: 9 * Copyright 2008 Analog Devices Inc. 10 * 11 * Bugs: Enter bugs at http://blackfin.uclinux.org/ 12 * 13 * This program is free software; you can redistribute it and/or modify 14 * it under the terms of the GNU General Public License as published by 15 * the Free Software Foundation; either version 2 of the License, or 16 * (at your option) any later version. 17 * 18 * This program is distributed in the hope that it will be useful, 19 * but WITHOUT ANY WARRANTY; without even the implied warranty of 20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 21 * GNU General Public License for more details. 22 * 23 * You should have received a copy of the GNU General Public License 24 * along with this program; if not, see the file COPYING, or write 25 * to the Free Software Foundation, Inc., 26 * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 27 */ 28 29 #include <linux/module.h> 30 #include <linux/moduleparam.h> 31 #include <linux/init.h> 32 #include <linux/delay.h> 33 #include <linux/pm.h> 34 #include <linux/i2c.h> 35 #include <linux/platform_device.h> 36 #include <sound/core.h> 37 #include <sound/pcm.h> 38 #include <sound/pcm_params.h> 39 #include <sound/soc.h> 40 #include <sound/soc-dapm.h> 41 #include <sound/initval.h> 42 43 #include "ssm2602.h" 44 45 #define SSM2602_VERSION "0.1" 46 47 struct snd_soc_codec_device soc_codec_dev_ssm2602; 48 49 /* codec private data */ 50 struct ssm2602_priv { 51 unsigned int sysclk; 52 struct snd_pcm_substream *master_substream; 53 struct snd_pcm_substream *slave_substream; 54 }; 55 56 /* 57 * ssm2602 register cache 58 * We can't read the ssm2602 register space when we are 59 * using 2 wire for device control, so we cache them instead. 60 * There is no point in caching the reset register 61 */ 62 static const u16 ssm2602_reg[SSM2602_CACHEREGNUM] = { 63 0x0017, 0x0017, 0x0079, 0x0079, 64 0x0000, 0x0000, 0x0000, 0x000a, 65 0x0000, 0x0000 66 }; 67 68 /* 69 * read ssm2602 register cache 70 */ 71 static inline unsigned int ssm2602_read_reg_cache(struct snd_soc_codec *codec, 72 unsigned int reg) 73 { 74 u16 *cache = codec->reg_cache; 75 if (reg == SSM2602_RESET) 76 return 0; 77 if (reg >= SSM2602_CACHEREGNUM) 78 return -1; 79 return cache[reg]; 80 } 81 82 /* 83 * write ssm2602 register cache 84 */ 85 static inline void ssm2602_write_reg_cache(struct snd_soc_codec *codec, 86 u16 reg, unsigned int value) 87 { 88 u16 *cache = codec->reg_cache; 89 if (reg >= SSM2602_CACHEREGNUM) 90 return; 91 cache[reg] = value; 92 } 93 94 /* 95 * write to the ssm2602 register space 96 */ 97 static int ssm2602_write(struct snd_soc_codec *codec, unsigned int reg, 98 unsigned int value) 99 { 100 u8 data[2]; 101 102 /* data is 103 * D15..D9 ssm2602 register offset 104 * D8...D0 register data 105 */ 106 data[0] = (reg << 1) | ((value >> 8) & 0x0001); 107 data[1] = value & 0x00ff; 108 109 ssm2602_write_reg_cache(codec, reg, value); 110 if (codec->hw_write(codec->control_data, data, 2) == 2) 111 return 0; 112 else 113 return -EIO; 114 } 115 116 #define ssm2602_reset(c) ssm2602_write(c, SSM2602_RESET, 0) 117 118 /*Appending several "None"s just for OSS mixer use*/ 119 static const char *ssm2602_input_select[] = { 120 "Line", "Mic", "None", "None", "None", 121 "None", "None", "None", 122 }; 123 124 static const char *ssm2602_deemph[] = {"None", "32Khz", "44.1Khz", "48Khz"}; 125 126 static const struct soc_enum ssm2602_enum[] = { 127 SOC_ENUM_SINGLE(SSM2602_APANA, 2, 2, ssm2602_input_select), 128 SOC_ENUM_SINGLE(SSM2602_APDIGI, 1, 4, ssm2602_deemph), 129 }; 130 131 static const struct snd_kcontrol_new ssm2602_snd_controls[] = { 132 133 SOC_DOUBLE_R("Master Playback Volume", SSM2602_LOUT1V, SSM2602_ROUT1V, 134 0, 127, 0), 135 SOC_DOUBLE_R("Master Playback ZC Switch", SSM2602_LOUT1V, SSM2602_ROUT1V, 136 7, 1, 0), 137 138 SOC_DOUBLE_R("Capture Volume", SSM2602_LINVOL, SSM2602_RINVOL, 0, 31, 0), 139 SOC_DOUBLE_R("Capture Switch", SSM2602_LINVOL, SSM2602_RINVOL, 7, 1, 1), 140 141 SOC_SINGLE("Mic Boost (+20dB)", SSM2602_APANA, 0, 1, 0), 142 SOC_SINGLE("Mic Switch", SSM2602_APANA, 1, 1, 1), 143 144 SOC_SINGLE("Sidetone Playback Volume", SSM2602_APANA, 6, 3, 1), 145 146 SOC_SINGLE("ADC High Pass Filter Switch", SSM2602_APDIGI, 0, 1, 1), 147 SOC_SINGLE("Store DC Offset Switch", SSM2602_APDIGI, 4, 1, 0), 148 149 SOC_ENUM("Capture Source", ssm2602_enum[0]), 150 151 SOC_ENUM("Playback De-emphasis", ssm2602_enum[1]), 152 }; 153 154 /* Output Mixer */ 155 static const struct snd_kcontrol_new ssm2602_output_mixer_controls[] = { 156 SOC_DAPM_SINGLE("Line Bypass Switch", SSM2602_APANA, 3, 1, 0), 157 SOC_DAPM_SINGLE("Mic Sidetone Switch", SSM2602_APANA, 5, 1, 0), 158 SOC_DAPM_SINGLE("HiFi Playback Switch", SSM2602_APANA, 4, 1, 0), 159 }; 160 161 /* Input mux */ 162 static const struct snd_kcontrol_new ssm2602_input_mux_controls = 163 SOC_DAPM_ENUM("Input Select", ssm2602_enum[0]); 164 165 static const struct snd_soc_dapm_widget ssm2602_dapm_widgets[] = { 166 SND_SOC_DAPM_MIXER("Output Mixer", SSM2602_PWR, 4, 1, 167 &ssm2602_output_mixer_controls[0], 168 ARRAY_SIZE(ssm2602_output_mixer_controls)), 169 SND_SOC_DAPM_DAC("DAC", "HiFi Playback", SSM2602_PWR, 3, 1), 170 SND_SOC_DAPM_OUTPUT("LOUT"), 171 SND_SOC_DAPM_OUTPUT("LHPOUT"), 172 SND_SOC_DAPM_OUTPUT("ROUT"), 173 SND_SOC_DAPM_OUTPUT("RHPOUT"), 174 SND_SOC_DAPM_ADC("ADC", "HiFi Capture", SSM2602_PWR, 2, 1), 175 SND_SOC_DAPM_MUX("Input Mux", SND_SOC_NOPM, 0, 0, &ssm2602_input_mux_controls), 176 SND_SOC_DAPM_PGA("Line Input", SSM2602_PWR, 0, 1, NULL, 0), 177 SND_SOC_DAPM_MICBIAS("Mic Bias", SSM2602_PWR, 1, 1), 178 SND_SOC_DAPM_INPUT("MICIN"), 179 SND_SOC_DAPM_INPUT("RLINEIN"), 180 SND_SOC_DAPM_INPUT("LLINEIN"), 181 }; 182 183 static const struct snd_soc_dapm_route audio_conn[] = { 184 /* output mixer */ 185 {"Output Mixer", "Line Bypass Switch", "Line Input"}, 186 {"Output Mixer", "HiFi Playback Switch", "DAC"}, 187 {"Output Mixer", "Mic Sidetone Switch", "Mic Bias"}, 188 189 /* outputs */ 190 {"RHPOUT", NULL, "Output Mixer"}, 191 {"ROUT", NULL, "Output Mixer"}, 192 {"LHPOUT", NULL, "Output Mixer"}, 193 {"LOUT", NULL, "Output Mixer"}, 194 195 /* input mux */ 196 {"Input Mux", "Line", "Line Input"}, 197 {"Input Mux", "Mic", "Mic Bias"}, 198 {"ADC", NULL, "Input Mux"}, 199 200 /* inputs */ 201 {"Line Input", NULL, "LLINEIN"}, 202 {"Line Input", NULL, "RLINEIN"}, 203 {"Mic Bias", NULL, "MICIN"}, 204 }; 205 206 static int ssm2602_add_widgets(struct snd_soc_codec *codec) 207 { 208 snd_soc_dapm_new_controls(codec, ssm2602_dapm_widgets, 209 ARRAY_SIZE(ssm2602_dapm_widgets)); 210 211 snd_soc_dapm_add_routes(codec, audio_conn, ARRAY_SIZE(audio_conn)); 212 213 snd_soc_dapm_new_widgets(codec); 214 return 0; 215 } 216 217 struct _coeff_div { 218 u32 mclk; 219 u32 rate; 220 u16 fs; 221 u8 sr:4; 222 u8 bosr:1; 223 u8 usb:1; 224 }; 225 226 /* codec mclk clock divider coefficients */ 227 static const struct _coeff_div coeff_div[] = { 228 /* 48k */ 229 {12288000, 48000, 256, 0x0, 0x0, 0x0}, 230 {18432000, 48000, 384, 0x0, 0x1, 0x0}, 231 {12000000, 48000, 250, 0x0, 0x0, 0x1}, 232 233 /* 32k */ 234 {12288000, 32000, 384, 0x6, 0x0, 0x0}, 235 {18432000, 32000, 576, 0x6, 0x1, 0x0}, 236 {12000000, 32000, 375, 0x6, 0x0, 0x1}, 237 238 /* 8k */ 239 {12288000, 8000, 1536, 0x3, 0x0, 0x0}, 240 {18432000, 8000, 2304, 0x3, 0x1, 0x0}, 241 {11289600, 8000, 1408, 0xb, 0x0, 0x0}, 242 {16934400, 8000, 2112, 0xb, 0x1, 0x0}, 243 {12000000, 8000, 1500, 0x3, 0x0, 0x1}, 244 245 /* 96k */ 246 {12288000, 96000, 128, 0x7, 0x0, 0x0}, 247 {18432000, 96000, 192, 0x7, 0x1, 0x0}, 248 {12000000, 96000, 125, 0x7, 0x0, 0x1}, 249 250 /* 44.1k */ 251 {11289600, 44100, 256, 0x8, 0x0, 0x0}, 252 {16934400, 44100, 384, 0x8, 0x1, 0x0}, 253 {12000000, 44100, 272, 0x8, 0x1, 0x1}, 254 255 /* 88.2k */ 256 {11289600, 88200, 128, 0xf, 0x0, 0x0}, 257 {16934400, 88200, 192, 0xf, 0x1, 0x0}, 258 {12000000, 88200, 136, 0xf, 0x1, 0x1}, 259 }; 260 261 static inline int get_coeff(int mclk, int rate) 262 { 263 int i; 264 265 for (i = 0; i < ARRAY_SIZE(coeff_div); i++) { 266 if (coeff_div[i].rate == rate && coeff_div[i].mclk == mclk) 267 return i; 268 } 269 return i; 270 } 271 272 static int ssm2602_hw_params(struct snd_pcm_substream *substream, 273 struct snd_pcm_hw_params *params, 274 struct snd_soc_dai *dai) 275 { 276 u16 srate; 277 struct snd_soc_pcm_runtime *rtd = substream->private_data; 278 struct snd_soc_device *socdev = rtd->socdev; 279 struct snd_soc_codec *codec = socdev->card->codec; 280 struct ssm2602_priv *ssm2602 = codec->private_data; 281 struct i2c_client *i2c = codec->control_data; 282 u16 iface = ssm2602_read_reg_cache(codec, SSM2602_IFACE) & 0xfff3; 283 int i = get_coeff(ssm2602->sysclk, params_rate(params)); 284 285 if (substream == ssm2602->slave_substream) { 286 dev_dbg(&i2c->dev, "Ignoring hw_params for slave substream\n"); 287 return 0; 288 } 289 290 /*no match is found*/ 291 if (i == ARRAY_SIZE(coeff_div)) 292 return -EINVAL; 293 294 srate = (coeff_div[i].sr << 2) | 295 (coeff_div[i].bosr << 1) | coeff_div[i].usb; 296 297 ssm2602_write(codec, SSM2602_ACTIVE, 0); 298 ssm2602_write(codec, SSM2602_SRATE, srate); 299 300 /* bit size */ 301 switch (params_format(params)) { 302 case SNDRV_PCM_FORMAT_S16_LE: 303 break; 304 case SNDRV_PCM_FORMAT_S20_3LE: 305 iface |= 0x0004; 306 break; 307 case SNDRV_PCM_FORMAT_S24_LE: 308 iface |= 0x0008; 309 break; 310 case SNDRV_PCM_FORMAT_S32_LE: 311 iface |= 0x000c; 312 break; 313 } 314 ssm2602_write(codec, SSM2602_IFACE, iface); 315 ssm2602_write(codec, SSM2602_ACTIVE, ACTIVE_ACTIVATE_CODEC); 316 return 0; 317 } 318 319 static int ssm2602_startup(struct snd_pcm_substream *substream, 320 struct snd_soc_dai *dai) 321 { 322 struct snd_soc_pcm_runtime *rtd = substream->private_data; 323 struct snd_soc_device *socdev = rtd->socdev; 324 struct snd_soc_codec *codec = socdev->card->codec; 325 struct ssm2602_priv *ssm2602 = codec->private_data; 326 struct i2c_client *i2c = codec->control_data; 327 struct snd_pcm_runtime *master_runtime; 328 329 /* The DAI has shared clocks so if we already have a playback or 330 * capture going then constrain this substream to match it. 331 * TODO: the ssm2602 allows pairs of non-matching PB/REC rates 332 */ 333 if (ssm2602->master_substream) { 334 master_runtime = ssm2602->master_substream->runtime; 335 dev_dbg(&i2c->dev, "Constraining to %d bits at %dHz\n", 336 master_runtime->sample_bits, 337 master_runtime->rate); 338 339 if (master_runtime->rate != 0) 340 snd_pcm_hw_constraint_minmax(substream->runtime, 341 SNDRV_PCM_HW_PARAM_RATE, 342 master_runtime->rate, 343 master_runtime->rate); 344 345 if (master_runtime->sample_bits != 0) 346 snd_pcm_hw_constraint_minmax(substream->runtime, 347 SNDRV_PCM_HW_PARAM_SAMPLE_BITS, 348 master_runtime->sample_bits, 349 master_runtime->sample_bits); 350 351 ssm2602->slave_substream = substream; 352 } else 353 ssm2602->master_substream = substream; 354 355 return 0; 356 } 357 358 static int ssm2602_pcm_prepare(struct snd_pcm_substream *substream, 359 struct snd_soc_dai *dai) 360 { 361 struct snd_soc_pcm_runtime *rtd = substream->private_data; 362 struct snd_soc_device *socdev = rtd->socdev; 363 struct snd_soc_codec *codec = socdev->card->codec; 364 /* set active */ 365 ssm2602_write(codec, SSM2602_ACTIVE, ACTIVE_ACTIVATE_CODEC); 366 367 return 0; 368 } 369 370 static void ssm2602_shutdown(struct snd_pcm_substream *substream, 371 struct snd_soc_dai *dai) 372 { 373 struct snd_soc_pcm_runtime *rtd = substream->private_data; 374 struct snd_soc_device *socdev = rtd->socdev; 375 struct snd_soc_codec *codec = socdev->card->codec; 376 struct ssm2602_priv *ssm2602 = codec->private_data; 377 378 /* deactivate */ 379 if (!codec->active) 380 ssm2602_write(codec, SSM2602_ACTIVE, 0); 381 382 if (ssm2602->master_substream == substream) 383 ssm2602->master_substream = ssm2602->slave_substream; 384 385 ssm2602->slave_substream = NULL; 386 } 387 388 static int ssm2602_mute(struct snd_soc_dai *dai, int mute) 389 { 390 struct snd_soc_codec *codec = dai->codec; 391 u16 mute_reg = ssm2602_read_reg_cache(codec, SSM2602_APDIGI) & ~APDIGI_ENABLE_DAC_MUTE; 392 if (mute) 393 ssm2602_write(codec, SSM2602_APDIGI, 394 mute_reg | APDIGI_ENABLE_DAC_MUTE); 395 else 396 ssm2602_write(codec, SSM2602_APDIGI, mute_reg); 397 return 0; 398 } 399 400 static int ssm2602_set_dai_sysclk(struct snd_soc_dai *codec_dai, 401 int clk_id, unsigned int freq, int dir) 402 { 403 struct snd_soc_codec *codec = codec_dai->codec; 404 struct ssm2602_priv *ssm2602 = codec->private_data; 405 switch (freq) { 406 case 11289600: 407 case 12000000: 408 case 12288000: 409 case 16934400: 410 case 18432000: 411 ssm2602->sysclk = freq; 412 return 0; 413 } 414 return -EINVAL; 415 } 416 417 static int ssm2602_set_dai_fmt(struct snd_soc_dai *codec_dai, 418 unsigned int fmt) 419 { 420 struct snd_soc_codec *codec = codec_dai->codec; 421 u16 iface = 0; 422 423 /* set master/slave audio interface */ 424 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { 425 case SND_SOC_DAIFMT_CBM_CFM: 426 iface |= 0x0040; 427 break; 428 case SND_SOC_DAIFMT_CBS_CFS: 429 break; 430 default: 431 return -EINVAL; 432 } 433 434 /* interface format */ 435 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { 436 case SND_SOC_DAIFMT_I2S: 437 iface |= 0x0002; 438 break; 439 case SND_SOC_DAIFMT_RIGHT_J: 440 break; 441 case SND_SOC_DAIFMT_LEFT_J: 442 iface |= 0x0001; 443 break; 444 case SND_SOC_DAIFMT_DSP_A: 445 iface |= 0x0013; 446 break; 447 case SND_SOC_DAIFMT_DSP_B: 448 iface |= 0x0003; 449 break; 450 default: 451 return -EINVAL; 452 } 453 454 /* clock inversion */ 455 switch (fmt & SND_SOC_DAIFMT_INV_MASK) { 456 case SND_SOC_DAIFMT_NB_NF: 457 break; 458 case SND_SOC_DAIFMT_IB_IF: 459 iface |= 0x0090; 460 break; 461 case SND_SOC_DAIFMT_IB_NF: 462 iface |= 0x0080; 463 break; 464 case SND_SOC_DAIFMT_NB_IF: 465 iface |= 0x0010; 466 break; 467 default: 468 return -EINVAL; 469 } 470 471 /* set iface */ 472 ssm2602_write(codec, SSM2602_IFACE, iface); 473 return 0; 474 } 475 476 static int ssm2602_set_bias_level(struct snd_soc_codec *codec, 477 enum snd_soc_bias_level level) 478 { 479 u16 reg = ssm2602_read_reg_cache(codec, SSM2602_PWR) & 0xff7f; 480 481 switch (level) { 482 case SND_SOC_BIAS_ON: 483 /* vref/mid, osc on, dac unmute */ 484 ssm2602_write(codec, SSM2602_PWR, reg); 485 break; 486 case SND_SOC_BIAS_PREPARE: 487 break; 488 case SND_SOC_BIAS_STANDBY: 489 /* everything off except vref/vmid, */ 490 ssm2602_write(codec, SSM2602_PWR, reg | PWR_CLK_OUT_PDN); 491 break; 492 case SND_SOC_BIAS_OFF: 493 /* everything off, dac mute, inactive */ 494 ssm2602_write(codec, SSM2602_ACTIVE, 0); 495 ssm2602_write(codec, SSM2602_PWR, 0xffff); 496 break; 497 498 } 499 codec->bias_level = level; 500 return 0; 501 } 502 503 #define SSM2602_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_32000 |\ 504 SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |\ 505 SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000) 506 507 #define SSM2602_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\ 508 SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE) 509 510 static struct snd_soc_dai_ops ssm2602_dai_ops = { 511 .startup = ssm2602_startup, 512 .prepare = ssm2602_pcm_prepare, 513 .hw_params = ssm2602_hw_params, 514 .shutdown = ssm2602_shutdown, 515 .digital_mute = ssm2602_mute, 516 .set_sysclk = ssm2602_set_dai_sysclk, 517 .set_fmt = ssm2602_set_dai_fmt, 518 }; 519 520 struct snd_soc_dai ssm2602_dai = { 521 .name = "SSM2602", 522 .playback = { 523 .stream_name = "Playback", 524 .channels_min = 2, 525 .channels_max = 2, 526 .rates = SSM2602_RATES, 527 .formats = SSM2602_FORMATS,}, 528 .capture = { 529 .stream_name = "Capture", 530 .channels_min = 2, 531 .channels_max = 2, 532 .rates = SSM2602_RATES, 533 .formats = SSM2602_FORMATS,}, 534 .ops = &ssm2602_dai_ops, 535 }; 536 EXPORT_SYMBOL_GPL(ssm2602_dai); 537 538 static int ssm2602_suspend(struct platform_device *pdev, pm_message_t state) 539 { 540 struct snd_soc_device *socdev = platform_get_drvdata(pdev); 541 struct snd_soc_codec *codec = socdev->card->codec; 542 543 ssm2602_set_bias_level(codec, SND_SOC_BIAS_OFF); 544 return 0; 545 } 546 547 static int ssm2602_resume(struct platform_device *pdev) 548 { 549 struct snd_soc_device *socdev = platform_get_drvdata(pdev); 550 struct snd_soc_codec *codec = socdev->card->codec; 551 int i; 552 u8 data[2]; 553 u16 *cache = codec->reg_cache; 554 555 /* Sync reg_cache with the hardware */ 556 for (i = 0; i < ARRAY_SIZE(ssm2602_reg); i++) { 557 data[0] = (i << 1) | ((cache[i] >> 8) & 0x0001); 558 data[1] = cache[i] & 0x00ff; 559 codec->hw_write(codec->control_data, data, 2); 560 } 561 ssm2602_set_bias_level(codec, SND_SOC_BIAS_STANDBY); 562 ssm2602_set_bias_level(codec, codec->suspend_bias_level); 563 return 0; 564 } 565 566 /* 567 * initialise the ssm2602 driver 568 * register the mixer and dsp interfaces with the kernel 569 */ 570 static int ssm2602_init(struct snd_soc_device *socdev) 571 { 572 struct snd_soc_codec *codec = socdev->card->codec; 573 int reg, ret = 0; 574 575 codec->name = "SSM2602"; 576 codec->owner = THIS_MODULE; 577 codec->read = ssm2602_read_reg_cache; 578 codec->write = ssm2602_write; 579 codec->set_bias_level = ssm2602_set_bias_level; 580 codec->dai = &ssm2602_dai; 581 codec->num_dai = 1; 582 codec->reg_cache_size = sizeof(ssm2602_reg); 583 codec->reg_cache = kmemdup(ssm2602_reg, sizeof(ssm2602_reg), 584 GFP_KERNEL); 585 if (codec->reg_cache == NULL) 586 return -ENOMEM; 587 588 ssm2602_reset(codec); 589 590 /* register pcms */ 591 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); 592 if (ret < 0) { 593 pr_err("ssm2602: failed to create pcms\n"); 594 goto pcm_err; 595 } 596 /*power on device*/ 597 ssm2602_write(codec, SSM2602_ACTIVE, 0); 598 /* set the update bits */ 599 reg = ssm2602_read_reg_cache(codec, SSM2602_LINVOL); 600 ssm2602_write(codec, SSM2602_LINVOL, reg | LINVOL_LRIN_BOTH); 601 reg = ssm2602_read_reg_cache(codec, SSM2602_RINVOL); 602 ssm2602_write(codec, SSM2602_RINVOL, reg | RINVOL_RLIN_BOTH); 603 reg = ssm2602_read_reg_cache(codec, SSM2602_LOUT1V); 604 ssm2602_write(codec, SSM2602_LOUT1V, reg | LOUT1V_LRHP_BOTH); 605 reg = ssm2602_read_reg_cache(codec, SSM2602_ROUT1V); 606 ssm2602_write(codec, SSM2602_ROUT1V, reg | ROUT1V_RLHP_BOTH); 607 /*select Line in as default input*/ 608 ssm2602_write(codec, SSM2602_APANA, 609 APANA_ENABLE_MIC_BOOST2 | APANA_SELECT_DAC | 610 APANA_ENABLE_MIC_BOOST); 611 ssm2602_write(codec, SSM2602_PWR, 0); 612 613 snd_soc_add_controls(codec, ssm2602_snd_controls, 614 ARRAY_SIZE(ssm2602_snd_controls)); 615 ssm2602_add_widgets(codec); 616 ret = snd_soc_init_card(socdev); 617 if (ret < 0) { 618 pr_err("ssm2602: failed to register card\n"); 619 goto card_err; 620 } 621 622 return ret; 623 624 card_err: 625 snd_soc_free_pcms(socdev); 626 snd_soc_dapm_free(socdev); 627 pcm_err: 628 kfree(codec->reg_cache); 629 return ret; 630 } 631 632 static struct snd_soc_device *ssm2602_socdev; 633 634 #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) 635 /* 636 * ssm2602 2 wire address is determined by GPIO5 637 * state during powerup. 638 * low = 0x1a 639 * high = 0x1b 640 */ 641 static int ssm2602_i2c_probe(struct i2c_client *i2c, 642 const struct i2c_device_id *id) 643 { 644 struct snd_soc_device *socdev = ssm2602_socdev; 645 struct snd_soc_codec *codec = socdev->card->codec; 646 int ret; 647 648 i2c_set_clientdata(i2c, codec); 649 codec->control_data = i2c; 650 651 ret = ssm2602_init(socdev); 652 if (ret < 0) 653 pr_err("failed to initialise SSM2602\n"); 654 655 return ret; 656 } 657 658 static int ssm2602_i2c_remove(struct i2c_client *client) 659 { 660 struct snd_soc_codec *codec = i2c_get_clientdata(client); 661 kfree(codec->reg_cache); 662 return 0; 663 } 664 665 static const struct i2c_device_id ssm2602_i2c_id[] = { 666 { "ssm2602", 0 }, 667 { } 668 }; 669 MODULE_DEVICE_TABLE(i2c, ssm2602_i2c_id); 670 /* corgi i2c codec control layer */ 671 static struct i2c_driver ssm2602_i2c_driver = { 672 .driver = { 673 .name = "SSM2602 I2C Codec", 674 .owner = THIS_MODULE, 675 }, 676 .probe = ssm2602_i2c_probe, 677 .remove = ssm2602_i2c_remove, 678 .id_table = ssm2602_i2c_id, 679 }; 680 681 static int ssm2602_add_i2c_device(struct platform_device *pdev, 682 const struct ssm2602_setup_data *setup) 683 { 684 struct i2c_board_info info; 685 struct i2c_adapter *adapter; 686 struct i2c_client *client; 687 int ret; 688 689 ret = i2c_add_driver(&ssm2602_i2c_driver); 690 if (ret != 0) { 691 dev_err(&pdev->dev, "can't add i2c driver\n"); 692 return ret; 693 } 694 memset(&info, 0, sizeof(struct i2c_board_info)); 695 info.addr = setup->i2c_address; 696 strlcpy(info.type, "ssm2602", I2C_NAME_SIZE); 697 adapter = i2c_get_adapter(setup->i2c_bus); 698 if (!adapter) { 699 dev_err(&pdev->dev, "can't get i2c adapter %d\n", 700 setup->i2c_bus); 701 goto err_driver; 702 } 703 client = i2c_new_device(adapter, &info); 704 i2c_put_adapter(adapter); 705 if (!client) { 706 dev_err(&pdev->dev, "can't add i2c device at 0x%x\n", 707 (unsigned int)info.addr); 708 goto err_driver; 709 } 710 return 0; 711 err_driver: 712 i2c_del_driver(&ssm2602_i2c_driver); 713 return -ENODEV; 714 } 715 #endif 716 717 static int ssm2602_probe(struct platform_device *pdev) 718 { 719 struct snd_soc_device *socdev = platform_get_drvdata(pdev); 720 struct ssm2602_setup_data *setup; 721 struct snd_soc_codec *codec; 722 struct ssm2602_priv *ssm2602; 723 int ret = 0; 724 725 pr_info("ssm2602 Audio Codec %s", SSM2602_VERSION); 726 727 setup = socdev->codec_data; 728 codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL); 729 if (codec == NULL) 730 return -ENOMEM; 731 732 ssm2602 = kzalloc(sizeof(struct ssm2602_priv), GFP_KERNEL); 733 if (ssm2602 == NULL) { 734 kfree(codec); 735 return -ENOMEM; 736 } 737 738 codec->private_data = ssm2602; 739 socdev->card->codec = codec; 740 mutex_init(&codec->mutex); 741 INIT_LIST_HEAD(&codec->dapm_widgets); 742 INIT_LIST_HEAD(&codec->dapm_paths); 743 744 ssm2602_socdev = socdev; 745 #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) 746 if (setup->i2c_address) { 747 codec->hw_write = (hw_write_t)i2c_master_send; 748 ret = ssm2602_add_i2c_device(pdev, setup); 749 } 750 #else 751 /* other interfaces */ 752 #endif 753 return ret; 754 } 755 756 /* remove everything here */ 757 static int ssm2602_remove(struct platform_device *pdev) 758 { 759 struct snd_soc_device *socdev = platform_get_drvdata(pdev); 760 struct snd_soc_codec *codec = socdev->card->codec; 761 762 if (codec->control_data) 763 ssm2602_set_bias_level(codec, SND_SOC_BIAS_OFF); 764 765 snd_soc_free_pcms(socdev); 766 snd_soc_dapm_free(socdev); 767 #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) 768 i2c_unregister_device(codec->control_data); 769 i2c_del_driver(&ssm2602_i2c_driver); 770 #endif 771 kfree(codec->private_data); 772 kfree(codec); 773 774 return 0; 775 } 776 777 struct snd_soc_codec_device soc_codec_dev_ssm2602 = { 778 .probe = ssm2602_probe, 779 .remove = ssm2602_remove, 780 .suspend = ssm2602_suspend, 781 .resume = ssm2602_resume, 782 }; 783 EXPORT_SYMBOL_GPL(soc_codec_dev_ssm2602); 784 785 static int __init ssm2602_modinit(void) 786 { 787 return snd_soc_register_dai(&ssm2602_dai); 788 } 789 module_init(ssm2602_modinit); 790 791 static void __exit ssm2602_exit(void) 792 { 793 snd_soc_unregister_dai(&ssm2602_dai); 794 } 795 module_exit(ssm2602_exit); 796 797 MODULE_DESCRIPTION("ASoC ssm2602 driver"); 798 MODULE_AUTHOR("Cliff Cai"); 799 MODULE_LICENSE("GPL"); 800