diff options
Diffstat (limited to 'sound/soc/codecs/wm8991.c')
-rw-r--r-- | sound/soc/codecs/wm8991.c | 293 |
1 files changed, 153 insertions, 140 deletions
diff --git a/sound/soc/codecs/wm8991.c b/sound/soc/codecs/wm8991.c index 3a39df7a3829..dba0306c42a5 100644 --- a/sound/soc/codecs/wm8991.c +++ b/sound/soc/codecs/wm8991.c | |||
@@ -18,6 +18,7 @@ | |||
18 | #include <linux/delay.h> | 18 | #include <linux/delay.h> |
19 | #include <linux/pm.h> | 19 | #include <linux/pm.h> |
20 | #include <linux/i2c.h> | 20 | #include <linux/i2c.h> |
21 | #include <linux/regmap.h> | ||
21 | #include <linux/slab.h> | 22 | #include <linux/slab.h> |
22 | #include <sound/core.h> | 23 | #include <sound/core.h> |
23 | #include <sound/pcm.h> | 24 | #include <sound/pcm.h> |
@@ -31,77 +32,84 @@ | |||
31 | #include "wm8991.h" | 32 | #include "wm8991.h" |
32 | 33 | ||
33 | struct wm8991_priv { | 34 | struct wm8991_priv { |
34 | enum snd_soc_control_type control_type; | 35 | struct regmap *regmap; |
35 | unsigned int pcmclk; | 36 | unsigned int pcmclk; |
36 | }; | 37 | }; |
37 | 38 | ||
38 | static const u16 wm8991_reg_defs[] = { | 39 | static const struct reg_default wm8991_reg_defaults[] = { |
39 | 0x8991, /* R0 - Reset */ | 40 | { 1, 0x0000 }, /* R1 - Power Management (1) */ |
40 | 0x0000, /* R1 - Power Management (1) */ | 41 | { 2, 0x6000 }, /* R2 - Power Management (2) */ |
41 | 0x6000, /* R2 - Power Management (2) */ | 42 | { 3, 0x0000 }, /* R3 - Power Management (3) */ |
42 | 0x0000, /* R3 - Power Management (3) */ | 43 | { 4, 0x4050 }, /* R4 - Audio Interface (1) */ |
43 | 0x4050, /* R4 - Audio Interface (1) */ | 44 | { 5, 0x4000 }, /* R5 - Audio Interface (2) */ |
44 | 0x4000, /* R5 - Audio Interface (2) */ | 45 | { 6, 0x01C8 }, /* R6 - Clocking (1) */ |
45 | 0x01C8, /* R6 - Clocking (1) */ | 46 | { 7, 0x0000 }, /* R7 - Clocking (2) */ |
46 | 0x0000, /* R7 - Clocking (2) */ | 47 | { 8, 0x0040 }, /* R8 - Audio Interface (3) */ |
47 | 0x0040, /* R8 - Audio Interface (3) */ | 48 | { 9, 0x0040 }, /* R9 - Audio Interface (4) */ |
48 | 0x0040, /* R9 - Audio Interface (4) */ | 49 | { 10, 0x0004 }, /* R10 - DAC CTRL */ |
49 | 0x0004, /* R10 - DAC CTRL */ | 50 | { 11, 0x00C0 }, /* R11 - Left DAC Digital Volume */ |
50 | 0x00C0, /* R11 - Left DAC Digital Volume */ | 51 | { 12, 0x00C0 }, /* R12 - Right DAC Digital Volume */ |
51 | 0x00C0, /* R12 - Right DAC Digital Volume */ | 52 | { 13, 0x0000 }, /* R13 - Digital Side Tone */ |
52 | 0x0000, /* R13 - Digital Side Tone */ | 53 | { 14, 0x0100 }, /* R14 - ADC CTRL */ |
53 | 0x0100, /* R14 - ADC CTRL */ | 54 | { 15, 0x00C0 }, /* R15 - Left ADC Digital Volume */ |
54 | 0x00C0, /* R15 - Left ADC Digital Volume */ | 55 | { 16, 0x00C0 }, /* R16 - Right ADC Digital Volume */ |
55 | 0x00C0, /* R16 - Right ADC Digital Volume */ | 56 | |
56 | 0x0000, /* R17 */ | 57 | { 18, 0x0000 }, /* R18 - GPIO CTRL 1 */ |
57 | 0x0000, /* R18 - GPIO CTRL 1 */ | 58 | { 19, 0x1000 }, /* R19 - GPIO1 & GPIO2 */ |
58 | 0x1000, /* R19 - GPIO1 & GPIO2 */ | 59 | { 20, 0x1010 }, /* R20 - GPIO3 & GPIO4 */ |
59 | 0x1010, /* R20 - GPIO3 & GPIO4 */ | 60 | { 21, 0x1010 }, /* R21 - GPIO5 & GPIO6 */ |
60 | 0x1010, /* R21 - GPIO5 & GPIO6 */ | 61 | { 22, 0x8000 }, /* R22 - GPIOCTRL 2 */ |
61 | 0x8000, /* R22 - GPIOCTRL 2 */ | 62 | { 23, 0x0800 }, /* R23 - GPIO_POL */ |
62 | 0x0800, /* R23 - GPIO_POL */ | 63 | { 24, 0x008B }, /* R24 - Left Line Input 1&2 Volume */ |
63 | 0x008B, /* R24 - Left Line Input 1&2 Volume */ | 64 | { 25, 0x008B }, /* R25 - Left Line Input 3&4 Volume */ |
64 | 0x008B, /* R25 - Left Line Input 3&4 Volume */ | 65 | { 26, 0x008B }, /* R26 - Right Line Input 1&2 Volume */ |
65 | 0x008B, /* R26 - Right Line Input 1&2 Volume */ | 66 | { 27, 0x008B }, /* R27 - Right Line Input 3&4 Volume */ |
66 | 0x008B, /* R27 - Right Line Input 3&4 Volume */ | 67 | { 28, 0x0000 }, /* R28 - Left Output Volume */ |
67 | 0x0000, /* R28 - Left Output Volume */ | 68 | { 29, 0x0000 }, /* R29 - Right Output Volume */ |
68 | 0x0000, /* R29 - Right Output Volume */ | 69 | { 30, 0x0066 }, /* R30 - Line Outputs Volume */ |
69 | 0x0066, /* R30 - Line Outputs Volume */ | 70 | { 31, 0x0022 }, /* R31 - Out3/4 Volume */ |
70 | 0x0022, /* R31 - Out3/4 Volume */ | 71 | { 32, 0x0079 }, /* R32 - Left OPGA Volume */ |
71 | 0x0079, /* R32 - Left OPGA Volume */ | 72 | { 33, 0x0079 }, /* R33 - Right OPGA Volume */ |
72 | 0x0079, /* R33 - Right OPGA Volume */ | 73 | { 34, 0x0003 }, /* R34 - Speaker Volume */ |
73 | 0x0003, /* R34 - Speaker Volume */ | 74 | { 35, 0x0003 }, /* R35 - ClassD1 */ |
74 | 0x0003, /* R35 - ClassD1 */ | 75 | |
75 | 0x0000, /* R36 */ | 76 | { 37, 0x0100 }, /* R37 - ClassD3 */ |
76 | 0x0100, /* R37 - ClassD3 */ | 77 | |
77 | 0x0000, /* R38 */ | 78 | { 39, 0x0000 }, /* R39 - Input Mixer1 */ |
78 | 0x0000, /* R39 - Input Mixer1 */ | 79 | { 40, 0x0000 }, /* R40 - Input Mixer2 */ |
79 | 0x0000, /* R40 - Input Mixer2 */ | 80 | { 41, 0x0000 }, /* R41 - Input Mixer3 */ |
80 | 0x0000, /* R41 - Input Mixer3 */ | 81 | { 42, 0x0000 }, /* R42 - Input Mixer4 */ |
81 | 0x0000, /* R42 - Input Mixer4 */ | 82 | { 43, 0x0000 }, /* R43 - Input Mixer5 */ |
82 | 0x0000, /* R43 - Input Mixer5 */ | 83 | { 44, 0x0000 }, /* R44 - Input Mixer6 */ |
83 | 0x0000, /* R44 - Input Mixer6 */ | 84 | { 45, 0x0000 }, /* R45 - Output Mixer1 */ |
84 | 0x0000, /* R45 - Output Mixer1 */ | 85 | { 46, 0x0000 }, /* R46 - Output Mixer2 */ |
85 | 0x0000, /* R46 - Output Mixer2 */ | 86 | { 47, 0x0000 }, /* R47 - Output Mixer3 */ |
86 | 0x0000, /* R47 - Output Mixer3 */ | 87 | { 48, 0x0000 }, /* R48 - Output Mixer4 */ |
87 | 0x0000, /* R48 - Output Mixer4 */ | 88 | { 49, 0x0000 }, /* R49 - Output Mixer5 */ |
88 | 0x0000, /* R49 - Output Mixer5 */ | 89 | { 50, 0x0000 }, /* R50 - Output Mixer6 */ |
89 | 0x0000, /* R50 - Output Mixer6 */ | 90 | { 51, 0x0180 }, /* R51 - Out3/4 Mixer */ |
90 | 0x0180, /* R51 - Out3/4 Mixer */ | 91 | { 52, 0x0000 }, /* R52 - Line Mixer1 */ |
91 | 0x0000, /* R52 - Line Mixer1 */ | 92 | { 53, 0x0000 }, /* R53 - Line Mixer2 */ |
92 | 0x0000, /* R53 - Line Mixer2 */ | 93 | { 54, 0x0000 }, /* R54 - Speaker Mixer */ |
93 | 0x0000, /* R54 - Speaker Mixer */ | 94 | { 55, 0x0000 }, /* R55 - Additional Control */ |
94 | 0x0000, /* R55 - Additional Control */ | 95 | { 56, 0x0000 }, /* R56 - AntiPOP1 */ |
95 | 0x0000, /* R56 - AntiPOP1 */ | 96 | { 57, 0x0000 }, /* R57 - AntiPOP2 */ |
96 | 0x0000, /* R57 - AntiPOP2 */ | 97 | { 58, 0x0000 }, /* R58 - MICBIAS */ |
97 | 0x0000, /* R58 - MICBIAS */ | 98 | |
98 | 0x0000, /* R59 */ | 99 | { 60, 0x0008 }, /* R60 - PLL1 */ |
99 | 0x0008, /* R60 - PLL1 */ | 100 | { 61, 0x0031 }, /* R61 - PLL2 */ |
100 | 0x0031, /* R61 - PLL2 */ | 101 | { 62, 0x0026 }, /* R62 - PLL3 */ |
101 | 0x0026, /* R62 - PLL3 */ | ||
102 | }; | 102 | }; |
103 | 103 | ||
104 | #define wm8991_reset(c) snd_soc_write(c, WM8991_RESET, 0) | 104 | static bool wm8991_volatile(struct device *dev, unsigned int reg) |
105 | { | ||
106 | switch (reg) { | ||
107 | case WM8991_RESET: | ||
108 | return true; | ||
109 | default: | ||
110 | return false; | ||
111 | } | ||
112 | } | ||
105 | 113 | ||
106 | static const unsigned int rec_mix_tlv[] = { | 114 | static const unsigned int rec_mix_tlv[] = { |
107 | TLV_DB_RANGE_HEAD(1), | 115 | TLV_DB_RANGE_HEAD(1), |
@@ -374,30 +382,6 @@ static const struct snd_kcontrol_new wm8991_snd_controls[] = { | |||
374 | /* | 382 | /* |
375 | * _DAPM_ Controls | 383 | * _DAPM_ Controls |
376 | */ | 384 | */ |
377 | static int inmixer_event(struct snd_soc_dapm_widget *w, | ||
378 | struct snd_kcontrol *kcontrol, int event) | ||
379 | { | ||
380 | u16 reg, fakepower; | ||
381 | |||
382 | reg = snd_soc_read(w->codec, WM8991_POWER_MANAGEMENT_2); | ||
383 | fakepower = snd_soc_read(w->codec, WM8991_INTDRIVBITS); | ||
384 | |||
385 | if (fakepower & ((1 << WM8991_INMIXL_PWR_BIT) | | ||
386 | (1 << WM8991_AINLMUX_PWR_BIT))) | ||
387 | reg |= WM8991_AINL_ENA; | ||
388 | else | ||
389 | reg &= ~WM8991_AINL_ENA; | ||
390 | |||
391 | if (fakepower & ((1 << WM8991_INMIXR_PWR_BIT) | | ||
392 | (1 << WM8991_AINRMUX_PWR_BIT))) | ||
393 | reg |= WM8991_AINR_ENA; | ||
394 | else | ||
395 | reg &= ~WM8991_AINR_ENA; | ||
396 | |||
397 | snd_soc_write(w->codec, WM8991_POWER_MANAGEMENT_2, reg); | ||
398 | return 0; | ||
399 | } | ||
400 | |||
401 | static int outmixer_event(struct snd_soc_dapm_widget *w, | 385 | static int outmixer_event(struct snd_soc_dapm_widget *w, |
402 | struct snd_kcontrol *kcontrol, int event) | 386 | struct snd_kcontrol *kcontrol, int event) |
403 | { | 387 | { |
@@ -655,6 +639,11 @@ static const struct snd_soc_dapm_widget wm8991_dapm_widgets[] = { | |||
655 | SND_SOC_DAPM_INPUT("RIN2"), | 639 | SND_SOC_DAPM_INPUT("RIN2"), |
656 | SND_SOC_DAPM_INPUT("Internal ADC Source"), | 640 | SND_SOC_DAPM_INPUT("Internal ADC Source"), |
657 | 641 | ||
642 | SND_SOC_DAPM_SUPPLY("INL", WM8991_POWER_MANAGEMENT_2, | ||
643 | WM8991_AINL_ENA_BIT, 0, NULL, 0), | ||
644 | SND_SOC_DAPM_SUPPLY("INR", WM8991_POWER_MANAGEMENT_2, | ||
645 | WM8991_AINR_ENA_BIT, 0, NULL, 0), | ||
646 | |||
658 | /* DACs */ | 647 | /* DACs */ |
659 | SND_SOC_DAPM_ADC("Left ADC", "Left Capture", WM8991_POWER_MANAGEMENT_2, | 648 | SND_SOC_DAPM_ADC("Left ADC", "Left Capture", WM8991_POWER_MANAGEMENT_2, |
660 | WM8991_ADCL_ENA_BIT, 0), | 649 | WM8991_ADCL_ENA_BIT, 0), |
@@ -676,26 +665,22 @@ static const struct snd_soc_dapm_widget wm8991_dapm_widgets[] = { | |||
676 | ARRAY_SIZE(wm8991_dapm_rin34_pga_controls)), | 665 | ARRAY_SIZE(wm8991_dapm_rin34_pga_controls)), |
677 | 666 | ||
678 | /* INMIXL */ | 667 | /* INMIXL */ |
679 | SND_SOC_DAPM_MIXER_E("INMIXL", WM8991_INTDRIVBITS, WM8991_INMIXL_PWR_BIT, 0, | 668 | SND_SOC_DAPM_MIXER("INMIXL", SND_SOC_NOPM, 0, 0, |
680 | &wm8991_dapm_inmixl_controls[0], | 669 | &wm8991_dapm_inmixl_controls[0], |
681 | ARRAY_SIZE(wm8991_dapm_inmixl_controls), | 670 | ARRAY_SIZE(wm8991_dapm_inmixl_controls)), |
682 | inmixer_event, SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), | ||
683 | 671 | ||
684 | /* AINLMUX */ | 672 | /* AINLMUX */ |
685 | SND_SOC_DAPM_MUX_E("AINLMUX", WM8991_INTDRIVBITS, WM8991_AINLMUX_PWR_BIT, 0, | 673 | SND_SOC_DAPM_MUX("AINLMUX", SND_SOC_NOPM, 0, 0, |
686 | &wm8991_dapm_ainlmux_controls, inmixer_event, | 674 | &wm8991_dapm_ainlmux_controls), |
687 | SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), | ||
688 | 675 | ||
689 | /* INMIXR */ | 676 | /* INMIXR */ |
690 | SND_SOC_DAPM_MIXER_E("INMIXR", WM8991_INTDRIVBITS, WM8991_INMIXR_PWR_BIT, 0, | 677 | SND_SOC_DAPM_MIXER("INMIXR", SND_SOC_NOPM, 0, 0, |
691 | &wm8991_dapm_inmixr_controls[0], | 678 | &wm8991_dapm_inmixr_controls[0], |
692 | ARRAY_SIZE(wm8991_dapm_inmixr_controls), | 679 | ARRAY_SIZE(wm8991_dapm_inmixr_controls)), |
693 | inmixer_event, SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), | ||
694 | 680 | ||
695 | /* AINRMUX */ | 681 | /* AINRMUX */ |
696 | SND_SOC_DAPM_MUX_E("AINRMUX", WM8991_INTDRIVBITS, WM8991_AINRMUX_PWR_BIT, 0, | 682 | SND_SOC_DAPM_MUX("AINRMUX", SND_SOC_NOPM, 0, 0, |
697 | &wm8991_dapm_ainrmux_controls, inmixer_event, | 683 | &wm8991_dapm_ainrmux_controls), |
698 | SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), | ||
699 | 684 | ||
700 | /* Output Side */ | 685 | /* Output Side */ |
701 | /* DACs */ | 686 | /* DACs */ |
@@ -787,7 +772,7 @@ static const struct snd_soc_dapm_widget wm8991_dapm_widgets[] = { | |||
787 | SND_SOC_DAPM_OUTPUT("Internal DAC Sink"), | 772 | SND_SOC_DAPM_OUTPUT("Internal DAC Sink"), |
788 | }; | 773 | }; |
789 | 774 | ||
790 | static const struct snd_soc_dapm_route audio_map[] = { | 775 | static const struct snd_soc_dapm_route wm8991_dapm_routes[] = { |
791 | /* Make DACs turn on when playing even if not mixed into any outputs */ | 776 | /* Make DACs turn on when playing even if not mixed into any outputs */ |
792 | {"Internal DAC Sink", NULL, "Left DAC"}, | 777 | {"Internal DAC Sink", NULL, "Left DAC"}, |
793 | {"Internal DAC Sink", NULL, "Right DAC"}, | 778 | {"Internal DAC Sink", NULL, "Right DAC"}, |
@@ -797,6 +782,10 @@ static const struct snd_soc_dapm_route audio_map[] = { | |||
797 | {"Right ADC", NULL, "Internal ADC Source"}, | 782 | {"Right ADC", NULL, "Internal ADC Source"}, |
798 | 783 | ||
799 | /* Input Side */ | 784 | /* Input Side */ |
785 | {"INMIXL", NULL, "INL"}, | ||
786 | {"AINLMUX", NULL, "INL"}, | ||
787 | {"INMIXR", NULL, "INR"}, | ||
788 | {"AINRMUX", NULL, "INR"}, | ||
800 | /* LIN12 PGA */ | 789 | /* LIN12 PGA */ |
801 | {"LIN12 PGA", "LIN1 Switch", "LIN1"}, | 790 | {"LIN12 PGA", "LIN1 Switch", "LIN1"}, |
802 | {"LIN12 PGA", "LIN2 Switch", "LIN2"}, | 791 | {"LIN12 PGA", "LIN2 Switch", "LIN2"}, |
@@ -1129,6 +1118,7 @@ static int wm8991_mute(struct snd_soc_dai *dai, int mute) | |||
1129 | static int wm8991_set_bias_level(struct snd_soc_codec *codec, | 1118 | static int wm8991_set_bias_level(struct snd_soc_codec *codec, |
1130 | enum snd_soc_bias_level level) | 1119 | enum snd_soc_bias_level level) |
1131 | { | 1120 | { |
1121 | struct wm8991_priv *wm8991 = snd_soc_codec_get_drvdata(codec); | ||
1132 | u16 val; | 1122 | u16 val; |
1133 | 1123 | ||
1134 | switch (level) { | 1124 | switch (level) { |
@@ -1144,7 +1134,7 @@ static int wm8991_set_bias_level(struct snd_soc_codec *codec, | |||
1144 | 1134 | ||
1145 | case SND_SOC_BIAS_STANDBY: | 1135 | case SND_SOC_BIAS_STANDBY: |
1146 | if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { | 1136 | if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { |
1147 | snd_soc_cache_sync(codec); | 1137 | regcache_sync(wm8991->regmap); |
1148 | /* Enable all output discharge bits */ | 1138 | /* Enable all output discharge bits */ |
1149 | snd_soc_write(codec, WM8991_ANTIPOP1, WM8991_DIS_LLINE | | 1139 | snd_soc_write(codec, WM8991_ANTIPOP1, WM8991_DIS_LLINE | |
1150 | WM8991_DIS_RLINE | WM8991_DIS_OUT3 | | 1140 | WM8991_DIS_RLINE | WM8991_DIS_OUT3 | |
@@ -1232,7 +1222,7 @@ static int wm8991_set_bias_level(struct snd_soc_codec *codec, | |||
1232 | 1222 | ||
1233 | /* disable POBCTRL, SOFT_ST and BUFDCOPEN */ | 1223 | /* disable POBCTRL, SOFT_ST and BUFDCOPEN */ |
1234 | snd_soc_write(codec, WM8991_ANTIPOP2, 0x0); | 1224 | snd_soc_write(codec, WM8991_ANTIPOP2, 0x0); |
1235 | codec->cache_sync = 1; | 1225 | regcache_mark_dirty(wm8991->regmap); |
1236 | break; | 1226 | break; |
1237 | } | 1227 | } |
1238 | 1228 | ||
@@ -1266,44 +1256,14 @@ static int wm8991_probe(struct snd_soc_codec *codec) | |||
1266 | 1256 | ||
1267 | wm8991 = snd_soc_codec_get_drvdata(codec); | 1257 | wm8991 = snd_soc_codec_get_drvdata(codec); |
1268 | 1258 | ||
1269 | ret = snd_soc_codec_set_cache_io(codec, 8, 16, wm8991->control_type); | 1259 | ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_REGMAP); |
1270 | if (ret < 0) { | 1260 | if (ret < 0) { |
1271 | dev_err(codec->dev, "Failed to set cache i/o: %d\n", ret); | 1261 | dev_err(codec->dev, "Failed to set cache i/o: %d\n", ret); |
1272 | return ret; | 1262 | return ret; |
1273 | } | 1263 | } |
1274 | 1264 | ||
1275 | ret = wm8991_reset(codec); | ||
1276 | if (ret < 0) { | ||
1277 | dev_err(codec->dev, "Failed to issue reset\n"); | ||
1278 | return ret; | ||
1279 | } | ||
1280 | |||
1281 | wm8991_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | 1265 | wm8991_set_bias_level(codec, SND_SOC_BIAS_STANDBY); |
1282 | 1266 | ||
1283 | snd_soc_update_bits(codec, WM8991_AUDIO_INTERFACE_4, | ||
1284 | WM8991_ALRCGPIO1, WM8991_ALRCGPIO1); | ||
1285 | |||
1286 | snd_soc_update_bits(codec, WM8991_GPIO1_GPIO2, | ||
1287 | WM8991_GPIO1_SEL_MASK, 1); | ||
1288 | |||
1289 | snd_soc_update_bits(codec, WM8991_POWER_MANAGEMENT_1, | ||
1290 | WM8991_VREF_ENA | WM8991_VMID_MODE_MASK, | ||
1291 | WM8991_VREF_ENA | WM8991_VMID_MODE_MASK); | ||
1292 | |||
1293 | snd_soc_update_bits(codec, WM8991_POWER_MANAGEMENT_2, | ||
1294 | WM8991_OPCLK_ENA, WM8991_OPCLK_ENA); | ||
1295 | |||
1296 | snd_soc_write(codec, WM8991_DAC_CTRL, 0); | ||
1297 | snd_soc_write(codec, WM8991_LEFT_OUTPUT_VOLUME, 0x50 | (1<<8)); | ||
1298 | snd_soc_write(codec, WM8991_RIGHT_OUTPUT_VOLUME, 0x50 | (1<<8)); | ||
1299 | |||
1300 | snd_soc_add_codec_controls(codec, wm8991_snd_controls, | ||
1301 | ARRAY_SIZE(wm8991_snd_controls)); | ||
1302 | |||
1303 | snd_soc_dapm_new_controls(&codec->dapm, wm8991_dapm_widgets, | ||
1304 | ARRAY_SIZE(wm8991_dapm_widgets)); | ||
1305 | snd_soc_dapm_add_routes(&codec->dapm, audio_map, | ||
1306 | ARRAY_SIZE(audio_map)); | ||
1307 | return 0; | 1267 | return 0; |
1308 | } | 1268 | } |
1309 | 1269 | ||
@@ -1352,24 +1312,77 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8991 = { | |||
1352 | .suspend = wm8991_suspend, | 1312 | .suspend = wm8991_suspend, |
1353 | .resume = wm8991_resume, | 1313 | .resume = wm8991_resume, |
1354 | .set_bias_level = wm8991_set_bias_level, | 1314 | .set_bias_level = wm8991_set_bias_level, |
1355 | .reg_cache_size = WM8991_MAX_REGISTER + 1, | 1315 | .controls = wm8991_snd_controls, |
1356 | .reg_word_size = sizeof(u16), | 1316 | .num_controls = ARRAY_SIZE(wm8991_snd_controls), |
1357 | .reg_cache_default = wm8991_reg_defs | 1317 | .dapm_widgets = wm8991_dapm_widgets, |
1318 | .num_dapm_widgets = ARRAY_SIZE(wm8991_dapm_widgets), | ||
1319 | .dapm_routes = wm8991_dapm_routes, | ||
1320 | .num_dapm_routes = ARRAY_SIZE(wm8991_dapm_routes), | ||
1321 | }; | ||
1322 | |||
1323 | static const struct regmap_config wm8991_regmap = { | ||
1324 | .reg_bits = 8, | ||
1325 | .val_bits = 16, | ||
1326 | |||
1327 | .max_register = WM8991_PLL3, | ||
1328 | .volatile_reg = wm8991_volatile, | ||
1329 | .reg_defaults = wm8991_reg_defaults, | ||
1330 | .num_reg_defaults = ARRAY_SIZE(wm8991_reg_defaults), | ||
1331 | .cache_type = REGCACHE_RBTREE, | ||
1358 | }; | 1332 | }; |
1359 | 1333 | ||
1360 | static int wm8991_i2c_probe(struct i2c_client *i2c, | 1334 | static int wm8991_i2c_probe(struct i2c_client *i2c, |
1361 | const struct i2c_device_id *id) | 1335 | const struct i2c_device_id *id) |
1362 | { | 1336 | { |
1363 | struct wm8991_priv *wm8991; | 1337 | struct wm8991_priv *wm8991; |
1338 | unsigned int val; | ||
1364 | int ret; | 1339 | int ret; |
1365 | 1340 | ||
1366 | wm8991 = devm_kzalloc(&i2c->dev, sizeof(*wm8991), GFP_KERNEL); | 1341 | wm8991 = devm_kzalloc(&i2c->dev, sizeof(*wm8991), GFP_KERNEL); |
1367 | if (!wm8991) | 1342 | if (!wm8991) |
1368 | return -ENOMEM; | 1343 | return -ENOMEM; |
1369 | 1344 | ||
1370 | wm8991->control_type = SND_SOC_I2C; | 1345 | wm8991->regmap = devm_regmap_init_i2c(i2c, &wm8991_regmap); |
1346 | if (IS_ERR(wm8991->regmap)) | ||
1347 | return PTR_ERR(wm8991->regmap); | ||
1348 | |||
1371 | i2c_set_clientdata(i2c, wm8991); | 1349 | i2c_set_clientdata(i2c, wm8991); |
1372 | 1350 | ||
1351 | ret = regmap_read(wm8991->regmap, WM8991_RESET, &val); | ||
1352 | if (ret != 0) { | ||
1353 | dev_err(&i2c->dev, "Failed to read device ID: %d\n", ret); | ||
1354 | return ret; | ||
1355 | } | ||
1356 | if (val != 0x8991) { | ||
1357 | dev_err(&i2c->dev, "Device with ID %x is not a WM8991\n", val); | ||
1358 | return -EINVAL; | ||
1359 | } | ||
1360 | |||
1361 | ret = regmap_write(wm8991->regmap, WM8991_RESET, 0); | ||
1362 | if (ret < 0) { | ||
1363 | dev_err(&i2c->dev, "Failed to issue reset: %d\n", ret); | ||
1364 | return ret; | ||
1365 | } | ||
1366 | |||
1367 | regmap_update_bits(wm8991->regmap, WM8991_AUDIO_INTERFACE_4, | ||
1368 | WM8991_ALRCGPIO1, WM8991_ALRCGPIO1); | ||
1369 | |||
1370 | regmap_update_bits(wm8991->regmap, WM8991_GPIO1_GPIO2, | ||
1371 | WM8991_GPIO1_SEL_MASK, 1); | ||
1372 | |||
1373 | regmap_update_bits(wm8991->regmap, WM8991_POWER_MANAGEMENT_1, | ||
1374 | WM8991_VREF_ENA | WM8991_VMID_MODE_MASK, | ||
1375 | WM8991_VREF_ENA | WM8991_VMID_MODE_MASK); | ||
1376 | |||
1377 | regmap_update_bits(wm8991->regmap, WM8991_POWER_MANAGEMENT_2, | ||
1378 | WM8991_OPCLK_ENA, WM8991_OPCLK_ENA); | ||
1379 | |||
1380 | regmap_write(wm8991->regmap, WM8991_DAC_CTRL, 0); | ||
1381 | regmap_write(wm8991->regmap, WM8991_LEFT_OUTPUT_VOLUME, | ||
1382 | 0x50 | (1<<8)); | ||
1383 | regmap_write(wm8991->regmap, WM8991_RIGHT_OUTPUT_VOLUME, | ||
1384 | 0x50 | (1<<8)); | ||
1385 | |||
1373 | ret = snd_soc_register_codec(&i2c->dev, | 1386 | ret = snd_soc_register_codec(&i2c->dev, |
1374 | &soc_codec_dev_wm8991, &wm8991_dai, 1); | 1387 | &soc_codec_dev_wm8991, &wm8991_dai, 1); |
1375 | 1388 | ||