aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/codecs/ssm2602.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/soc/codecs/ssm2602.c')
-rw-r--r--sound/soc/codecs/ssm2602.c196
1 files changed, 96 insertions, 100 deletions
diff --git a/sound/soc/codecs/ssm2602.c b/sound/soc/codecs/ssm2602.c
index 2727befd158e..7e2194975360 100644
--- a/sound/soc/codecs/ssm2602.c
+++ b/sound/soc/codecs/ssm2602.c
@@ -32,6 +32,7 @@
32#include <linux/delay.h> 32#include <linux/delay.h>
33#include <linux/pm.h> 33#include <linux/pm.h>
34#include <linux/i2c.h> 34#include <linux/i2c.h>
35#include <linux/spi/spi.h>
35#include <linux/platform_device.h> 36#include <linux/platform_device.h>
36#include <linux/slab.h> 37#include <linux/slab.h>
37#include <sound/core.h> 38#include <sound/core.h>
@@ -48,7 +49,6 @@
48struct ssm2602_priv { 49struct ssm2602_priv {
49 unsigned int sysclk; 50 unsigned int sysclk;
50 enum snd_soc_control_type control_type; 51 enum snd_soc_control_type control_type;
51 void *control_data;
52 struct snd_pcm_substream *master_substream; 52 struct snd_pcm_substream *master_substream;
53 struct snd_pcm_substream *slave_substream; 53 struct snd_pcm_substream *slave_substream;
54}; 54};
@@ -65,55 +65,7 @@ static const u16 ssm2602_reg[SSM2602_CACHEREGNUM] = {
65 0x0000, 0x0000 65 0x0000, 0x0000
66}; 66};
67 67
68/* 68#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 69
118/*Appending several "None"s just for OSS mixer use*/ 70/*Appending several "None"s just for OSS mixer use*/
119static const char *ssm2602_input_select[] = { 71static const char *ssm2602_input_select[] = {
@@ -278,12 +230,11 @@ static int ssm2602_hw_params(struct snd_pcm_substream *substream,
278 struct snd_soc_pcm_runtime *rtd = substream->private_data; 230 struct snd_soc_pcm_runtime *rtd = substream->private_data;
279 struct snd_soc_codec *codec = rtd->codec; 231 struct snd_soc_codec *codec = rtd->codec;
280 struct ssm2602_priv *ssm2602 = snd_soc_codec_get_drvdata(codec); 232 struct ssm2602_priv *ssm2602 = snd_soc_codec_get_drvdata(codec);
281 struct i2c_client *i2c = codec->control_data; 233 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)); 234 int i = get_coeff(ssm2602->sysclk, params_rate(params));
284 235
285 if (substream == ssm2602->slave_substream) { 236 if (substream == ssm2602->slave_substream) {
286 dev_dbg(&i2c->dev, "Ignoring hw_params for slave substream\n"); 237 dev_dbg(codec->dev, "Ignoring hw_params for slave substream\n");
287 return 0; 238 return 0;
288 } 239 }
289 240
@@ -294,8 +245,8 @@ static int ssm2602_hw_params(struct snd_pcm_substream *substream,
294 srate = (coeff_div[i].sr << 2) | 245 srate = (coeff_div[i].sr << 2) |
295 (coeff_div[i].bosr << 1) | coeff_div[i].usb; 246 (coeff_div[i].bosr << 1) | coeff_div[i].usb;
296 247
297 ssm2602_write(codec, SSM2602_ACTIVE, 0); 248 snd_soc_write(codec, SSM2602_ACTIVE, 0);
298 ssm2602_write(codec, SSM2602_SRATE, srate); 249 snd_soc_write(codec, SSM2602_SRATE, srate);
299 250
300 /* bit size */ 251 /* bit size */
301 switch (params_format(params)) { 252 switch (params_format(params)) {
@@ -311,8 +262,8 @@ static int ssm2602_hw_params(struct snd_pcm_substream *substream,
311 iface |= 0x000c; 262 iface |= 0x000c;
312 break; 263 break;
313 } 264 }
314 ssm2602_write(codec, SSM2602_IFACE, iface); 265 snd_soc_write(codec, SSM2602_IFACE, iface);
315 ssm2602_write(codec, SSM2602_ACTIVE, ACTIVE_ACTIVATE_CODEC); 266 snd_soc_write(codec, SSM2602_ACTIVE, ACTIVE_ACTIVATE_CODEC);
316 return 0; 267 return 0;
317} 268}
318 269
@@ -360,7 +311,7 @@ static int ssm2602_pcm_prepare(struct snd_pcm_substream *substream,
360 struct snd_soc_pcm_runtime *rtd = substream->private_data; 311 struct snd_soc_pcm_runtime *rtd = substream->private_data;
361 struct snd_soc_codec *codec = rtd->codec; 312 struct snd_soc_codec *codec = rtd->codec;
362 /* set active */ 313 /* set active */
363 ssm2602_write(codec, SSM2602_ACTIVE, ACTIVE_ACTIVATE_CODEC); 314 snd_soc_write(codec, SSM2602_ACTIVE, ACTIVE_ACTIVATE_CODEC);
364 315
365 return 0; 316 return 0;
366} 317}
@@ -374,7 +325,7 @@ static void ssm2602_shutdown(struct snd_pcm_substream *substream,
374 325
375 /* deactivate */ 326 /* deactivate */
376 if (!codec->active) 327 if (!codec->active)
377 ssm2602_write(codec, SSM2602_ACTIVE, 0); 328 snd_soc_write(codec, SSM2602_ACTIVE, 0);
378 329
379 if (ssm2602->master_substream == substream) 330 if (ssm2602->master_substream == substream)
380 ssm2602->master_substream = ssm2602->slave_substream; 331 ssm2602->master_substream = ssm2602->slave_substream;
@@ -385,12 +336,12 @@ static void ssm2602_shutdown(struct snd_pcm_substream *substream,
385static int ssm2602_mute(struct snd_soc_dai *dai, int mute) 336static int ssm2602_mute(struct snd_soc_dai *dai, int mute)
386{ 337{
387 struct snd_soc_codec *codec = dai->codec; 338 struct snd_soc_codec *codec = dai->codec;
388 u16 mute_reg = ssm2602_read_reg_cache(codec, SSM2602_APDIGI) & ~APDIGI_ENABLE_DAC_MUTE; 339 u16 mute_reg = snd_soc_read(codec, SSM2602_APDIGI) & ~APDIGI_ENABLE_DAC_MUTE;
389 if (mute) 340 if (mute)
390 ssm2602_write(codec, SSM2602_APDIGI, 341 snd_soc_write(codec, SSM2602_APDIGI,
391 mute_reg | APDIGI_ENABLE_DAC_MUTE); 342 mute_reg | APDIGI_ENABLE_DAC_MUTE);
392 else 343 else
393 ssm2602_write(codec, SSM2602_APDIGI, mute_reg); 344 snd_soc_write(codec, SSM2602_APDIGI, mute_reg);
394 return 0; 345 return 0;
395} 346}
396 347
@@ -466,30 +417,30 @@ static int ssm2602_set_dai_fmt(struct snd_soc_dai *codec_dai,
466 } 417 }
467 418
468 /* set iface */ 419 /* set iface */
469 ssm2602_write(codec, SSM2602_IFACE, iface); 420 snd_soc_write(codec, SSM2602_IFACE, iface);
470 return 0; 421 return 0;
471} 422}
472 423
473static int ssm2602_set_bias_level(struct snd_soc_codec *codec, 424static int ssm2602_set_bias_level(struct snd_soc_codec *codec,
474 enum snd_soc_bias_level level) 425 enum snd_soc_bias_level level)
475{ 426{
476 u16 reg = ssm2602_read_reg_cache(codec, SSM2602_PWR) & 0xff7f; 427 u16 reg = snd_soc_read(codec, SSM2602_PWR) & 0xff7f;
477 428
478 switch (level) { 429 switch (level) {
479 case SND_SOC_BIAS_ON: 430 case SND_SOC_BIAS_ON:
480 /* vref/mid, osc on, dac unmute */ 431 /* vref/mid, osc on, dac unmute */
481 ssm2602_write(codec, SSM2602_PWR, reg); 432 snd_soc_write(codec, SSM2602_PWR, reg);
482 break; 433 break;
483 case SND_SOC_BIAS_PREPARE: 434 case SND_SOC_BIAS_PREPARE:
484 break; 435 break;
485 case SND_SOC_BIAS_STANDBY: 436 case SND_SOC_BIAS_STANDBY:
486 /* everything off except vref/vmid, */ 437 /* everything off except vref/vmid, */
487 ssm2602_write(codec, SSM2602_PWR, reg | PWR_CLK_OUT_PDN); 438 snd_soc_write(codec, SSM2602_PWR, reg | PWR_CLK_OUT_PDN);
488 break; 439 break;
489 case SND_SOC_BIAS_OFF: 440 case SND_SOC_BIAS_OFF:
490 /* everything off, dac mute, inactive */ 441 /* everything off, dac mute, inactive */
491 ssm2602_write(codec, SSM2602_ACTIVE, 0); 442 snd_soc_write(codec, SSM2602_ACTIVE, 0);
492 ssm2602_write(codec, SSM2602_PWR, 0xffff); 443 snd_soc_write(codec, SSM2602_PWR, 0xffff);
493 break; 444 break;
494 445
495 } 446 }
@@ -539,17 +490,10 @@ static int ssm2602_suspend(struct snd_soc_codec *codec, pm_message_t state)
539 490
540static int ssm2602_resume(struct snd_soc_codec *codec) 491static int ssm2602_resume(struct snd_soc_codec *codec)
541{ 492{
542 int i; 493 snd_soc_cache_sync(codec);
543 u8 data[2]; 494
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); 495 ssm2602_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
496
553 return 0; 497 return 0;
554} 498}
555 499
@@ -560,31 +504,39 @@ static int ssm2602_probe(struct snd_soc_codec *codec)
560 504
561 pr_info("ssm2602 Audio Codec %s", SSM2602_VERSION); 505 pr_info("ssm2602 Audio Codec %s", SSM2602_VERSION);
562 506
563 codec->control_data = ssm2602->control_data; 507 ret = snd_soc_codec_set_cache_io(codec, 7, 9, ssm2602->control_type);
508 if (ret < 0) {
509 dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
510 return ret;
511 }
564 512
565 ssm2602_reset(codec); 513 ret = ssm2602_reset(codec);
514 if (ret < 0) {
515 dev_err(codec->dev, "Failed to issue reset: %d\n", ret);
516 return ret;
517 }
566 518
567 /*power on device*/ 519 /*power on device*/
568 ssm2602_write(codec, SSM2602_ACTIVE, 0); 520 snd_soc_write(codec, SSM2602_ACTIVE, 0);
569 /* set the update bits */ 521 /* set the update bits */
570 reg = ssm2602_read_reg_cache(codec, SSM2602_LINVOL); 522 reg = snd_soc_read(codec, SSM2602_LINVOL);
571 ssm2602_write(codec, SSM2602_LINVOL, reg | LINVOL_LRIN_BOTH); 523 snd_soc_write(codec, SSM2602_LINVOL, reg | LINVOL_LRIN_BOTH);
572 reg = ssm2602_read_reg_cache(codec, SSM2602_RINVOL); 524 reg = snd_soc_read(codec, SSM2602_RINVOL);
573 ssm2602_write(codec, SSM2602_RINVOL, reg | RINVOL_RLIN_BOTH); 525 snd_soc_write(codec, SSM2602_RINVOL, reg | RINVOL_RLIN_BOTH);
574 reg = ssm2602_read_reg_cache(codec, SSM2602_LOUT1V); 526 reg = snd_soc_read(codec, SSM2602_LOUT1V);
575 ssm2602_write(codec, SSM2602_LOUT1V, reg | LOUT1V_LRHP_BOTH); 527 snd_soc_write(codec, SSM2602_LOUT1V, reg | LOUT1V_LRHP_BOTH);
576 reg = ssm2602_read_reg_cache(codec, SSM2602_ROUT1V); 528 reg = snd_soc_read(codec, SSM2602_ROUT1V);
577 ssm2602_write(codec, SSM2602_ROUT1V, reg | ROUT1V_RLHP_BOTH); 529 snd_soc_write(codec, SSM2602_ROUT1V, reg | ROUT1V_RLHP_BOTH);
578 /*select Line in as default input*/ 530 /*select Line in as default input*/
579 ssm2602_write(codec, SSM2602_APANA, APANA_SELECT_DAC | 531 snd_soc_write(codec, SSM2602_APANA, APANA_SELECT_DAC |
580 APANA_ENABLE_MIC_BOOST); 532 APANA_ENABLE_MIC_BOOST);
581 ssm2602_write(codec, SSM2602_PWR, 0); 533 snd_soc_write(codec, SSM2602_PWR, 0);
582 534
583 snd_soc_add_controls(codec, ssm2602_snd_controls, 535 snd_soc_add_controls(codec, ssm2602_snd_controls,
584 ARRAY_SIZE(ssm2602_snd_controls)); 536 ARRAY_SIZE(ssm2602_snd_controls));
585 ssm2602_add_widgets(codec); 537 ssm2602_add_widgets(codec);
586 538
587 return ret; 539 return 0;
588} 540}
589 541
590/* remove everything here */ 542/* remove everything here */
@@ -599,14 +551,49 @@ static struct snd_soc_codec_driver soc_codec_dev_ssm2602 = {
599 .remove = ssm2602_remove, 551 .remove = ssm2602_remove,
600 .suspend = ssm2602_suspend, 552 .suspend = ssm2602_suspend,
601 .resume = ssm2602_resume, 553 .resume = ssm2602_resume,
602 .read = ssm2602_read_reg_cache,
603 .write = ssm2602_write,
604 .set_bias_level = ssm2602_set_bias_level, 554 .set_bias_level = ssm2602_set_bias_level,
605 .reg_cache_size = sizeof(ssm2602_reg), 555 .reg_cache_size = sizeof(ssm2602_reg),
606 .reg_word_size = sizeof(u16), 556 .reg_word_size = sizeof(u16),
607 .reg_cache_default = ssm2602_reg, 557 .reg_cache_default = ssm2602_reg,
608}; 558};
609 559
560#if defined(CONFIG_SPI_MASTER)
561static int __devinit ssm2602_spi_probe(struct spi_device *spi)
562{
563 struct ssm2602_priv *ssm2602;
564 int ret;
565
566 ssm2602 = kzalloc(sizeof(struct ssm2602_priv), GFP_KERNEL);
567 if (ssm2602 == NULL)
568 return -ENOMEM;
569
570 spi_set_drvdata(spi, ssm2602);
571 ssm2602->control_type = SND_SOC_SPI;
572
573 ret = snd_soc_register_codec(&spi->dev,
574 &soc_codec_dev_ssm2602, &ssm2602_dai, 1);
575 if (ret < 0)
576 kfree(ssm2602);
577 return ret;
578}
579
580static int __devexit ssm2602_spi_remove(struct spi_device *spi)
581{
582 snd_soc_unregister_codec(&spi->dev);
583 kfree(spi_get_drvdata(spi));
584 return 0;
585}
586
587static struct spi_driver ssm2602_spi_driver = {
588 .driver = {
589 .name = "ssm2602",
590 .owner = THIS_MODULE,
591 },
592 .probe = ssm2602_spi_probe,
593 .remove = __devexit_p(ssm2602_spi_remove),
594};
595#endif
596
610#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) 597#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
611/* 598/*
612 * ssm2602 2 wire address is determined by GPIO5 599 * ssm2602 2 wire address is determined by GPIO5
@@ -625,7 +612,6 @@ static int ssm2602_i2c_probe(struct i2c_client *i2c,
625 return -ENOMEM; 612 return -ENOMEM;
626 613
627 i2c_set_clientdata(i2c, ssm2602); 614 i2c_set_clientdata(i2c, ssm2602);
628 ssm2602->control_data = i2c;
629 ssm2602->control_type = SND_SOC_I2C; 615 ssm2602->control_type = SND_SOC_I2C;
630 616
631 ret = snd_soc_register_codec(&i2c->dev, 617 ret = snd_soc_register_codec(&i2c->dev,
@@ -651,7 +637,7 @@ MODULE_DEVICE_TABLE(i2c, ssm2602_i2c_id);
651/* corgi i2c codec control layer */ 637/* corgi i2c codec control layer */
652static struct i2c_driver ssm2602_i2c_driver = { 638static struct i2c_driver ssm2602_i2c_driver = {
653 .driver = { 639 .driver = {
654 .name = "ssm2602-codec", 640 .name = "ssm2602",
655 .owner = THIS_MODULE, 641 .owner = THIS_MODULE,
656 }, 642 },
657 .probe = ssm2602_i2c_probe, 643 .probe = ssm2602_i2c_probe,
@@ -664,19 +650,29 @@ static struct i2c_driver ssm2602_i2c_driver = {
664static int __init ssm2602_modinit(void) 650static int __init ssm2602_modinit(void)
665{ 651{
666 int ret = 0; 652 int ret = 0;
653
654#if defined(CONFIG_SPI_MASTER)
655 ret = spi_register_driver(&ssm2602_spi_driver);
656 if (ret)
657 return ret;
658#endif
659
667#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) 660#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
668 ret = i2c_add_driver(&ssm2602_i2c_driver); 661 ret = i2c_add_driver(&ssm2602_i2c_driver);
669 if (ret != 0) { 662 if (ret)
670 printk(KERN_ERR "Failed to register SSM2602 I2C driver: %d\n", 663 return ret;
671 ret);
672 }
673#endif 664#endif
665
674 return ret; 666 return ret;
675} 667}
676module_init(ssm2602_modinit); 668module_init(ssm2602_modinit);
677 669
678static void __exit ssm2602_exit(void) 670static void __exit ssm2602_exit(void)
679{ 671{
672#if defined(CONFIG_SPI_MASTER)
673 spi_unregister_driver(&ssm2602_spi_driver);
674#endif
675
680#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) 676#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
681 i2c_del_driver(&ssm2602_i2c_driver); 677 i2c_del_driver(&ssm2602_i2c_driver);
682#endif 678#endif