diff options
author | Takashi Iwai <tiwai@suse.de> | 2013-10-25 05:43:47 -0400 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2013-10-25 05:43:47 -0400 |
commit | 6913a9dbf18f08e3577695032da15812bda92b66 (patch) | |
tree | 05ca8620b11f2898022a7fd8a00f1f8566161428 /sound/soc/codecs/tlv320aic23.c | |
parent | 7342017f4a0f129d277f78b8761f2732661ba30a (diff) | |
parent | 9645083ca5ef365b7b750cf219bb20b61bb925f8 (diff) |
Merge tag 'asoc-v3.13' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound into for-next
ASoC: Updates for v3.13
- Further work on the dmaengine helpers, including support for
configuring the parameters for DMA by reading the capabilities of the
DMA controller which removes some guesswork and magic numbers fromm
drivers.
- A refresh of the documentation.
- Conversions of many drivers to direct regmap API usage in order to
allow the ASoC level register I/O code to be removed, this will
hopefully be completed by v3.14.
- Support for using async register I/O in DAPM, reducing the time taken
to implement power transitions on systems that support it.
Diffstat (limited to 'sound/soc/codecs/tlv320aic23.c')
-rw-r--r-- | sound/soc/codecs/tlv320aic23.c | 84 |
1 files changed, 34 insertions, 50 deletions
diff --git a/sound/soc/codecs/tlv320aic23.c b/sound/soc/codecs/tlv320aic23.c index 31762ebdd774..5d430cc56f51 100644 --- a/sound/soc/codecs/tlv320aic23.c +++ b/sound/soc/codecs/tlv320aic23.c | |||
@@ -24,6 +24,7 @@ | |||
24 | #include <linux/delay.h> | 24 | #include <linux/delay.h> |
25 | #include <linux/pm.h> | 25 | #include <linux/pm.h> |
26 | #include <linux/i2c.h> | 26 | #include <linux/i2c.h> |
27 | #include <linux/regmap.h> | ||
27 | #include <linux/slab.h> | 28 | #include <linux/slab.h> |
28 | #include <sound/core.h> | 29 | #include <sound/core.h> |
29 | #include <sound/pcm.h> | 30 | #include <sound/pcm.h> |
@@ -37,11 +38,27 @@ | |||
37 | /* | 38 | /* |
38 | * AIC23 register cache | 39 | * AIC23 register cache |
39 | */ | 40 | */ |
40 | static const u16 tlv320aic23_reg[] = { | 41 | static const struct reg_default tlv320aic23_reg[] = { |
41 | 0x0097, 0x0097, 0x00F9, 0x00F9, /* 0 */ | 42 | { 0, 0x0097 }, |
42 | 0x001A, 0x0004, 0x0007, 0x0001, /* 4 */ | 43 | { 1, 0x0097 }, |
43 | 0x0020, 0x0000, 0x0000, 0x0000, /* 8 */ | 44 | { 2, 0x00F9 }, |
44 | 0x0000, 0x0000, 0x0000, 0x0000, /* 12 */ | 45 | { 3, 0x00F9 }, |
46 | { 4, 0x001A }, | ||
47 | { 5, 0x0004 }, | ||
48 | { 6, 0x0007 }, | ||
49 | { 7, 0x0001 }, | ||
50 | { 8, 0x0020 }, | ||
51 | { 9, 0x0000 }, | ||
52 | }; | ||
53 | |||
54 | static const struct regmap_config tlv320aic23_regmap = { | ||
55 | .reg_bits = 7, | ||
56 | .val_bits = 9, | ||
57 | |||
58 | .max_register = TLV320AIC23_RESET, | ||
59 | .reg_defaults = tlv320aic23_reg, | ||
60 | .num_reg_defaults = ARRAY_SIZE(tlv320aic23_reg), | ||
61 | .cache_type = REGCACHE_RBTREE, | ||
45 | }; | 62 | }; |
46 | 63 | ||
47 | static const char *rec_src_text[] = { "Line", "Mic" }; | 64 | static const char *rec_src_text[] = { "Line", "Mic" }; |
@@ -171,7 +188,7 @@ static const struct snd_soc_dapm_route tlv320aic23_intercon[] = { | |||
171 | 188 | ||
172 | /* AIC23 driver data */ | 189 | /* AIC23 driver data */ |
173 | struct aic23 { | 190 | struct aic23 { |
174 | enum snd_soc_control_type control_type; | 191 | struct regmap *regmap; |
175 | int mclk; | 192 | int mclk; |
176 | int requested_adc; | 193 | int requested_adc; |
177 | int requested_dac; | 194 | int requested_dac; |
@@ -532,7 +549,9 @@ static int tlv320aic23_suspend(struct snd_soc_codec *codec) | |||
532 | 549 | ||
533 | static int tlv320aic23_resume(struct snd_soc_codec *codec) | 550 | static int tlv320aic23_resume(struct snd_soc_codec *codec) |
534 | { | 551 | { |
535 | snd_soc_cache_sync(codec); | 552 | struct aic23 *aic23 = snd_soc_codec_get_drvdata(codec); |
553 | regcache_mark_dirty(aic23->regmap); | ||
554 | regcache_sync(aic23->regmap); | ||
536 | tlv320aic23_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | 555 | tlv320aic23_set_bias_level(codec, SND_SOC_BIAS_STANDBY); |
537 | 556 | ||
538 | return 0; | 557 | return 0; |
@@ -540,10 +559,9 @@ static int tlv320aic23_resume(struct snd_soc_codec *codec) | |||
540 | 559 | ||
541 | static int tlv320aic23_probe(struct snd_soc_codec *codec) | 560 | static int tlv320aic23_probe(struct snd_soc_codec *codec) |
542 | { | 561 | { |
543 | struct aic23 *aic23 = snd_soc_codec_get_drvdata(codec); | ||
544 | int ret; | 562 | int ret; |
545 | 563 | ||
546 | ret = snd_soc_codec_set_cache_io(codec, 7, 9, aic23->control_type); | 564 | ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_REGMAP); |
547 | if (ret < 0) { | 565 | if (ret < 0) { |
548 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); | 566 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); |
549 | return ret; | 567 | return ret; |
@@ -552,16 +570,6 @@ static int tlv320aic23_probe(struct snd_soc_codec *codec) | |||
552 | /* Reset codec */ | 570 | /* Reset codec */ |
553 | snd_soc_write(codec, TLV320AIC23_RESET, 0); | 571 | snd_soc_write(codec, TLV320AIC23_RESET, 0); |
554 | 572 | ||
555 | /* Write the register default value to cache for reserved registers, | ||
556 | * so the write to the these registers are suppressed by the cache | ||
557 | * restore code when it skips writes of default registers. | ||
558 | */ | ||
559 | snd_soc_cache_write(codec, 0x0A, 0); | ||
560 | snd_soc_cache_write(codec, 0x0B, 0); | ||
561 | snd_soc_cache_write(codec, 0x0C, 0); | ||
562 | snd_soc_cache_write(codec, 0x0D, 0); | ||
563 | snd_soc_cache_write(codec, 0x0E, 0); | ||
564 | |||
565 | /* power on device */ | 573 | /* power on device */ |
566 | tlv320aic23_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | 574 | tlv320aic23_set_bias_level(codec, SND_SOC_BIAS_STANDBY); |
567 | 575 | ||
@@ -586,9 +594,6 @@ static int tlv320aic23_probe(struct snd_soc_codec *codec) | |||
586 | 594 | ||
587 | snd_soc_write(codec, TLV320AIC23_ACTIVE, 0x1); | 595 | snd_soc_write(codec, TLV320AIC23_ACTIVE, 0x1); |
588 | 596 | ||
589 | snd_soc_add_codec_controls(codec, tlv320aic23_snd_controls, | ||
590 | ARRAY_SIZE(tlv320aic23_snd_controls)); | ||
591 | |||
592 | return 0; | 597 | return 0; |
593 | } | 598 | } |
594 | 599 | ||
@@ -599,21 +604,19 @@ static int tlv320aic23_remove(struct snd_soc_codec *codec) | |||
599 | } | 604 | } |
600 | 605 | ||
601 | static struct snd_soc_codec_driver soc_codec_dev_tlv320aic23 = { | 606 | static struct snd_soc_codec_driver soc_codec_dev_tlv320aic23 = { |
602 | .reg_cache_size = ARRAY_SIZE(tlv320aic23_reg), | ||
603 | .reg_word_size = sizeof(u16), | ||
604 | .reg_cache_default = tlv320aic23_reg, | ||
605 | .probe = tlv320aic23_probe, | 607 | .probe = tlv320aic23_probe, |
606 | .remove = tlv320aic23_remove, | 608 | .remove = tlv320aic23_remove, |
607 | .suspend = tlv320aic23_suspend, | 609 | .suspend = tlv320aic23_suspend, |
608 | .resume = tlv320aic23_resume, | 610 | .resume = tlv320aic23_resume, |
609 | .set_bias_level = tlv320aic23_set_bias_level, | 611 | .set_bias_level = tlv320aic23_set_bias_level, |
612 | .controls = tlv320aic23_snd_controls, | ||
613 | .num_controls = ARRAY_SIZE(tlv320aic23_snd_controls), | ||
610 | .dapm_widgets = tlv320aic23_dapm_widgets, | 614 | .dapm_widgets = tlv320aic23_dapm_widgets, |
611 | .num_dapm_widgets = ARRAY_SIZE(tlv320aic23_dapm_widgets), | 615 | .num_dapm_widgets = ARRAY_SIZE(tlv320aic23_dapm_widgets), |
612 | .dapm_routes = tlv320aic23_intercon, | 616 | .dapm_routes = tlv320aic23_intercon, |
613 | .num_dapm_routes = ARRAY_SIZE(tlv320aic23_intercon), | 617 | .num_dapm_routes = ARRAY_SIZE(tlv320aic23_intercon), |
614 | }; | 618 | }; |
615 | 619 | ||
616 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | ||
617 | /* | 620 | /* |
618 | * If the i2c layer weren't so broken, we could pass this kind of data | 621 | * If the i2c layer weren't so broken, we could pass this kind of data |
619 | * around | 622 | * around |
@@ -631,8 +634,11 @@ static int tlv320aic23_codec_probe(struct i2c_client *i2c, | |||
631 | if (aic23 == NULL) | 634 | if (aic23 == NULL) |
632 | return -ENOMEM; | 635 | return -ENOMEM; |
633 | 636 | ||
637 | aic23->regmap = devm_regmap_init_i2c(i2c, &tlv320aic23_regmap); | ||
638 | if (IS_ERR(aic23->regmap)) | ||
639 | return PTR_ERR(aic23->regmap); | ||
640 | |||
634 | i2c_set_clientdata(i2c, aic23); | 641 | i2c_set_clientdata(i2c, aic23); |
635 | aic23->control_type = SND_SOC_I2C; | ||
636 | 642 | ||
637 | ret = snd_soc_register_codec(&i2c->dev, | 643 | ret = snd_soc_register_codec(&i2c->dev, |
638 | &soc_codec_dev_tlv320aic23, &tlv320aic23_dai, 1); | 644 | &soc_codec_dev_tlv320aic23, &tlv320aic23_dai, 1); |
@@ -660,29 +666,7 @@ static struct i2c_driver tlv320aic23_i2c_driver = { | |||
660 | .id_table = tlv320aic23_id, | 666 | .id_table = tlv320aic23_id, |
661 | }; | 667 | }; |
662 | 668 | ||
663 | #endif | 669 | module_i2c_driver(tlv320aic23_i2c_driver); |
664 | |||
665 | static int __init tlv320aic23_modinit(void) | ||
666 | { | ||
667 | int ret; | ||
668 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | ||
669 | ret = i2c_add_driver(&tlv320aic23_i2c_driver); | ||
670 | if (ret != 0) { | ||
671 | printk(KERN_ERR "Failed to register TLV320AIC23 I2C driver: %d\n", | ||
672 | ret); | ||
673 | } | ||
674 | #endif | ||
675 | return ret; | ||
676 | } | ||
677 | module_init(tlv320aic23_modinit); | ||
678 | |||
679 | static void __exit tlv320aic23_exit(void) | ||
680 | { | ||
681 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | ||
682 | i2c_del_driver(&tlv320aic23_i2c_driver); | ||
683 | #endif | ||
684 | } | ||
685 | module_exit(tlv320aic23_exit); | ||
686 | 670 | ||
687 | MODULE_DESCRIPTION("ASoC TLV320AIC23 codec driver"); | 671 | MODULE_DESCRIPTION("ASoC TLV320AIC23 codec driver"); |
688 | MODULE_AUTHOR("Arun KS <arunks@mistralsolutions.com>"); | 672 | MODULE_AUTHOR("Arun KS <arunks@mistralsolutions.com>"); |