diff options
Diffstat (limited to 'sound/soc/codecs/wm8983.c')
-rw-r--r-- | sound/soc/codecs/wm8983.c | 162 |
1 files changed, 88 insertions, 74 deletions
diff --git a/sound/soc/codecs/wm8983.c b/sound/soc/codecs/wm8983.c index 367388fdc486..d8879f262d27 100644 --- a/sound/soc/codecs/wm8983.c +++ b/sound/soc/codecs/wm8983.c | |||
@@ -16,6 +16,7 @@ | |||
16 | #include <linux/delay.h> | 16 | #include <linux/delay.h> |
17 | #include <linux/pm.h> | 17 | #include <linux/pm.h> |
18 | #include <linux/i2c.h> | 18 | #include <linux/i2c.h> |
19 | #include <linux/regmap.h> | ||
19 | #include <linux/spi/spi.h> | 20 | #include <linux/spi/spi.h> |
20 | #include <linux/slab.h> | 21 | #include <linux/slab.h> |
21 | #include <sound/core.h> | 22 | #include <sound/core.h> |
@@ -27,61 +28,60 @@ | |||
27 | 28 | ||
28 | #include "wm8983.h" | 29 | #include "wm8983.h" |
29 | 30 | ||
30 | static const u16 wm8983_reg_defs[WM8983_MAX_REGISTER + 1] = { | 31 | static const struct reg_default wm8983_defaults[] = { |
31 | [0x00] = 0x0000, /* R0 - Software Reset */ | 32 | { 0x01, 0x0000 }, /* R1 - Power management 1 */ |
32 | [0x01] = 0x0000, /* R1 - Power management 1 */ | 33 | { 0x02, 0x0000 }, /* R2 - Power management 2 */ |
33 | [0x02] = 0x0000, /* R2 - Power management 2 */ | 34 | { 0x03, 0x0000 }, /* R3 - Power management 3 */ |
34 | [0x03] = 0x0000, /* R3 - Power management 3 */ | 35 | { 0x04, 0x0050 }, /* R4 - Audio Interface */ |
35 | [0x04] = 0x0050, /* R4 - Audio Interface */ | 36 | { 0x05, 0x0000 }, /* R5 - Companding control */ |
36 | [0x05] = 0x0000, /* R5 - Companding control */ | 37 | { 0x06, 0x0140 }, /* R6 - Clock Gen control */ |
37 | [0x06] = 0x0140, /* R6 - Clock Gen control */ | 38 | { 0x07, 0x0000 }, /* R7 - Additional control */ |
38 | [0x07] = 0x0000, /* R7 - Additional control */ | 39 | { 0x08, 0x0000 }, /* R8 - GPIO Control */ |
39 | [0x08] = 0x0000, /* R8 - GPIO Control */ | 40 | { 0x09, 0x0000 }, /* R9 - Jack Detect Control 1 */ |
40 | [0x09] = 0x0000, /* R9 - Jack Detect Control 1 */ | 41 | { 0x0A, 0x0000 }, /* R10 - DAC Control */ |
41 | [0x0A] = 0x0000, /* R10 - DAC Control */ | 42 | { 0x0B, 0x00FF }, /* R11 - Left DAC digital Vol */ |
42 | [0x0B] = 0x00FF, /* R11 - Left DAC digital Vol */ | 43 | { 0x0C, 0x00FF }, /* R12 - Right DAC digital vol */ |
43 | [0x0C] = 0x00FF, /* R12 - Right DAC digital vol */ | 44 | { 0x0D, 0x0000 }, /* R13 - Jack Detect Control 2 */ |
44 | [0x0D] = 0x0000, /* R13 - Jack Detect Control 2 */ | 45 | { 0x0E, 0x0100 }, /* R14 - ADC Control */ |
45 | [0x0E] = 0x0100, /* R14 - ADC Control */ | 46 | { 0x0F, 0x00FF }, /* R15 - Left ADC Digital Vol */ |
46 | [0x0F] = 0x00FF, /* R15 - Left ADC Digital Vol */ | 47 | { 0x10, 0x00FF }, /* R16 - Right ADC Digital Vol */ |
47 | [0x10] = 0x00FF, /* R16 - Right ADC Digital Vol */ | 48 | { 0x12, 0x012C }, /* R18 - EQ1 - low shelf */ |
48 | [0x12] = 0x012C, /* R18 - EQ1 - low shelf */ | 49 | { 0x13, 0x002C }, /* R19 - EQ2 - peak 1 */ |
49 | [0x13] = 0x002C, /* R19 - EQ2 - peak 1 */ | 50 | { 0x14, 0x002C }, /* R20 - EQ3 - peak 2 */ |
50 | [0x14] = 0x002C, /* R20 - EQ3 - peak 2 */ | 51 | { 0x15, 0x002C }, /* R21 - EQ4 - peak 3 */ |
51 | [0x15] = 0x002C, /* R21 - EQ4 - peak 3 */ | 52 | { 0x16, 0x002C }, /* R22 - EQ5 - high shelf */ |
52 | [0x16] = 0x002C, /* R22 - EQ5 - high shelf */ | 53 | { 0x18, 0x0032 }, /* R24 - DAC Limiter 1 */ |
53 | [0x18] = 0x0032, /* R24 - DAC Limiter 1 */ | 54 | { 0x19, 0x0000 }, /* R25 - DAC Limiter 2 */ |
54 | [0x19] = 0x0000, /* R25 - DAC Limiter 2 */ | 55 | { 0x1B, 0x0000 }, /* R27 - Notch Filter 1 */ |
55 | [0x1B] = 0x0000, /* R27 - Notch Filter 1 */ | 56 | { 0x1C, 0x0000 }, /* R28 - Notch Filter 2 */ |
56 | [0x1C] = 0x0000, /* R28 - Notch Filter 2 */ | 57 | { 0x1D, 0x0000 }, /* R29 - Notch Filter 3 */ |
57 | [0x1D] = 0x0000, /* R29 - Notch Filter 3 */ | 58 | { 0x1E, 0x0000 }, /* R30 - Notch Filter 4 */ |
58 | [0x1E] = 0x0000, /* R30 - Notch Filter 4 */ | 59 | { 0x20, 0x0038 }, /* R32 - ALC control 1 */ |
59 | [0x20] = 0x0038, /* R32 - ALC control 1 */ | 60 | { 0x21, 0x000B }, /* R33 - ALC control 2 */ |
60 | [0x21] = 0x000B, /* R33 - ALC control 2 */ | 61 | { 0x22, 0x0032 }, /* R34 - ALC control 3 */ |
61 | [0x22] = 0x0032, /* R34 - ALC control 3 */ | 62 | { 0x23, 0x0000 }, /* R35 - Noise Gate */ |
62 | [0x23] = 0x0000, /* R35 - Noise Gate */ | 63 | { 0x24, 0x0008 }, /* R36 - PLL N */ |
63 | [0x24] = 0x0008, /* R36 - PLL N */ | 64 | { 0x25, 0x000C }, /* R37 - PLL K 1 */ |
64 | [0x25] = 0x000C, /* R37 - PLL K 1 */ | 65 | { 0x26, 0x0093 }, /* R38 - PLL K 2 */ |
65 | [0x26] = 0x0093, /* R38 - PLL K 2 */ | 66 | { 0x27, 0x00E9 }, /* R39 - PLL K 3 */ |
66 | [0x27] = 0x00E9, /* R39 - PLL K 3 */ | 67 | { 0x29, 0x0000 }, /* R41 - 3D control */ |
67 | [0x29] = 0x0000, /* R41 - 3D control */ | 68 | { 0x2A, 0x0000 }, /* R42 - OUT4 to ADC */ |
68 | [0x2A] = 0x0000, /* R42 - OUT4 to ADC */ | 69 | { 0x2B, 0x0000 }, /* R43 - Beep control */ |
69 | [0x2B] = 0x0000, /* R43 - Beep control */ | 70 | { 0x2C, 0x0033 }, /* R44 - Input ctrl */ |
70 | [0x2C] = 0x0033, /* R44 - Input ctrl */ | 71 | { 0x2D, 0x0010 }, /* R45 - Left INP PGA gain ctrl */ |
71 | [0x2D] = 0x0010, /* R45 - Left INP PGA gain ctrl */ | 72 | { 0x2E, 0x0010 }, /* R46 - Right INP PGA gain ctrl */ |
72 | [0x2E] = 0x0010, /* R46 - Right INP PGA gain ctrl */ | 73 | { 0x2F, 0x0100 }, /* R47 - Left ADC BOOST ctrl */ |
73 | [0x2F] = 0x0100, /* R47 - Left ADC BOOST ctrl */ | 74 | { 0x30, 0x0100 }, /* R48 - Right ADC BOOST ctrl */ |
74 | [0x30] = 0x0100, /* R48 - Right ADC BOOST ctrl */ | 75 | { 0x31, 0x0002 }, /* R49 - Output ctrl */ |
75 | [0x31] = 0x0002, /* R49 - Output ctrl */ | 76 | { 0x32, 0x0001 }, /* R50 - Left mixer ctrl */ |
76 | [0x32] = 0x0001, /* R50 - Left mixer ctrl */ | 77 | { 0x33, 0x0001 }, /* R51 - Right mixer ctrl */ |
77 | [0x33] = 0x0001, /* R51 - Right mixer ctrl */ | 78 | { 0x34, 0x0039 }, /* R52 - LOUT1 (HP) volume ctrl */ |
78 | [0x34] = 0x0039, /* R52 - LOUT1 (HP) volume ctrl */ | 79 | { 0x35, 0x0039 }, /* R53 - ROUT1 (HP) volume ctrl */ |
79 | [0x35] = 0x0039, /* R53 - ROUT1 (HP) volume ctrl */ | 80 | { 0x36, 0x0039 }, /* R54 - LOUT2 (SPK) volume ctrl */ |
80 | [0x36] = 0x0039, /* R54 - LOUT2 (SPK) volume ctrl */ | 81 | { 0x37, 0x0039 }, /* R55 - ROUT2 (SPK) volume ctrl */ |
81 | [0x37] = 0x0039, /* R55 - ROUT2 (SPK) volume ctrl */ | 82 | { 0x38, 0x0001 }, /* R56 - OUT3 mixer ctrl */ |
82 | [0x38] = 0x0001, /* R56 - OUT3 mixer ctrl */ | 83 | { 0x39, 0x0001 }, /* R57 - OUT4 (MONO) mix ctrl */ |
83 | [0x39] = 0x0001, /* R57 - OUT4 (MONO) mix ctrl */ | 84 | { 0x3D, 0x0000 }, /* R61 - BIAS CTRL */ |
84 | [0x3D] = 0x0000 /* R61 - BIAS CTRL */ | ||
85 | }; | 85 | }; |
86 | 86 | ||
87 | static const struct wm8983_reg_access { | 87 | static const struct wm8983_reg_access { |
@@ -159,7 +159,7 @@ static const int vol_update_regs[] = { | |||
159 | }; | 159 | }; |
160 | 160 | ||
161 | struct wm8983_priv { | 161 | struct wm8983_priv { |
162 | enum snd_soc_control_type control_type; | 162 | struct regmap *regmap; |
163 | u32 sysclk; | 163 | u32 sysclk; |
164 | u32 bclk; | 164 | u32 bclk; |
165 | }; | 165 | }; |
@@ -610,7 +610,7 @@ static int eqmode_put(struct snd_kcontrol *kcontrol, | |||
610 | return 0; | 610 | return 0; |
611 | } | 611 | } |
612 | 612 | ||
613 | static int wm8983_readable(struct snd_soc_codec *codec, unsigned int reg) | 613 | static bool wm8983_readable(struct device *dev, unsigned int reg) |
614 | { | 614 | { |
615 | if (reg > WM8983_MAX_REGISTER) | 615 | if (reg > WM8983_MAX_REGISTER) |
616 | return 0; | 616 | return 0; |
@@ -905,6 +905,7 @@ static int wm8983_set_sysclk(struct snd_soc_dai *dai, | |||
905 | static int wm8983_set_bias_level(struct snd_soc_codec *codec, | 905 | static int wm8983_set_bias_level(struct snd_soc_codec *codec, |
906 | enum snd_soc_bias_level level) | 906 | enum snd_soc_bias_level level) |
907 | { | 907 | { |
908 | struct wm8983_priv *wm8983 = snd_soc_codec_get_drvdata(codec); | ||
908 | int ret; | 909 | int ret; |
909 | 910 | ||
910 | switch (level) { | 911 | switch (level) { |
@@ -917,7 +918,7 @@ static int wm8983_set_bias_level(struct snd_soc_codec *codec, | |||
917 | break; | 918 | break; |
918 | case SND_SOC_BIAS_STANDBY: | 919 | case SND_SOC_BIAS_STANDBY: |
919 | if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { | 920 | if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { |
920 | ret = snd_soc_cache_sync(codec); | 921 | ret = regcache_sync(wm8983->regmap); |
921 | if (ret < 0) { | 922 | if (ret < 0) { |
922 | dev_err(codec->dev, "Failed to sync cache: %d\n", ret); | 923 | dev_err(codec->dev, "Failed to sync cache: %d\n", ret); |
923 | return ret; | 924 | return ret; |
@@ -994,10 +995,9 @@ static int wm8983_remove(struct snd_soc_codec *codec) | |||
994 | static int wm8983_probe(struct snd_soc_codec *codec) | 995 | static int wm8983_probe(struct snd_soc_codec *codec) |
995 | { | 996 | { |
996 | int ret; | 997 | int ret; |
997 | struct wm8983_priv *wm8983 = snd_soc_codec_get_drvdata(codec); | ||
998 | int i; | 998 | int i; |
999 | 999 | ||
1000 | ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8983->control_type); | 1000 | ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_REGMAP); |
1001 | if (ret < 0) { | 1001 | if (ret < 0) { |
1002 | 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); |
1003 | return ret; | 1003 | return ret; |
@@ -1067,16 +1067,23 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8983 = { | |||
1067 | .suspend = wm8983_suspend, | 1067 | .suspend = wm8983_suspend, |
1068 | .resume = wm8983_resume, | 1068 | .resume = wm8983_resume, |
1069 | .set_bias_level = wm8983_set_bias_level, | 1069 | .set_bias_level = wm8983_set_bias_level, |
1070 | .reg_cache_size = ARRAY_SIZE(wm8983_reg_defs), | ||
1071 | .reg_word_size = sizeof(u16), | ||
1072 | .reg_cache_default = wm8983_reg_defs, | ||
1073 | .controls = wm8983_snd_controls, | 1070 | .controls = wm8983_snd_controls, |
1074 | .num_controls = ARRAY_SIZE(wm8983_snd_controls), | 1071 | .num_controls = ARRAY_SIZE(wm8983_snd_controls), |
1075 | .dapm_widgets = wm8983_dapm_widgets, | 1072 | .dapm_widgets = wm8983_dapm_widgets, |
1076 | .num_dapm_widgets = ARRAY_SIZE(wm8983_dapm_widgets), | 1073 | .num_dapm_widgets = ARRAY_SIZE(wm8983_dapm_widgets), |
1077 | .dapm_routes = wm8983_audio_map, | 1074 | .dapm_routes = wm8983_audio_map, |
1078 | .num_dapm_routes = ARRAY_SIZE(wm8983_audio_map), | 1075 | .num_dapm_routes = ARRAY_SIZE(wm8983_audio_map), |
1079 | .readable_register = wm8983_readable | 1076 | }; |
1077 | |||
1078 | static const struct regmap_config wm8983_regmap = { | ||
1079 | .reg_bits = 7, | ||
1080 | .val_bits = 9, | ||
1081 | |||
1082 | .reg_defaults = wm8983_defaults, | ||
1083 | .num_reg_defaults = ARRAY_SIZE(wm8983_defaults), | ||
1084 | .cache_type = REGCACHE_RBTREE, | ||
1085 | |||
1086 | .readable_reg = wm8983_readable, | ||
1080 | }; | 1087 | }; |
1081 | 1088 | ||
1082 | #if defined(CONFIG_SPI_MASTER) | 1089 | #if defined(CONFIG_SPI_MASTER) |
@@ -1085,24 +1092,27 @@ static int __devinit wm8983_spi_probe(struct spi_device *spi) | |||
1085 | struct wm8983_priv *wm8983; | 1092 | struct wm8983_priv *wm8983; |
1086 | int ret; | 1093 | int ret; |
1087 | 1094 | ||
1088 | wm8983 = kzalloc(sizeof *wm8983, GFP_KERNEL); | 1095 | wm8983 = devm_kzalloc(&spi->dev, sizeof *wm8983, GFP_KERNEL); |
1089 | if (!wm8983) | 1096 | if (!wm8983) |
1090 | return -ENOMEM; | 1097 | return -ENOMEM; |
1091 | 1098 | ||
1092 | wm8983->control_type = SND_SOC_SPI; | 1099 | wm8983->regmap = devm_regmap_init_spi(spi, &wm8983_regmap); |
1100 | if (IS_ERR(wm8983->regmap)) { | ||
1101 | ret = PTR_ERR(wm8983->regmap); | ||
1102 | dev_err(&spi->dev, "Failed to init regmap: %d\n", ret); | ||
1103 | return ret; | ||
1104 | } | ||
1105 | |||
1093 | spi_set_drvdata(spi, wm8983); | 1106 | spi_set_drvdata(spi, wm8983); |
1094 | 1107 | ||
1095 | ret = snd_soc_register_codec(&spi->dev, | 1108 | ret = snd_soc_register_codec(&spi->dev, |
1096 | &soc_codec_dev_wm8983, &wm8983_dai, 1); | 1109 | &soc_codec_dev_wm8983, &wm8983_dai, 1); |
1097 | if (ret < 0) | ||
1098 | kfree(wm8983); | ||
1099 | return ret; | 1110 | return ret; |
1100 | } | 1111 | } |
1101 | 1112 | ||
1102 | static int __devexit wm8983_spi_remove(struct spi_device *spi) | 1113 | static int __devexit wm8983_spi_remove(struct spi_device *spi) |
1103 | { | 1114 | { |
1104 | snd_soc_unregister_codec(&spi->dev); | 1115 | snd_soc_unregister_codec(&spi->dev); |
1105 | kfree(spi_get_drvdata(spi)); | ||
1106 | return 0; | 1116 | return 0; |
1107 | } | 1117 | } |
1108 | 1118 | ||
@@ -1123,24 +1133,28 @@ static __devinit int wm8983_i2c_probe(struct i2c_client *i2c, | |||
1123 | struct wm8983_priv *wm8983; | 1133 | struct wm8983_priv *wm8983; |
1124 | int ret; | 1134 | int ret; |
1125 | 1135 | ||
1126 | wm8983 = kzalloc(sizeof *wm8983, GFP_KERNEL); | 1136 | wm8983 = devm_kzalloc(&i2c->dev, sizeof *wm8983, GFP_KERNEL); |
1127 | if (!wm8983) | 1137 | if (!wm8983) |
1128 | return -ENOMEM; | 1138 | return -ENOMEM; |
1129 | 1139 | ||
1130 | wm8983->control_type = SND_SOC_I2C; | 1140 | wm8983->regmap = devm_regmap_init_i2c(i2c, &wm8983_regmap); |
1141 | if (IS_ERR(wm8983->regmap)) { | ||
1142 | ret = PTR_ERR(wm8983->regmap); | ||
1143 | dev_err(&i2c->dev, "Failed to init regmap: %d\n", ret); | ||
1144 | return ret; | ||
1145 | } | ||
1146 | |||
1131 | i2c_set_clientdata(i2c, wm8983); | 1147 | i2c_set_clientdata(i2c, wm8983); |
1132 | 1148 | ||
1133 | ret = snd_soc_register_codec(&i2c->dev, | 1149 | ret = snd_soc_register_codec(&i2c->dev, |
1134 | &soc_codec_dev_wm8983, &wm8983_dai, 1); | 1150 | &soc_codec_dev_wm8983, &wm8983_dai, 1); |
1135 | if (ret < 0) | 1151 | |
1136 | kfree(wm8983); | ||
1137 | return ret; | 1152 | return ret; |
1138 | } | 1153 | } |
1139 | 1154 | ||
1140 | static __devexit int wm8983_i2c_remove(struct i2c_client *client) | 1155 | static __devexit int wm8983_i2c_remove(struct i2c_client *client) |
1141 | { | 1156 | { |
1142 | snd_soc_unregister_codec(&client->dev); | 1157 | snd_soc_unregister_codec(&client->dev); |
1143 | kfree(i2c_get_clientdata(client)); | ||
1144 | return 0; | 1158 | return 0; |
1145 | } | 1159 | } |
1146 | 1160 | ||