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/spi/spi.h> 36 #include <linux/platform_device.h> 37 #include <linux/slab.h> 38 #include <sound/core.h> 39 #include <sound/pcm.h> 40 #include <sound/pcm_params.h> 41 #include <sound/soc.h> 42 #include <sound/initval.h> 43 #include <sound/tlv.h> 44 45 #include "ssm2602.h" 46 47 #define SSM2602_VERSION "0.1" 48 49 enum ssm2602_type { 50 SSM2602, 51 SSM2604, 52 }; 53 54 /* codec private data */ 55 struct ssm2602_priv { 56 unsigned int sysclk; 57 enum snd_soc_control_type control_type; 58 struct snd_pcm_substream *master_substream; 59 struct snd_pcm_substream *slave_substream; 60 61 enum ssm2602_type type; 62 }; 63 64 /* 65 * ssm2602 register cache 66 * We can't read the ssm2602 register space when we are 67 * using 2 wire for device control, so we cache them instead. 68 * There is no point in caching the reset register 69 */ 70 static const u16 ssm2602_reg[SSM2602_CACHEREGNUM] = { 71 0x0097, 0x0097, 0x0079, 0x0079, 72 0x000a, 0x0008, 0x009f, 0x000a, 73 0x0000, 0x0000 74 }; 75 76 #define ssm2602_reset(c) snd_soc_write(c, SSM2602_RESET, 0) 77 78 /*Appending several "None"s just for OSS mixer use*/ 79 static const char *ssm2602_input_select[] = { 80 "Line", "Mic", "None", "None", "None", 81 "None", "None", "None", 82 }; 83 84 static const char *ssm2602_deemph[] = {"None", "32Khz", "44.1Khz", "48Khz"}; 85 86 static const struct soc_enum ssm2602_enum[] = { 87 SOC_ENUM_SINGLE(SSM2602_APANA, 2, 2, ssm2602_input_select), 88 SOC_ENUM_SINGLE(SSM2602_APDIGI, 1, 4, ssm2602_deemph), 89 }; 90 91 static const unsigned int ssm260x_outmix_tlv[] = { 92 TLV_DB_RANGE_HEAD(2), 93 0, 47, TLV_DB_SCALE_ITEM(TLV_DB_GAIN_MUTE, 0, 0), 94 48, 127, TLV_DB_SCALE_ITEM(-7400, 100, 0), 95 }; 96 97 static const DECLARE_TLV_DB_SCALE(ssm260x_inpga_tlv, -3450, 150, 0); 98 static const DECLARE_TLV_DB_SCALE(ssm260x_sidetone_tlv, -1500, 300, 0); 99 100 static const struct snd_kcontrol_new ssm260x_snd_controls[] = { 101 SOC_DOUBLE_R_TLV("Capture Volume", SSM2602_LINVOL, SSM2602_RINVOL, 0, 45, 0, 102 ssm260x_inpga_tlv), 103 SOC_DOUBLE_R("Capture Switch", SSM2602_LINVOL, SSM2602_RINVOL, 7, 1, 1), 104 105 SOC_SINGLE("ADC High Pass Filter Switch", SSM2602_APDIGI, 0, 1, 1), 106 SOC_SINGLE("Store DC Offset Switch", SSM2602_APDIGI, 4, 1, 0), 107 108 SOC_ENUM("Playback De-emphasis", ssm2602_enum[1]), 109 }; 110 111 static const struct snd_kcontrol_new ssm2602_snd_controls[] = { 112 SOC_DOUBLE_R_TLV("Master Playback Volume", SSM2602_LOUT1V, SSM2602_ROUT1V, 113 0, 127, 0, ssm260x_outmix_tlv), 114 SOC_DOUBLE_R("Master Playback ZC Switch", SSM2602_LOUT1V, SSM2602_ROUT1V, 115 7, 1, 0), 116 SOC_SINGLE_TLV("Sidetone Playback Volume", SSM2602_APANA, 6, 3, 1, 117 ssm260x_sidetone_tlv), 118 119 SOC_SINGLE("Mic Boost (+20dB)", SSM2602_APANA, 0, 1, 0), 120 SOC_SINGLE("Mic Boost2 (+20dB)", SSM2602_APANA, 8, 1, 0), 121 SOC_SINGLE("Mic Switch", SSM2602_APANA, 1, 1, 1), 122 }; 123 124 /* Output Mixer */ 125 static const struct snd_kcontrol_new ssm260x_output_mixer_controls[] = { 126 SOC_DAPM_SINGLE("Line Bypass Switch", SSM2602_APANA, 3, 1, 0), 127 SOC_DAPM_SINGLE("HiFi Playback Switch", SSM2602_APANA, 4, 1, 0), 128 SOC_DAPM_SINGLE("Mic Sidetone Switch", SSM2602_APANA, 5, 1, 0), 129 }; 130 131 /* Input mux */ 132 static const struct snd_kcontrol_new ssm2602_input_mux_controls = 133 SOC_DAPM_ENUM("Input Select", ssm2602_enum[0]); 134 135 static const struct snd_soc_dapm_widget ssm260x_dapm_widgets[] = { 136 SND_SOC_DAPM_DAC("DAC", "HiFi Playback", SSM2602_PWR, 3, 1), 137 SND_SOC_DAPM_ADC("ADC", "HiFi Capture", SSM2602_PWR, 2, 1), 138 SND_SOC_DAPM_PGA("Line Input", SSM2602_PWR, 0, 1, NULL, 0), 139 140 SND_SOC_DAPM_SUPPLY("Digital Core Power", SSM2602_ACTIVE, 0, 0, NULL, 0), 141 142 SND_SOC_DAPM_OUTPUT("LOUT"), 143 SND_SOC_DAPM_OUTPUT("ROUT"), 144 SND_SOC_DAPM_INPUT("RLINEIN"), 145 SND_SOC_DAPM_INPUT("LLINEIN"), 146 }; 147 148 static const struct snd_soc_dapm_widget ssm2602_dapm_widgets[] = { 149 SND_SOC_DAPM_MIXER("Output Mixer", SSM2602_PWR, 4, 1, 150 ssm260x_output_mixer_controls, 151 ARRAY_SIZE(ssm260x_output_mixer_controls)), 152 153 SND_SOC_DAPM_MUX("Input Mux", SND_SOC_NOPM, 0, 0, &ssm2602_input_mux_controls), 154 SND_SOC_DAPM_MICBIAS("Mic Bias", SSM2602_PWR, 1, 1), 155 156 SND_SOC_DAPM_OUTPUT("LHPOUT"), 157 SND_SOC_DAPM_OUTPUT("RHPOUT"), 158 SND_SOC_DAPM_INPUT("MICIN"), 159 }; 160 161 static const struct snd_soc_dapm_widget ssm2604_dapm_widgets[] = { 162 SND_SOC_DAPM_MIXER("Output Mixer", SND_SOC_NOPM, 0, 0, 163 ssm260x_output_mixer_controls, 164 ARRAY_SIZE(ssm260x_output_mixer_controls) - 1), /* Last element is the mic */ 165 }; 166 167 static const struct snd_soc_dapm_route ssm260x_routes[] = { 168 {"DAC", NULL, "Digital Core Power"}, 169 {"ADC", NULL, "Digital Core Power"}, 170 171 {"Output Mixer", "Line Bypass Switch", "Line Input"}, 172 {"Output Mixer", "HiFi Playback Switch", "DAC"}, 173 174 {"ROUT", NULL, "Output Mixer"}, 175 {"LOUT", NULL, "Output Mixer"}, 176 177 {"Line Input", NULL, "LLINEIN"}, 178 {"Line Input", NULL, "RLINEIN"}, 179 }; 180 181 static const struct snd_soc_dapm_route ssm2602_routes[] = { 182 {"Output Mixer", "Mic Sidetone Switch", "Mic Bias"}, 183 184 {"RHPOUT", NULL, "Output Mixer"}, 185 {"LHPOUT", NULL, "Output Mixer"}, 186 187 {"Input Mux", "Line", "Line Input"}, 188 {"Input Mux", "Mic", "Mic Bias"}, 189 {"ADC", NULL, "Input Mux"}, 190 191 {"Mic Bias", NULL, "MICIN"}, 192 }; 193 194 static const struct snd_soc_dapm_route ssm2604_routes[] = { 195 {"ADC", NULL, "Line Input"}, 196 }; 197 198 struct ssm2602_coeff { 199 u32 mclk; 200 u32 rate; 201 u8 srate; 202 }; 203 204 #define SSM2602_COEFF_SRATE(sr, bosr, usb) (((sr) << 2) | ((bosr) << 1) | (usb)) 205 206 /* codec mclk clock coefficients */ 207 static const struct ssm2602_coeff ssm2602_coeff_table[] = { 208 /* 48k */ 209 {12288000, 48000, SSM2602_COEFF_SRATE(0x0, 0x0, 0x0)}, 210 {18432000, 48000, SSM2602_COEFF_SRATE(0x0, 0x1, 0x0)}, 211 {12000000, 48000, SSM2602_COEFF_SRATE(0x0, 0x0, 0x1)}, 212 213 /* 32k */ 214 {12288000, 32000, SSM2602_COEFF_SRATE(0x6, 0x0, 0x0)}, 215 {18432000, 32000, SSM2602_COEFF_SRATE(0x6, 0x1, 0x0)}, 216 {12000000, 32000, SSM2602_COEFF_SRATE(0x6, 0x0, 0x1)}, 217 218 /* 8k */ 219 {12288000, 8000, SSM2602_COEFF_SRATE(0x3, 0x0, 0x0)}, 220 {18432000, 8000, SSM2602_COEFF_SRATE(0x3, 0x1, 0x0)}, 221 {11289600, 8000, SSM2602_COEFF_SRATE(0xb, 0x0, 0x0)}, 222 {16934400, 8000, SSM2602_COEFF_SRATE(0xb, 0x1, 0x0)}, 223 {12000000, 8000, SSM2602_COEFF_SRATE(0x3, 0x0, 0x1)}, 224 225 /* 96k */ 226 {12288000, 96000, SSM2602_COEFF_SRATE(0x7, 0x0, 0x0)}, 227 {18432000, 96000, SSM2602_COEFF_SRATE(0x7, 0x1, 0x0)}, 228 {12000000, 96000, SSM2602_COEFF_SRATE(0x7, 0x0, 0x1)}, 229 230 /* 44.1k */ 231 {11289600, 44100, SSM2602_COEFF_SRATE(0x8, 0x0, 0x0)}, 232 {16934400, 44100, SSM2602_COEFF_SRATE(0x8, 0x1, 0x0)}, 233 {12000000, 44100, SSM2602_COEFF_SRATE(0x8, 0x1, 0x1)}, 234 235 /* 88.2k */ 236 {11289600, 88200, SSM2602_COEFF_SRATE(0xf, 0x0, 0x0)}, 237 {16934400, 88200, SSM2602_COEFF_SRATE(0xf, 0x1, 0x0)}, 238 {12000000, 88200, SSM2602_COEFF_SRATE(0xf, 0x1, 0x1)}, 239 }; 240 241 static inline int ssm2602_get_coeff(int mclk, int rate) 242 { 243 int i; 244 245 for (i = 0; i < ARRAY_SIZE(ssm2602_coeff_table); i++) { 246 if (ssm2602_coeff_table[i].rate == rate && 247 ssm2602_coeff_table[i].mclk == mclk) 248 return ssm2602_coeff_table[i].srate; 249 } 250 return -EINVAL; 251 } 252 253 static int ssm2602_hw_params(struct snd_pcm_substream *substream, 254 struct snd_pcm_hw_params *params, 255 struct snd_soc_dai *dai) 256 { 257 struct snd_soc_pcm_runtime *rtd = substream->private_data; 258 struct snd_soc_codec *codec = rtd->codec; 259 struct ssm2602_priv *ssm2602 = snd_soc_codec_get_drvdata(codec); 260 u16 iface = snd_soc_read(codec, SSM2602_IFACE) & 0xfff3; 261 int srate = ssm2602_get_coeff(ssm2602->sysclk, params_rate(params)); 262 263 if (substream == ssm2602->slave_substream) { 264 dev_dbg(codec->dev, "Ignoring hw_params for slave substream\n"); 265 return 0; 266 } 267 268 if (srate < 0) 269 return srate; 270 271 snd_soc_write(codec, SSM2602_SRATE, srate); 272 273 /* bit size */ 274 switch (params_format(params)) { 275 case SNDRV_PCM_FORMAT_S16_LE: 276 break; 277 case SNDRV_PCM_FORMAT_S20_3LE: 278 iface |= 0x0004; 279 break; 280 case SNDRV_PCM_FORMAT_S24_LE: 281 iface |= 0x0008; 282 break; 283 case SNDRV_PCM_FORMAT_S32_LE: 284 iface |= 0x000c; 285 break; 286 } 287 snd_soc_write(codec, SSM2602_IFACE, iface); 288 return 0; 289 } 290 291 static int ssm2602_startup(struct snd_pcm_substream *substream, 292 struct snd_soc_dai *dai) 293 { 294 struct snd_soc_pcm_runtime *rtd = substream->private_data; 295 struct snd_soc_codec *codec = rtd->codec; 296 struct ssm2602_priv *ssm2602 = snd_soc_codec_get_drvdata(codec); 297 struct i2c_client *i2c = codec->control_data; 298 struct snd_pcm_runtime *master_runtime; 299 300 /* The DAI has shared clocks so if we already have a playback or 301 * capture going then constrain this substream to match it. 302 * TODO: the ssm2602 allows pairs of non-matching PB/REC rates 303 */ 304 if (ssm2602->master_substream) { 305 master_runtime = ssm2602->master_substream->runtime; 306 dev_dbg(&i2c->dev, "Constraining to %d bits at %dHz\n", 307 master_runtime->sample_bits, 308 master_runtime->rate); 309 310 if (master_runtime->rate != 0) 311 snd_pcm_hw_constraint_minmax(substream->runtime, 312 SNDRV_PCM_HW_PARAM_RATE, 313 master_runtime->rate, 314 master_runtime->rate); 315 316 if (master_runtime->sample_bits != 0) 317 snd_pcm_hw_constraint_minmax(substream->runtime, 318 SNDRV_PCM_HW_PARAM_SAMPLE_BITS, 319 master_runtime->sample_bits, 320 master_runtime->sample_bits); 321 322 ssm2602->slave_substream = substream; 323 } else 324 ssm2602->master_substream = substream; 325 326 return 0; 327 } 328 329 static void ssm2602_shutdown(struct snd_pcm_substream *substream, 330 struct snd_soc_dai *dai) 331 { 332 struct snd_soc_pcm_runtime *rtd = substream->private_data; 333 struct snd_soc_codec *codec = rtd->codec; 334 struct ssm2602_priv *ssm2602 = snd_soc_codec_get_drvdata(codec); 335 336 if (ssm2602->master_substream == substream) 337 ssm2602->master_substream = ssm2602->slave_substream; 338 339 ssm2602->slave_substream = NULL; 340 } 341 342 343 static int ssm2602_mute(struct snd_soc_dai *dai, int mute) 344 { 345 struct snd_soc_codec *codec = dai->codec; 346 u16 mute_reg = snd_soc_read(codec, SSM2602_APDIGI) & ~APDIGI_ENABLE_DAC_MUTE; 347 if (mute) 348 snd_soc_write(codec, SSM2602_APDIGI, 349 mute_reg | APDIGI_ENABLE_DAC_MUTE); 350 else 351 snd_soc_write(codec, SSM2602_APDIGI, mute_reg); 352 return 0; 353 } 354 355 static int ssm2602_set_dai_sysclk(struct snd_soc_dai *codec_dai, 356 int clk_id, unsigned int freq, int dir) 357 { 358 struct snd_soc_codec *codec = codec_dai->codec; 359 struct ssm2602_priv *ssm2602 = snd_soc_codec_get_drvdata(codec); 360 switch (freq) { 361 case 11289600: 362 case 12000000: 363 case 12288000: 364 case 16934400: 365 case 18432000: 366 ssm2602->sysclk = freq; 367 return 0; 368 } 369 return -EINVAL; 370 } 371 372 static int ssm2602_set_dai_fmt(struct snd_soc_dai *codec_dai, 373 unsigned int fmt) 374 { 375 struct snd_soc_codec *codec = codec_dai->codec; 376 u16 iface = 0; 377 378 /* set master/slave audio interface */ 379 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { 380 case SND_SOC_DAIFMT_CBM_CFM: 381 iface |= 0x0040; 382 break; 383 case SND_SOC_DAIFMT_CBS_CFS: 384 break; 385 default: 386 return -EINVAL; 387 } 388 389 /* interface format */ 390 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { 391 case SND_SOC_DAIFMT_I2S: 392 iface |= 0x0002; 393 break; 394 case SND_SOC_DAIFMT_RIGHT_J: 395 break; 396 case SND_SOC_DAIFMT_LEFT_J: 397 iface |= 0x0001; 398 break; 399 case SND_SOC_DAIFMT_DSP_A: 400 iface |= 0x0013; 401 break; 402 case SND_SOC_DAIFMT_DSP_B: 403 iface |= 0x0003; 404 break; 405 default: 406 return -EINVAL; 407 } 408 409 /* clock inversion */ 410 switch (fmt & SND_SOC_DAIFMT_INV_MASK) { 411 case SND_SOC_DAIFMT_NB_NF: 412 break; 413 case SND_SOC_DAIFMT_IB_IF: 414 iface |= 0x0090; 415 break; 416 case SND_SOC_DAIFMT_IB_NF: 417 iface |= 0x0080; 418 break; 419 case SND_SOC_DAIFMT_NB_IF: 420 iface |= 0x0010; 421 break; 422 default: 423 return -EINVAL; 424 } 425 426 /* set iface */ 427 snd_soc_write(codec, SSM2602_IFACE, iface); 428 return 0; 429 } 430 431 static int ssm2602_set_bias_level(struct snd_soc_codec *codec, 432 enum snd_soc_bias_level level) 433 { 434 u16 reg = snd_soc_read(codec, SSM2602_PWR) & 0xff7f; 435 436 switch (level) { 437 case SND_SOC_BIAS_ON: 438 /* vref/mid, osc on, dac unmute */ 439 snd_soc_write(codec, SSM2602_PWR, reg); 440 break; 441 case SND_SOC_BIAS_PREPARE: 442 break; 443 case SND_SOC_BIAS_STANDBY: 444 /* everything off except vref/vmid, */ 445 snd_soc_write(codec, SSM2602_PWR, reg | PWR_CLK_OUT_PDN); 446 break; 447 case SND_SOC_BIAS_OFF: 448 /* everything off, dac mute, inactive */ 449 snd_soc_write(codec, SSM2602_PWR, 0xffff); 450 break; 451 452 } 453 codec->dapm.bias_level = level; 454 return 0; 455 } 456 457 #define SSM2602_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_32000 |\ 458 SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |\ 459 SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000) 460 461 #define SSM2602_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\ 462 SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE) 463 464 static struct snd_soc_dai_ops ssm2602_dai_ops = { 465 .startup = ssm2602_startup, 466 .hw_params = ssm2602_hw_params, 467 .shutdown = ssm2602_shutdown, 468 .digital_mute = ssm2602_mute, 469 .set_sysclk = ssm2602_set_dai_sysclk, 470 .set_fmt = ssm2602_set_dai_fmt, 471 }; 472 473 static struct snd_soc_dai_driver ssm2602_dai = { 474 .name = "ssm2602-hifi", 475 .playback = { 476 .stream_name = "Playback", 477 .channels_min = 2, 478 .channels_max = 2, 479 .rates = SSM2602_RATES, 480 .formats = SSM2602_FORMATS,}, 481 .capture = { 482 .stream_name = "Capture", 483 .channels_min = 2, 484 .channels_max = 2, 485 .rates = SSM2602_RATES, 486 .formats = SSM2602_FORMATS,}, 487 .ops = &ssm2602_dai_ops, 488 }; 489 490 static int ssm2602_suspend(struct snd_soc_codec *codec, pm_message_t state) 491 { 492 ssm2602_set_bias_level(codec, SND_SOC_BIAS_OFF); 493 return 0; 494 } 495 496 static int ssm2602_resume(struct snd_soc_codec *codec) 497 { 498 snd_soc_cache_sync(codec); 499 500 ssm2602_set_bias_level(codec, SND_SOC_BIAS_STANDBY); 501 502 return 0; 503 } 504 505 static int ssm2602_probe(struct snd_soc_codec *codec) 506 { 507 struct snd_soc_dapm_context *dapm = &codec->dapm; 508 int ret, reg; 509 510 reg = snd_soc_read(codec, SSM2602_LOUT1V); 511 snd_soc_write(codec, SSM2602_LOUT1V, reg | LOUT1V_LRHP_BOTH); 512 reg = snd_soc_read(codec, SSM2602_ROUT1V); 513 snd_soc_write(codec, SSM2602_ROUT1V, reg | ROUT1V_RLHP_BOTH); 514 515 ret = snd_soc_add_controls(codec, ssm2602_snd_controls, 516 ARRAY_SIZE(ssm2602_snd_controls)); 517 if (ret) 518 return ret; 519 520 ret = snd_soc_dapm_new_controls(dapm, ssm2602_dapm_widgets, 521 ARRAY_SIZE(ssm2602_dapm_widgets)); 522 if (ret) 523 return ret; 524 525 return snd_soc_dapm_add_routes(dapm, ssm2602_routes, 526 ARRAY_SIZE(ssm2602_routes)); 527 } 528 529 static int ssm2604_probe(struct snd_soc_codec *codec) 530 { 531 struct snd_soc_dapm_context *dapm = &codec->dapm; 532 int ret; 533 534 ret = snd_soc_dapm_new_controls(dapm, ssm2604_dapm_widgets, 535 ARRAY_SIZE(ssm2604_dapm_widgets)); 536 if (ret) 537 return ret; 538 539 return snd_soc_dapm_add_routes(dapm, ssm2604_routes, 540 ARRAY_SIZE(ssm2604_routes)); 541 } 542 543 static int ssm260x_probe(struct snd_soc_codec *codec) 544 { 545 struct ssm2602_priv *ssm2602 = snd_soc_codec_get_drvdata(codec); 546 int ret, reg; 547 548 pr_info("ssm2602 Audio Codec %s", SSM2602_VERSION); 549 550 ret = snd_soc_codec_set_cache_io(codec, 7, 9, ssm2602->control_type); 551 if (ret < 0) { 552 dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); 553 return ret; 554 } 555 556 ret = ssm2602_reset(codec); 557 if (ret < 0) { 558 dev_err(codec->dev, "Failed to issue reset: %d\n", ret); 559 return ret; 560 } 561 562 /* set the update bits */ 563 reg = snd_soc_read(codec, SSM2602_LINVOL); 564 snd_soc_write(codec, SSM2602_LINVOL, reg | LINVOL_LRIN_BOTH); 565 reg = snd_soc_read(codec, SSM2602_RINVOL); 566 snd_soc_write(codec, SSM2602_RINVOL, reg | RINVOL_RLIN_BOTH); 567 /*select Line in as default input*/ 568 snd_soc_write(codec, SSM2602_APANA, APANA_SELECT_DAC | 569 APANA_ENABLE_MIC_BOOST); 570 571 switch (ssm2602->type) { 572 case SSM2602: 573 ret = ssm2602_probe(codec); 574 break; 575 case SSM2604: 576 ret = ssm2604_probe(codec); 577 break; 578 } 579 580 return ret; 581 } 582 583 /* remove everything here */ 584 static int ssm2602_remove(struct snd_soc_codec *codec) 585 { 586 ssm2602_set_bias_level(codec, SND_SOC_BIAS_OFF); 587 return 0; 588 } 589 590 static struct snd_soc_codec_driver soc_codec_dev_ssm2602 = { 591 .probe = ssm260x_probe, 592 .remove = ssm2602_remove, 593 .suspend = ssm2602_suspend, 594 .resume = ssm2602_resume, 595 .set_bias_level = ssm2602_set_bias_level, 596 .reg_cache_size = ARRAY_SIZE(ssm2602_reg), 597 .reg_word_size = sizeof(u16), 598 .reg_cache_default = ssm2602_reg, 599 600 .controls = ssm260x_snd_controls, 601 .num_controls = ARRAY_SIZE(ssm260x_snd_controls), 602 .dapm_widgets = ssm260x_dapm_widgets, 603 .num_dapm_widgets = ARRAY_SIZE(ssm260x_dapm_widgets), 604 .dapm_routes = ssm260x_routes, 605 .num_dapm_routes = ARRAY_SIZE(ssm260x_routes), 606 }; 607 608 #if defined(CONFIG_SPI_MASTER) 609 static int __devinit ssm2602_spi_probe(struct spi_device *spi) 610 { 611 struct ssm2602_priv *ssm2602; 612 int ret; 613 614 ssm2602 = kzalloc(sizeof(struct ssm2602_priv), GFP_KERNEL); 615 if (ssm2602 == NULL) 616 return -ENOMEM; 617 618 spi_set_drvdata(spi, ssm2602); 619 ssm2602->control_type = SND_SOC_SPI; 620 ssm2602->type = SSM2602; 621 622 ret = snd_soc_register_codec(&spi->dev, 623 &soc_codec_dev_ssm2602, &ssm2602_dai, 1); 624 if (ret < 0) 625 kfree(ssm2602); 626 return ret; 627 } 628 629 static int __devexit ssm2602_spi_remove(struct spi_device *spi) 630 { 631 snd_soc_unregister_codec(&spi->dev); 632 kfree(spi_get_drvdata(spi)); 633 return 0; 634 } 635 636 static struct spi_driver ssm2602_spi_driver = { 637 .driver = { 638 .name = "ssm2602", 639 .owner = THIS_MODULE, 640 }, 641 .probe = ssm2602_spi_probe, 642 .remove = __devexit_p(ssm2602_spi_remove), 643 }; 644 #endif 645 646 #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) 647 /* 648 * ssm2602 2 wire address is determined by GPIO5 649 * state during powerup. 650 * low = 0x1a 651 * high = 0x1b 652 */ 653 static int __devinit ssm2602_i2c_probe(struct i2c_client *i2c, 654 const struct i2c_device_id *id) 655 { 656 struct ssm2602_priv *ssm2602; 657 int ret; 658 659 ssm2602 = kzalloc(sizeof(struct ssm2602_priv), GFP_KERNEL); 660 if (ssm2602 == NULL) 661 return -ENOMEM; 662 663 i2c_set_clientdata(i2c, ssm2602); 664 ssm2602->control_type = SND_SOC_I2C; 665 ssm2602->type = id->driver_data; 666 667 ret = snd_soc_register_codec(&i2c->dev, 668 &soc_codec_dev_ssm2602, &ssm2602_dai, 1); 669 if (ret < 0) 670 kfree(ssm2602); 671 return ret; 672 } 673 674 static int __devexit ssm2602_i2c_remove(struct i2c_client *client) 675 { 676 snd_soc_unregister_codec(&client->dev); 677 kfree(i2c_get_clientdata(client)); 678 return 0; 679 } 680 681 static const struct i2c_device_id ssm2602_i2c_id[] = { 682 { "ssm2602", SSM2602 }, 683 { "ssm2603", SSM2602 }, 684 { "ssm2604", SSM2604 }, 685 { } 686 }; 687 MODULE_DEVICE_TABLE(i2c, ssm2602_i2c_id); 688 689 /* corgi i2c codec control layer */ 690 static struct i2c_driver ssm2602_i2c_driver = { 691 .driver = { 692 .name = "ssm2602", 693 .owner = THIS_MODULE, 694 }, 695 .probe = ssm2602_i2c_probe, 696 .remove = __devexit_p(ssm2602_i2c_remove), 697 .id_table = ssm2602_i2c_id, 698 }; 699 #endif 700 701 702 static int __init ssm2602_modinit(void) 703 { 704 int ret = 0; 705 706 #if defined(CONFIG_SPI_MASTER) 707 ret = spi_register_driver(&ssm2602_spi_driver); 708 if (ret) 709 return ret; 710 #endif 711 712 #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) 713 ret = i2c_add_driver(&ssm2602_i2c_driver); 714 if (ret) 715 return ret; 716 #endif 717 718 return ret; 719 } 720 module_init(ssm2602_modinit); 721 722 static void __exit ssm2602_exit(void) 723 { 724 #if defined(CONFIG_SPI_MASTER) 725 spi_unregister_driver(&ssm2602_spi_driver); 726 #endif 727 728 #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) 729 i2c_del_driver(&ssm2602_i2c_driver); 730 #endif 731 } 732 module_exit(ssm2602_exit); 733 734 MODULE_DESCRIPTION("ASoC SSM2602/SSM2603/SSM2604 driver"); 735 MODULE_AUTHOR("Cliff Cai"); 736 MODULE_LICENSE("GPL"); 737