diff options
Diffstat (limited to 'sound/soc/codecs/wm_hubs.c')
-rw-r--r-- | sound/soc/codecs/wm_hubs.c | 222 |
1 files changed, 186 insertions, 36 deletions
diff --git a/sound/soc/codecs/wm_hubs.c b/sound/soc/codecs/wm_hubs.c index e542027eea89..e1f225a3ac46 100644 --- a/sound/soc/codecs/wm_hubs.c +++ b/sound/soc/codecs/wm_hubs.c | |||
@@ -62,36 +62,108 @@ static const char *speaker_mode_text[] = { | |||
62 | static const struct soc_enum speaker_mode = | 62 | static const struct soc_enum speaker_mode = |
63 | SOC_ENUM_SINGLE(WM8993_SPKMIXR_ATTENUATION, 8, 2, speaker_mode_text); | 63 | SOC_ENUM_SINGLE(WM8993_SPKMIXR_ATTENUATION, 8, 2, speaker_mode_text); |
64 | 64 | ||
65 | static void wait_for_dc_servo(struct snd_soc_codec *codec) | 65 | static void wait_for_dc_servo(struct snd_soc_codec *codec, unsigned int op) |
66 | { | 66 | { |
67 | unsigned int reg; | 67 | unsigned int reg; |
68 | int count = 0; | 68 | int count = 0; |
69 | unsigned int val; | ||
70 | |||
71 | val = op | WM8993_DCS_ENA_CHAN_0 | WM8993_DCS_ENA_CHAN_1; | ||
72 | |||
73 | /* Trigger the command */ | ||
74 | snd_soc_write(codec, WM8993_DC_SERVO_0, val); | ||
69 | 75 | ||
70 | dev_dbg(codec->dev, "Waiting for DC servo...\n"); | 76 | dev_dbg(codec->dev, "Waiting for DC servo...\n"); |
77 | |||
71 | do { | 78 | do { |
72 | count++; | 79 | count++; |
73 | msleep(1); | 80 | msleep(1); |
74 | reg = snd_soc_read(codec, WM8993_DC_SERVO_READBACK_0); | 81 | reg = snd_soc_read(codec, WM8993_DC_SERVO_0); |
75 | dev_dbg(codec->dev, "DC servo status: %x\n", reg); | 82 | dev_dbg(codec->dev, "DC servo: %x\n", reg); |
76 | } while ((reg & WM8993_DCS_CAL_COMPLETE_MASK) | 83 | } while (reg & op && count < 400); |
77 | != WM8993_DCS_CAL_COMPLETE_MASK && count < 1000); | ||
78 | 84 | ||
79 | if ((reg & WM8993_DCS_CAL_COMPLETE_MASK) | 85 | if (reg & op) |
80 | != WM8993_DCS_CAL_COMPLETE_MASK) | ||
81 | dev_err(codec->dev, "Timed out waiting for DC Servo\n"); | 86 | dev_err(codec->dev, "Timed out waiting for DC Servo\n"); |
82 | } | 87 | } |
83 | 88 | ||
84 | /* | 89 | /* |
90 | * Startup calibration of the DC servo | ||
91 | */ | ||
92 | static void calibrate_dc_servo(struct snd_soc_codec *codec) | ||
93 | { | ||
94 | struct wm_hubs_data *hubs = codec->private_data; | ||
95 | u16 reg, reg_l, reg_r, dcs_cfg; | ||
96 | |||
97 | /* Set for 32 series updates */ | ||
98 | snd_soc_update_bits(codec, WM8993_DC_SERVO_1, | ||
99 | WM8993_DCS_SERIES_NO_01_MASK, | ||
100 | 32 << WM8993_DCS_SERIES_NO_01_SHIFT); | ||
101 | wait_for_dc_servo(codec, | ||
102 | WM8993_DCS_TRIG_SERIES_0 | WM8993_DCS_TRIG_SERIES_1); | ||
103 | |||
104 | /* Apply correction to DC servo result */ | ||
105 | if (hubs->dcs_codes) { | ||
106 | dev_dbg(codec->dev, "Applying %d code DC servo correction\n", | ||
107 | hubs->dcs_codes); | ||
108 | |||
109 | /* Different chips in the family support different | ||
110 | * readback methods. | ||
111 | */ | ||
112 | switch (hubs->dcs_readback_mode) { | ||
113 | case 0: | ||
114 | reg_l = snd_soc_read(codec, WM8993_DC_SERVO_READBACK_1) | ||
115 | & WM8993_DCS_INTEG_CHAN_0_MASK;; | ||
116 | reg_r = snd_soc_read(codec, WM8993_DC_SERVO_READBACK_2) | ||
117 | & WM8993_DCS_INTEG_CHAN_1_MASK; | ||
118 | break; | ||
119 | case 1: | ||
120 | reg = snd_soc_read(codec, WM8993_DC_SERVO_3); | ||
121 | reg_l = (reg & WM8993_DCS_DAC_WR_VAL_1_MASK) | ||
122 | >> WM8993_DCS_DAC_WR_VAL_1_SHIFT; | ||
123 | reg_r = reg & WM8993_DCS_DAC_WR_VAL_0_MASK; | ||
124 | break; | ||
125 | default: | ||
126 | WARN(1, "Unknown DCS readback method"); | ||
127 | break; | ||
128 | } | ||
129 | |||
130 | /* HPOUT1L */ | ||
131 | if (reg_l + hubs->dcs_codes > 0 && | ||
132 | reg_l + hubs->dcs_codes < 0xff) | ||
133 | reg_l += hubs->dcs_codes; | ||
134 | dcs_cfg = reg_l << WM8993_DCS_DAC_WR_VAL_1_SHIFT; | ||
135 | |||
136 | /* HPOUT1R */ | ||
137 | if (reg_r + hubs->dcs_codes > 0 && | ||
138 | reg_r + hubs->dcs_codes < 0xff) | ||
139 | reg_r += hubs->dcs_codes; | ||
140 | dcs_cfg |= reg_r; | ||
141 | |||
142 | /* Do it */ | ||
143 | snd_soc_write(codec, WM8993_DC_SERVO_3, dcs_cfg); | ||
144 | wait_for_dc_servo(codec, | ||
145 | WM8993_DCS_TRIG_DAC_WR_0 | | ||
146 | WM8993_DCS_TRIG_DAC_WR_1); | ||
147 | } | ||
148 | } | ||
149 | |||
150 | /* | ||
85 | * Update the DC servo calibration on gain changes | 151 | * Update the DC servo calibration on gain changes |
86 | */ | 152 | */ |
87 | static int wm8993_put_dc_servo(struct snd_kcontrol *kcontrol, | 153 | static int wm8993_put_dc_servo(struct snd_kcontrol *kcontrol, |
88 | struct snd_ctl_elem_value *ucontrol) | 154 | struct snd_ctl_elem_value *ucontrol) |
89 | { | 155 | { |
90 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | 156 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); |
157 | struct wm_hubs_data *hubs = codec->private_data; | ||
91 | int ret; | 158 | int ret; |
92 | 159 | ||
93 | ret = snd_soc_put_volsw_2r(kcontrol, ucontrol); | 160 | ret = snd_soc_put_volsw_2r(kcontrol, ucontrol); |
94 | 161 | ||
162 | /* If we're applying an offset correction then updating the | ||
163 | * callibration would be likely to introduce further offsets. */ | ||
164 | if (hubs->dcs_codes) | ||
165 | return ret; | ||
166 | |||
95 | /* Only need to do this if the outputs are active */ | 167 | /* Only need to do this if the outputs are active */ |
96 | if (snd_soc_read(codec, WM8993_POWER_MANAGEMENT_1) | 168 | if (snd_soc_read(codec, WM8993_POWER_MANAGEMENT_1) |
97 | & (WM8993_HPOUT1L_ENA | WM8993_HPOUT1R_ENA)) | 169 | & (WM8993_HPOUT1L_ENA | WM8993_HPOUT1R_ENA)) |
@@ -251,6 +323,47 @@ SOC_SINGLE_TLV("LINEOUT2 Volume", WM8993_LINE_OUTPUTS_VOLUME, 0, 1, 1, | |||
251 | line_tlv), | 323 | line_tlv), |
252 | }; | 324 | }; |
253 | 325 | ||
326 | static int hp_supply_event(struct snd_soc_dapm_widget *w, | ||
327 | struct snd_kcontrol *kcontrol, int event) | ||
328 | { | ||
329 | struct snd_soc_codec *codec = w->codec; | ||
330 | struct wm_hubs_data *hubs = codec->private_data; | ||
331 | |||
332 | switch (event) { | ||
333 | case SND_SOC_DAPM_PRE_PMU: | ||
334 | switch (hubs->hp_startup_mode) { | ||
335 | case 0: | ||
336 | break; | ||
337 | case 1: | ||
338 | /* Enable the headphone amp */ | ||
339 | snd_soc_update_bits(codec, WM8993_POWER_MANAGEMENT_1, | ||
340 | WM8993_HPOUT1L_ENA | | ||
341 | WM8993_HPOUT1R_ENA, | ||
342 | WM8993_HPOUT1L_ENA | | ||
343 | WM8993_HPOUT1R_ENA); | ||
344 | |||
345 | /* Enable the second stage */ | ||
346 | snd_soc_update_bits(codec, WM8993_ANALOGUE_HP_0, | ||
347 | WM8993_HPOUT1L_DLY | | ||
348 | WM8993_HPOUT1R_DLY, | ||
349 | WM8993_HPOUT1L_DLY | | ||
350 | WM8993_HPOUT1R_DLY); | ||
351 | break; | ||
352 | default: | ||
353 | dev_err(codec->dev, "Unknown HP startup mode %d\n", | ||
354 | hubs->hp_startup_mode); | ||
355 | break; | ||
356 | } | ||
357 | |||
358 | case SND_SOC_DAPM_PRE_PMD: | ||
359 | snd_soc_update_bits(codec, WM8993_CHARGE_PUMP_1, | ||
360 | WM8993_CP_ENA, 0); | ||
361 | break; | ||
362 | } | ||
363 | |||
364 | return 0; | ||
365 | } | ||
366 | |||
254 | static int hp_event(struct snd_soc_dapm_widget *w, | 367 | static int hp_event(struct snd_soc_dapm_widget *w, |
255 | struct snd_kcontrol *kcontrol, int event) | 368 | struct snd_kcontrol *kcontrol, int event) |
256 | { | 369 | { |
@@ -271,14 +384,11 @@ static int hp_event(struct snd_soc_dapm_widget *w, | |||
271 | reg |= WM8993_HPOUT1L_DLY | WM8993_HPOUT1R_DLY; | 384 | reg |= WM8993_HPOUT1L_DLY | WM8993_HPOUT1R_DLY; |
272 | snd_soc_write(codec, WM8993_ANALOGUE_HP_0, reg); | 385 | snd_soc_write(codec, WM8993_ANALOGUE_HP_0, reg); |
273 | 386 | ||
274 | /* Start the DC servo */ | 387 | /* Smallest supported update interval */ |
275 | snd_soc_update_bits(codec, WM8993_DC_SERVO_0, | 388 | snd_soc_update_bits(codec, WM8993_DC_SERVO_1, |
276 | 0xFFFF, | 389 | WM8993_DCS_TIMER_PERIOD_01_MASK, 1); |
277 | WM8993_DCS_ENA_CHAN_0 | | 390 | |
278 | WM8993_DCS_ENA_CHAN_1 | | 391 | calibrate_dc_servo(codec); |
279 | WM8993_DCS_TRIG_STARTUP_1 | | ||
280 | WM8993_DCS_TRIG_STARTUP_0); | ||
281 | wait_for_dc_servo(codec); | ||
282 | 392 | ||
283 | reg |= WM8993_HPOUT1R_OUTP | WM8993_HPOUT1R_RMV_SHORT | | 393 | reg |= WM8993_HPOUT1R_OUTP | WM8993_HPOUT1R_RMV_SHORT | |
284 | WM8993_HPOUT1L_OUTP | WM8993_HPOUT1L_RMV_SHORT; | 394 | WM8993_HPOUT1L_OUTP | WM8993_HPOUT1L_RMV_SHORT; |
@@ -286,23 +396,19 @@ static int hp_event(struct snd_soc_dapm_widget *w, | |||
286 | break; | 396 | break; |
287 | 397 | ||
288 | case SND_SOC_DAPM_PRE_PMD: | 398 | case SND_SOC_DAPM_PRE_PMD: |
289 | reg &= ~(WM8993_HPOUT1L_RMV_SHORT | | 399 | snd_soc_update_bits(codec, WM8993_ANALOGUE_HP_0, |
290 | WM8993_HPOUT1L_DLY | | 400 | WM8993_HPOUT1L_DLY | |
291 | WM8993_HPOUT1L_OUTP | | 401 | WM8993_HPOUT1R_DLY | |
292 | WM8993_HPOUT1R_RMV_SHORT | | 402 | WM8993_HPOUT1L_RMV_SHORT | |
293 | WM8993_HPOUT1R_DLY | | 403 | WM8993_HPOUT1R_RMV_SHORT, 0); |
294 | WM8993_HPOUT1R_OUTP); | ||
295 | 404 | ||
296 | snd_soc_update_bits(codec, WM8993_DC_SERVO_0, | 405 | snd_soc_update_bits(codec, WM8993_ANALOGUE_HP_0, |
297 | 0xffff, 0); | 406 | WM8993_HPOUT1L_OUTP | |
407 | WM8993_HPOUT1R_OUTP, 0); | ||
298 | 408 | ||
299 | snd_soc_write(codec, WM8993_ANALOGUE_HP_0, reg); | ||
300 | snd_soc_update_bits(codec, WM8993_POWER_MANAGEMENT_1, | 409 | snd_soc_update_bits(codec, WM8993_POWER_MANAGEMENT_1, |
301 | WM8993_HPOUT1L_ENA | WM8993_HPOUT1R_ENA, | 410 | WM8993_HPOUT1L_ENA | WM8993_HPOUT1R_ENA, |
302 | 0); | 411 | 0); |
303 | |||
304 | snd_soc_update_bits(codec, WM8993_CHARGE_PUMP_1, | ||
305 | WM8993_CP_ENA, 0); | ||
306 | break; | 412 | break; |
307 | } | 413 | } |
308 | 414 | ||
@@ -438,11 +544,11 @@ static const struct snd_soc_dapm_widget analogue_dapm_widgets[] = { | |||
438 | SND_SOC_DAPM_INPUT("IN1LN"), | 544 | SND_SOC_DAPM_INPUT("IN1LN"), |
439 | SND_SOC_DAPM_INPUT("IN1LP"), | 545 | SND_SOC_DAPM_INPUT("IN1LP"), |
440 | SND_SOC_DAPM_INPUT("IN2LN"), | 546 | SND_SOC_DAPM_INPUT("IN2LN"), |
441 | SND_SOC_DAPM_INPUT("IN2LP/VXRN"), | 547 | SND_SOC_DAPM_INPUT("IN2LP:VXRN"), |
442 | SND_SOC_DAPM_INPUT("IN1RN"), | 548 | SND_SOC_DAPM_INPUT("IN1RN"), |
443 | SND_SOC_DAPM_INPUT("IN1RP"), | 549 | SND_SOC_DAPM_INPUT("IN1RP"), |
444 | SND_SOC_DAPM_INPUT("IN2RN"), | 550 | SND_SOC_DAPM_INPUT("IN2RN"), |
445 | SND_SOC_DAPM_INPUT("IN2RP/VXRP"), | 551 | SND_SOC_DAPM_INPUT("IN2RP:VXRP"), |
446 | 552 | ||
447 | SND_SOC_DAPM_MICBIAS("MICBIAS2", WM8993_POWER_MANAGEMENT_1, 5, 0), | 553 | SND_SOC_DAPM_MICBIAS("MICBIAS2", WM8993_POWER_MANAGEMENT_1, 5, 0), |
448 | SND_SOC_DAPM_MICBIAS("MICBIAS1", WM8993_POWER_MANAGEMENT_1, 4, 0), | 554 | SND_SOC_DAPM_MICBIAS("MICBIAS1", WM8993_POWER_MANAGEMENT_1, 4, 0), |
@@ -473,6 +579,8 @@ SND_SOC_DAPM_MIXER("Right Output Mixer", WM8993_POWER_MANAGEMENT_3, 4, 0, | |||
473 | SND_SOC_DAPM_PGA("Left Output PGA", WM8993_POWER_MANAGEMENT_3, 7, 0, NULL, 0), | 579 | SND_SOC_DAPM_PGA("Left Output PGA", WM8993_POWER_MANAGEMENT_3, 7, 0, NULL, 0), |
474 | SND_SOC_DAPM_PGA("Right Output PGA", WM8993_POWER_MANAGEMENT_3, 6, 0, NULL, 0), | 580 | SND_SOC_DAPM_PGA("Right Output PGA", WM8993_POWER_MANAGEMENT_3, 6, 0, NULL, 0), |
475 | 581 | ||
582 | SND_SOC_DAPM_SUPPLY("Headphone Supply", SND_SOC_NOPM, 0, 0, hp_supply_event, | ||
583 | SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_PRE_PMD), | ||
476 | SND_SOC_DAPM_PGA_E("Headphone PGA", SND_SOC_NOPM, 0, 0, | 584 | SND_SOC_DAPM_PGA_E("Headphone PGA", SND_SOC_NOPM, 0, 0, |
477 | NULL, 0, | 585 | NULL, 0, |
478 | hp_event, SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), | 586 | hp_event, SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), |
@@ -537,14 +645,14 @@ static const struct snd_soc_dapm_route analogue_routes[] = { | |||
537 | { "IN1R PGA", "IN1RP Switch", "IN1RP" }, | 645 | { "IN1R PGA", "IN1RP Switch", "IN1RP" }, |
538 | { "IN1R PGA", "IN1RN Switch", "IN1RN" }, | 646 | { "IN1R PGA", "IN1RN Switch", "IN1RN" }, |
539 | 647 | ||
540 | { "IN2L PGA", "IN2LP Switch", "IN2LP/VXRN" }, | 648 | { "IN2L PGA", "IN2LP Switch", "IN2LP:VXRN" }, |
541 | { "IN2L PGA", "IN2LN Switch", "IN2LN" }, | 649 | { "IN2L PGA", "IN2LN Switch", "IN2LN" }, |
542 | 650 | ||
543 | { "IN2R PGA", "IN2RP Switch", "IN2RP/VXRP" }, | 651 | { "IN2R PGA", "IN2RP Switch", "IN2RP:VXRP" }, |
544 | { "IN2R PGA", "IN2RN Switch", "IN2RN" }, | 652 | { "IN2R PGA", "IN2RN Switch", "IN2RN" }, |
545 | 653 | ||
546 | { "Direct Voice", NULL, "IN2LP/VXRN" }, | 654 | { "Direct Voice", NULL, "IN2LP:VXRN" }, |
547 | { "Direct Voice", NULL, "IN2RP/VXRP" }, | 655 | { "Direct Voice", NULL, "IN2RP:VXRP" }, |
548 | 656 | ||
549 | { "MIXINL", "IN1L Switch", "IN1L PGA" }, | 657 | { "MIXINL", "IN1L Switch", "IN1L PGA" }, |
550 | { "MIXINL", "IN2L Switch", "IN2L PGA" }, | 658 | { "MIXINL", "IN2L Switch", "IN2L PGA" }, |
@@ -565,7 +673,7 @@ static const struct snd_soc_dapm_route analogue_routes[] = { | |||
565 | { "Left Output Mixer", "Right Input Switch", "MIXINR" }, | 673 | { "Left Output Mixer", "Right Input Switch", "MIXINR" }, |
566 | { "Left Output Mixer", "IN2RN Switch", "IN2RN" }, | 674 | { "Left Output Mixer", "IN2RN Switch", "IN2RN" }, |
567 | { "Left Output Mixer", "IN2LN Switch", "IN2LN" }, | 675 | { "Left Output Mixer", "IN2LN Switch", "IN2LN" }, |
568 | { "Left Output Mixer", "IN2LP Switch", "IN2LP/VXRN" }, | 676 | { "Left Output Mixer", "IN2LP Switch", "IN2LP:VXRN" }, |
569 | { "Left Output Mixer", "IN1L Switch", "IN1L PGA" }, | 677 | { "Left Output Mixer", "IN1L Switch", "IN1L PGA" }, |
570 | { "Left Output Mixer", "IN1R Switch", "IN1R PGA" }, | 678 | { "Left Output Mixer", "IN1R Switch", "IN1R PGA" }, |
571 | 679 | ||
@@ -573,7 +681,7 @@ static const struct snd_soc_dapm_route analogue_routes[] = { | |||
573 | { "Right Output Mixer", "Right Input Switch", "MIXINR" }, | 681 | { "Right Output Mixer", "Right Input Switch", "MIXINR" }, |
574 | { "Right Output Mixer", "IN2LN Switch", "IN2LN" }, | 682 | { "Right Output Mixer", "IN2LN Switch", "IN2LN" }, |
575 | { "Right Output Mixer", "IN2RN Switch", "IN2RN" }, | 683 | { "Right Output Mixer", "IN2RN Switch", "IN2RN" }, |
576 | { "Right Output Mixer", "IN2RP Switch", "IN2RP/VXRP" }, | 684 | { "Right Output Mixer", "IN2RP Switch", "IN2RP:VXRP" }, |
577 | { "Right Output Mixer", "IN1L Switch", "IN1L PGA" }, | 685 | { "Right Output Mixer", "IN1L Switch", "IN1L PGA" }, |
578 | { "Right Output Mixer", "IN1R Switch", "IN1R PGA" }, | 686 | { "Right Output Mixer", "IN1R Switch", "IN1R PGA" }, |
579 | 687 | ||
@@ -626,6 +734,7 @@ static const struct snd_soc_dapm_route analogue_routes[] = { | |||
626 | { "Headphone PGA", NULL, "Left Headphone Mux" }, | 734 | { "Headphone PGA", NULL, "Left Headphone Mux" }, |
627 | { "Headphone PGA", NULL, "Right Headphone Mux" }, | 735 | { "Headphone PGA", NULL, "Right Headphone Mux" }, |
628 | { "Headphone PGA", NULL, "CLK_SYS" }, | 736 | { "Headphone PGA", NULL, "CLK_SYS" }, |
737 | { "Headphone PGA", NULL, "Headphone Supply" }, | ||
629 | 738 | ||
630 | { "HPOUT1L", NULL, "Headphone PGA" }, | 739 | { "HPOUT1L", NULL, "Headphone PGA" }, |
631 | { "HPOUT1R", NULL, "Headphone PGA" }, | 740 | { "HPOUT1R", NULL, "Headphone PGA" }, |
@@ -738,6 +847,47 @@ int wm_hubs_add_analogue_routes(struct snd_soc_codec *codec, | |||
738 | } | 847 | } |
739 | EXPORT_SYMBOL_GPL(wm_hubs_add_analogue_routes); | 848 | EXPORT_SYMBOL_GPL(wm_hubs_add_analogue_routes); |
740 | 849 | ||
850 | int wm_hubs_handle_analogue_pdata(struct snd_soc_codec *codec, | ||
851 | int lineout1_diff, int lineout2_diff, | ||
852 | int lineout1fb, int lineout2fb, | ||
853 | int jd_scthr, int jd_thr, int micbias1_lvl, | ||
854 | int micbias2_lvl) | ||
855 | { | ||
856 | if (!lineout1_diff) | ||
857 | snd_soc_update_bits(codec, WM8993_LINE_MIXER1, | ||
858 | WM8993_LINEOUT1_MODE, | ||
859 | WM8993_LINEOUT1_MODE); | ||
860 | if (!lineout2_diff) | ||
861 | snd_soc_update_bits(codec, WM8993_LINE_MIXER2, | ||
862 | WM8993_LINEOUT2_MODE, | ||
863 | WM8993_LINEOUT2_MODE); | ||
864 | |||
865 | /* If the line outputs are differential then we aren't presenting | ||
866 | * VMID as an output and can disable it. | ||
867 | */ | ||
868 | if (lineout1_diff && lineout2_diff) | ||
869 | codec->idle_bias_off = 1; | ||
870 | |||
871 | if (lineout1fb) | ||
872 | snd_soc_update_bits(codec, WM8993_ADDITIONAL_CONTROL, | ||
873 | WM8993_LINEOUT1_FB, WM8993_LINEOUT1_FB); | ||
874 | |||
875 | if (lineout2fb) | ||
876 | snd_soc_update_bits(codec, WM8993_ADDITIONAL_CONTROL, | ||
877 | WM8993_LINEOUT2_FB, WM8993_LINEOUT2_FB); | ||
878 | |||
879 | snd_soc_update_bits(codec, WM8993_MICBIAS, | ||
880 | WM8993_JD_SCTHR_MASK | WM8993_JD_THR_MASK | | ||
881 | WM8993_MICB1_LVL | WM8993_MICB2_LVL, | ||
882 | jd_scthr << WM8993_JD_SCTHR_SHIFT | | ||
883 | jd_thr << WM8993_JD_THR_SHIFT | | ||
884 | micbias1_lvl | | ||
885 | micbias2_lvl << WM8993_MICB2_LVL_SHIFT); | ||
886 | |||
887 | return 0; | ||
888 | } | ||
889 | EXPORT_SYMBOL_GPL(wm_hubs_handle_analogue_pdata); | ||
890 | |||
741 | MODULE_DESCRIPTION("Shared support for Wolfson hubs products"); | 891 | MODULE_DESCRIPTION("Shared support for Wolfson hubs products"); |
742 | MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>"); | 892 | MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>"); |
743 | MODULE_LICENSE("GPL"); | 893 | MODULE_LICENSE("GPL"); |