aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/codecs/ssm2602.c
diff options
context:
space:
mode:
authorCliff Cai <cliff.cai@analog.com>2011-03-27 17:22:57 -0400
committerMark Brown <broonie@opensource.wolfsonmicro.com>2011-03-29 18:17:35 -0400
commit93547e89b6d2adeec627d2a8d8fc4d4b40b0e2c4 (patch)
tree36ba515bb7447c95864d9392c2b5c7c9ce8f7782 /sound/soc/codecs/ssm2602.c
parent1afa98b8074136c81d23e56836a59b2c8f1529c8 (diff)
ASoC: SSM2602: convert to soc-cache
Signed-off-by: Cliff Cai <cliff.cai@analog.com> Signed-off-by: Mike Frysinger <vapier@gentoo.org> Acked-by: Liam Girdwood <lrg@ti.com> Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Diffstat (limited to 'sound/soc/codecs/ssm2602.c')
-rw-r--r--sound/soc/codecs/ssm2602.c138
1 files changed, 43 insertions, 95 deletions
diff --git a/sound/soc/codecs/ssm2602.c b/sound/soc/codecs/ssm2602.c
index 5a5a6b16911..8a2b52fa4a7 100644
--- a/sound/soc/codecs/ssm2602.c
+++ b/sound/soc/codecs/ssm2602.c
@@ -48,7 +48,6 @@
48struct ssm2602_priv { 48struct ssm2602_priv {
49 unsigned int sysclk; 49 unsigned int sysclk;
50 enum snd_soc_control_type control_type; 50 enum snd_soc_control_type control_type;
51 void *control_data;
52 struct snd_pcm_substream *master_substream; 51 struct snd_pcm_substream *master_substream;
53 struct snd_pcm_substream *slave_substream; 52 struct snd_pcm_substream *slave_substream;
54}; 53};
@@ -65,55 +64,7 @@ static const u16 ssm2602_reg[SSM2602_CACHEREGNUM] = {
65 0x0000, 0x0000 64 0x0000, 0x0000
66}; 65};
67 66
68/* 67#define ssm2602_reset(c) snd_soc_write(c, SSM2602_RESET, 0)
69 * read ssm2602 register cache
70 */
71static 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 */
85static 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 */
97static 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 68
118/*Appending several "None"s just for OSS mixer use*/ 69/*Appending several "None"s just for OSS mixer use*/
119static const char *ssm2602_input_select[] = { 70static const char *ssm2602_input_select[] = {
@@ -278,12 +229,11 @@ static int ssm2602_hw_params(struct snd_pcm_substream *substream,
278 struct snd_soc_pcm_runtime *rtd = substream->private_data; 229 struct snd_soc_pcm_runtime *rtd = substream->private_data;
279 struct snd_soc_codec *codec = rtd->codec; 230 struct snd_soc_codec *codec = rtd->codec;
280 struct ssm2602_priv *ssm2602 = snd_soc_codec_get_drvdata(codec); 231 struct ssm2602_priv *ssm2602 = snd_soc_codec_get_drvdata(codec);
281 struct i2c_client *i2c = codec->control_data; 232 u16 iface = snd_soc_read(codec, SSM2602_IFACE) & 0xfff3;
282 u16 iface = ssm2602_read_reg_cache(codec, SSM2602_IFACE) & 0xfff3;
283 int i = get_coeff(ssm2602->sysclk, params_rate(params)); 233 int i = get_coeff(ssm2602->sysclk, params_rate(params));
284 234
285 if (substream == ssm2602->slave_substream) { 235 if (substream == ssm2602->slave_substream) {
286 dev_dbg(&i2c->dev, "Ignoring hw_params for slave substream\n"); 236 dev_dbg(codec->dev, "Ignoring hw_params for slave substream\n");
287 return 0; 237 return 0;
288 } 238 }
289 239
@@ -294,8 +244,8 @@ static int ssm2602_hw_params(struct snd_pcm_substream *substream,
294 srate = (coeff_div[i].sr << 2) | 244 srate = (coeff_div[i].sr << 2) |
295 (coeff_div[i].bosr << 1) | coeff_div[i].usb; 245 (coeff_div[i].bosr << 1) | coeff_div[i].usb;
296 246
297 ssm2602_write(codec, SSM2602_ACTIVE, 0); 247 snd_soc_write(codec, SSM2602_ACTIVE, 0);
298 ssm2602_write(codec, SSM2602_SRATE, srate); 248 snd_soc_write(codec, SSM2602_SRATE, srate);
299 249
300 /* bit size */ 250 /* bit size */
301 switch (params_format(params)) { 251 switch (params_format(params)) {
@@ -311,8 +261,8 @@ static int ssm2602_hw_params(struct snd_pcm_substream *substream,
311 iface |= 0x000c; 261 iface |= 0x000c;
312 break; 262 break;
313 } 263 }
314 ssm2602_write(codec, SSM2602_IFACE, iface); 264 snd_soc_write(codec, SSM2602_IFACE, iface);
315 ssm2602_write(codec, SSM2602_ACTIVE, ACTIVE_ACTIVATE_CODEC); 265 snd_soc_write(codec, SSM2602_ACTIVE, ACTIVE_ACTIVATE_CODEC);
316 return 0; 266 return 0;
317} 267}
318 268
@@ -360,7 +310,7 @@ static int ssm2602_pcm_prepare(struct snd_pcm_substream *substream,
360 struct snd_soc_pcm_runtime *rtd = substream->private_data; 310 struct snd_soc_pcm_runtime *rtd = substream->private_data;
361 struct snd_soc_codec *codec = rtd->codec; 311 struct snd_soc_codec *codec = rtd->codec;
362 /* set active */ 312 /* set active */
363 ssm2602_write(codec, SSM2602_ACTIVE, ACTIVE_ACTIVATE_CODEC); 313 snd_soc_write(codec, SSM2602_ACTIVE, ACTIVE_ACTIVATE_CODEC);
364 314
365 return 0; 315 return 0;
366} 316}
@@ -374,7 +324,7 @@ static void ssm2602_shutdown(struct snd_pcm_substream *substream,
374 324
375 /* deactivate */ 325 /* deactivate */
376 if (!codec->active) 326 if (!codec->active)
377 ssm2602_write(codec, SSM2602_ACTIVE, 0); 327 snd_soc_write(codec, SSM2602_ACTIVE, 0);
378 328
379 if (ssm2602->master_substream == substream) 329 if (ssm2602->master_substream == substream)
380 ssm2602->master_substream = ssm2602->slave_substream; 330 ssm2602->master_substream = ssm2602->slave_substream;
@@ -385,12 +335,12 @@ static void ssm2602_shutdown(struct snd_pcm_substream *substream,
385static int ssm2602_mute(struct snd_soc_dai *dai, int mute) 335static int ssm2602_mute(struct snd_soc_dai *dai, int mute)
386{ 336{
387 struct snd_soc_codec *codec = dai->codec; 337 struct snd_soc_codec *codec = dai->codec;
388 u16 mute_reg = ssm2602_read_reg_cache(codec, SSM2602_APDIGI) & ~APDIGI_ENABLE_DAC_MUTE; 338 u16 mute_reg = snd_soc_read(codec, SSM2602_APDIGI) & ~APDIGI_ENABLE_DAC_MUTE;
389 if (mute) 339 if (mute)
390 ssm2602_write(codec, SSM2602_APDIGI, 340 snd_soc_write(codec, SSM2602_APDIGI,
391 mute_reg | APDIGI_ENABLE_DAC_MUTE); 341 mute_reg | APDIGI_ENABLE_DAC_MUTE);
392 else 342 else
393 ssm2602_write(codec, SSM2602_APDIGI, mute_reg); 343 snd_soc_write(codec, SSM2602_APDIGI, mute_reg);
394 return 0; 344 return 0;
395} 345}
396 346
@@ -466,30 +416,30 @@ static int ssm2602_set_dai_fmt(struct snd_soc_dai *codec_dai,
466 } 416 }
467 417
468 /* set iface */ 418 /* set iface */
469 ssm2602_write(codec, SSM2602_IFACE, iface); 419 snd_soc_write(codec, SSM2602_IFACE, iface);
470 return 0; 420 return 0;
471} 421}
472 422
473static int ssm2602_set_bias_level(struct snd_soc_codec *codec, 423static int ssm2602_set_bias_level(struct snd_soc_codec *codec,
474 enum snd_soc_bias_level level) 424 enum snd_soc_bias_level level)
475{ 425{
476 u16 reg = ssm2602_read_reg_cache(codec, SSM2602_PWR) & 0xff7f; 426 u16 reg = snd_soc_read(codec, SSM2602_PWR) & 0xff7f;
477 427
478 switch (level) { 428 switch (level) {
479 case SND_SOC_BIAS_ON: 429 case SND_SOC_BIAS_ON:
480 /* vref/mid, osc on, dac unmute */ 430 /* vref/mid, osc on, dac unmute */
481 ssm2602_write(codec, SSM2602_PWR, reg); 431 snd_soc_write(codec, SSM2602_PWR, reg);
482 break; 432 break;
483 case SND_SOC_BIAS_PREPARE: 433 case SND_SOC_BIAS_PREPARE:
484 break; 434 break;
485 case SND_SOC_BIAS_STANDBY: 435 case SND_SOC_BIAS_STANDBY:
486 /* everything off except vref/vmid, */ 436 /* everything off except vref/vmid, */
487 ssm2602_write(codec, SSM2602_PWR, reg | PWR_CLK_OUT_PDN); 437 snd_soc_write(codec, SSM2602_PWR, reg | PWR_CLK_OUT_PDN);
488 break; 438 break;
489 case SND_SOC_BIAS_OFF: 439 case SND_SOC_BIAS_OFF:
490 /* everything off, dac mute, inactive */ 440 /* everything off, dac mute, inactive */
491 ssm2602_write(codec, SSM2602_ACTIVE, 0); 441 snd_soc_write(codec, SSM2602_ACTIVE, 0);
492 ssm2602_write(codec, SSM2602_PWR, 0xffff); 442 snd_soc_write(codec, SSM2602_PWR, 0xffff);
493 break; 443 break;
494 444
495 } 445 }
@@ -539,17 +489,10 @@ static int ssm2602_suspend(struct snd_soc_codec *codec, pm_message_t state)
539 489
540static int ssm2602_resume(struct snd_soc_codec *codec) 490static int ssm2602_resume(struct snd_soc_codec *codec)
541{ 491{
542 int i; 492 snd_soc_cache_sync(codec);
543 u8 data[2]; 493
544 u16 *cache = codec->reg_cache;
545
546 /* Sync reg_cache with the hardware */
547 for (i = 0; i < ARRAY_SIZE(ssm2602_reg); i++) {
548 data[0] = (i << 1) | ((cache[i] >> 8) & 0x0001);
549 data[1] = cache[i] & 0x00ff;
550 codec->hw_write(codec->control_data, data, 2);
551 }
552 ssm2602_set_bias_level(codec, SND_SOC_BIAS_STANDBY); 494 ssm2602_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
495
553 return 0; 496 return 0;
554} 497}
555 498
@@ -560,31 +503,39 @@ static int ssm2602_probe(struct snd_soc_codec *codec)
560 503
561 pr_info("ssm2602 Audio Codec %s", SSM2602_VERSION); 504 pr_info("ssm2602 Audio Codec %s", SSM2602_VERSION);
562 505
563 codec->control_data = ssm2602->control_data; 506 ret = snd_soc_codec_set_cache_io(codec, 7, 9, ssm2602->control_type);
507 if (ret < 0) {
508 dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
509 return ret;
510 }
564 511
565 ssm2602_reset(codec); 512 ret = ssm2602_reset(codec);
513 if (ret < 0) {
514 dev_err(codec->dev, "Failed to issue reset: %d\n", ret);
515 return ret;
516 }
566 517
567 /*power on device*/ 518 /*power on device*/
568 ssm2602_write(codec, SSM2602_ACTIVE, 0); 519 snd_soc_write(codec, SSM2602_ACTIVE, 0);
569 /* set the update bits */ 520 /* set the update bits */
570 reg = ssm2602_read_reg_cache(codec, SSM2602_LINVOL); 521 reg = snd_soc_read(codec, SSM2602_LINVOL);
571 ssm2602_write(codec, SSM2602_LINVOL, reg | LINVOL_LRIN_BOTH); 522 snd_soc_write(codec, SSM2602_LINVOL, reg | LINVOL_LRIN_BOTH);
572 reg = ssm2602_read_reg_cache(codec, SSM2602_RINVOL); 523 reg = snd_soc_read(codec, SSM2602_RINVOL);
573 ssm2602_write(codec, SSM2602_RINVOL, reg | RINVOL_RLIN_BOTH); 524 snd_soc_write(codec, SSM2602_RINVOL, reg | RINVOL_RLIN_BOTH);
574 reg = ssm2602_read_reg_cache(codec, SSM2602_LOUT1V); 525 reg = snd_soc_read(codec, SSM2602_LOUT1V);
575 ssm2602_write(codec, SSM2602_LOUT1V, reg | LOUT1V_LRHP_BOTH); 526 snd_soc_write(codec, SSM2602_LOUT1V, reg | LOUT1V_LRHP_BOTH);
576 reg = ssm2602_read_reg_cache(codec, SSM2602_ROUT1V); 527 reg = snd_soc_read(codec, SSM2602_ROUT1V);
577 ssm2602_write(codec, SSM2602_ROUT1V, reg | ROUT1V_RLHP_BOTH); 528 snd_soc_write(codec, SSM2602_ROUT1V, reg | ROUT1V_RLHP_BOTH);
578 /*select Line in as default input*/ 529 /*select Line in as default input*/
579 ssm2602_write(codec, SSM2602_APANA, APANA_SELECT_DAC | 530 snd_soc_write(codec, SSM2602_APANA, APANA_SELECT_DAC |
580 APANA_ENABLE_MIC_BOOST); 531 APANA_ENABLE_MIC_BOOST);
581 ssm2602_write(codec, SSM2602_PWR, 0); 532 snd_soc_write(codec, SSM2602_PWR, 0);
582 533
583 snd_soc_add_controls(codec, ssm2602_snd_controls, 534 snd_soc_add_controls(codec, ssm2602_snd_controls,
584 ARRAY_SIZE(ssm2602_snd_controls)); 535 ARRAY_SIZE(ssm2602_snd_controls));
585 ssm2602_add_widgets(codec); 536 ssm2602_add_widgets(codec);
586 537
587 return ret; 538 return 0;
588} 539}
589 540
590/* remove everything here */ 541/* remove everything here */
@@ -599,8 +550,6 @@ static struct snd_soc_codec_driver soc_codec_dev_ssm2602 = {
599 .remove = ssm2602_remove, 550 .remove = ssm2602_remove,
600 .suspend = ssm2602_suspend, 551 .suspend = ssm2602_suspend,
601 .resume = ssm2602_resume, 552 .resume = ssm2602_resume,
602 .read = ssm2602_read_reg_cache,
603 .write = ssm2602_write,
604 .set_bias_level = ssm2602_set_bias_level, 553 .set_bias_level = ssm2602_set_bias_level,
605 .reg_cache_size = sizeof(ssm2602_reg), 554 .reg_cache_size = sizeof(ssm2602_reg),
606 .reg_word_size = sizeof(u16), 555 .reg_word_size = sizeof(u16),
@@ -625,7 +574,6 @@ static int ssm2602_i2c_probe(struct i2c_client *i2c,
625 return -ENOMEM; 574 return -ENOMEM;
626 575
627 i2c_set_clientdata(i2c, ssm2602); 576 i2c_set_clientdata(i2c, ssm2602);
628 ssm2602->control_data = i2c;
629 ssm2602->control_type = SND_SOC_I2C; 577 ssm2602->control_type = SND_SOC_I2C;
630 578
631 ret = snd_soc_register_codec(&i2c->dev, 579 ret = snd_soc_register_codec(&i2c->dev,