1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3 * wm_hubs.c -- WM8993/4 common code
4 *
5 * Copyright 2009-12 Wolfson Microelectronics plc
6 *
7 * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
8 */
9
10 #include <linux/module.h>
11 #include <linux/moduleparam.h>
12 #include <linux/init.h>
13 #include <linux/delay.h>
14 #include <linux/pm.h>
15 #include <linux/i2c.h>
16 #include <linux/mfd/wm8994/registers.h>
17 #include <linux/string_choices.h>
18 #include <sound/core.h>
19 #include <sound/pcm.h>
20 #include <sound/pcm_params.h>
21 #include <sound/soc.h>
22 #include <sound/initval.h>
23 #include <sound/tlv.h>
24
25 #include "wm8993.h"
26 #include "wm_hubs.h"
27
28 const DECLARE_TLV_DB_SCALE(wm_hubs_spkmix_tlv, -300, 300, 0);
29 EXPORT_SYMBOL_GPL(wm_hubs_spkmix_tlv);
30
31 static const DECLARE_TLV_DB_SCALE(inpga_tlv, -1650, 150, 0);
32 static const DECLARE_TLV_DB_SCALE(inmix_sw_tlv, 0, 3000, 0);
33 static const DECLARE_TLV_DB_SCALE(inmix_tlv, -1500, 300, 1);
34 static const DECLARE_TLV_DB_SCALE(earpiece_tlv, -600, 600, 0);
35 static const DECLARE_TLV_DB_SCALE(outmix_tlv, -2100, 300, 0);
36 static const DECLARE_TLV_DB_SCALE(spkmixout_tlv, -1800, 600, 1);
37 static const DECLARE_TLV_DB_SCALE(outpga_tlv, -5700, 100, 0);
38 static const DECLARE_TLV_DB_RANGE(spkboost_tlv,
39 0, 6, TLV_DB_SCALE_ITEM(0, 150, 0),
40 7, 7, TLV_DB_SCALE_ITEM(1200, 0, 0)
41 );
42 static const DECLARE_TLV_DB_SCALE(line_tlv, -600, 600, 0);
43
44 static const char *speaker_ref_text[] = {
45 "SPKVDD/2",
46 "VMID",
47 };
48
49 static SOC_ENUM_SINGLE_DECL(speaker_ref,
50 WM8993_SPEAKER_MIXER, 8, speaker_ref_text);
51
52 static const char *speaker_mode_text[] = {
53 "Class D",
54 "Class AB",
55 };
56
57 static SOC_ENUM_SINGLE_DECL(speaker_mode,
58 WM8993_SPKMIXR_ATTENUATION, 8, speaker_mode_text);
59
wait_for_dc_servo(struct snd_soc_component * component,unsigned int op)60 static void wait_for_dc_servo(struct snd_soc_component *component, unsigned int op)
61 {
62 struct wm_hubs_data *hubs = snd_soc_component_get_drvdata(component);
63 unsigned int reg;
64 int count = 0;
65 int timeout;
66 unsigned int val;
67
68 val = op | WM8993_DCS_ENA_CHAN_0 | WM8993_DCS_ENA_CHAN_1;
69
70 /* Trigger the command */
71 snd_soc_component_write(component, WM8993_DC_SERVO_0, val);
72
73 dev_dbg(component->dev, "Waiting for DC servo...\n");
74
75 if (hubs->dcs_done_irq)
76 timeout = 4;
77 else
78 timeout = 400;
79
80 do {
81 count++;
82
83 if (hubs->dcs_done_irq)
84 wait_for_completion_timeout(&hubs->dcs_done,
85 msecs_to_jiffies(250));
86 else
87 msleep(1);
88
89 reg = snd_soc_component_read(component, WM8993_DC_SERVO_0);
90 dev_dbg(component->dev, "DC servo: %x\n", reg);
91 } while (reg & op && count < timeout);
92
93 if (reg & op)
94 dev_err(component->dev, "Timed out waiting for DC Servo %x\n",
95 op);
96 }
97
wm_hubs_dcs_done(int irq,void * data)98 irqreturn_t wm_hubs_dcs_done(int irq, void *data)
99 {
100 struct wm_hubs_data *hubs = data;
101
102 complete(&hubs->dcs_done);
103
104 return IRQ_HANDLED;
105 }
106 EXPORT_SYMBOL_GPL(wm_hubs_dcs_done);
107
wm_hubs_dac_hp_direct(struct snd_soc_component * component)108 static bool wm_hubs_dac_hp_direct(struct snd_soc_component *component)
109 {
110 int reg;
111
112 /* If we're going via the mixer we'll need to do additional checks */
113 reg = snd_soc_component_read(component, WM8993_OUTPUT_MIXER1);
114 if (!(reg & WM8993_DACL_TO_HPOUT1L)) {
115 if (reg & ~WM8993_DACL_TO_MIXOUTL) {
116 dev_vdbg(component->dev, "Analogue paths connected: %x\n",
117 reg & ~WM8993_DACL_TO_HPOUT1L);
118 return false;
119 } else {
120 dev_vdbg(component->dev, "HPL connected to mixer\n");
121 }
122 } else {
123 dev_vdbg(component->dev, "HPL connected to DAC\n");
124 }
125
126 reg = snd_soc_component_read(component, WM8993_OUTPUT_MIXER2);
127 if (!(reg & WM8993_DACR_TO_HPOUT1R)) {
128 if (reg & ~WM8993_DACR_TO_MIXOUTR) {
129 dev_vdbg(component->dev, "Analogue paths connected: %x\n",
130 reg & ~WM8993_DACR_TO_HPOUT1R);
131 return false;
132 } else {
133 dev_vdbg(component->dev, "HPR connected to mixer\n");
134 }
135 } else {
136 dev_vdbg(component->dev, "HPR connected to DAC\n");
137 }
138
139 return true;
140 }
141
142 struct wm_hubs_dcs_cache {
143 struct list_head list;
144 unsigned int left;
145 unsigned int right;
146 u16 dcs_cfg;
147 };
148
wm_hubs_dcs_cache_get(struct snd_soc_component * component,struct wm_hubs_dcs_cache ** entry)149 static bool wm_hubs_dcs_cache_get(struct snd_soc_component *component,
150 struct wm_hubs_dcs_cache **entry)
151 {
152 struct wm_hubs_data *hubs = snd_soc_component_get_drvdata(component);
153 struct wm_hubs_dcs_cache *cache;
154 unsigned int left, right;
155
156 left = snd_soc_component_read(component, WM8993_LEFT_OUTPUT_VOLUME);
157 left &= WM8993_HPOUT1L_VOL_MASK;
158
159 right = snd_soc_component_read(component, WM8993_RIGHT_OUTPUT_VOLUME);
160 right &= WM8993_HPOUT1R_VOL_MASK;
161
162 list_for_each_entry(cache, &hubs->dcs_cache, list) {
163 if (cache->left != left || cache->right != right)
164 continue;
165
166 *entry = cache;
167 return true;
168 }
169
170 return false;
171 }
172
wm_hubs_dcs_cache_set(struct snd_soc_component * component,u16 dcs_cfg)173 static void wm_hubs_dcs_cache_set(struct snd_soc_component *component, u16 dcs_cfg)
174 {
175 struct wm_hubs_data *hubs = snd_soc_component_get_drvdata(component);
176 struct wm_hubs_dcs_cache *cache;
177
178 if (hubs->no_cache_dac_hp_direct)
179 return;
180
181 cache = devm_kzalloc(component->dev, sizeof(*cache), GFP_KERNEL);
182 if (!cache)
183 return;
184
185 cache->left = snd_soc_component_read(component, WM8993_LEFT_OUTPUT_VOLUME);
186 cache->left &= WM8993_HPOUT1L_VOL_MASK;
187
188 cache->right = snd_soc_component_read(component, WM8993_RIGHT_OUTPUT_VOLUME);
189 cache->right &= WM8993_HPOUT1R_VOL_MASK;
190
191 cache->dcs_cfg = dcs_cfg;
192
193 list_add_tail(&cache->list, &hubs->dcs_cache);
194 }
195
wm_hubs_read_dc_servo(struct snd_soc_component * component,u16 * reg_l,u16 * reg_r)196 static int wm_hubs_read_dc_servo(struct snd_soc_component *component,
197 u16 *reg_l, u16 *reg_r)
198 {
199 struct wm_hubs_data *hubs = snd_soc_component_get_drvdata(component);
200 u16 dcs_reg, reg;
201 int ret = 0;
202
203 switch (hubs->dcs_readback_mode) {
204 case 2:
205 dcs_reg = WM8994_DC_SERVO_4E;
206 break;
207 case 1:
208 dcs_reg = WM8994_DC_SERVO_READBACK;
209 break;
210 default:
211 dcs_reg = WM8993_DC_SERVO_3;
212 break;
213 }
214
215 /* Different chips in the family support different readback
216 * methods.
217 */
218 switch (hubs->dcs_readback_mode) {
219 case 0:
220 *reg_l = snd_soc_component_read(component, WM8993_DC_SERVO_READBACK_1)
221 & WM8993_DCS_INTEG_CHAN_0_MASK;
222 *reg_r = snd_soc_component_read(component, WM8993_DC_SERVO_READBACK_2)
223 & WM8993_DCS_INTEG_CHAN_1_MASK;
224 break;
225 case 2:
226 case 1:
227 reg = snd_soc_component_read(component, dcs_reg);
228 *reg_r = (reg & WM8993_DCS_DAC_WR_VAL_1_MASK)
229 >> WM8993_DCS_DAC_WR_VAL_1_SHIFT;
230 *reg_l = reg & WM8993_DCS_DAC_WR_VAL_0_MASK;
231 break;
232 default:
233 WARN(1, "Unknown DCS readback method\n");
234 ret = -1;
235 }
236 return ret;
237 }
238
239 /*
240 * Startup calibration of the DC servo
241 */
enable_dc_servo(struct snd_soc_component * component)242 static void enable_dc_servo(struct snd_soc_component *component)
243 {
244 struct wm_hubs_data *hubs = snd_soc_component_get_drvdata(component);
245 struct wm_hubs_dcs_cache *cache;
246 s8 offset;
247 u16 reg_l, reg_r, dcs_cfg, dcs_reg;
248
249 switch (hubs->dcs_readback_mode) {
250 case 2:
251 dcs_reg = WM8994_DC_SERVO_4E;
252 break;
253 default:
254 dcs_reg = WM8993_DC_SERVO_3;
255 break;
256 }
257
258 /* If we're using a digital only path and have a previously
259 * callibrated DC servo offset stored then use that. */
260 if (wm_hubs_dac_hp_direct(component) &&
261 wm_hubs_dcs_cache_get(component, &cache)) {
262 dev_dbg(component->dev, "Using cached DCS offset %x for %d,%d\n",
263 cache->dcs_cfg, cache->left, cache->right);
264 snd_soc_component_write(component, dcs_reg, cache->dcs_cfg);
265 wait_for_dc_servo(component,
266 WM8993_DCS_TRIG_DAC_WR_0 |
267 WM8993_DCS_TRIG_DAC_WR_1);
268 return;
269 }
270
271 if (hubs->series_startup) {
272 /* Set for 32 series updates */
273 snd_soc_component_update_bits(component, WM8993_DC_SERVO_1,
274 WM8993_DCS_SERIES_NO_01_MASK,
275 32 << WM8993_DCS_SERIES_NO_01_SHIFT);
276 wait_for_dc_servo(component,
277 WM8993_DCS_TRIG_SERIES_0 |
278 WM8993_DCS_TRIG_SERIES_1);
279 } else {
280 wait_for_dc_servo(component,
281 WM8993_DCS_TRIG_STARTUP_0 |
282 WM8993_DCS_TRIG_STARTUP_1);
283 }
284
285 if (wm_hubs_read_dc_servo(component, ®_l, ®_r) < 0)
286 return;
287
288 dev_dbg(component->dev, "DCS input: %x %x\n", reg_l, reg_r);
289
290 /* Apply correction to DC servo result */
291 if (hubs->dcs_codes_l || hubs->dcs_codes_r) {
292 dev_dbg(component->dev,
293 "Applying %d/%d code DC servo correction\n",
294 hubs->dcs_codes_l, hubs->dcs_codes_r);
295
296 /* HPOUT1R */
297 offset = (s8)reg_r;
298 dev_dbg(component->dev, "DCS right %d->%d\n", offset,
299 offset + hubs->dcs_codes_r);
300 offset += hubs->dcs_codes_r;
301 dcs_cfg = (u8)offset << WM8993_DCS_DAC_WR_VAL_1_SHIFT;
302
303 /* HPOUT1L */
304 offset = (s8)reg_l;
305 dev_dbg(component->dev, "DCS left %d->%d\n", offset,
306 offset + hubs->dcs_codes_l);
307 offset += hubs->dcs_codes_l;
308 dcs_cfg |= (u8)offset;
309
310 dev_dbg(component->dev, "DCS result: %x\n", dcs_cfg);
311
312 /* Do it */
313 snd_soc_component_write(component, dcs_reg, dcs_cfg);
314 wait_for_dc_servo(component,
315 WM8993_DCS_TRIG_DAC_WR_0 |
316 WM8993_DCS_TRIG_DAC_WR_1);
317 } else {
318 dcs_cfg = reg_r << WM8993_DCS_DAC_WR_VAL_1_SHIFT;
319 dcs_cfg |= reg_l;
320 }
321
322 /* Save the callibrated offset if we're in class W mode and
323 * therefore don't have any analogue signal mixed in. */
324 if (wm_hubs_dac_hp_direct(component))
325 wm_hubs_dcs_cache_set(component, dcs_cfg);
326 }
327
328 /*
329 * Update the DC servo calibration on gain changes
330 */
wm8993_put_dc_servo(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)331 static int wm8993_put_dc_servo(struct snd_kcontrol *kcontrol,
332 struct snd_ctl_elem_value *ucontrol)
333 {
334 struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
335 struct wm_hubs_data *hubs = snd_soc_component_get_drvdata(component);
336 int ret;
337
338 ret = snd_soc_put_volsw(kcontrol, ucontrol);
339
340 /* If we're applying an offset correction then updating the
341 * callibration would be likely to introduce further offsets. */
342 if (hubs->dcs_codes_l || hubs->dcs_codes_r || hubs->no_series_update)
343 return ret;
344
345 /* Only need to do this if the outputs are active */
346 if (snd_soc_component_read(component, WM8993_POWER_MANAGEMENT_1)
347 & (WM8993_HPOUT1L_ENA | WM8993_HPOUT1R_ENA))
348 snd_soc_component_update_bits(component,
349 WM8993_DC_SERVO_0,
350 WM8993_DCS_TRIG_SINGLE_0 |
351 WM8993_DCS_TRIG_SINGLE_1,
352 WM8993_DCS_TRIG_SINGLE_0 |
353 WM8993_DCS_TRIG_SINGLE_1);
354
355 return ret;
356 }
357
358 static const struct snd_kcontrol_new analogue_snd_controls[] = {
359 SOC_SINGLE_TLV("IN1L Volume", WM8993_LEFT_LINE_INPUT_1_2_VOLUME, 0, 31, 0,
360 inpga_tlv),
361 SOC_SINGLE("IN1L Switch", WM8993_LEFT_LINE_INPUT_1_2_VOLUME, 7, 1, 1),
362 SOC_SINGLE("IN1L ZC Switch", WM8993_LEFT_LINE_INPUT_1_2_VOLUME, 6, 1, 0),
363
364 SOC_SINGLE_TLV("IN1R Volume", WM8993_RIGHT_LINE_INPUT_1_2_VOLUME, 0, 31, 0,
365 inpga_tlv),
366 SOC_SINGLE("IN1R Switch", WM8993_RIGHT_LINE_INPUT_1_2_VOLUME, 7, 1, 1),
367 SOC_SINGLE("IN1R ZC Switch", WM8993_RIGHT_LINE_INPUT_1_2_VOLUME, 6, 1, 0),
368
369
370 SOC_SINGLE_TLV("IN2L Volume", WM8993_LEFT_LINE_INPUT_3_4_VOLUME, 0, 31, 0,
371 inpga_tlv),
372 SOC_SINGLE("IN2L Switch", WM8993_LEFT_LINE_INPUT_3_4_VOLUME, 7, 1, 1),
373 SOC_SINGLE("IN2L ZC Switch", WM8993_LEFT_LINE_INPUT_3_4_VOLUME, 6, 1, 0),
374
375 SOC_SINGLE_TLV("IN2R Volume", WM8993_RIGHT_LINE_INPUT_3_4_VOLUME, 0, 31, 0,
376 inpga_tlv),
377 SOC_SINGLE("IN2R Switch", WM8993_RIGHT_LINE_INPUT_3_4_VOLUME, 7, 1, 1),
378 SOC_SINGLE("IN2R ZC Switch", WM8993_RIGHT_LINE_INPUT_3_4_VOLUME, 6, 1, 0),
379
380 SOC_SINGLE_TLV("MIXINL IN2L Volume", WM8993_INPUT_MIXER3, 7, 1, 0,
381 inmix_sw_tlv),
382 SOC_SINGLE_TLV("MIXINL IN1L Volume", WM8993_INPUT_MIXER3, 4, 1, 0,
383 inmix_sw_tlv),
384 SOC_SINGLE_TLV("MIXINL Output Record Volume", WM8993_INPUT_MIXER3, 0, 7, 0,
385 inmix_tlv),
386 SOC_SINGLE_TLV("MIXINL IN1LP Volume", WM8993_INPUT_MIXER5, 6, 7, 0, inmix_tlv),
387 SOC_SINGLE_TLV("MIXINL Direct Voice Volume", WM8993_INPUT_MIXER5, 0, 6, 0,
388 inmix_tlv),
389
390 SOC_SINGLE_TLV("MIXINR IN2R Volume", WM8993_INPUT_MIXER4, 7, 1, 0,
391 inmix_sw_tlv),
392 SOC_SINGLE_TLV("MIXINR IN1R Volume", WM8993_INPUT_MIXER4, 4, 1, 0,
393 inmix_sw_tlv),
394 SOC_SINGLE_TLV("MIXINR Output Record Volume", WM8993_INPUT_MIXER4, 0, 7, 0,
395 inmix_tlv),
396 SOC_SINGLE_TLV("MIXINR IN1RP Volume", WM8993_INPUT_MIXER6, 6, 7, 0, inmix_tlv),
397 SOC_SINGLE_TLV("MIXINR Direct Voice Volume", WM8993_INPUT_MIXER6, 0, 6, 0,
398 inmix_tlv),
399
400 SOC_SINGLE_TLV("Left Output Mixer IN2RN Volume", WM8993_OUTPUT_MIXER5, 6, 7, 1,
401 outmix_tlv),
402 SOC_SINGLE_TLV("Left Output Mixer IN2LN Volume", WM8993_OUTPUT_MIXER3, 6, 7, 1,
403 outmix_tlv),
404 SOC_SINGLE_TLV("Left Output Mixer IN2LP Volume", WM8993_OUTPUT_MIXER3, 9, 7, 1,
405 outmix_tlv),
406 SOC_SINGLE_TLV("Left Output Mixer IN1L Volume", WM8993_OUTPUT_MIXER3, 0, 7, 1,
407 outmix_tlv),
408 SOC_SINGLE_TLV("Left Output Mixer IN1R Volume", WM8993_OUTPUT_MIXER3, 3, 7, 1,
409 outmix_tlv),
410 SOC_SINGLE_TLV("Left Output Mixer Right Input Volume",
411 WM8993_OUTPUT_MIXER5, 3, 7, 1, outmix_tlv),
412 SOC_SINGLE_TLV("Left Output Mixer Left Input Volume",
413 WM8993_OUTPUT_MIXER5, 0, 7, 1, outmix_tlv),
414 SOC_SINGLE_TLV("Left Output Mixer DAC Volume", WM8993_OUTPUT_MIXER5, 9, 7, 1,
415 outmix_tlv),
416
417 SOC_SINGLE_TLV("Right Output Mixer IN2LN Volume",
418 WM8993_OUTPUT_MIXER6, 6, 7, 1, outmix_tlv),
419 SOC_SINGLE_TLV("Right Output Mixer IN2RN Volume",
420 WM8993_OUTPUT_MIXER4, 6, 7, 1, outmix_tlv),
421 SOC_SINGLE_TLV("Right Output Mixer IN1L Volume",
422 WM8993_OUTPUT_MIXER4, 3, 7, 1, outmix_tlv),
423 SOC_SINGLE_TLV("Right Output Mixer IN1R Volume",
424 WM8993_OUTPUT_MIXER4, 0, 7, 1, outmix_tlv),
425 SOC_SINGLE_TLV("Right Output Mixer IN2RP Volume",
426 WM8993_OUTPUT_MIXER4, 9, 7, 1, outmix_tlv),
427 SOC_SINGLE_TLV("Right Output Mixer Left Input Volume",
428 WM8993_OUTPUT_MIXER6, 3, 7, 1, outmix_tlv),
429 SOC_SINGLE_TLV("Right Output Mixer Right Input Volume",
430 WM8993_OUTPUT_MIXER6, 6, 7, 1, outmix_tlv),
431 SOC_SINGLE_TLV("Right Output Mixer DAC Volume",
432 WM8993_OUTPUT_MIXER6, 9, 7, 1, outmix_tlv),
433
434 SOC_DOUBLE_R_TLV("Output Volume", WM8993_LEFT_OPGA_VOLUME,
435 WM8993_RIGHT_OPGA_VOLUME, 0, 63, 0, outpga_tlv),
436 SOC_DOUBLE_R("Output Switch", WM8993_LEFT_OPGA_VOLUME,
437 WM8993_RIGHT_OPGA_VOLUME, 6, 1, 0),
438 SOC_DOUBLE_R("Output ZC Switch", WM8993_LEFT_OPGA_VOLUME,
439 WM8993_RIGHT_OPGA_VOLUME, 7, 1, 0),
440
441 SOC_SINGLE("Earpiece Switch", WM8993_HPOUT2_VOLUME, 5, 1, 1),
442 SOC_SINGLE_TLV("Earpiece Volume", WM8993_HPOUT2_VOLUME, 4, 1, 1, earpiece_tlv),
443
444 SOC_SINGLE_TLV("SPKL Input Volume", WM8993_SPKMIXL_ATTENUATION,
445 5, 1, 1, wm_hubs_spkmix_tlv),
446 SOC_SINGLE_TLV("SPKL IN1LP Volume", WM8993_SPKMIXL_ATTENUATION,
447 4, 1, 1, wm_hubs_spkmix_tlv),
448 SOC_SINGLE_TLV("SPKL Output Volume", WM8993_SPKMIXL_ATTENUATION,
449 3, 1, 1, wm_hubs_spkmix_tlv),
450
451 SOC_SINGLE_TLV("SPKR Input Volume", WM8993_SPKMIXR_ATTENUATION,
452 5, 1, 1, wm_hubs_spkmix_tlv),
453 SOC_SINGLE_TLV("SPKR IN1RP Volume", WM8993_SPKMIXR_ATTENUATION,
454 4, 1, 1, wm_hubs_spkmix_tlv),
455 SOC_SINGLE_TLV("SPKR Output Volume", WM8993_SPKMIXR_ATTENUATION,
456 3, 1, 1, wm_hubs_spkmix_tlv),
457
458 SOC_DOUBLE_R_TLV("Speaker Mixer Volume",
459 WM8993_SPKMIXL_ATTENUATION, WM8993_SPKMIXR_ATTENUATION,
460 0, 3, 1, spkmixout_tlv),
461 SOC_DOUBLE_R_TLV("Speaker Volume",
462 WM8993_SPEAKER_VOLUME_LEFT, WM8993_SPEAKER_VOLUME_RIGHT,
463 0, 63, 0, outpga_tlv),
464 SOC_DOUBLE_R("Speaker Switch",
465 WM8993_SPEAKER_VOLUME_LEFT, WM8993_SPEAKER_VOLUME_RIGHT,
466 6, 1, 0),
467 SOC_DOUBLE_R("Speaker ZC Switch",
468 WM8993_SPEAKER_VOLUME_LEFT, WM8993_SPEAKER_VOLUME_RIGHT,
469 7, 1, 0),
470 SOC_DOUBLE_TLV("Speaker Boost Volume", WM8993_SPKOUT_BOOST, 3, 0, 7, 0,
471 spkboost_tlv),
472 SOC_ENUM("Speaker Reference", speaker_ref),
473 SOC_ENUM("Speaker Mode", speaker_mode),
474
475 SOC_DOUBLE_R_EXT_TLV("Headphone Volume",
476 WM8993_LEFT_OUTPUT_VOLUME, WM8993_RIGHT_OUTPUT_VOLUME,
477 0, 63, 0, snd_soc_get_volsw, wm8993_put_dc_servo,
478 outpga_tlv),
479
480 SOC_DOUBLE_R("Headphone Switch", WM8993_LEFT_OUTPUT_VOLUME,
481 WM8993_RIGHT_OUTPUT_VOLUME, 6, 1, 0),
482 SOC_DOUBLE_R("Headphone ZC Switch", WM8993_LEFT_OUTPUT_VOLUME,
483 WM8993_RIGHT_OUTPUT_VOLUME, 7, 1, 0),
484
485 SOC_SINGLE("LINEOUT1N Switch", WM8993_LINE_OUTPUTS_VOLUME, 6, 1, 1),
486 SOC_SINGLE("LINEOUT1P Switch", WM8993_LINE_OUTPUTS_VOLUME, 5, 1, 1),
487 SOC_SINGLE_TLV("LINEOUT1 Volume", WM8993_LINE_OUTPUTS_VOLUME, 4, 1, 1,
488 line_tlv),
489
490 SOC_SINGLE("LINEOUT2N Switch", WM8993_LINE_OUTPUTS_VOLUME, 2, 1, 1),
491 SOC_SINGLE("LINEOUT2P Switch", WM8993_LINE_OUTPUTS_VOLUME, 1, 1, 1),
492 SOC_SINGLE_TLV("LINEOUT2 Volume", WM8993_LINE_OUTPUTS_VOLUME, 0, 1, 1,
493 line_tlv),
494 };
495
hp_supply_event(struct snd_soc_dapm_widget * w,struct snd_kcontrol * kcontrol,int event)496 static int hp_supply_event(struct snd_soc_dapm_widget *w,
497 struct snd_kcontrol *kcontrol, int event)
498 {
499 struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
500 struct wm_hubs_data *hubs = snd_soc_component_get_drvdata(component);
501
502 switch (event) {
503 case SND_SOC_DAPM_PRE_PMU:
504 switch (hubs->hp_startup_mode) {
505 case 0:
506 break;
507 case 1:
508 /* Enable the headphone amp */
509 snd_soc_component_update_bits(component, WM8993_POWER_MANAGEMENT_1,
510 WM8993_HPOUT1L_ENA |
511 WM8993_HPOUT1R_ENA,
512 WM8993_HPOUT1L_ENA |
513 WM8993_HPOUT1R_ENA);
514
515 /* Enable the second stage */
516 snd_soc_component_update_bits(component, WM8993_ANALOGUE_HP_0,
517 WM8993_HPOUT1L_DLY |
518 WM8993_HPOUT1R_DLY,
519 WM8993_HPOUT1L_DLY |
520 WM8993_HPOUT1R_DLY);
521 break;
522 default:
523 dev_err(component->dev, "Unknown HP startup mode %d\n",
524 hubs->hp_startup_mode);
525 break;
526 }
527 break;
528
529 case SND_SOC_DAPM_PRE_PMD:
530 snd_soc_component_update_bits(component, WM8993_CHARGE_PUMP_1,
531 WM8993_CP_ENA, 0);
532 break;
533 }
534
535 return 0;
536 }
537
hp_event(struct snd_soc_dapm_widget * w,struct snd_kcontrol * kcontrol,int event)538 static int hp_event(struct snd_soc_dapm_widget *w,
539 struct snd_kcontrol *kcontrol, int event)
540 {
541 struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
542 unsigned int reg = snd_soc_component_read(component, WM8993_ANALOGUE_HP_0);
543
544 switch (event) {
545 case SND_SOC_DAPM_POST_PMU:
546 snd_soc_component_update_bits(component, WM8993_CHARGE_PUMP_1,
547 WM8993_CP_ENA, WM8993_CP_ENA);
548
549 msleep(5);
550
551 snd_soc_component_update_bits(component, WM8993_POWER_MANAGEMENT_1,
552 WM8993_HPOUT1L_ENA | WM8993_HPOUT1R_ENA,
553 WM8993_HPOUT1L_ENA | WM8993_HPOUT1R_ENA);
554
555 reg |= WM8993_HPOUT1L_DLY | WM8993_HPOUT1R_DLY;
556 snd_soc_component_write(component, WM8993_ANALOGUE_HP_0, reg);
557
558 snd_soc_component_update_bits(component, WM8993_DC_SERVO_1,
559 WM8993_DCS_TIMER_PERIOD_01_MASK, 0);
560
561 enable_dc_servo(component);
562
563 reg |= WM8993_HPOUT1R_OUTP | WM8993_HPOUT1R_RMV_SHORT |
564 WM8993_HPOUT1L_OUTP | WM8993_HPOUT1L_RMV_SHORT;
565 snd_soc_component_write(component, WM8993_ANALOGUE_HP_0, reg);
566 break;
567
568 case SND_SOC_DAPM_PRE_PMD:
569 snd_soc_component_update_bits(component, WM8993_ANALOGUE_HP_0,
570 WM8993_HPOUT1L_OUTP |
571 WM8993_HPOUT1R_OUTP |
572 WM8993_HPOUT1L_RMV_SHORT |
573 WM8993_HPOUT1R_RMV_SHORT, 0);
574
575 snd_soc_component_update_bits(component, WM8993_ANALOGUE_HP_0,
576 WM8993_HPOUT1L_DLY |
577 WM8993_HPOUT1R_DLY, 0);
578
579 snd_soc_component_write(component, WM8993_DC_SERVO_0, 0);
580
581 snd_soc_component_update_bits(component, WM8993_POWER_MANAGEMENT_1,
582 WM8993_HPOUT1L_ENA | WM8993_HPOUT1R_ENA,
583 0);
584 break;
585 }
586
587 return 0;
588 }
589
earpiece_event(struct snd_soc_dapm_widget * w,struct snd_kcontrol * control,int event)590 static int earpiece_event(struct snd_soc_dapm_widget *w,
591 struct snd_kcontrol *control, int event)
592 {
593 struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
594 u16 reg = snd_soc_component_read(component, WM8993_ANTIPOP1) & ~WM8993_HPOUT2_IN_ENA;
595
596 switch (event) {
597 case SND_SOC_DAPM_PRE_PMU:
598 reg |= WM8993_HPOUT2_IN_ENA;
599 snd_soc_component_write(component, WM8993_ANTIPOP1, reg);
600 udelay(50);
601 break;
602
603 case SND_SOC_DAPM_POST_PMD:
604 snd_soc_component_write(component, WM8993_ANTIPOP1, reg);
605 break;
606
607 default:
608 WARN(1, "Invalid event %d\n", event);
609 break;
610 }
611
612 return 0;
613 }
614
lineout_event(struct snd_soc_dapm_widget * w,struct snd_kcontrol * control,int event)615 static int lineout_event(struct snd_soc_dapm_widget *w,
616 struct snd_kcontrol *control, int event)
617 {
618 struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
619 struct wm_hubs_data *hubs = snd_soc_component_get_drvdata(component);
620 bool *flag;
621
622 switch (w->shift) {
623 case WM8993_LINEOUT1N_ENA_SHIFT:
624 flag = &hubs->lineout1n_ena;
625 break;
626 case WM8993_LINEOUT1P_ENA_SHIFT:
627 flag = &hubs->lineout1p_ena;
628 break;
629 case WM8993_LINEOUT2N_ENA_SHIFT:
630 flag = &hubs->lineout2n_ena;
631 break;
632 case WM8993_LINEOUT2P_ENA_SHIFT:
633 flag = &hubs->lineout2p_ena;
634 break;
635 default:
636 WARN(1, "Unknown line output");
637 return -EINVAL;
638 }
639
640 *flag = SND_SOC_DAPM_EVENT_ON(event);
641
642 return 0;
643 }
644
micbias_event(struct snd_soc_dapm_widget * w,struct snd_kcontrol * kcontrol,int event)645 static int micbias_event(struct snd_soc_dapm_widget *w,
646 struct snd_kcontrol *kcontrol, int event)
647 {
648 struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
649 struct wm_hubs_data *hubs = snd_soc_component_get_drvdata(component);
650
651 switch (w->shift) {
652 case WM8993_MICB1_ENA_SHIFT:
653 if (hubs->micb1_delay)
654 msleep(hubs->micb1_delay);
655 break;
656 case WM8993_MICB2_ENA_SHIFT:
657 if (hubs->micb2_delay)
658 msleep(hubs->micb2_delay);
659 break;
660 default:
661 return -EINVAL;
662 }
663
664 return 0;
665 }
666
wm_hubs_update_class_w(struct snd_soc_component * component)667 void wm_hubs_update_class_w(struct snd_soc_component *component)
668 {
669 struct wm_hubs_data *hubs = snd_soc_component_get_drvdata(component);
670 int enable = WM8993_CP_DYN_V | WM8993_CP_DYN_FREQ;
671
672 if (!wm_hubs_dac_hp_direct(component))
673 enable = false;
674
675 if (hubs->check_class_w_digital && !hubs->check_class_w_digital(component))
676 enable = false;
677
678 dev_vdbg(component->dev, "Class W %s\n", str_enabled_disabled(enable));
679
680 snd_soc_component_update_bits(component, WM8993_CLASS_W_0,
681 WM8993_CP_DYN_V | WM8993_CP_DYN_FREQ, enable);
682
683 snd_soc_component_write(component, WM8993_LEFT_OUTPUT_VOLUME,
684 snd_soc_component_read(component, WM8993_LEFT_OUTPUT_VOLUME));
685 snd_soc_component_write(component, WM8993_RIGHT_OUTPUT_VOLUME,
686 snd_soc_component_read(component, WM8993_RIGHT_OUTPUT_VOLUME));
687 }
688 EXPORT_SYMBOL_GPL(wm_hubs_update_class_w);
689
690 #define WM_HUBS_SINGLE_W(xname, reg, shift, max, invert) \
691 SOC_SINGLE_EXT(xname, reg, shift, max, invert, \
692 snd_soc_dapm_get_volsw, class_w_put_volsw)
693
class_w_put_volsw(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)694 static int class_w_put_volsw(struct snd_kcontrol *kcontrol,
695 struct snd_ctl_elem_value *ucontrol)
696 {
697 struct snd_soc_component *component = snd_soc_dapm_kcontrol_component(kcontrol);
698 int ret;
699
700 ret = snd_soc_dapm_put_volsw(kcontrol, ucontrol);
701
702 wm_hubs_update_class_w(component);
703
704 return ret;
705 }
706
707 #define WM_HUBS_ENUM_W(xname, xenum) \
708 { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
709 .info = snd_soc_info_enum_double, \
710 .get = snd_soc_dapm_get_enum_double, \
711 .put = class_w_put_double, \
712 .private_value = (unsigned long)&xenum }
713
class_w_put_double(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)714 static int class_w_put_double(struct snd_kcontrol *kcontrol,
715 struct snd_ctl_elem_value *ucontrol)
716 {
717 struct snd_soc_component *component = snd_soc_dapm_kcontrol_component(kcontrol);
718 int ret;
719
720 ret = snd_soc_dapm_put_enum_double(kcontrol, ucontrol);
721
722 wm_hubs_update_class_w(component);
723
724 return ret;
725 }
726
727 static const char *hp_mux_text[] = {
728 "Mixer",
729 "DAC",
730 };
731
732 static SOC_ENUM_SINGLE_DECL(hpl_enum,
733 WM8993_OUTPUT_MIXER1, 8, hp_mux_text);
734
735 const struct snd_kcontrol_new wm_hubs_hpl_mux =
736 WM_HUBS_ENUM_W("Left Headphone Mux", hpl_enum);
737 EXPORT_SYMBOL_GPL(wm_hubs_hpl_mux);
738
739 static SOC_ENUM_SINGLE_DECL(hpr_enum,
740 WM8993_OUTPUT_MIXER2, 8, hp_mux_text);
741
742 const struct snd_kcontrol_new wm_hubs_hpr_mux =
743 WM_HUBS_ENUM_W("Right Headphone Mux", hpr_enum);
744 EXPORT_SYMBOL_GPL(wm_hubs_hpr_mux);
745
746 static const struct snd_kcontrol_new in1l_pga[] = {
747 SOC_DAPM_SINGLE("IN1LP Switch", WM8993_INPUT_MIXER2, 5, 1, 0),
748 SOC_DAPM_SINGLE("IN1LN Switch", WM8993_INPUT_MIXER2, 4, 1, 0),
749 };
750
751 static const struct snd_kcontrol_new in1r_pga[] = {
752 SOC_DAPM_SINGLE("IN1RP Switch", WM8993_INPUT_MIXER2, 1, 1, 0),
753 SOC_DAPM_SINGLE("IN1RN Switch", WM8993_INPUT_MIXER2, 0, 1, 0),
754 };
755
756 static const struct snd_kcontrol_new in2l_pga[] = {
757 SOC_DAPM_SINGLE("IN2LP Switch", WM8993_INPUT_MIXER2, 7, 1, 0),
758 SOC_DAPM_SINGLE("IN2LN Switch", WM8993_INPUT_MIXER2, 6, 1, 0),
759 };
760
761 static const struct snd_kcontrol_new in2r_pga[] = {
762 SOC_DAPM_SINGLE("IN2RP Switch", WM8993_INPUT_MIXER2, 3, 1, 0),
763 SOC_DAPM_SINGLE("IN2RN Switch", WM8993_INPUT_MIXER2, 2, 1, 0),
764 };
765
766 static const struct snd_kcontrol_new mixinl[] = {
767 SOC_DAPM_SINGLE("IN2L Switch", WM8993_INPUT_MIXER3, 8, 1, 0),
768 SOC_DAPM_SINGLE("IN1L Switch", WM8993_INPUT_MIXER3, 5, 1, 0),
769 };
770
771 static const struct snd_kcontrol_new mixinr[] = {
772 SOC_DAPM_SINGLE("IN2R Switch", WM8993_INPUT_MIXER4, 8, 1, 0),
773 SOC_DAPM_SINGLE("IN1R Switch", WM8993_INPUT_MIXER4, 5, 1, 0),
774 };
775
776 static const struct snd_kcontrol_new left_output_mixer[] = {
777 WM_HUBS_SINGLE_W("Right Input Switch", WM8993_OUTPUT_MIXER1, 7, 1, 0),
778 WM_HUBS_SINGLE_W("Left Input Switch", WM8993_OUTPUT_MIXER1, 6, 1, 0),
779 WM_HUBS_SINGLE_W("IN2RN Switch", WM8993_OUTPUT_MIXER1, 5, 1, 0),
780 WM_HUBS_SINGLE_W("IN2LN Switch", WM8993_OUTPUT_MIXER1, 4, 1, 0),
781 WM_HUBS_SINGLE_W("IN2LP Switch", WM8993_OUTPUT_MIXER1, 1, 1, 0),
782 WM_HUBS_SINGLE_W("IN1R Switch", WM8993_OUTPUT_MIXER1, 3, 1, 0),
783 WM_HUBS_SINGLE_W("IN1L Switch", WM8993_OUTPUT_MIXER1, 2, 1, 0),
784 WM_HUBS_SINGLE_W("DAC Switch", WM8993_OUTPUT_MIXER1, 0, 1, 0),
785 };
786
787 static const struct snd_kcontrol_new right_output_mixer[] = {
788 WM_HUBS_SINGLE_W("Left Input Switch", WM8993_OUTPUT_MIXER2, 7, 1, 0),
789 WM_HUBS_SINGLE_W("Right Input Switch", WM8993_OUTPUT_MIXER2, 6, 1, 0),
790 WM_HUBS_SINGLE_W("IN2LN Switch", WM8993_OUTPUT_MIXER2, 5, 1, 0),
791 WM_HUBS_SINGLE_W("IN2RN Switch", WM8993_OUTPUT_MIXER2, 4, 1, 0),
792 WM_HUBS_SINGLE_W("IN1L Switch", WM8993_OUTPUT_MIXER2, 3, 1, 0),
793 WM_HUBS_SINGLE_W("IN1R Switch", WM8993_OUTPUT_MIXER2, 2, 1, 0),
794 WM_HUBS_SINGLE_W("IN2RP Switch", WM8993_OUTPUT_MIXER2, 1, 1, 0),
795 WM_HUBS_SINGLE_W("DAC Switch", WM8993_OUTPUT_MIXER2, 0, 1, 0),
796 };
797
798 static const struct snd_kcontrol_new earpiece_mixer[] = {
799 SOC_DAPM_SINGLE("Direct Voice Switch", WM8993_HPOUT2_MIXER, 5, 1, 0),
800 SOC_DAPM_SINGLE("Left Output Switch", WM8993_HPOUT2_MIXER, 4, 1, 0),
801 SOC_DAPM_SINGLE("Right Output Switch", WM8993_HPOUT2_MIXER, 3, 1, 0),
802 };
803
804 static const struct snd_kcontrol_new left_speaker_boost[] = {
805 SOC_DAPM_SINGLE("Direct Voice Switch", WM8993_SPKOUT_MIXERS, 5, 1, 0),
806 SOC_DAPM_SINGLE("SPKL Switch", WM8993_SPKOUT_MIXERS, 4, 1, 0),
807 SOC_DAPM_SINGLE("SPKR Switch", WM8993_SPKOUT_MIXERS, 3, 1, 0),
808 };
809
810 static const struct snd_kcontrol_new right_speaker_boost[] = {
811 SOC_DAPM_SINGLE("Direct Voice Switch", WM8993_SPKOUT_MIXERS, 2, 1, 0),
812 SOC_DAPM_SINGLE("SPKL Switch", WM8993_SPKOUT_MIXERS, 1, 1, 0),
813 SOC_DAPM_SINGLE("SPKR Switch", WM8993_SPKOUT_MIXERS, 0, 1, 0),
814 };
815
816 static const struct snd_kcontrol_new line1_mix[] = {
817 SOC_DAPM_SINGLE("IN1R Switch", WM8993_LINE_MIXER1, 2, 1, 0),
818 SOC_DAPM_SINGLE("IN1L Switch", WM8993_LINE_MIXER1, 1, 1, 0),
819 SOC_DAPM_SINGLE("Output Switch", WM8993_LINE_MIXER1, 0, 1, 0),
820 };
821
822 static const struct snd_kcontrol_new line1n_mix[] = {
823 SOC_DAPM_SINGLE("Left Output Switch", WM8993_LINE_MIXER1, 6, 1, 0),
824 SOC_DAPM_SINGLE("Right Output Switch", WM8993_LINE_MIXER1, 5, 1, 0),
825 };
826
827 static const struct snd_kcontrol_new line1p_mix[] = {
828 SOC_DAPM_SINGLE("Left Output Switch", WM8993_LINE_MIXER1, 0, 1, 0),
829 };
830
831 static const struct snd_kcontrol_new line2_mix[] = {
832 SOC_DAPM_SINGLE("IN1L Switch", WM8993_LINE_MIXER2, 2, 1, 0),
833 SOC_DAPM_SINGLE("IN1R Switch", WM8993_LINE_MIXER2, 1, 1, 0),
834 SOC_DAPM_SINGLE("Output Switch", WM8993_LINE_MIXER2, 0, 1, 0),
835 };
836
837 static const struct snd_kcontrol_new line2n_mix[] = {
838 SOC_DAPM_SINGLE("Left Output Switch", WM8993_LINE_MIXER2, 5, 1, 0),
839 SOC_DAPM_SINGLE("Right Output Switch", WM8993_LINE_MIXER2, 6, 1, 0),
840 };
841
842 static const struct snd_kcontrol_new line2p_mix[] = {
843 SOC_DAPM_SINGLE("Right Output Switch", WM8993_LINE_MIXER2, 0, 1, 0),
844 };
845
846 static const struct snd_soc_dapm_widget analogue_dapm_widgets[] = {
847 SND_SOC_DAPM_INPUT("IN1LN"),
848 SND_SOC_DAPM_INPUT("IN1LP"),
849 SND_SOC_DAPM_INPUT("IN2LN"),
850 SND_SOC_DAPM_INPUT("IN2LP:VXRN"),
851 SND_SOC_DAPM_INPUT("IN1RN"),
852 SND_SOC_DAPM_INPUT("IN1RP"),
853 SND_SOC_DAPM_INPUT("IN2RN"),
854 SND_SOC_DAPM_INPUT("IN2RP:VXRP"),
855
856 SND_SOC_DAPM_SUPPLY("MICBIAS2", WM8993_POWER_MANAGEMENT_1, 5, 0,
857 micbias_event, SND_SOC_DAPM_POST_PMU),
858 SND_SOC_DAPM_SUPPLY("MICBIAS1", WM8993_POWER_MANAGEMENT_1, 4, 0,
859 micbias_event, SND_SOC_DAPM_POST_PMU),
860
861 SND_SOC_DAPM_MIXER("IN1L PGA", WM8993_POWER_MANAGEMENT_2, 6, 0,
862 in1l_pga, ARRAY_SIZE(in1l_pga)),
863 SND_SOC_DAPM_MIXER("IN1R PGA", WM8993_POWER_MANAGEMENT_2, 4, 0,
864 in1r_pga, ARRAY_SIZE(in1r_pga)),
865
866 SND_SOC_DAPM_MIXER("IN2L PGA", WM8993_POWER_MANAGEMENT_2, 7, 0,
867 in2l_pga, ARRAY_SIZE(in2l_pga)),
868 SND_SOC_DAPM_MIXER("IN2R PGA", WM8993_POWER_MANAGEMENT_2, 5, 0,
869 in2r_pga, ARRAY_SIZE(in2r_pga)),
870
871 SND_SOC_DAPM_MIXER("MIXINL", WM8993_POWER_MANAGEMENT_2, 9, 0,
872 mixinl, ARRAY_SIZE(mixinl)),
873 SND_SOC_DAPM_MIXER("MIXINR", WM8993_POWER_MANAGEMENT_2, 8, 0,
874 mixinr, ARRAY_SIZE(mixinr)),
875
876 SND_SOC_DAPM_MIXER("Left Output Mixer", WM8993_POWER_MANAGEMENT_3, 5, 0,
877 left_output_mixer, ARRAY_SIZE(left_output_mixer)),
878 SND_SOC_DAPM_MIXER("Right Output Mixer", WM8993_POWER_MANAGEMENT_3, 4, 0,
879 right_output_mixer, ARRAY_SIZE(right_output_mixer)),
880
881 SND_SOC_DAPM_PGA("Left Output PGA", WM8993_POWER_MANAGEMENT_3, 7, 0, NULL, 0),
882 SND_SOC_DAPM_PGA("Right Output PGA", WM8993_POWER_MANAGEMENT_3, 6, 0, NULL, 0),
883
884 SND_SOC_DAPM_SUPPLY("Headphone Supply", SND_SOC_NOPM, 0, 0, hp_supply_event,
885 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_PRE_PMD),
886 SND_SOC_DAPM_OUT_DRV_E("Headphone PGA", SND_SOC_NOPM, 0, 0, NULL, 0,
887 hp_event, SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
888
889 SND_SOC_DAPM_MIXER("Earpiece Mixer", SND_SOC_NOPM, 0, 0,
890 earpiece_mixer, ARRAY_SIZE(earpiece_mixer)),
891 SND_SOC_DAPM_PGA_E("Earpiece Driver", WM8993_POWER_MANAGEMENT_1, 11, 0,
892 NULL, 0, earpiece_event,
893 SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
894
895 SND_SOC_DAPM_MIXER("SPKL Boost", SND_SOC_NOPM, 0, 0,
896 left_speaker_boost, ARRAY_SIZE(left_speaker_boost)),
897 SND_SOC_DAPM_MIXER("SPKR Boost", SND_SOC_NOPM, 0, 0,
898 right_speaker_boost, ARRAY_SIZE(right_speaker_boost)),
899
900 SND_SOC_DAPM_SUPPLY("TSHUT", WM8993_POWER_MANAGEMENT_2, 14, 0, NULL, 0),
901 SND_SOC_DAPM_OUT_DRV("SPKL Driver", WM8993_POWER_MANAGEMENT_1, 12, 0,
902 NULL, 0),
903 SND_SOC_DAPM_OUT_DRV("SPKR Driver", WM8993_POWER_MANAGEMENT_1, 13, 0,
904 NULL, 0),
905
906 SND_SOC_DAPM_MIXER("LINEOUT1 Mixer", SND_SOC_NOPM, 0, 0,
907 line1_mix, ARRAY_SIZE(line1_mix)),
908 SND_SOC_DAPM_MIXER("LINEOUT2 Mixer", SND_SOC_NOPM, 0, 0,
909 line2_mix, ARRAY_SIZE(line2_mix)),
910
911 SND_SOC_DAPM_MIXER("LINEOUT1N Mixer", SND_SOC_NOPM, 0, 0,
912 line1n_mix, ARRAY_SIZE(line1n_mix)),
913 SND_SOC_DAPM_MIXER("LINEOUT1P Mixer", SND_SOC_NOPM, 0, 0,
914 line1p_mix, ARRAY_SIZE(line1p_mix)),
915 SND_SOC_DAPM_MIXER("LINEOUT2N Mixer", SND_SOC_NOPM, 0, 0,
916 line2n_mix, ARRAY_SIZE(line2n_mix)),
917 SND_SOC_DAPM_MIXER("LINEOUT2P Mixer", SND_SOC_NOPM, 0, 0,
918 line2p_mix, ARRAY_SIZE(line2p_mix)),
919
920 SND_SOC_DAPM_OUT_DRV_E("LINEOUT1N Driver", WM8993_POWER_MANAGEMENT_3, 13, 0,
921 NULL, 0, lineout_event,
922 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
923 SND_SOC_DAPM_OUT_DRV_E("LINEOUT1P Driver", WM8993_POWER_MANAGEMENT_3, 12, 0,
924 NULL, 0, lineout_event,
925 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
926 SND_SOC_DAPM_OUT_DRV_E("LINEOUT2N Driver", WM8993_POWER_MANAGEMENT_3, 11, 0,
927 NULL, 0, lineout_event,
928 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
929 SND_SOC_DAPM_OUT_DRV_E("LINEOUT2P Driver", WM8993_POWER_MANAGEMENT_3, 10, 0,
930 NULL, 0, lineout_event,
931 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
932
933 SND_SOC_DAPM_OUTPUT("SPKOUTLP"),
934 SND_SOC_DAPM_OUTPUT("SPKOUTLN"),
935 SND_SOC_DAPM_OUTPUT("SPKOUTRP"),
936 SND_SOC_DAPM_OUTPUT("SPKOUTRN"),
937 SND_SOC_DAPM_OUTPUT("HPOUT1L"),
938 SND_SOC_DAPM_OUTPUT("HPOUT1R"),
939 SND_SOC_DAPM_OUTPUT("HPOUT2P"),
940 SND_SOC_DAPM_OUTPUT("HPOUT2N"),
941 SND_SOC_DAPM_OUTPUT("LINEOUT1P"),
942 SND_SOC_DAPM_OUTPUT("LINEOUT1N"),
943 SND_SOC_DAPM_OUTPUT("LINEOUT2P"),
944 SND_SOC_DAPM_OUTPUT("LINEOUT2N"),
945 };
946
947 static const struct snd_soc_dapm_route analogue_routes[] = {
948 { "MICBIAS1", NULL, "CLK_SYS" },
949 { "MICBIAS2", NULL, "CLK_SYS" },
950
951 { "IN1L PGA", "IN1LP Switch", "IN1LP" },
952 { "IN1L PGA", "IN1LN Switch", "IN1LN" },
953
954 { "IN1L PGA", NULL, "VMID" },
955 { "IN1R PGA", NULL, "VMID" },
956 { "IN2L PGA", NULL, "VMID" },
957 { "IN2R PGA", NULL, "VMID" },
958
959 { "IN1R PGA", "IN1RP Switch", "IN1RP" },
960 { "IN1R PGA", "IN1RN Switch", "IN1RN" },
961
962 { "IN2L PGA", "IN2LP Switch", "IN2LP:VXRN" },
963 { "IN2L PGA", "IN2LN Switch", "IN2LN" },
964
965 { "IN2R PGA", "IN2RP Switch", "IN2RP:VXRP" },
966 { "IN2R PGA", "IN2RN Switch", "IN2RN" },
967
968 { "Direct Voice", NULL, "IN2LP:VXRN" },
969 { "Direct Voice", NULL, "IN2RP:VXRP" },
970
971 { "MIXINL", "IN1L Switch", "IN1L PGA" },
972 { "MIXINL", "IN2L Switch", "IN2L PGA" },
973 { "MIXINL", NULL, "Direct Voice" },
974 { "MIXINL", NULL, "IN1LP" },
975 { "MIXINL", NULL, "Left Output Mixer" },
976 { "MIXINL", NULL, "VMID" },
977
978 { "MIXINR", "IN1R Switch", "IN1R PGA" },
979 { "MIXINR", "IN2R Switch", "IN2R PGA" },
980 { "MIXINR", NULL, "Direct Voice" },
981 { "MIXINR", NULL, "IN1RP" },
982 { "MIXINR", NULL, "Right Output Mixer" },
983 { "MIXINR", NULL, "VMID" },
984
985 { "ADCL", NULL, "MIXINL" },
986 { "ADCR", NULL, "MIXINR" },
987
988 { "Left Output Mixer", "Left Input Switch", "MIXINL" },
989 { "Left Output Mixer", "Right Input Switch", "MIXINR" },
990 { "Left Output Mixer", "IN2RN Switch", "IN2RN" },
991 { "Left Output Mixer", "IN2LN Switch", "IN2LN" },
992 { "Left Output Mixer", "IN2LP Switch", "IN2LP:VXRN" },
993 { "Left Output Mixer", "IN1L Switch", "IN1L PGA" },
994 { "Left Output Mixer", "IN1R Switch", "IN1R PGA" },
995
996 { "Right Output Mixer", "Left Input Switch", "MIXINL" },
997 { "Right Output Mixer", "Right Input Switch", "MIXINR" },
998 { "Right Output Mixer", "IN2LN Switch", "IN2LN" },
999 { "Right Output Mixer", "IN2RN Switch", "IN2RN" },
1000 { "Right Output Mixer", "IN2RP Switch", "IN2RP:VXRP" },
1001 { "Right Output Mixer", "IN1L Switch", "IN1L PGA" },
1002 { "Right Output Mixer", "IN1R Switch", "IN1R PGA" },
1003
1004 { "Left Output PGA", NULL, "Left Output Mixer" },
1005 { "Left Output PGA", NULL, "TOCLK" },
1006
1007 { "Right Output PGA", NULL, "Right Output Mixer" },
1008 { "Right Output PGA", NULL, "TOCLK" },
1009
1010 { "Earpiece Mixer", "Direct Voice Switch", "Direct Voice" },
1011 { "Earpiece Mixer", "Left Output Switch", "Left Output PGA" },
1012 { "Earpiece Mixer", "Right Output Switch", "Right Output PGA" },
1013
1014 { "Earpiece Driver", NULL, "VMID" },
1015 { "Earpiece Driver", NULL, "Earpiece Mixer" },
1016 { "HPOUT2N", NULL, "Earpiece Driver" },
1017 { "HPOUT2P", NULL, "Earpiece Driver" },
1018
1019 { "SPKL", "Input Switch", "MIXINL" },
1020 { "SPKL", "IN1LP Switch", "IN1LP" },
1021 { "SPKL", "Output Switch", "Left Output PGA" },
1022 { "SPKL", NULL, "TOCLK" },
1023
1024 { "SPKR", "Input Switch", "MIXINR" },
1025 { "SPKR", "IN1RP Switch", "IN1RP" },
1026 { "SPKR", "Output Switch", "Right Output PGA" },
1027 { "SPKR", NULL, "TOCLK" },
1028
1029 { "SPKL Boost", "Direct Voice Switch", "Direct Voice" },
1030 { "SPKL Boost", "SPKL Switch", "SPKL" },
1031 { "SPKL Boost", "SPKR Switch", "SPKR" },
1032
1033 { "SPKR Boost", "Direct Voice Switch", "Direct Voice" },
1034 { "SPKR Boost", "SPKR Switch", "SPKR" },
1035 { "SPKR Boost", "SPKL Switch", "SPKL" },
1036
1037 { "SPKL Driver", NULL, "VMID" },
1038 { "SPKL Driver", NULL, "SPKL Boost" },
1039 { "SPKL Driver", NULL, "CLK_SYS" },
1040 { "SPKL Driver", NULL, "TSHUT" },
1041
1042 { "SPKR Driver", NULL, "VMID" },
1043 { "SPKR Driver", NULL, "SPKR Boost" },
1044 { "SPKR Driver", NULL, "CLK_SYS" },
1045 { "SPKR Driver", NULL, "TSHUT" },
1046
1047 { "SPKOUTLP", NULL, "SPKL Driver" },
1048 { "SPKOUTLN", NULL, "SPKL Driver" },
1049 { "SPKOUTRP", NULL, "SPKR Driver" },
1050 { "SPKOUTRN", NULL, "SPKR Driver" },
1051
1052 { "Left Headphone Mux", "Mixer", "Left Output PGA" },
1053 { "Right Headphone Mux", "Mixer", "Right Output PGA" },
1054
1055 { "Headphone PGA", NULL, "Left Headphone Mux" },
1056 { "Headphone PGA", NULL, "Right Headphone Mux" },
1057 { "Headphone PGA", NULL, "VMID" },
1058 { "Headphone PGA", NULL, "CLK_SYS" },
1059 { "Headphone PGA", NULL, "Headphone Supply" },
1060
1061 { "HPOUT1L", NULL, "Headphone PGA" },
1062 { "HPOUT1R", NULL, "Headphone PGA" },
1063
1064 { "LINEOUT1N Driver", NULL, "VMID" },
1065 { "LINEOUT1P Driver", NULL, "VMID" },
1066 { "LINEOUT2N Driver", NULL, "VMID" },
1067 { "LINEOUT2P Driver", NULL, "VMID" },
1068
1069 { "LINEOUT1N", NULL, "LINEOUT1N Driver" },
1070 { "LINEOUT1P", NULL, "LINEOUT1P Driver" },
1071 { "LINEOUT2N", NULL, "LINEOUT2N Driver" },
1072 { "LINEOUT2P", NULL, "LINEOUT2P Driver" },
1073 };
1074
1075 static const struct snd_soc_dapm_route lineout1_diff_routes[] = {
1076 { "LINEOUT1 Mixer", "IN1L Switch", "IN1L PGA" },
1077 { "LINEOUT1 Mixer", "IN1R Switch", "IN1R PGA" },
1078 { "LINEOUT1 Mixer", "Output Switch", "Left Output PGA" },
1079
1080 { "LINEOUT1N Driver", NULL, "LINEOUT1 Mixer" },
1081 { "LINEOUT1P Driver", NULL, "LINEOUT1 Mixer" },
1082 };
1083
1084 static const struct snd_soc_dapm_route lineout1_se_routes[] = {
1085 { "LINEOUT1N Mixer", "Left Output Switch", "Left Output PGA" },
1086 { "LINEOUT1N Mixer", "Right Output Switch", "Right Output PGA" },
1087
1088 { "LINEOUT1P Mixer", "Left Output Switch", "Left Output PGA" },
1089
1090 { "LINEOUT1N Driver", NULL, "LINEOUT1N Mixer" },
1091 { "LINEOUT1P Driver", NULL, "LINEOUT1P Mixer" },
1092 };
1093
1094 static const struct snd_soc_dapm_route lineout2_diff_routes[] = {
1095 { "LINEOUT2 Mixer", "IN1L Switch", "IN1L PGA" },
1096 { "LINEOUT2 Mixer", "IN1R Switch", "IN1R PGA" },
1097 { "LINEOUT2 Mixer", "Output Switch", "Right Output PGA" },
1098
1099 { "LINEOUT2N Driver", NULL, "LINEOUT2 Mixer" },
1100 { "LINEOUT2P Driver", NULL, "LINEOUT2 Mixer" },
1101 };
1102
1103 static const struct snd_soc_dapm_route lineout2_se_routes[] = {
1104 { "LINEOUT2N Mixer", "Left Output Switch", "Left Output PGA" },
1105 { "LINEOUT2N Mixer", "Right Output Switch", "Right Output PGA" },
1106
1107 { "LINEOUT2P Mixer", "Right Output Switch", "Right Output PGA" },
1108
1109 { "LINEOUT2N Driver", NULL, "LINEOUT2N Mixer" },
1110 { "LINEOUT2P Driver", NULL, "LINEOUT2P Mixer" },
1111 };
1112
wm_hubs_add_analogue_controls(struct snd_soc_component * component)1113 int wm_hubs_add_analogue_controls(struct snd_soc_component *component)
1114 {
1115 struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component);
1116
1117 /* Latch volume update bits & default ZC on */
1118 snd_soc_component_update_bits(component, WM8993_LEFT_LINE_INPUT_1_2_VOLUME,
1119 WM8993_IN1_VU, WM8993_IN1_VU);
1120 snd_soc_component_update_bits(component, WM8993_RIGHT_LINE_INPUT_1_2_VOLUME,
1121 WM8993_IN1_VU, WM8993_IN1_VU);
1122 snd_soc_component_update_bits(component, WM8993_LEFT_LINE_INPUT_3_4_VOLUME,
1123 WM8993_IN2_VU, WM8993_IN2_VU);
1124 snd_soc_component_update_bits(component, WM8993_RIGHT_LINE_INPUT_3_4_VOLUME,
1125 WM8993_IN2_VU, WM8993_IN2_VU);
1126
1127 snd_soc_component_update_bits(component, WM8993_SPEAKER_VOLUME_LEFT,
1128 WM8993_SPKOUT_VU, WM8993_SPKOUT_VU);
1129 snd_soc_component_update_bits(component, WM8993_SPEAKER_VOLUME_RIGHT,
1130 WM8993_SPKOUT_VU, WM8993_SPKOUT_VU);
1131
1132 snd_soc_component_update_bits(component, WM8993_LEFT_OUTPUT_VOLUME,
1133 WM8993_HPOUT1_VU | WM8993_HPOUT1L_ZC,
1134 WM8993_HPOUT1_VU | WM8993_HPOUT1L_ZC);
1135 snd_soc_component_update_bits(component, WM8993_RIGHT_OUTPUT_VOLUME,
1136 WM8993_HPOUT1_VU | WM8993_HPOUT1R_ZC,
1137 WM8993_HPOUT1_VU | WM8993_HPOUT1R_ZC);
1138
1139 snd_soc_component_update_bits(component, WM8993_LEFT_OPGA_VOLUME,
1140 WM8993_MIXOUTL_ZC | WM8993_MIXOUT_VU,
1141 WM8993_MIXOUTL_ZC | WM8993_MIXOUT_VU);
1142 snd_soc_component_update_bits(component, WM8993_RIGHT_OPGA_VOLUME,
1143 WM8993_MIXOUTR_ZC | WM8993_MIXOUT_VU,
1144 WM8993_MIXOUTR_ZC | WM8993_MIXOUT_VU);
1145
1146 snd_soc_add_component_controls(component, analogue_snd_controls,
1147 ARRAY_SIZE(analogue_snd_controls));
1148
1149 snd_soc_dapm_new_controls(dapm, analogue_dapm_widgets,
1150 ARRAY_SIZE(analogue_dapm_widgets));
1151 return 0;
1152 }
1153 EXPORT_SYMBOL_GPL(wm_hubs_add_analogue_controls);
1154
wm_hubs_add_analogue_routes(struct snd_soc_component * component,int lineout1_diff,int lineout2_diff)1155 int wm_hubs_add_analogue_routes(struct snd_soc_component *component,
1156 int lineout1_diff, int lineout2_diff)
1157 {
1158 struct wm_hubs_data *hubs = snd_soc_component_get_drvdata(component);
1159 struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component);
1160
1161 hubs->component = component;
1162
1163 INIT_LIST_HEAD(&hubs->dcs_cache);
1164 init_completion(&hubs->dcs_done);
1165
1166 snd_soc_dapm_add_routes(dapm, analogue_routes,
1167 ARRAY_SIZE(analogue_routes));
1168
1169 if (lineout1_diff)
1170 snd_soc_dapm_add_routes(dapm,
1171 lineout1_diff_routes,
1172 ARRAY_SIZE(lineout1_diff_routes));
1173 else
1174 snd_soc_dapm_add_routes(dapm,
1175 lineout1_se_routes,
1176 ARRAY_SIZE(lineout1_se_routes));
1177
1178 if (lineout2_diff)
1179 snd_soc_dapm_add_routes(dapm,
1180 lineout2_diff_routes,
1181 ARRAY_SIZE(lineout2_diff_routes));
1182 else
1183 snd_soc_dapm_add_routes(dapm,
1184 lineout2_se_routes,
1185 ARRAY_SIZE(lineout2_se_routes));
1186
1187 return 0;
1188 }
1189 EXPORT_SYMBOL_GPL(wm_hubs_add_analogue_routes);
1190
wm_hubs_handle_analogue_pdata(struct snd_soc_component * component,int lineout1_diff,int lineout2_diff,int lineout1fb,int lineout2fb,int jd_scthr,int jd_thr,int micbias1_delay,int micbias2_delay,int micbias1_lvl,int micbias2_lvl)1191 int wm_hubs_handle_analogue_pdata(struct snd_soc_component *component,
1192 int lineout1_diff, int lineout2_diff,
1193 int lineout1fb, int lineout2fb,
1194 int jd_scthr, int jd_thr,
1195 int micbias1_delay, int micbias2_delay,
1196 int micbias1_lvl, int micbias2_lvl)
1197 {
1198 struct wm_hubs_data *hubs = snd_soc_component_get_drvdata(component);
1199
1200 hubs->lineout1_se = !lineout1_diff;
1201 hubs->lineout2_se = !lineout2_diff;
1202 hubs->micb1_delay = micbias1_delay;
1203 hubs->micb2_delay = micbias2_delay;
1204
1205 if (!lineout1_diff)
1206 snd_soc_component_update_bits(component, WM8993_LINE_MIXER1,
1207 WM8993_LINEOUT1_MODE,
1208 WM8993_LINEOUT1_MODE);
1209 if (!lineout2_diff)
1210 snd_soc_component_update_bits(component, WM8993_LINE_MIXER2,
1211 WM8993_LINEOUT2_MODE,
1212 WM8993_LINEOUT2_MODE);
1213
1214 if (!lineout1_diff && !lineout2_diff)
1215 snd_soc_component_update_bits(component, WM8993_ANTIPOP1,
1216 WM8993_LINEOUT_VMID_BUF_ENA,
1217 WM8993_LINEOUT_VMID_BUF_ENA);
1218
1219 if (lineout1fb)
1220 snd_soc_component_update_bits(component, WM8993_ADDITIONAL_CONTROL,
1221 WM8993_LINEOUT1_FB, WM8993_LINEOUT1_FB);
1222
1223 if (lineout2fb)
1224 snd_soc_component_update_bits(component, WM8993_ADDITIONAL_CONTROL,
1225 WM8993_LINEOUT2_FB, WM8993_LINEOUT2_FB);
1226
1227 if (!hubs->micd_scthr)
1228 return 0;
1229
1230 snd_soc_component_update_bits(component, WM8993_MICBIAS,
1231 WM8993_JD_SCTHR_MASK | WM8993_JD_THR_MASK |
1232 WM8993_MICB1_LVL | WM8993_MICB2_LVL,
1233 jd_scthr << WM8993_JD_SCTHR_SHIFT |
1234 jd_thr << WM8993_JD_THR_SHIFT |
1235 micbias1_lvl |
1236 micbias2_lvl << WM8993_MICB2_LVL_SHIFT);
1237
1238 return 0;
1239 }
1240 EXPORT_SYMBOL_GPL(wm_hubs_handle_analogue_pdata);
1241
wm_hubs_vmid_ena(struct snd_soc_component * component)1242 void wm_hubs_vmid_ena(struct snd_soc_component *component)
1243 {
1244 struct wm_hubs_data *hubs = snd_soc_component_get_drvdata(component);
1245 int val = 0;
1246
1247 if (hubs->lineout1_se)
1248 val |= WM8993_LINEOUT1N_ENA | WM8993_LINEOUT1P_ENA;
1249
1250 if (hubs->lineout2_se)
1251 val |= WM8993_LINEOUT2N_ENA | WM8993_LINEOUT2P_ENA;
1252
1253 /* Enable the line outputs while we power up */
1254 snd_soc_component_update_bits(component, WM8993_POWER_MANAGEMENT_3, val, val);
1255 }
1256 EXPORT_SYMBOL_GPL(wm_hubs_vmid_ena);
1257
wm_hubs_set_bias_level(struct snd_soc_component * component,enum snd_soc_bias_level level)1258 void wm_hubs_set_bias_level(struct snd_soc_component *component,
1259 enum snd_soc_bias_level level)
1260 {
1261 struct wm_hubs_data *hubs = snd_soc_component_get_drvdata(component);
1262 int mask, val;
1263
1264 switch (level) {
1265 case SND_SOC_BIAS_STANDBY:
1266 /* Clamp the inputs to VMID while we ramp to charge caps */
1267 snd_soc_component_update_bits(component, WM8993_INPUTS_CLAMP_REG,
1268 WM8993_INPUTS_CLAMP, WM8993_INPUTS_CLAMP);
1269 break;
1270
1271 case SND_SOC_BIAS_ON:
1272 /* Turn off any unneeded single ended outputs */
1273 val = 0;
1274 mask = 0;
1275
1276 if (hubs->lineout1_se)
1277 mask |= WM8993_LINEOUT1N_ENA | WM8993_LINEOUT1P_ENA;
1278
1279 if (hubs->lineout2_se)
1280 mask |= WM8993_LINEOUT2N_ENA | WM8993_LINEOUT2P_ENA;
1281
1282 if (hubs->lineout1_se && hubs->lineout1n_ena)
1283 val |= WM8993_LINEOUT1N_ENA;
1284
1285 if (hubs->lineout1_se && hubs->lineout1p_ena)
1286 val |= WM8993_LINEOUT1P_ENA;
1287
1288 if (hubs->lineout2_se && hubs->lineout2n_ena)
1289 val |= WM8993_LINEOUT2N_ENA;
1290
1291 if (hubs->lineout2_se && hubs->lineout2p_ena)
1292 val |= WM8993_LINEOUT2P_ENA;
1293
1294 snd_soc_component_update_bits(component, WM8993_POWER_MANAGEMENT_3,
1295 mask, val);
1296
1297 /* Remove the input clamps */
1298 snd_soc_component_update_bits(component, WM8993_INPUTS_CLAMP_REG,
1299 WM8993_INPUTS_CLAMP, 0);
1300 break;
1301
1302 default:
1303 break;
1304 }
1305 }
1306 EXPORT_SYMBOL_GPL(wm_hubs_set_bias_level);
1307
1308 MODULE_DESCRIPTION("Shared support for Wolfson hubs products");
1309 MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
1310 MODULE_LICENSE("GPL");
1311