Lines Matching +full:regulator +full:- +full:decay

1 // SPDX-License-Identifier: GPL-2.0-only
3 * wm8993.c -- WM8993 ALSA SoC audio driver
5 * Copyright 2009-12 Wolfson Microelectronics plc
17 #include <linux/regulator/consumer.h>
42 { 1, 0x0000 }, /* R1 - Power Management (1) */
43 { 2, 0x6000 }, /* R2 - Power Management (2) */
44 { 3, 0x0000 }, /* R3 - Power Management (3) */
45 { 4, 0x4050 }, /* R4 - Audio Interface (1) */
46 { 5, 0x4000 }, /* R5 - Audio Interface (2) */
47 { 6, 0x01C8 }, /* R6 - Clocking 1 */
48 { 7, 0x0000 }, /* R7 - Clocking 2 */
49 { 8, 0x0000 }, /* R8 - Audio Interface (3) */
50 { 9, 0x0040 }, /* R9 - Audio Interface (4) */
51 { 10, 0x0004 }, /* R10 - DAC CTRL */
52 { 11, 0x00C0 }, /* R11 - Left DAC Digital Volume */
53 { 12, 0x00C0 }, /* R12 - Right DAC Digital Volume */
54 { 13, 0x0000 }, /* R13 - Digital Side Tone */
55 { 14, 0x0300 }, /* R14 - ADC CTRL */
56 { 15, 0x00C0 }, /* R15 - Left ADC Digital Volume */
57 { 16, 0x00C0 }, /* R16 - Right ADC Digital Volume */
58 { 18, 0x0000 }, /* R18 - GPIO CTRL 1 */
59 { 19, 0x0010 }, /* R19 - GPIO1 */
60 { 20, 0x0000 }, /* R20 - IRQ_DEBOUNCE */
61 { 21, 0x0000 }, /* R21 - Inputs Clamp */
62 { 22, 0x8000 }, /* R22 - GPIOCTRL 2 */
63 { 23, 0x0800 }, /* R23 - GPIO_POL */
64 { 24, 0x008B }, /* R24 - Left Line Input 1&2 Volume */
65 { 25, 0x008B }, /* R25 - Left Line Input 3&4 Volume */
66 { 26, 0x008B }, /* R26 - Right Line Input 1&2 Volume */
67 { 27, 0x008B }, /* R27 - Right Line Input 3&4 Volume */
68 { 28, 0x006D }, /* R28 - Left Output Volume */
69 { 29, 0x006D }, /* R29 - Right Output Volume */
70 { 30, 0x0066 }, /* R30 - Line Outputs Volume */
71 { 31, 0x0020 }, /* R31 - HPOUT2 Volume */
72 { 32, 0x0079 }, /* R32 - Left OPGA Volume */
73 { 33, 0x0079 }, /* R33 - Right OPGA Volume */
74 { 34, 0x0003 }, /* R34 - SPKMIXL Attenuation */
75 { 35, 0x0003 }, /* R35 - SPKMIXR Attenuation */
76 { 36, 0x0011 }, /* R36 - SPKOUT Mixers */
77 { 37, 0x0100 }, /* R37 - SPKOUT Boost */
78 { 38, 0x0079 }, /* R38 - Speaker Volume Left */
79 { 39, 0x0079 }, /* R39 - Speaker Volume Right */
80 { 40, 0x0000 }, /* R40 - Input Mixer2 */
81 { 41, 0x0000 }, /* R41 - Input Mixer3 */
82 { 42, 0x0000 }, /* R42 - Input Mixer4 */
83 { 43, 0x0000 }, /* R43 - Input Mixer5 */
84 { 44, 0x0000 }, /* R44 - Input Mixer6 */
85 { 45, 0x0000 }, /* R45 - Output Mixer1 */
86 { 46, 0x0000 }, /* R46 - Output Mixer2 */
87 { 47, 0x0000 }, /* R47 - Output Mixer3 */
88 { 48, 0x0000 }, /* R48 - Output Mixer4 */
89 { 49, 0x0000 }, /* R49 - Output Mixer5 */
90 { 50, 0x0000 }, /* R50 - Output Mixer6 */
91 { 51, 0x0000 }, /* R51 - HPOUT2 Mixer */
92 { 52, 0x0000 }, /* R52 - Line Mixer1 */
93 { 53, 0x0000 }, /* R53 - Line Mixer2 */
94 { 54, 0x0000 }, /* R54 - Speaker Mixer */
95 { 55, 0x0000 }, /* R55 - Additional Control */
96 { 56, 0x0000 }, /* R56 - AntiPOP1 */
97 { 57, 0x0000 }, /* R57 - AntiPOP2 */
98 { 58, 0x0000 }, /* R58 - MICBIAS */
99 { 60, 0x0000 }, /* R60 - FLL Control 1 */
100 { 61, 0x0000 }, /* R61 - FLL Control 2 */
101 { 62, 0x0000 }, /* R62 - FLL Control 3 */
102 { 63, 0x2EE0 }, /* R63 - FLL Control 4 */
103 { 64, 0x0002 }, /* R64 - FLL Control 5 */
104 { 65, 0x2287 }, /* R65 - Clocking 3 */
105 { 66, 0x025F }, /* R66 - Clocking 4 */
106 { 67, 0x0000 }, /* R67 - MW Slave Control */
107 { 69, 0x0002 }, /* R69 - Bus Control 1 */
108 { 70, 0x0000 }, /* R70 - Write Sequencer 0 */
109 { 71, 0x0000 }, /* R71 - Write Sequencer 1 */
110 { 72, 0x0000 }, /* R72 - Write Sequencer 2 */
111 { 73, 0x0000 }, /* R73 - Write Sequencer 3 */
112 { 74, 0x0000 }, /* R74 - Write Sequencer 4 */
113 { 75, 0x0000 }, /* R75 - Write Sequencer 5 */
114 { 76, 0x1F25 }, /* R76 - Charge Pump 1 */
115 { 81, 0x0000 }, /* R81 - Class W 0 */
116 { 85, 0x054A }, /* R85 - DC Servo 1 */
117 { 87, 0x0000 }, /* R87 - DC Servo 3 */
118 { 96, 0x0100 }, /* R96 - Analogue HP 0 */
119 { 98, 0x0000 }, /* R98 - EQ1 */
120 { 99, 0x000C }, /* R99 - EQ2 */
121 { 100, 0x000C }, /* R100 - EQ3 */
122 { 101, 0x000C }, /* R101 - EQ4 */
123 { 102, 0x000C }, /* R102 - EQ5 */
124 { 103, 0x000C }, /* R103 - EQ6 */
125 { 104, 0x0FCA }, /* R104 - EQ7 */
126 { 105, 0x0400 }, /* R105 - EQ8 */
127 { 106, 0x00D8 }, /* R106 - EQ9 */
128 { 107, 0x1EB5 }, /* R107 - EQ10 */
129 { 108, 0xF145 }, /* R108 - EQ11 */
130 { 109, 0x0B75 }, /* R109 - EQ12 */
131 { 110, 0x01C5 }, /* R110 - EQ13 */
132 { 111, 0x1C58 }, /* R111 - EQ14 */
133 { 112, 0xF373 }, /* R112 - EQ15 */
134 { 113, 0x0A54 }, /* R113 - EQ16 */
135 { 114, 0x0558 }, /* R114 - EQ17 */
136 { 115, 0x168E }, /* R115 - EQ18 */
137 { 116, 0xF829 }, /* R116 - EQ19 */
138 { 117, 0x07AD }, /* R117 - EQ20 */
139 { 118, 0x1103 }, /* R118 - EQ21 */
140 { 119, 0x0564 }, /* R119 - EQ22 */
141 { 120, 0x0559 }, /* R120 - EQ23 */
142 { 121, 0x4000 }, /* R121 - EQ24 */
143 { 122, 0x0000 }, /* R122 - Digital Pulls */
144 { 123, 0x0F08 }, /* R123 - DRC Control 1 */
145 { 124, 0x0000 }, /* R124 - DRC Control 2 */
146 { 125, 0x0080 }, /* R125 - DRC Control 3 */
147 { 126, 0x0000 }, /* R126 - DRC Control 4 */
392 fll_div->fll_clk_ref_div = 0;
395 fll_div->fll_clk_ref_div++;
400 return -EINVAL;
409 /* Fvco should be 90-100MHz; don't check the upper bound */
418 return -EINVAL;
421 fll_div->fll_outdiv = div;
428 fll_div->fll_fratio = fll_fratios[i].fll_fratio;
435 return -EINVAL;
441 fll_div->n = Ndiv;
445 /* Calculate fractional part - scale up so we can round. */
456 fll_div->k = K / 10;
459 fll_div->n, fll_div->k,
460 fll_div->fll_fratio, fll_div->fll_outdiv,
461 fll_div->fll_clk_ref_div);
470 struct i2c_client *i2c = to_i2c_client(component->dev);
477 if (Fref == wm8993->fll_fref && Fout == wm8993->fll_fout)
482 dev_dbg(component->dev, "FLL disabled\n");
483 wm8993->fll_fref = 0;
484 wm8993->fll_fout = 0;
513 dev_err(component->dev, "Unknown FLL ID %d\n", fll_id);
514 return -EINVAL;
545 if (i2c->irq)
552 try_wait_for_completion(&wm8993->fll_lock);
557 time_left = wait_for_completion_timeout(&wm8993->fll_lock, time_left);
558 if (i2c->irq && !time_left)
559 dev_warn(component->dev, "Timed out waiting for FLL\n");
561 dev_dbg(component->dev, "FLL enabled at %dHz->%dHz\n", Fref, Fout);
563 wm8993->fll_fref = Fref;
564 wm8993->fll_fout = Fout;
565 wm8993->fll_src = source;
573 return _wm8993_set_fll(dai->component, fll_id, source, Fref, Fout);
582 switch (wm8993->sysclk_source) {
584 dev_dbg(component->dev, "Using %dHz MCLK\n", wm8993->mclk_rate);
588 if (wm8993->mclk_rate > 13500000) {
590 wm8993->sysclk_rate = wm8993->mclk_rate / 2;
593 wm8993->sysclk_rate = wm8993->mclk_rate;
599 dev_dbg(component->dev, "Using %dHz FLL clock\n",
600 wm8993->fll_fout);
604 if (wm8993->fll_fout > 13500000) {
606 wm8993->sysclk_rate = wm8993->fll_fout / 2;
609 wm8993->sysclk_rate = wm8993->fll_fout;
615 dev_err(component->dev, "System clock not configured\n");
616 return -EINVAL;
619 dev_dbg(component->dev, "CLK_SYS is %dHz\n", wm8993->sysclk_rate);
624 static const DECLARE_TLV_DB_SCALE(sidetone_tlv, -3600, 300, 0);
625 static const DECLARE_TLV_DB_SCALE(drc_comp_threash, -4500, 75, 0);
626 static const DECLARE_TLV_DB_SCALE(drc_comp_amp, -2250, 75, 0);
627 static const DECLARE_TLV_DB_SCALE(drc_min_tlv, -1800, 600, 0);
633 static const DECLARE_TLV_DB_SCALE(drc_startup_tlv, -1800, 300, 0);
634 static const DECLARE_TLV_DB_SCALE(eq_tlv, -1200, 100, 0);
635 static const DECLARE_TLV_DB_SCALE(digital_tlv, -7200, 75, 1);
649 "Hi-Fi",
765 SOC_ENUM("DRC Decay Rate", drc_decay),
767 SOC_SINGLE("DRC Anti-clip Switch", WM8993_DRC_CONTROL_1, 9, 1, 0),
809 struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
992 ret = regulator_bulk_enable(ARRAY_SIZE(wm8993->supplies),
993 wm8993->supplies);
997 regcache_cache_only(wm8993->regmap, false);
998 regcache_sync(wm8993->regmap);
1015 if (!wm8993->pdata.lineout1_diff ||
1016 !wm8993->pdata.lineout2_diff)
1056 regcache_cache_only(wm8993->regmap, true);
1057 regcache_mark_dirty(wm8993->regmap);
1059 regulator_bulk_disable(ARRAY_SIZE(wm8993->supplies),
1060 wm8993->supplies);
1070 struct snd_soc_component *component = codec_dai->component;
1075 wm8993->mclk_rate = freq;
1078 wm8993->sysclk_source = clk_id;
1082 return -EINVAL;
1091 struct snd_soc_component *component = dai->component;
1102 wm8993->master = 0;
1106 wm8993->master = 1;
1110 wm8993->master = 1;
1115 wm8993->master = 1;
1118 return -EINVAL;
1137 return -EINVAL;
1151 return -EINVAL;
1171 return -EINVAL;
1175 return -EINVAL;
1188 struct snd_soc_component *component = dai->component;
1206 wm8993->fs = params_rate(params);
1207 wm8993->bclk = 2 * wm8993->fs;
1208 if (wm8993->tdm_slots) {
1209 dev_dbg(component->dev, "Configuring for %d %d bit TDM slots\n",
1210 wm8993->tdm_slots, wm8993->tdm_width);
1211 wm8993->bclk *= wm8993->tdm_width * wm8993->tdm_slots;
1215 wm8993->bclk *= 16;
1218 wm8993->bclk *= 20;
1222 wm8993->bclk *= 24;
1226 wm8993->bclk *= 32;
1230 return -EINVAL;
1234 dev_dbg(component->dev, "Target BCLK is %dHz\n", wm8993->bclk);
1242 best_val = abs((wm8993->sysclk_rate / clk_sys_rates[0].ratio)
1243 - wm8993->fs);
1245 cur_val = abs((wm8993->sysclk_rate /
1246 clk_sys_rates[i].ratio) - wm8993->fs);
1252 dev_dbg(component->dev, "Selected CLK_SYS_RATIO of %d\n",
1259 best_val = abs(wm8993->fs - sample_rates[0].rate);
1262 cur_val = abs(wm8993->fs - sample_rates[i].rate);
1268 dev_dbg(component->dev, "Selected SAMPLE_RATE of %dHz\n",
1277 cur_val = ((wm8993->sysclk_rate * 10) / bclk_divs[i].div)
1278 - wm8993->bclk;
1286 wm8993->bclk = (wm8993->sysclk_rate * 10) / bclk_divs[best].div;
1287 dev_dbg(component->dev, "Selected BCLK_DIV of %d for %dHz BCLK\n",
1288 bclk_divs[best].div, wm8993->bclk);
1292 dev_dbg(component->dev, "LRCLK_RATE is %d\n", wm8993->bclk / wm8993->fs);
1293 aif4 |= wm8993->bclk / wm8993->fs;
1301 if (wm8993->pdata.num_retune_configs) {
1306 best_val = abs(wm8993->pdata.retune_configs[0].rate
1307 - wm8993->fs);
1308 for (i = 0; i < wm8993->pdata.num_retune_configs; i++) {
1309 cur_val = abs(wm8993->pdata.retune_configs[i].rate
1310 - wm8993->fs);
1316 s = &wm8993->pdata.retune_configs[best];
1318 dev_dbg(component->dev, "ReTune Mobile %s tuned for %dHz\n",
1319 s->name, s->rate);
1324 for (i = 1; i < ARRAY_SIZE(s->config); i++)
1325 snd_soc_component_write(component, WM8993_EQ1 + i, s->config[i]);
1335 struct snd_soc_component *component = codec_dai->component;
1353 struct snd_soc_component *component = dai->component;
1360 wm8993->tdm_slots = 0;
1364 /* Note that we allow configurations we can't handle ourselves -
1378 return -EINVAL;
1389 return -EINVAL;
1393 wm8993->tdm_width = slot_width;
1394 wm8993->tdm_slots = slots / 2;
1409 ret = regmap_read(wm8993->regmap, WM8993_GPIO_CTRL_1, &val);
1411 dev_err(wm8993->dev, "Failed to read interrupt status: %d\n",
1416 ret = regmap_read(wm8993->regmap, WM8993_GPIOCTRL_2, &mask);
1418 dev_err(wm8993->dev, "Failed to read interrupt mask: %d\n",
1429 dev_crit(wm8993->dev, "Thermal warning\n");
1432 dev_dbg(wm8993->dev, "FLL locked\n");
1433 complete(&wm8993->fll_lock);
1436 ret = regmap_write(wm8993->regmap, WM8993_GPIO_CTRL_1, val);
1438 dev_err(wm8993->dev, "Failed to ack interrupt: %d\n", ret);
1461 .name = "wm8993-hifi",
1487 wm8993->hubs_data.hp_startup_mode = 1;
1488 wm8993->hubs_data.dcs_codes_l = -2;
1489 wm8993->hubs_data.dcs_codes_r = -2;
1490 wm8993->hubs_data.series_startup = 1;
1506 wm_hubs_handle_analogue_pdata(component, wm8993->pdata.lineout1_diff,
1507 wm8993->pdata.lineout2_diff,
1508 wm8993->pdata.lineout1fb,
1509 wm8993->pdata.lineout2fb,
1510 wm8993->pdata.jd_scthr,
1511 wm8993->pdata.jd_thr,
1512 wm8993->pdata.micbias1_delay,
1513 wm8993->pdata.micbias2_delay,
1514 wm8993->pdata.micbias1_lvl,
1515 wm8993->pdata.micbias2_lvl);
1519 if (wm8993->pdata.num_retune_configs != 0) {
1520 dev_dbg(component->dev, "Using ReTune Mobile\n");
1522 dev_dbg(component->dev, "No ReTune Mobile, using normal EQ\n");
1532 wm_hubs_add_analogue_routes(component, wm8993->pdata.lineout1_diff,
1533 wm8993->pdata.lineout2_diff);
1538 if (wm8993->pdata.lineout1_diff && wm8993->pdata.lineout2_diff)
1539 dapm->idle_bias_off = 1;
1549 int fll_fout = wm8993->fll_fout;
1550 int fll_fref = wm8993->fll_fref;
1556 dev_err(component->dev, "Failed to stop FLL\n");
1560 wm8993->fll_fout = fll_fout;
1561 wm8993->fll_fref = fll_fref;
1576 if (wm8993->fll_fout) {
1577 int fll_fout = wm8993->fll_fout;
1578 int fll_fref = wm8993->fll_fref;
1580 wm8993->fll_fref = 0;
1581 wm8993->fll_fout = 0;
1583 ret = _wm8993_set_fll(component, 0, wm8993->fll_src,
1586 dev_err(component->dev, "Failed to restart FLL\n");
1632 wm8993 = devm_kzalloc(&i2c->dev, sizeof(struct wm8993_priv),
1635 return -ENOMEM;
1637 wm8993->dev = &i2c->dev;
1638 init_completion(&wm8993->fll_lock);
1640 wm8993->regmap = devm_regmap_init_i2c(i2c, &wm8993_regmap);
1641 if (IS_ERR(wm8993->regmap)) {
1642 ret = PTR_ERR(wm8993->regmap);
1643 dev_err(&i2c->dev, "Failed to allocate regmap: %d\n", ret);
1649 for (i = 0; i < ARRAY_SIZE(wm8993->supplies); i++)
1650 wm8993->supplies[i].supply = wm8993_supply_names[i];
1652 ret = devm_regulator_bulk_get(&i2c->dev, ARRAY_SIZE(wm8993->supplies),
1653 wm8993->supplies);
1655 dev_err(&i2c->dev, "Failed to request supplies: %d\n", ret);
1659 ret = regulator_bulk_enable(ARRAY_SIZE(wm8993->supplies),
1660 wm8993->supplies);
1662 dev_err(&i2c->dev, "Failed to enable supplies: %d\n", ret);
1666 ret = regmap_read(wm8993->regmap, WM8993_SOFTWARE_RESET, &reg);
1668 dev_err(&i2c->dev, "Failed to read chip ID: %d\n", ret);
1673 dev_err(&i2c->dev, "Invalid ID register value %x\n", reg);
1674 ret = -EINVAL;
1678 ret = regmap_write(wm8993->regmap, WM8993_SOFTWARE_RESET, 0xffff);
1682 ret = regmap_register_patch(wm8993->regmap, wm8993_regmap_patch,
1685 dev_warn(wm8993->dev, "Failed to apply regmap patch: %d\n",
1688 if (i2c->irq) {
1690 ret = regmap_update_bits(wm8993->regmap, WM8993_GPIO1,
1696 ret = request_threaded_irq(i2c->irq, NULL, wm8993_irq,
1704 regulator_bulk_disable(ARRAY_SIZE(wm8993->supplies), wm8993->supplies);
1706 regcache_cache_only(wm8993->regmap, true);
1708 ret = devm_snd_soc_register_component(&i2c->dev,
1711 dev_err(&i2c->dev, "Failed to register CODEC: %d\n", ret);
1718 if (i2c->irq)
1719 free_irq(i2c->irq, wm8993);
1721 regulator_bulk_disable(ARRAY_SIZE(wm8993->supplies), wm8993->supplies);
1729 if (i2c->irq)
1730 free_irq(i2c->irq, wm8993);
1731 regulator_bulk_disable(ARRAY_SIZE(wm8993->supplies), wm8993->supplies);