diff options
author | Cliff Cai <cliff.cai@analog.com> | 2011-03-27 17:22:57 -0400 |
---|---|---|
committer | Mark Brown <broonie@opensource.wolfsonmicro.com> | 2011-03-29 18:17:35 -0400 |
commit | 93547e89b6d2adeec627d2a8d8fc4d4b40b0e2c4 (patch) | |
tree | 36ba515bb7447c95864d9392c2b5c7c9ce8f7782 /sound/soc/codecs/ssm2602.c | |
parent | 1afa98b8074136c81d23e56836a59b2c8f1529c8 (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.c | 138 |
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 @@ | |||
48 | struct ssm2602_priv { | 48 | struct 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 | */ | ||
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 | 68 | ||
118 | /*Appending several "None"s just for OSS mixer use*/ | 69 | /*Appending several "None"s just for OSS mixer use*/ |
119 | static const char *ssm2602_input_select[] = { | 70 | static 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, | |||
385 | static int ssm2602_mute(struct snd_soc_dai *dai, int mute) | 335 | static 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 | ||
473 | static int ssm2602_set_bias_level(struct snd_soc_codec *codec, | 423 | static 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 | ||
540 | static int ssm2602_resume(struct snd_soc_codec *codec) | 490 | static 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, |