diff options
-rw-r--r-- | sound/soc/codecs/da7210.c | 234 |
1 files changed, 196 insertions, 38 deletions
diff --git a/sound/soc/codecs/da7210.c b/sound/soc/codecs/da7210.c index ab38e93c3543..0c23f19dfca2 100644 --- a/sound/soc/codecs/da7210.c +++ b/sound/soc/codecs/da7210.c | |||
@@ -17,6 +17,7 @@ | |||
17 | 17 | ||
18 | #include <linux/delay.h> | 18 | #include <linux/delay.h> |
19 | #include <linux/i2c.h> | 19 | #include <linux/i2c.h> |
20 | #include <linux/regmap.h> | ||
20 | #include <linux/slab.h> | 21 | #include <linux/slab.h> |
21 | #include <linux/module.h> | 22 | #include <linux/module.h> |
22 | #include <sound/pcm.h> | 23 | #include <sound/pcm.h> |
@@ -626,41 +627,170 @@ static const struct snd_soc_dapm_route da7210_audio_map[] = { | |||
626 | 627 | ||
627 | /* Codec private data */ | 628 | /* Codec private data */ |
628 | struct da7210_priv { | 629 | struct da7210_priv { |
629 | enum snd_soc_control_type control_type; | 630 | struct regmap *regmap; |
630 | }; | 631 | }; |
631 | 632 | ||
632 | /* | 633 | static struct reg_default da7210_reg_defaults[] = { |
633 | * Register cache | 634 | { 0x00, 0x00 }, |
634 | */ | 635 | { 0x01, 0x11 }, |
635 | static const u8 da7210_reg[] = { | 636 | { 0x02, 0x00 }, |
636 | 0x00, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* R0 - R7 */ | 637 | { 0x03, 0x00 }, |
637 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, /* R8 - RF */ | 638 | { 0x04, 0x00 }, |
638 | 0x00, 0x00, 0x00, 0x00, 0x08, 0x10, 0x10, 0x54, /* R10 - R17 */ | 639 | { 0x05, 0x00 }, |
639 | 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* R18 - R1F */ | 640 | { 0x06, 0x00 }, |
640 | 0x00, 0x00, 0x00, 0x02, 0x00, 0x76, 0x00, 0x00, /* R20 - R27 */ | 641 | { 0x07, 0x00 }, |
641 | 0x04, 0x00, 0x00, 0x30, 0x2A, 0x00, 0x40, 0x00, /* R28 - R2F */ | 642 | { 0x08, 0x00 }, |
642 | 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, /* R30 - R37 */ | 643 | { 0x09, 0x00 }, |
643 | 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x00, 0x00, /* R38 - R3F */ | 644 | { 0x0a, 0x00 }, |
644 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* R40 - R4F */ | 645 | { 0x0b, 0x00 }, |
645 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* R48 - R4F */ | 646 | { 0x0c, 0x00 }, |
646 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* R50 - R57 */ | 647 | { 0x0d, 0x00 }, |
647 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* R58 - R5F */ | 648 | { 0x0e, 0x00 }, |
648 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* R60 - R67 */ | 649 | { 0x0f, 0x08 }, |
649 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* R68 - R6F */ | 650 | { 0x10, 0x00 }, |
650 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* R70 - R77 */ | 651 | { 0x11, 0x00 }, |
651 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x54, 0x54, 0x00, /* R78 - R7F */ | 652 | { 0x12, 0x00 }, |
652 | 0x00, 0x00, 0x2C, 0x00, 0x00, 0x00, 0x00, 0x00, /* R80 - R87 */ | 653 | { 0x13, 0x00 }, |
653 | 0x00, /* R88 */ | 654 | { 0x14, 0x08 }, |
655 | { 0x15, 0x10 }, | ||
656 | { 0x16, 0x10 }, | ||
657 | { 0x17, 0x54 }, | ||
658 | { 0x18, 0x40 }, | ||
659 | { 0x19, 0x00 }, | ||
660 | { 0x1a, 0x00 }, | ||
661 | { 0x1b, 0x00 }, | ||
662 | { 0x1c, 0x00 }, | ||
663 | { 0x1d, 0x00 }, | ||
664 | { 0x1e, 0x00 }, | ||
665 | { 0x1f, 0x00 }, | ||
666 | { 0x20, 0x00 }, | ||
667 | { 0x21, 0x00 }, | ||
668 | { 0x22, 0x00 }, | ||
669 | { 0x23, 0x02 }, | ||
670 | { 0x24, 0x00 }, | ||
671 | { 0x25, 0x76 }, | ||
672 | { 0x26, 0x00 }, | ||
673 | { 0x27, 0x00 }, | ||
674 | { 0x28, 0x04 }, | ||
675 | { 0x29, 0x00 }, | ||
676 | { 0x2a, 0x00 }, | ||
677 | { 0x2b, 0x30 }, | ||
678 | { 0x2c, 0x2A }, | ||
679 | { 0x2d, 0x00 }, | ||
680 | { 0x2e, 0x40 }, | ||
681 | { 0x2f, 0x00 }, | ||
682 | { 0x30, 0x40 }, | ||
683 | { 0x31, 0x00 }, | ||
684 | { 0x32, 0x40 }, | ||
685 | { 0x33, 0x00 }, | ||
686 | { 0x34, 0x40 }, | ||
687 | { 0x35, 0x00 }, | ||
688 | { 0x36, 0x40 }, | ||
689 | { 0x37, 0x00 }, | ||
690 | { 0x38, 0x40 }, | ||
691 | { 0x39, 0x00 }, | ||
692 | { 0x3a, 0x40 }, | ||
693 | { 0x3b, 0x00 }, | ||
694 | { 0x3c, 0x40 }, | ||
695 | { 0x3d, 0x00 }, | ||
696 | { 0x3e, 0x00 }, | ||
697 | { 0x3f, 0x00 }, | ||
698 | { 0x40, 0x00 }, | ||
699 | { 0x41, 0x00 }, | ||
700 | { 0x42, 0x00 }, | ||
701 | { 0x43, 0x00 }, | ||
702 | { 0x44, 0x00 }, | ||
703 | { 0x45, 0x00 }, | ||
704 | { 0x46, 0x00 }, | ||
705 | { 0x47, 0x00 }, | ||
706 | { 0x48, 0x00 }, | ||
707 | { 0x49, 0x00 }, | ||
708 | { 0x4a, 0x00 }, | ||
709 | { 0x4b, 0x00 }, | ||
710 | { 0x4c, 0x00 }, | ||
711 | { 0x4d, 0x00 }, | ||
712 | { 0x4e, 0x00 }, | ||
713 | { 0x4f, 0x00 }, | ||
714 | { 0x50, 0x00 }, | ||
715 | { 0x51, 0x00 }, | ||
716 | { 0x52, 0x00 }, | ||
717 | { 0x53, 0x00 }, | ||
718 | { 0x54, 0x00 }, | ||
719 | { 0x55, 0x00 }, | ||
720 | { 0x56, 0x00 }, | ||
721 | { 0x57, 0x00 }, | ||
722 | { 0x58, 0x00 }, | ||
723 | { 0x59, 0x00 }, | ||
724 | { 0x5a, 0x00 }, | ||
725 | { 0x5b, 0x00 }, | ||
726 | { 0x5c, 0x00 }, | ||
727 | { 0x5d, 0x00 }, | ||
728 | { 0x5e, 0x00 }, | ||
729 | { 0x5f, 0x00 }, | ||
730 | { 0x60, 0x00 }, | ||
731 | { 0x61, 0x00 }, | ||
732 | { 0x62, 0x00 }, | ||
733 | { 0x63, 0x00 }, | ||
734 | { 0x64, 0x00 }, | ||
735 | { 0x65, 0x00 }, | ||
736 | { 0x66, 0x00 }, | ||
737 | { 0x67, 0x00 }, | ||
738 | { 0x68, 0x00 }, | ||
739 | { 0x69, 0x00 }, | ||
740 | { 0x6a, 0x00 }, | ||
741 | { 0x6b, 0x00 }, | ||
742 | { 0x6c, 0x00 }, | ||
743 | { 0x6d, 0x00 }, | ||
744 | { 0x6e, 0x00 }, | ||
745 | { 0x6f, 0x00 }, | ||
746 | { 0x70, 0x00 }, | ||
747 | { 0x71, 0x00 }, | ||
748 | { 0x72, 0x00 }, | ||
749 | { 0x73, 0x00 }, | ||
750 | { 0x74, 0x00 }, | ||
751 | { 0x75, 0x00 }, | ||
752 | { 0x76, 0x00 }, | ||
753 | { 0x77, 0x00 }, | ||
754 | { 0x78, 0x00 }, | ||
755 | { 0x79, 0x00 }, | ||
756 | { 0x7a, 0x00 }, | ||
757 | { 0x7b, 0x00 }, | ||
758 | { 0x7c, 0x00 }, | ||
759 | { 0x7d, 0x54 }, | ||
760 | { 0x7e, 0x54 }, | ||
761 | { 0x7f, 0x00 }, | ||
762 | { 0x80, 0x00 }, | ||
763 | { 0x81, 0x00 }, | ||
764 | { 0x82, 0x2c }, | ||
765 | { 0x83, 0x00 }, | ||
766 | { 0x84, 0x00 }, | ||
767 | { 0x85, 0x00 }, | ||
768 | { 0x86, 0x00 }, | ||
769 | { 0x87, 0x00 }, | ||
770 | { 0x88, 0x00 }, | ||
654 | }; | 771 | }; |
655 | 772 | ||
656 | static int da7210_volatile_register(struct snd_soc_codec *codec, | 773 | static bool da7210_readable_register(struct device *dev, unsigned int reg) |
774 | { | ||
775 | switch (reg) { | ||
776 | case DA7210_A_HID_UNLOCK: | ||
777 | case DA7210_A_TEST_UNLOCK: | ||
778 | case DA7210_A_PLL1: | ||
779 | case DA7210_A_CP_MODE: | ||
780 | return false; | ||
781 | default: | ||
782 | return true; | ||
783 | } | ||
784 | } | ||
785 | |||
786 | static bool da7210_volatile_register(struct device *dev, | ||
657 | unsigned int reg) | 787 | unsigned int reg) |
658 | { | 788 | { |
659 | switch (reg) { | 789 | switch (reg) { |
660 | case DA7210_STATUS: | 790 | case DA7210_STATUS: |
661 | return 1; | 791 | return true; |
662 | default: | 792 | default: |
663 | return 0; | 793 | return false; |
664 | } | 794 | } |
665 | } | 795 | } |
666 | 796 | ||
@@ -866,7 +996,8 @@ static int da7210_probe(struct snd_soc_codec *codec) | |||
866 | 996 | ||
867 | dev_info(codec->dev, "DA7210 Audio Codec %s\n", DA7210_VERSION); | 997 | dev_info(codec->dev, "DA7210 Audio Codec %s\n", DA7210_VERSION); |
868 | 998 | ||
869 | ret = snd_soc_codec_set_cache_io(codec, 8, 8, da7210->control_type); | 999 | codec->control_data = da7210->regmap; |
1000 | ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_REGMAP); | ||
870 | if (ret < 0) { | 1001 | if (ret < 0) { |
871 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); | 1002 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); |
872 | return ret; | 1003 | return ret; |
@@ -983,12 +1114,14 @@ static int da7210_probe(struct snd_soc_codec *codec) | |||
983 | snd_soc_update_bits(codec, DA7210_PLL, DA7210_PLL_EN, DA7210_PLL_EN); | 1114 | snd_soc_update_bits(codec, DA7210_PLL, DA7210_PLL_EN, DA7210_PLL_EN); |
984 | 1115 | ||
985 | /* As suggested by Dialog */ | 1116 | /* As suggested by Dialog */ |
986 | snd_soc_write(codec, DA7210_A_HID_UNLOCK, 0x8B); /* unlock */ | 1117 | /* unlock */ |
987 | snd_soc_write(codec, DA7210_A_TEST_UNLOCK, 0xB4); | 1118 | regmap_write(da7210->regmap, DA7210_A_HID_UNLOCK, 0x8B); |
988 | snd_soc_write(codec, DA7210_A_PLL1, 0x01); | 1119 | regmap_write(da7210->regmap, DA7210_A_TEST_UNLOCK, 0xB4); |
989 | snd_soc_write(codec, DA7210_A_CP_MODE, 0x7C); | 1120 | regmap_write(da7210->regmap, DA7210_A_PLL1, 0x01); |
990 | snd_soc_write(codec, DA7210_A_HID_UNLOCK, 0x00); /* re-lock */ | 1121 | regmap_write(da7210->regmap, DA7210_A_CP_MODE, 0x7C); |
991 | snd_soc_write(codec, DA7210_A_TEST_UNLOCK, 0x00); | 1122 | /* re-lock */ |
1123 | regmap_write(da7210->regmap, DA7210_A_HID_UNLOCK, 0x00); | ||
1124 | regmap_write(da7210->regmap, DA7210_A_TEST_UNLOCK, 0x00); | ||
992 | 1125 | ||
993 | /* Activate all enabled subsystem */ | 1126 | /* Activate all enabled subsystem */ |
994 | snd_soc_write(codec, DA7210_STARTUP1, DA7210_SC_MST_EN); | 1127 | snd_soc_write(codec, DA7210_STARTUP1, DA7210_SC_MST_EN); |
@@ -1000,10 +1133,6 @@ static int da7210_probe(struct snd_soc_codec *codec) | |||
1000 | 1133 | ||
1001 | static struct snd_soc_codec_driver soc_codec_dev_da7210 = { | 1134 | static struct snd_soc_codec_driver soc_codec_dev_da7210 = { |
1002 | .probe = da7210_probe, | 1135 | .probe = da7210_probe, |
1003 | .reg_cache_size = ARRAY_SIZE(da7210_reg), | ||
1004 | .reg_word_size = sizeof(u8), | ||
1005 | .reg_cache_default = da7210_reg, | ||
1006 | .volatile_register = da7210_volatile_register, | ||
1007 | 1136 | ||
1008 | .controls = da7210_snd_controls, | 1137 | .controls = da7210_snd_controls, |
1009 | .num_controls = ARRAY_SIZE(da7210_snd_controls), | 1138 | .num_controls = ARRAY_SIZE(da7210_snd_controls), |
@@ -1014,6 +1143,17 @@ static struct snd_soc_codec_driver soc_codec_dev_da7210 = { | |||
1014 | .num_dapm_routes = ARRAY_SIZE(da7210_audio_map), | 1143 | .num_dapm_routes = ARRAY_SIZE(da7210_audio_map), |
1015 | }; | 1144 | }; |
1016 | 1145 | ||
1146 | static struct regmap_config da7210_regmap = { | ||
1147 | .reg_bits = 8, | ||
1148 | .val_bits = 8, | ||
1149 | |||
1150 | .reg_defaults = da7210_reg_defaults, | ||
1151 | .num_reg_defaults = ARRAY_SIZE(da7210_reg_defaults), | ||
1152 | .volatile_reg = da7210_volatile_register, | ||
1153 | .readable_reg = da7210_readable_register, | ||
1154 | .cache_type = REGCACHE_RBTREE, | ||
1155 | }; | ||
1156 | |||
1017 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 1157 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) |
1018 | static int __devinit da7210_i2c_probe(struct i2c_client *i2c, | 1158 | static int __devinit da7210_i2c_probe(struct i2c_client *i2c, |
1019 | const struct i2c_device_id *id) | 1159 | const struct i2c_device_id *id) |
@@ -1027,16 +1167,34 @@ static int __devinit da7210_i2c_probe(struct i2c_client *i2c, | |||
1027 | return -ENOMEM; | 1167 | return -ENOMEM; |
1028 | 1168 | ||
1029 | i2c_set_clientdata(i2c, da7210); | 1169 | i2c_set_clientdata(i2c, da7210); |
1030 | da7210->control_type = SND_SOC_I2C; | 1170 | |
1171 | da7210->regmap = regmap_init_i2c(i2c, &da7210_regmap); | ||
1172 | if (IS_ERR(da7210->regmap)) { | ||
1173 | ret = PTR_ERR(da7210->regmap); | ||
1174 | dev_err(&i2c->dev, "regmap_init() failed: %d\n", ret); | ||
1175 | return ret; | ||
1176 | } | ||
1031 | 1177 | ||
1032 | ret = snd_soc_register_codec(&i2c->dev, | 1178 | ret = snd_soc_register_codec(&i2c->dev, |
1033 | &soc_codec_dev_da7210, &da7210_dai, 1); | 1179 | &soc_codec_dev_da7210, &da7210_dai, 1); |
1180 | if (ret < 0) { | ||
1181 | dev_err(&i2c->dev, "Failed to register codec: %d\n", ret); | ||
1182 | goto err_regmap; | ||
1183 | } | ||
1184 | return ret; | ||
1185 | |||
1186 | err_regmap: | ||
1187 | regmap_exit(da7210->regmap); | ||
1188 | |||
1034 | return ret; | 1189 | return ret; |
1035 | } | 1190 | } |
1036 | 1191 | ||
1037 | static int __devexit da7210_i2c_remove(struct i2c_client *client) | 1192 | static int __devexit da7210_i2c_remove(struct i2c_client *client) |
1038 | { | 1193 | { |
1194 | struct da7210_priv *da7210 = i2c_get_clientdata(client); | ||
1195 | |||
1039 | snd_soc_unregister_codec(&client->dev); | 1196 | snd_soc_unregister_codec(&client->dev); |
1197 | regmap_exit(da7210->regmap); | ||
1040 | return 0; | 1198 | return 0; |
1041 | } | 1199 | } |
1042 | 1200 | ||