1// SPDX-License-Identifier: GPL-2.0-only
2//
3// Components shared between ASoC and HDA CS35L56 drivers
4//
5// Copyright (C) 2023 Cirrus Logic, Inc. and
6// Cirrus Logic International Semiconductor Ltd.
7
8#include <linux/firmware/cirrus/wmfw.h>
9#include <linux/gpio/consumer.h>
10#include <linux/regmap.h>
11#include <linux/regulator/consumer.h>
12#include <linux/types.h>
13#include <sound/cs-amp-lib.h>
14
15#include "cs35l56.h"
16
17static const struct reg_sequence cs35l56_patch[] = {
18 /*
19 * Firmware can change these to non-defaults to satisfy SDCA.
20 * Ensure that they are at known defaults.
21 */
22 { CS35L56_SWIRE_DP3_CH1_INPUT, 0x00000018 },
23 { CS35L56_SWIRE_DP3_CH2_INPUT, 0x00000019 },
24 { CS35L56_SWIRE_DP3_CH3_INPUT, 0x00000029 },
25 { CS35L56_SWIRE_DP3_CH4_INPUT, 0x00000028 },
26
27 /* These are not reset by a soft-reset, so patch to defaults. */
28 { CS35L56_MAIN_RENDER_USER_MUTE, 0x00000000 },
29 { CS35L56_MAIN_RENDER_USER_VOLUME, 0x00000000 },
30 { CS35L56_MAIN_POSTURE_NUMBER, 0x00000000 },
31};
32
33int cs35l56_set_patch(struct cs35l56_base *cs35l56_base)
34{
35 return regmap_register_patch(map: cs35l56_base->regmap, regs: cs35l56_patch,
36 ARRAY_SIZE(cs35l56_patch));
37}
38EXPORT_SYMBOL_NS_GPL(cs35l56_set_patch, SND_SOC_CS35L56_SHARED);
39
40static const struct reg_default cs35l56_reg_defaults[] = {
41 /* no defaults for OTP_MEM - first read populates cache */
42
43 { CS35L56_ASP1_ENABLES1, 0x00000000 },
44 { CS35L56_ASP1_CONTROL1, 0x00000028 },
45 { CS35L56_ASP1_CONTROL2, 0x18180200 },
46 { CS35L56_ASP1_CONTROL3, 0x00000002 },
47 { CS35L56_ASP1_FRAME_CONTROL1, 0x03020100 },
48 { CS35L56_ASP1_FRAME_CONTROL5, 0x00020100 },
49 { CS35L56_ASP1_DATA_CONTROL1, 0x00000018 },
50 { CS35L56_ASP1_DATA_CONTROL5, 0x00000018 },
51
52 /* no defaults for ASP1TX mixer */
53
54 { CS35L56_SWIRE_DP3_CH1_INPUT, 0x00000018 },
55 { CS35L56_SWIRE_DP3_CH2_INPUT, 0x00000019 },
56 { CS35L56_SWIRE_DP3_CH3_INPUT, 0x00000029 },
57 { CS35L56_SWIRE_DP3_CH4_INPUT, 0x00000028 },
58 { CS35L56_IRQ1_MASK_1, 0x83ffffff },
59 { CS35L56_IRQ1_MASK_2, 0xffff7fff },
60 { CS35L56_IRQ1_MASK_4, 0xe0ffffff },
61 { CS35L56_IRQ1_MASK_8, 0xfc000fff },
62 { CS35L56_IRQ1_MASK_18, 0x1f7df0ff },
63 { CS35L56_IRQ1_MASK_20, 0x15c00000 },
64 { CS35L56_MAIN_RENDER_USER_MUTE, 0x00000000 },
65 { CS35L56_MAIN_RENDER_USER_VOLUME, 0x00000000 },
66 { CS35L56_MAIN_POSTURE_NUMBER, 0x00000000 },
67};
68
69static bool cs35l56_is_dsp_memory(unsigned int reg)
70{
71 switch (reg) {
72 case CS35L56_DSP1_XMEM_PACKED_0 ... CS35L56_DSP1_XMEM_PACKED_6143:
73 case CS35L56_DSP1_XMEM_UNPACKED32_0 ... CS35L56_DSP1_XMEM_UNPACKED32_4095:
74 case CS35L56_DSP1_XMEM_UNPACKED24_0 ... CS35L56_DSP1_XMEM_UNPACKED24_8191:
75 case CS35L56_DSP1_YMEM_PACKED_0 ... CS35L56_DSP1_YMEM_PACKED_4604:
76 case CS35L56_DSP1_YMEM_UNPACKED32_0 ... CS35L56_DSP1_YMEM_UNPACKED32_3070:
77 case CS35L56_DSP1_YMEM_UNPACKED24_0 ... CS35L56_DSP1_YMEM_UNPACKED24_6141:
78 case CS35L56_DSP1_PMEM_0 ... CS35L56_DSP1_PMEM_5114:
79 return true;
80 default:
81 return false;
82 }
83}
84
85static bool cs35l56_readable_reg(struct device *dev, unsigned int reg)
86{
87 switch (reg) {
88 case CS35L56_DEVID:
89 case CS35L56_REVID:
90 case CS35L56_RELID:
91 case CS35L56_OTPID:
92 case CS35L56_SFT_RESET:
93 case CS35L56_GLOBAL_ENABLES:
94 case CS35L56_BLOCK_ENABLES:
95 case CS35L56_BLOCK_ENABLES2:
96 case CS35L56_REFCLK_INPUT:
97 case CS35L56_GLOBAL_SAMPLE_RATE:
98 case CS35L56_OTP_MEM_53:
99 case CS35L56_OTP_MEM_54:
100 case CS35L56_OTP_MEM_55:
101 case CS35L56_ASP1_ENABLES1:
102 case CS35L56_ASP1_CONTROL1:
103 case CS35L56_ASP1_CONTROL2:
104 case CS35L56_ASP1_CONTROL3:
105 case CS35L56_ASP1_FRAME_CONTROL1:
106 case CS35L56_ASP1_FRAME_CONTROL5:
107 case CS35L56_ASP1_DATA_CONTROL1:
108 case CS35L56_ASP1_DATA_CONTROL5:
109 case CS35L56_DACPCM1_INPUT:
110 case CS35L56_DACPCM2_INPUT:
111 case CS35L56_ASP1TX1_INPUT:
112 case CS35L56_ASP1TX2_INPUT:
113 case CS35L56_ASP1TX3_INPUT:
114 case CS35L56_ASP1TX4_INPUT:
115 case CS35L56_DSP1RX1_INPUT:
116 case CS35L56_DSP1RX2_INPUT:
117 case CS35L56_SWIRE_DP3_CH1_INPUT:
118 case CS35L56_SWIRE_DP3_CH2_INPUT:
119 case CS35L56_SWIRE_DP3_CH3_INPUT:
120 case CS35L56_SWIRE_DP3_CH4_INPUT:
121 case CS35L56_IRQ1_CFG:
122 case CS35L56_IRQ1_STATUS:
123 case CS35L56_IRQ1_EINT_1 ... CS35L56_IRQ1_EINT_8:
124 case CS35L56_IRQ1_EINT_18:
125 case CS35L56_IRQ1_EINT_20:
126 case CS35L56_IRQ1_MASK_1:
127 case CS35L56_IRQ1_MASK_2:
128 case CS35L56_IRQ1_MASK_4:
129 case CS35L56_IRQ1_MASK_8:
130 case CS35L56_IRQ1_MASK_18:
131 case CS35L56_IRQ1_MASK_20:
132 case CS35L56_DSP_VIRTUAL1_MBOX_1:
133 case CS35L56_DSP_VIRTUAL1_MBOX_2:
134 case CS35L56_DSP_VIRTUAL1_MBOX_3:
135 case CS35L56_DSP_VIRTUAL1_MBOX_4:
136 case CS35L56_DSP_VIRTUAL1_MBOX_5:
137 case CS35L56_DSP_VIRTUAL1_MBOX_6:
138 case CS35L56_DSP_VIRTUAL1_MBOX_7:
139 case CS35L56_DSP_VIRTUAL1_MBOX_8:
140 case CS35L56_DSP_RESTRICT_STS1:
141 case CS35L56_DSP1_SYS_INFO_ID ... CS35L56_DSP1_SYS_INFO_END:
142 case CS35L56_DSP1_AHBM_WINDOW_DEBUG_0:
143 case CS35L56_DSP1_AHBM_WINDOW_DEBUG_1:
144 case CS35L56_DSP1_SCRATCH1:
145 case CS35L56_DSP1_SCRATCH2:
146 case CS35L56_DSP1_SCRATCH3:
147 case CS35L56_DSP1_SCRATCH4:
148 return true;
149 default:
150 return cs35l56_is_dsp_memory(reg);
151 }
152}
153
154static bool cs35l56_precious_reg(struct device *dev, unsigned int reg)
155{
156 switch (reg) {
157 case CS35L56_DSP1_XMEM_PACKED_0 ... CS35L56_DSP1_XMEM_PACKED_6143:
158 case CS35L56_DSP1_YMEM_PACKED_0 ... CS35L56_DSP1_YMEM_PACKED_4604:
159 case CS35L56_DSP1_PMEM_0 ... CS35L56_DSP1_PMEM_5114:
160 return true;
161 default:
162 return false;
163 }
164}
165
166static bool cs35l56_volatile_reg(struct device *dev, unsigned int reg)
167{
168 switch (reg) {
169 case CS35L56_DEVID:
170 case CS35L56_REVID:
171 case CS35L56_RELID:
172 case CS35L56_OTPID:
173 case CS35L56_SFT_RESET:
174 case CS35L56_GLOBAL_ENABLES: /* owned by firmware */
175 case CS35L56_BLOCK_ENABLES: /* owned by firmware */
176 case CS35L56_BLOCK_ENABLES2: /* owned by firmware */
177 case CS35L56_REFCLK_INPUT: /* owned by firmware */
178 case CS35L56_GLOBAL_SAMPLE_RATE: /* owned by firmware */
179 case CS35L56_DACPCM1_INPUT: /* owned by firmware */
180 case CS35L56_DACPCM2_INPUT: /* owned by firmware */
181 case CS35L56_DSP1RX1_INPUT: /* owned by firmware */
182 case CS35L56_DSP1RX2_INPUT: /* owned by firmware */
183 case CS35L56_IRQ1_STATUS:
184 case CS35L56_IRQ1_EINT_1 ... CS35L56_IRQ1_EINT_8:
185 case CS35L56_IRQ1_EINT_18:
186 case CS35L56_IRQ1_EINT_20:
187 case CS35L56_DSP_VIRTUAL1_MBOX_1:
188 case CS35L56_DSP_VIRTUAL1_MBOX_2:
189 case CS35L56_DSP_VIRTUAL1_MBOX_3:
190 case CS35L56_DSP_VIRTUAL1_MBOX_4:
191 case CS35L56_DSP_VIRTUAL1_MBOX_5:
192 case CS35L56_DSP_VIRTUAL1_MBOX_6:
193 case CS35L56_DSP_VIRTUAL1_MBOX_7:
194 case CS35L56_DSP_VIRTUAL1_MBOX_8:
195 case CS35L56_DSP_RESTRICT_STS1:
196 case CS35L56_DSP1_SYS_INFO_ID ... CS35L56_DSP1_SYS_INFO_END:
197 case CS35L56_DSP1_AHBM_WINDOW_DEBUG_0:
198 case CS35L56_DSP1_AHBM_WINDOW_DEBUG_1:
199 case CS35L56_DSP1_SCRATCH1:
200 case CS35L56_DSP1_SCRATCH2:
201 case CS35L56_DSP1_SCRATCH3:
202 case CS35L56_DSP1_SCRATCH4:
203 return true;
204 case CS35L56_MAIN_RENDER_USER_MUTE:
205 case CS35L56_MAIN_RENDER_USER_VOLUME:
206 case CS35L56_MAIN_POSTURE_NUMBER:
207 return false;
208 default:
209 return cs35l56_is_dsp_memory(reg);
210 }
211}
212
213/*
214 * The firmware boot sequence can overwrite the ASP1 config registers so that
215 * they don't match regmap's view of their values. Rewrite the values from the
216 * regmap cache into the hardware registers.
217 */
218int cs35l56_force_sync_asp1_registers_from_cache(struct cs35l56_base *cs35l56_base)
219{
220 struct reg_sequence asp1_regs[] = {
221 { .reg = CS35L56_ASP1_ENABLES1 },
222 { .reg = CS35L56_ASP1_CONTROL1 },
223 { .reg = CS35L56_ASP1_CONTROL2 },
224 { .reg = CS35L56_ASP1_CONTROL3 },
225 { .reg = CS35L56_ASP1_FRAME_CONTROL1 },
226 { .reg = CS35L56_ASP1_FRAME_CONTROL5 },
227 { .reg = CS35L56_ASP1_DATA_CONTROL1 },
228 { .reg = CS35L56_ASP1_DATA_CONTROL5 },
229 };
230 int i, ret;
231
232 /* Read values from regmap cache into a write sequence */
233 for (i = 0; i < ARRAY_SIZE(asp1_regs); ++i) {
234 ret = regmap_read(map: cs35l56_base->regmap, reg: asp1_regs[i].reg, val: &asp1_regs[i].def);
235 if (ret)
236 goto err;
237 }
238
239 /* Write the values cache-bypassed so that they will be written to silicon */
240 ret = regmap_multi_reg_write_bypassed(map: cs35l56_base->regmap, regs: asp1_regs,
241 ARRAY_SIZE(asp1_regs));
242 if (ret)
243 goto err;
244
245 return 0;
246
247err:
248 dev_err(cs35l56_base->dev, "Failed to sync ASP1 registers: %d\n", ret);
249
250 return ret;
251}
252EXPORT_SYMBOL_NS_GPL(cs35l56_force_sync_asp1_registers_from_cache, SND_SOC_CS35L56_SHARED);
253
254int cs35l56_mbox_send(struct cs35l56_base *cs35l56_base, unsigned int command)
255{
256 unsigned int val;
257 int ret;
258
259 regmap_write(map: cs35l56_base->regmap, CS35L56_DSP_VIRTUAL1_MBOX_1, val: command);
260 ret = regmap_read_poll_timeout(cs35l56_base->regmap, CS35L56_DSP_VIRTUAL1_MBOX_1,
261 val, (val == 0),
262 CS35L56_MBOX_POLL_US, CS35L56_MBOX_TIMEOUT_US);
263 if (ret) {
264 dev_warn(cs35l56_base->dev, "MBOX command %#x failed: %d\n", command, ret);
265 return ret;
266 }
267
268 return 0;
269}
270EXPORT_SYMBOL_NS_GPL(cs35l56_mbox_send, SND_SOC_CS35L56_SHARED);
271
272int cs35l56_firmware_shutdown(struct cs35l56_base *cs35l56_base)
273{
274 int ret;
275 unsigned int reg;
276 unsigned int val;
277
278 ret = cs35l56_mbox_send(cs35l56_base, CS35L56_MBOX_CMD_SHUTDOWN);
279 if (ret)
280 return ret;
281
282 if (cs35l56_base->rev < CS35L56_REVID_B0)
283 reg = CS35L56_DSP1_PM_CUR_STATE_A1;
284 else
285 reg = CS35L56_DSP1_PM_CUR_STATE;
286
287 ret = regmap_read_poll_timeout(cs35l56_base->regmap, reg,
288 val, (val == CS35L56_HALO_STATE_SHUTDOWN),
289 CS35L56_HALO_STATE_POLL_US,
290 CS35L56_HALO_STATE_TIMEOUT_US);
291 if (ret < 0)
292 dev_err(cs35l56_base->dev, "Failed to poll PM_CUR_STATE to 1 is %d (ret %d)\n",
293 val, ret);
294 return ret;
295}
296EXPORT_SYMBOL_NS_GPL(cs35l56_firmware_shutdown, SND_SOC_CS35L56_SHARED);
297
298int cs35l56_wait_for_firmware_boot(struct cs35l56_base *cs35l56_base)
299{
300 unsigned int reg;
301 unsigned int val = 0;
302 int read_ret, poll_ret;
303
304 if (cs35l56_base->rev < CS35L56_REVID_B0)
305 reg = CS35L56_DSP1_HALO_STATE_A1;
306 else
307 reg = CS35L56_DSP1_HALO_STATE;
308
309 /*
310 * This can't be a regmap_read_poll_timeout() because cs35l56 will NAK
311 * I2C until it has booted which would terminate the poll
312 */
313 poll_ret = read_poll_timeout(regmap_read, read_ret,
314 (val < 0xFFFF) && (val >= CS35L56_HALO_STATE_BOOT_DONE),
315 CS35L56_HALO_STATE_POLL_US,
316 CS35L56_HALO_STATE_TIMEOUT_US,
317 false,
318 cs35l56_base->regmap, reg, &val);
319
320 if (poll_ret) {
321 dev_err(cs35l56_base->dev, "Firmware boot timed out(%d): HALO_STATE=%#x\n",
322 read_ret, val);
323 return -EIO;
324 }
325
326 return 0;
327}
328EXPORT_SYMBOL_NS_GPL(cs35l56_wait_for_firmware_boot, SND_SOC_CS35L56_SHARED);
329
330void cs35l56_wait_control_port_ready(void)
331{
332 /* Wait for control port to be ready (datasheet tIRS). */
333 usleep_range(CS35L56_CONTROL_PORT_READY_US, max: 2 * CS35L56_CONTROL_PORT_READY_US);
334}
335EXPORT_SYMBOL_NS_GPL(cs35l56_wait_control_port_ready, SND_SOC_CS35L56_SHARED);
336
337void cs35l56_wait_min_reset_pulse(void)
338{
339 /* Satisfy minimum reset pulse width spec */
340 usleep_range(CS35L56_RESET_PULSE_MIN_US, max: 2 * CS35L56_RESET_PULSE_MIN_US);
341}
342EXPORT_SYMBOL_NS_GPL(cs35l56_wait_min_reset_pulse, SND_SOC_CS35L56_SHARED);
343
344static const struct reg_sequence cs35l56_system_reset_seq[] = {
345 REG_SEQ0(CS35L56_DSP1_HALO_STATE, 0),
346 REG_SEQ0(CS35L56_DSP_VIRTUAL1_MBOX_1, CS35L56_MBOX_CMD_SYSTEM_RESET),
347};
348
349void cs35l56_system_reset(struct cs35l56_base *cs35l56_base, bool is_soundwire)
350{
351 /*
352 * Must enter cache-only first so there can't be any more register
353 * accesses other than the controlled system reset sequence below.
354 */
355 regcache_cache_only(map: cs35l56_base->regmap, enable: true);
356 regmap_multi_reg_write_bypassed(map: cs35l56_base->regmap,
357 regs: cs35l56_system_reset_seq,
358 ARRAY_SIZE(cs35l56_system_reset_seq));
359
360 /* On SoundWire the registers won't be accessible until it re-enumerates. */
361 if (is_soundwire)
362 return;
363
364 cs35l56_wait_control_port_ready();
365 regcache_cache_only(map: cs35l56_base->regmap, enable: false);
366}
367EXPORT_SYMBOL_NS_GPL(cs35l56_system_reset, SND_SOC_CS35L56_SHARED);
368
369int cs35l56_irq_request(struct cs35l56_base *cs35l56_base, int irq)
370{
371 int ret;
372
373 if (!irq)
374 return 0;
375
376 ret = devm_request_threaded_irq(dev: cs35l56_base->dev, irq, NULL, thread_fn: cs35l56_irq,
377 IRQF_ONESHOT | IRQF_SHARED | IRQF_TRIGGER_LOW,
378 devname: "cs35l56", dev_id: cs35l56_base);
379 if (!ret)
380 cs35l56_base->irq = irq;
381 else
382 dev_err(cs35l56_base->dev, "Failed to get IRQ: %d\n", ret);
383
384 return ret;
385}
386EXPORT_SYMBOL_NS_GPL(cs35l56_irq_request, SND_SOC_CS35L56_SHARED);
387
388irqreturn_t cs35l56_irq(int irq, void *data)
389{
390 struct cs35l56_base *cs35l56_base = data;
391 unsigned int status1 = 0, status8 = 0, status20 = 0;
392 unsigned int mask1, mask8, mask20;
393 unsigned int val;
394 int rv;
395
396 irqreturn_t ret = IRQ_NONE;
397
398 if (!cs35l56_base->init_done)
399 return IRQ_NONE;
400
401 mutex_lock(&cs35l56_base->irq_lock);
402
403 rv = pm_runtime_resume_and_get(dev: cs35l56_base->dev);
404 if (rv < 0) {
405 dev_err(cs35l56_base->dev, "irq: failed to get pm_runtime: %d\n", rv);
406 goto err_unlock;
407 }
408
409 regmap_read(map: cs35l56_base->regmap, CS35L56_IRQ1_STATUS, val: &val);
410 if ((val & CS35L56_IRQ1_STS_MASK) == 0) {
411 dev_dbg(cs35l56_base->dev, "Spurious IRQ: no pending interrupt\n");
412 goto err;
413 }
414
415 /* Ack interrupts */
416 regmap_read(map: cs35l56_base->regmap, CS35L56_IRQ1_EINT_1, val: &status1);
417 regmap_read(map: cs35l56_base->regmap, CS35L56_IRQ1_MASK_1, val: &mask1);
418 status1 &= ~mask1;
419 regmap_write(map: cs35l56_base->regmap, CS35L56_IRQ1_EINT_1, val: status1);
420
421 regmap_read(map: cs35l56_base->regmap, CS35L56_IRQ1_EINT_8, val: &status8);
422 regmap_read(map: cs35l56_base->regmap, CS35L56_IRQ1_MASK_8, val: &mask8);
423 status8 &= ~mask8;
424 regmap_write(map: cs35l56_base->regmap, CS35L56_IRQ1_EINT_8, val: status8);
425
426 regmap_read(map: cs35l56_base->regmap, CS35L56_IRQ1_EINT_20, val: &status20);
427 regmap_read(map: cs35l56_base->regmap, CS35L56_IRQ1_MASK_20, val: &mask20);
428 status20 &= ~mask20;
429 /* We don't want EINT20 but they default to unmasked: force mask */
430 regmap_write(map: cs35l56_base->regmap, CS35L56_IRQ1_MASK_20, val: 0xffffffff);
431
432 dev_dbg(cs35l56_base->dev, "%s: %#x %#x\n", __func__, status1, status8);
433
434 /* Check to see if unmasked bits are active */
435 if (!status1 && !status8 && !status20)
436 goto err;
437
438 if (status1 & CS35L56_AMP_SHORT_ERR_EINT1_MASK)
439 dev_crit(cs35l56_base->dev, "Amp short error\n");
440
441 if (status8 & CS35L56_TEMP_ERR_EINT1_MASK)
442 dev_crit(cs35l56_base->dev, "Overtemp error\n");
443
444 ret = IRQ_HANDLED;
445
446err:
447 pm_runtime_put(dev: cs35l56_base->dev);
448err_unlock:
449 mutex_unlock(lock: &cs35l56_base->irq_lock);
450
451 return ret;
452}
453EXPORT_SYMBOL_NS_GPL(cs35l56_irq, SND_SOC_CS35L56_SHARED);
454
455int cs35l56_is_fw_reload_needed(struct cs35l56_base *cs35l56_base)
456{
457 unsigned int val;
458 int ret;
459
460 /*
461 * In secure mode FIRMWARE_MISSING is cleared by the BIOS loader so
462 * can't be used here to test for memory retention.
463 * Assume that tuning must be re-loaded.
464 */
465 if (cs35l56_base->secured)
466 return true;
467
468 ret = pm_runtime_resume_and_get(dev: cs35l56_base->dev);
469 if (ret) {
470 dev_err(cs35l56_base->dev, "Failed to runtime_get: %d\n", ret);
471 return ret;
472 }
473
474 ret = regmap_read(map: cs35l56_base->regmap, CS35L56_PROTECTION_STATUS, val: &val);
475 if (ret)
476 dev_err(cs35l56_base->dev, "Failed to read PROTECTION_STATUS: %d\n", ret);
477 else
478 ret = !!(val & CS35L56_FIRMWARE_MISSING);
479
480 pm_runtime_put_autosuspend(dev: cs35l56_base->dev);
481
482 return ret;
483}
484EXPORT_SYMBOL_NS_GPL(cs35l56_is_fw_reload_needed, SND_SOC_CS35L56_SHARED);
485
486static const struct reg_sequence cs35l56_hibernate_seq[] = {
487 /* This must be the last register access */
488 REG_SEQ0(CS35L56_DSP_VIRTUAL1_MBOX_1, CS35L56_MBOX_CMD_ALLOW_AUTO_HIBERNATE),
489};
490
491static const struct reg_sequence cs35l56_hibernate_wake_seq[] = {
492 REG_SEQ0(CS35L56_DSP_VIRTUAL1_MBOX_1, CS35L56_MBOX_CMD_WAKEUP),
493};
494
495static void cs35l56_issue_wake_event(struct cs35l56_base *cs35l56_base)
496{
497 /*
498 * Dummy transactions to trigger I2C/SPI auto-wake. Issue two
499 * transactions to meet the minimum required time from the rising edge
500 * to the last falling edge of wake.
501 *
502 * It uses bypassed write because we must wake the chip before
503 * disabling regmap cache-only.
504 *
505 * This can NAK on I2C which will terminate the write sequence so the
506 * single-write sequence is issued twice.
507 */
508 regmap_multi_reg_write_bypassed(map: cs35l56_base->regmap,
509 regs: cs35l56_hibernate_wake_seq,
510 ARRAY_SIZE(cs35l56_hibernate_wake_seq));
511
512 usleep_range(CS35L56_WAKE_HOLD_TIME_US, max: 2 * CS35L56_WAKE_HOLD_TIME_US);
513
514 regmap_multi_reg_write_bypassed(map: cs35l56_base->regmap,
515 regs: cs35l56_hibernate_wake_seq,
516 ARRAY_SIZE(cs35l56_hibernate_wake_seq));
517
518 cs35l56_wait_control_port_ready();
519}
520
521int cs35l56_runtime_suspend_common(struct cs35l56_base *cs35l56_base)
522{
523 unsigned int val;
524 int ret;
525
526 if (!cs35l56_base->init_done)
527 return 0;
528
529 /* Firmware must have entered a power-save state */
530 ret = regmap_read_poll_timeout(cs35l56_base->regmap,
531 CS35L56_TRANSDUCER_ACTUAL_PS,
532 val, (val >= CS35L56_PS3),
533 CS35L56_PS3_POLL_US,
534 CS35L56_PS3_TIMEOUT_US);
535 if (ret)
536 dev_warn(cs35l56_base->dev, "PS3 wait failed: %d\n", ret);
537
538 /* Clear BOOT_DONE so it can be used to detect a reboot */
539 regmap_write(map: cs35l56_base->regmap, CS35L56_IRQ1_EINT_4, CS35L56_OTP_BOOT_DONE_MASK);
540
541 if (!cs35l56_base->can_hibernate) {
542 regcache_cache_only(map: cs35l56_base->regmap, enable: true);
543 dev_dbg(cs35l56_base->dev, "Suspended: no hibernate");
544
545 return 0;
546 }
547
548 /*
549 * Must enter cache-only first so there can't be any more register
550 * accesses other than the controlled hibernate sequence below.
551 */
552 regcache_cache_only(map: cs35l56_base->regmap, enable: true);
553
554 regmap_multi_reg_write_bypassed(map: cs35l56_base->regmap,
555 regs: cs35l56_hibernate_seq,
556 ARRAY_SIZE(cs35l56_hibernate_seq));
557
558 dev_dbg(cs35l56_base->dev, "Suspended: hibernate");
559
560 return 0;
561}
562EXPORT_SYMBOL_NS_GPL(cs35l56_runtime_suspend_common, SND_SOC_CS35L56_SHARED);
563
564int cs35l56_runtime_resume_common(struct cs35l56_base *cs35l56_base, bool is_soundwire)
565{
566 unsigned int val;
567 int ret;
568
569 if (!cs35l56_base->init_done)
570 return 0;
571
572 if (!cs35l56_base->can_hibernate)
573 goto out_sync;
574
575 /* Must be done before releasing cache-only */
576 if (!is_soundwire)
577 cs35l56_issue_wake_event(cs35l56_base);
578
579out_sync:
580 regcache_cache_only(map: cs35l56_base->regmap, enable: false);
581
582 ret = cs35l56_wait_for_firmware_boot(cs35l56_base);
583 if (ret) {
584 dev_err(cs35l56_base->dev, "Hibernate wake failed: %d\n", ret);
585 goto err;
586 }
587
588 ret = cs35l56_mbox_send(cs35l56_base, CS35L56_MBOX_CMD_PREVENT_AUTO_HIBERNATE);
589 if (ret)
590 goto err;
591
592 /* BOOT_DONE will be 1 if the amp reset */
593 regmap_read(map: cs35l56_base->regmap, CS35L56_IRQ1_EINT_4, val: &val);
594 if (val & CS35L56_OTP_BOOT_DONE_MASK) {
595 dev_dbg(cs35l56_base->dev, "Registers reset in suspend\n");
596 regcache_mark_dirty(map: cs35l56_base->regmap);
597 }
598
599 regcache_sync(map: cs35l56_base->regmap);
600
601 dev_dbg(cs35l56_base->dev, "Resumed");
602
603 return 0;
604
605err:
606 regcache_cache_only(map: cs35l56_base->regmap, enable: true);
607
608 regmap_multi_reg_write_bypassed(map: cs35l56_base->regmap,
609 regs: cs35l56_hibernate_seq,
610 ARRAY_SIZE(cs35l56_hibernate_seq));
611
612 return ret;
613}
614EXPORT_SYMBOL_NS_GPL(cs35l56_runtime_resume_common, SND_SOC_CS35L56_SHARED);
615
616static const struct cs_dsp_region cs35l56_dsp1_regions[] = {
617 { .type = WMFW_HALO_PM_PACKED, .base = CS35L56_DSP1_PMEM_0 },
618 { .type = WMFW_HALO_XM_PACKED, .base = CS35L56_DSP1_XMEM_PACKED_0 },
619 { .type = WMFW_HALO_YM_PACKED, .base = CS35L56_DSP1_YMEM_PACKED_0 },
620 { .type = WMFW_ADSP2_XM, .base = CS35L56_DSP1_XMEM_UNPACKED24_0 },
621 { .type = WMFW_ADSP2_YM, .base = CS35L56_DSP1_YMEM_UNPACKED24_0 },
622};
623
624void cs35l56_init_cs_dsp(struct cs35l56_base *cs35l56_base, struct cs_dsp *cs_dsp)
625{
626 cs_dsp->num = 1;
627 cs_dsp->type = WMFW_HALO;
628 cs_dsp->rev = 0;
629 cs_dsp->dev = cs35l56_base->dev;
630 cs_dsp->regmap = cs35l56_base->regmap;
631 cs_dsp->base = CS35L56_DSP1_CORE_BASE;
632 cs_dsp->base_sysinfo = CS35L56_DSP1_SYS_INFO_ID;
633 cs_dsp->mem = cs35l56_dsp1_regions;
634 cs_dsp->num_mems = ARRAY_SIZE(cs35l56_dsp1_regions);
635 cs_dsp->no_core_startstop = true;
636}
637EXPORT_SYMBOL_NS_GPL(cs35l56_init_cs_dsp, SND_SOC_CS35L56_SHARED);
638
639struct cs35l56_pte {
640 u8 x;
641 u8 wafer_id;
642 u8 pte[2];
643 u8 lot[3];
644 u8 y;
645 u8 unused[3];
646 u8 dvs;
647} __packed;
648static_assert((sizeof(struct cs35l56_pte) % sizeof(u32)) == 0);
649
650static int cs35l56_read_silicon_uid(struct cs35l56_base *cs35l56_base, u64 *uid)
651{
652 struct cs35l56_pte pte;
653 u64 unique_id;
654 int ret;
655
656 ret = regmap_raw_read(map: cs35l56_base->regmap, CS35L56_OTP_MEM_53, val: &pte, val_len: sizeof(pte));
657 if (ret) {
658 dev_err(cs35l56_base->dev, "Failed to read OTP: %d\n", ret);
659 return ret;
660 }
661
662 unique_id = (u32)pte.lot[2] | ((u32)pte.lot[1] << 8) | ((u32)pte.lot[0] << 16);
663 unique_id <<= 32;
664 unique_id |= (u32)pte.x | ((u32)pte.y << 8) | ((u32)pte.wafer_id << 16) |
665 ((u32)pte.dvs << 24);
666
667 dev_dbg(cs35l56_base->dev, "UniqueID = %#llx\n", unique_id);
668
669 *uid = unique_id;
670
671 return 0;
672}
673
674/* Firmware calibration controls */
675const struct cirrus_amp_cal_controls cs35l56_calibration_controls = {
676 .alg_id = 0x9f210,
677 .mem_region = WMFW_ADSP2_YM,
678 .ambient = "CAL_AMBIENT",
679 .calr = "CAL_R",
680 .status = "CAL_STATUS",
681 .checksum = "CAL_CHECKSUM",
682};
683EXPORT_SYMBOL_NS_GPL(cs35l56_calibration_controls, SND_SOC_CS35L56_SHARED);
684
685int cs35l56_get_calibration(struct cs35l56_base *cs35l56_base)
686{
687 u64 silicon_uid;
688 int ret;
689
690 /* Driver can't apply calibration to a secured part, so skip */
691 if (cs35l56_base->secured)
692 return 0;
693
694 ret = cs35l56_read_silicon_uid(cs35l56_base, uid: &silicon_uid);
695 if (ret < 0)
696 return ret;
697
698 ret = cs_amp_get_efi_calibration_data(dev: cs35l56_base->dev, target_uid: silicon_uid,
699 amp_index: cs35l56_base->cal_index,
700 out_data: &cs35l56_base->cal_data);
701
702 /* Only return an error status if probe should be aborted */
703 if ((ret == -ENOENT) || (ret == -EOVERFLOW))
704 return 0;
705
706 if (ret < 0)
707 return ret;
708
709 cs35l56_base->cal_data_valid = true;
710
711 return 0;
712}
713EXPORT_SYMBOL_NS_GPL(cs35l56_get_calibration, SND_SOC_CS35L56_SHARED);
714
715int cs35l56_read_prot_status(struct cs35l56_base *cs35l56_base,
716 bool *fw_missing, unsigned int *fw_version)
717{
718 unsigned int prot_status;
719 int ret;
720
721 ret = regmap_read(map: cs35l56_base->regmap, CS35L56_PROTECTION_STATUS, val: &prot_status);
722 if (ret) {
723 dev_err(cs35l56_base->dev, "Get PROTECTION_STATUS failed: %d\n", ret);
724 return ret;
725 }
726
727 *fw_missing = !!(prot_status & CS35L56_FIRMWARE_MISSING);
728
729 ret = regmap_read(map: cs35l56_base->regmap, CS35L56_DSP1_FW_VER, val: fw_version);
730 if (ret) {
731 dev_err(cs35l56_base->dev, "Get FW VER failed: %d\n", ret);
732 return ret;
733 }
734
735 return 0;
736}
737EXPORT_SYMBOL_NS_GPL(cs35l56_read_prot_status, SND_SOC_CS35L56_SHARED);
738
739int cs35l56_hw_init(struct cs35l56_base *cs35l56_base)
740{
741 int ret;
742 unsigned int devid, revid, otpid, secured, fw_ver;
743 bool fw_missing;
744
745 /*
746 * When the system is not using a reset_gpio ensure the device is
747 * awake, otherwise the device has just been released from reset and
748 * the driver must wait for the control port to become usable.
749 */
750 if (!cs35l56_base->reset_gpio)
751 cs35l56_issue_wake_event(cs35l56_base);
752 else
753 cs35l56_wait_control_port_ready();
754
755 /*
756 * The HALO_STATE register is in different locations on Ax and B0
757 * devices so the REVID needs to be determined before waiting for the
758 * firmware to boot.
759 */
760 ret = regmap_read(map: cs35l56_base->regmap, CS35L56_REVID, val: &revid);
761 if (ret < 0) {
762 dev_err(cs35l56_base->dev, "Get Revision ID failed\n");
763 return ret;
764 }
765 cs35l56_base->rev = revid & (CS35L56_AREVID_MASK | CS35L56_MTLREVID_MASK);
766
767 ret = cs35l56_wait_for_firmware_boot(cs35l56_base);
768 if (ret)
769 return ret;
770
771 ret = regmap_read(map: cs35l56_base->regmap, CS35L56_DEVID, val: &devid);
772 if (ret < 0) {
773 dev_err(cs35l56_base->dev, "Get Device ID failed\n");
774 return ret;
775 }
776 devid &= CS35L56_DEVID_MASK;
777
778 switch (devid) {
779 case 0x35A54:
780 case 0x35A56:
781 case 0x35A57:
782 break;
783 default:
784 dev_err(cs35l56_base->dev, "Unknown device %x\n", devid);
785 return ret;
786 }
787
788 cs35l56_base->type = devid & 0xFF;
789
790 ret = regmap_read(map: cs35l56_base->regmap, CS35L56_DSP_RESTRICT_STS1, val: &secured);
791 if (ret) {
792 dev_err(cs35l56_base->dev, "Get Secure status failed\n");
793 return ret;
794 }
795
796 /* When any bus is restricted treat the device as secured */
797 if (secured & CS35L56_RESTRICTED_MASK)
798 cs35l56_base->secured = true;
799
800 ret = regmap_read(map: cs35l56_base->regmap, CS35L56_OTPID, val: &otpid);
801 if (ret < 0) {
802 dev_err(cs35l56_base->dev, "Get OTP ID failed\n");
803 return ret;
804 }
805
806 ret = cs35l56_read_prot_status(cs35l56_base, &fw_missing, &fw_ver);
807 if (ret)
808 return ret;
809
810 dev_info(cs35l56_base->dev, "Cirrus Logic CS35L%02X%s Rev %02X OTP%d fw:%d.%d.%d (patched=%u)\n",
811 cs35l56_base->type, cs35l56_base->secured ? "s" : "", cs35l56_base->rev, otpid,
812 fw_ver >> 16, (fw_ver >> 8) & 0xff, fw_ver & 0xff, !fw_missing);
813
814 /* Wake source and *_BLOCKED interrupts default to unmasked, so mask them */
815 regmap_write(map: cs35l56_base->regmap, CS35L56_IRQ1_MASK_20, val: 0xffffffff);
816 regmap_update_bits(map: cs35l56_base->regmap, CS35L56_IRQ1_MASK_1,
817 CS35L56_AMP_SHORT_ERR_EINT1_MASK,
818 val: 0);
819 regmap_update_bits(map: cs35l56_base->regmap, CS35L56_IRQ1_MASK_8,
820 CS35L56_TEMP_ERR_EINT1_MASK,
821 val: 0);
822
823 return 0;
824}
825EXPORT_SYMBOL_NS_GPL(cs35l56_hw_init, SND_SOC_CS35L56_SHARED);
826
827int cs35l56_get_speaker_id(struct cs35l56_base *cs35l56_base)
828{
829 struct gpio_descs *descs;
830 int speaker_id;
831 int i, ret;
832
833 /* Read the speaker type qualifier from the motherboard GPIOs */
834 descs = gpiod_get_array_optional(dev: cs35l56_base->dev, con_id: "spk-id", flags: GPIOD_IN);
835 if (!descs) {
836 return -ENOENT;
837 } else if (IS_ERR(ptr: descs)) {
838 ret = PTR_ERR(ptr: descs);
839 return dev_err_probe(dev: cs35l56_base->dev, err: ret, fmt: "Failed to get spk-id-gpios\n");
840 }
841
842 speaker_id = 0;
843 for (i = 0; i < descs->ndescs; i++) {
844 ret = gpiod_get_value_cansleep(desc: descs->desc[i]);
845 if (ret < 0) {
846 dev_err_probe(dev: cs35l56_base->dev, err: ret, fmt: "Failed to read spk-id[%d]\n", i);
847 goto err;
848 }
849
850 speaker_id |= (ret << i);
851 }
852
853 dev_dbg(cs35l56_base->dev, "Speaker ID = %d\n", speaker_id);
854 ret = speaker_id;
855err:
856 gpiod_put_array(descs);
857
858 return ret;
859}
860EXPORT_SYMBOL_NS_GPL(cs35l56_get_speaker_id, SND_SOC_CS35L56_SHARED);
861
862static const u32 cs35l56_bclk_valid_for_pll_freq_table[] = {
863 [0x0C] = 128000,
864 [0x0F] = 256000,
865 [0x11] = 384000,
866 [0x12] = 512000,
867 [0x15] = 768000,
868 [0x17] = 1024000,
869 [0x1A] = 1500000,
870 [0x1B] = 1536000,
871 [0x1C] = 2000000,
872 [0x1D] = 2048000,
873 [0x1E] = 2400000,
874 [0x20] = 3000000,
875 [0x21] = 3072000,
876 [0x23] = 4000000,
877 [0x24] = 4096000,
878 [0x25] = 4800000,
879 [0x27] = 6000000,
880 [0x28] = 6144000,
881 [0x29] = 6250000,
882 [0x2A] = 6400000,
883 [0x2E] = 8000000,
884 [0x2F] = 8192000,
885 [0x30] = 9600000,
886 [0x32] = 12000000,
887 [0x33] = 12288000,
888 [0x37] = 13500000,
889 [0x38] = 19200000,
890 [0x39] = 22579200,
891 [0x3B] = 24576000,
892};
893
894int cs35l56_get_bclk_freq_id(unsigned int freq)
895{
896 int i;
897
898 if (freq == 0)
899 return -EINVAL;
900
901 /* The BCLK frequency must be a valid PLL REFCLK */
902 for (i = 0; i < ARRAY_SIZE(cs35l56_bclk_valid_for_pll_freq_table); ++i) {
903 if (cs35l56_bclk_valid_for_pll_freq_table[i] == freq)
904 return i;
905 }
906
907 return -EINVAL;
908}
909EXPORT_SYMBOL_NS_GPL(cs35l56_get_bclk_freq_id, SND_SOC_CS35L56_SHARED);
910
911static const char * const cs35l56_supplies[/* auto-sized */] = {
912 "VDD_P",
913 "VDD_IO",
914 "VDD_A",
915};
916
917void cs35l56_fill_supply_names(struct regulator_bulk_data *data)
918{
919 int i;
920
921 BUILD_BUG_ON(ARRAY_SIZE(cs35l56_supplies) != CS35L56_NUM_BULK_SUPPLIES);
922 for (i = 0; i < ARRAY_SIZE(cs35l56_supplies); i++)
923 data[i].supply = cs35l56_supplies[i];
924}
925EXPORT_SYMBOL_NS_GPL(cs35l56_fill_supply_names, SND_SOC_CS35L56_SHARED);
926
927const char * const cs35l56_tx_input_texts[] = {
928 "None", "ASP1RX1", "ASP1RX2", "VMON", "IMON", "ERRVOL", "CLASSH",
929 "VDDBMON", "VBSTMON", "DSP1TX1", "DSP1TX2", "DSP1TX3", "DSP1TX4",
930 "DSP1TX5", "DSP1TX6", "DSP1TX7", "DSP1TX8", "TEMPMON",
931 "INTERPOLATOR", "SDW1RX1", "SDW1RX2",
932};
933EXPORT_SYMBOL_NS_GPL(cs35l56_tx_input_texts, SND_SOC_CS35L56_SHARED);
934
935const unsigned int cs35l56_tx_input_values[] = {
936 CS35L56_INPUT_SRC_NONE,
937 CS35L56_INPUT_SRC_ASP1RX1,
938 CS35L56_INPUT_SRC_ASP1RX2,
939 CS35L56_INPUT_SRC_VMON,
940 CS35L56_INPUT_SRC_IMON,
941 CS35L56_INPUT_SRC_ERR_VOL,
942 CS35L56_INPUT_SRC_CLASSH,
943 CS35L56_INPUT_SRC_VDDBMON,
944 CS35L56_INPUT_SRC_VBSTMON,
945 CS35L56_INPUT_SRC_DSP1TX1,
946 CS35L56_INPUT_SRC_DSP1TX2,
947 CS35L56_INPUT_SRC_DSP1TX3,
948 CS35L56_INPUT_SRC_DSP1TX4,
949 CS35L56_INPUT_SRC_DSP1TX5,
950 CS35L56_INPUT_SRC_DSP1TX6,
951 CS35L56_INPUT_SRC_DSP1TX7,
952 CS35L56_INPUT_SRC_DSP1TX8,
953 CS35L56_INPUT_SRC_TEMPMON,
954 CS35L56_INPUT_SRC_INTERPOLATOR,
955 CS35L56_INPUT_SRC_SWIRE_DP1_CHANNEL1,
956 CS35L56_INPUT_SRC_SWIRE_DP1_CHANNEL2,
957};
958EXPORT_SYMBOL_NS_GPL(cs35l56_tx_input_values, SND_SOC_CS35L56_SHARED);
959
960struct regmap_config cs35l56_regmap_i2c = {
961 .reg_bits = 32,
962 .val_bits = 32,
963 .reg_stride = 4,
964 .reg_format_endian = REGMAP_ENDIAN_BIG,
965 .val_format_endian = REGMAP_ENDIAN_BIG,
966 .max_register = CS35L56_DSP1_PMEM_5114,
967 .reg_defaults = cs35l56_reg_defaults,
968 .num_reg_defaults = ARRAY_SIZE(cs35l56_reg_defaults),
969 .volatile_reg = cs35l56_volatile_reg,
970 .readable_reg = cs35l56_readable_reg,
971 .precious_reg = cs35l56_precious_reg,
972 .cache_type = REGCACHE_MAPLE,
973};
974EXPORT_SYMBOL_NS_GPL(cs35l56_regmap_i2c, SND_SOC_CS35L56_SHARED);
975
976struct regmap_config cs35l56_regmap_spi = {
977 .reg_bits = 32,
978 .val_bits = 32,
979 .pad_bits = 16,
980 .reg_stride = 4,
981 .reg_format_endian = REGMAP_ENDIAN_BIG,
982 .val_format_endian = REGMAP_ENDIAN_BIG,
983 .max_register = CS35L56_DSP1_PMEM_5114,
984 .reg_defaults = cs35l56_reg_defaults,
985 .num_reg_defaults = ARRAY_SIZE(cs35l56_reg_defaults),
986 .volatile_reg = cs35l56_volatile_reg,
987 .readable_reg = cs35l56_readable_reg,
988 .precious_reg = cs35l56_precious_reg,
989 .cache_type = REGCACHE_MAPLE,
990};
991EXPORT_SYMBOL_NS_GPL(cs35l56_regmap_spi, SND_SOC_CS35L56_SHARED);
992
993struct regmap_config cs35l56_regmap_sdw = {
994 .reg_bits = 32,
995 .val_bits = 32,
996 .reg_stride = 4,
997 .reg_format_endian = REGMAP_ENDIAN_LITTLE,
998 .val_format_endian = REGMAP_ENDIAN_BIG,
999 .max_register = CS35L56_DSP1_PMEM_5114,
1000 .reg_defaults = cs35l56_reg_defaults,
1001 .num_reg_defaults = ARRAY_SIZE(cs35l56_reg_defaults),
1002 .volatile_reg = cs35l56_volatile_reg,
1003 .readable_reg = cs35l56_readable_reg,
1004 .precious_reg = cs35l56_precious_reg,
1005 .cache_type = REGCACHE_MAPLE,
1006};
1007EXPORT_SYMBOL_NS_GPL(cs35l56_regmap_sdw, SND_SOC_CS35L56_SHARED);
1008
1009MODULE_DESCRIPTION("ASoC CS35L56 Shared");
1010MODULE_AUTHOR("Richard Fitzgerald <rf@opensource.cirrus.com>");
1011MODULE_AUTHOR("Simon Trimmer <simont@opensource.cirrus.com>");
1012MODULE_LICENSE("GPL");
1013MODULE_IMPORT_NS(SND_SOC_CS_AMP_LIB);
1014

source code of linux/sound/soc/codecs/cs35l56-shared.c