xref: /openbmc/linux/sound/soc/codecs/cs35l56-shared.c (revision 7b7fd0ac7dc1ffcaf24d9bca0f051b0168e43cd4)
1e4961125SRichard Fitzgerald // SPDX-License-Identifier: GPL-2.0-only
2e4961125SRichard Fitzgerald //
3e4961125SRichard Fitzgerald // Components shared between ASoC and HDA CS35L56 drivers
4e4961125SRichard Fitzgerald //
5e4961125SRichard Fitzgerald // Copyright (C) 2023 Cirrus Logic, Inc. and
6e4961125SRichard Fitzgerald //                    Cirrus Logic International Semiconductor Ltd.
7e4961125SRichard Fitzgerald 
8*e905bc71SRichard Fitzgerald #include <linux/gpio/consumer.h>
9e4961125SRichard Fitzgerald #include <linux/regmap.h>
10e4961125SRichard Fitzgerald #include <linux/regulator/consumer.h>
11e4961125SRichard Fitzgerald #include <linux/types.h>
12e4961125SRichard Fitzgerald 
13e4961125SRichard Fitzgerald #include "cs35l56.h"
14e4961125SRichard Fitzgerald 
15df4167d6SRichard Fitzgerald static const struct reg_sequence cs35l56_patch[] = {
16df4167d6SRichard Fitzgerald 	/* These are not reset by a soft-reset, so patch to defaults. */
17df4167d6SRichard Fitzgerald 	{ CS35L56_MAIN_RENDER_USER_MUTE,	0x00000000 },
18df4167d6SRichard Fitzgerald 	{ CS35L56_MAIN_RENDER_USER_VOLUME,	0x00000000 },
19df4167d6SRichard Fitzgerald 	{ CS35L56_MAIN_POSTURE_NUMBER,		0x00000000 },
20df4167d6SRichard Fitzgerald };
21df4167d6SRichard Fitzgerald 
cs35l56_set_patch(struct cs35l56_base * cs35l56_base)22898673b9SSimon Trimmer int cs35l56_set_patch(struct cs35l56_base *cs35l56_base)
23df4167d6SRichard Fitzgerald {
24898673b9SSimon Trimmer 	return regmap_register_patch(cs35l56_base->regmap, cs35l56_patch,
25898673b9SSimon Trimmer 				     ARRAY_SIZE(cs35l56_patch));
26df4167d6SRichard Fitzgerald }
27df4167d6SRichard Fitzgerald EXPORT_SYMBOL_NS_GPL(cs35l56_set_patch, SND_SOC_CS35L56_SHARED);
28df4167d6SRichard Fitzgerald 
29e4961125SRichard Fitzgerald static const struct reg_default cs35l56_reg_defaults[] = {
30e4961125SRichard Fitzgerald 	{ CS35L56_ASP1_ENABLES1,		0x00000000 },
31e4961125SRichard Fitzgerald 	{ CS35L56_ASP1_CONTROL1,		0x00000028 },
32e4961125SRichard Fitzgerald 	{ CS35L56_ASP1_CONTROL2,		0x18180200 },
33e4961125SRichard Fitzgerald 	{ CS35L56_ASP1_CONTROL3,		0x00000002 },
34e4961125SRichard Fitzgerald 	{ CS35L56_ASP1_FRAME_CONTROL1,		0x03020100 },
35e4961125SRichard Fitzgerald 	{ CS35L56_ASP1_FRAME_CONTROL5,		0x00020100 },
36e4961125SRichard Fitzgerald 	{ CS35L56_ASP1_DATA_CONTROL1,		0x00000018 },
37e4961125SRichard Fitzgerald 	{ CS35L56_ASP1_DATA_CONTROL5,		0x00000018 },
38c249f04fSRichard Fitzgerald 
39c249f04fSRichard Fitzgerald 	/* no defaults for ASP1TX mixer */
40c249f04fSRichard Fitzgerald 
41e4961125SRichard Fitzgerald 	{ CS35L56_SWIRE_DP3_CH1_INPUT,		0x00000018 },
42e4961125SRichard Fitzgerald 	{ CS35L56_SWIRE_DP3_CH2_INPUT,		0x00000019 },
43e4961125SRichard Fitzgerald 	{ CS35L56_SWIRE_DP3_CH3_INPUT,		0x00000029 },
44e4961125SRichard Fitzgerald 	{ CS35L56_SWIRE_DP3_CH4_INPUT,		0x00000028 },
45e4961125SRichard Fitzgerald 	{ CS35L56_IRQ1_CFG,			0x00000000 },
46e4961125SRichard Fitzgerald 	{ CS35L56_IRQ1_MASK_1,			0x83ffffff },
47e4961125SRichard Fitzgerald 	{ CS35L56_IRQ1_MASK_2,			0xffff7fff },
48e4961125SRichard Fitzgerald 	{ CS35L56_IRQ1_MASK_4,			0xe0ffffff },
49e4961125SRichard Fitzgerald 	{ CS35L56_IRQ1_MASK_8,			0xfc000fff },
50e4961125SRichard Fitzgerald 	{ CS35L56_IRQ1_MASK_18,			0x1f7df0ff },
51e4961125SRichard Fitzgerald 	{ CS35L56_IRQ1_MASK_20,			0x15c00000 },
52df4167d6SRichard Fitzgerald 	{ CS35L56_MAIN_RENDER_USER_MUTE,	0x00000000 },
53df4167d6SRichard Fitzgerald 	{ CS35L56_MAIN_RENDER_USER_VOLUME,	0x00000000 },
54df4167d6SRichard Fitzgerald 	{ CS35L56_MAIN_POSTURE_NUMBER,		0x00000000 },
55e4961125SRichard Fitzgerald };
56e4961125SRichard Fitzgerald 
cs35l56_is_dsp_memory(unsigned int reg)57e4961125SRichard Fitzgerald static bool cs35l56_is_dsp_memory(unsigned int reg)
58e4961125SRichard Fitzgerald {
59e4961125SRichard Fitzgerald 	switch (reg) {
60e4961125SRichard Fitzgerald 	case CS35L56_DSP1_XMEM_PACKED_0 ... CS35L56_DSP1_XMEM_PACKED_6143:
61e4961125SRichard Fitzgerald 	case CS35L56_DSP1_XMEM_UNPACKED32_0 ... CS35L56_DSP1_XMEM_UNPACKED32_4095:
62e4961125SRichard Fitzgerald 	case CS35L56_DSP1_XMEM_UNPACKED24_0 ... CS35L56_DSP1_XMEM_UNPACKED24_8191:
63e4961125SRichard Fitzgerald 	case CS35L56_DSP1_YMEM_PACKED_0 ... CS35L56_DSP1_YMEM_PACKED_4604:
64e4961125SRichard Fitzgerald 	case CS35L56_DSP1_YMEM_UNPACKED32_0 ... CS35L56_DSP1_YMEM_UNPACKED32_3070:
65e4961125SRichard Fitzgerald 	case CS35L56_DSP1_YMEM_UNPACKED24_0 ... CS35L56_DSP1_YMEM_UNPACKED24_6141:
66e4961125SRichard Fitzgerald 	case CS35L56_DSP1_PMEM_0 ... CS35L56_DSP1_PMEM_5114:
67e4961125SRichard Fitzgerald 		return true;
68e4961125SRichard Fitzgerald 	default:
69e4961125SRichard Fitzgerald 		return false;
70e4961125SRichard Fitzgerald 	}
71e4961125SRichard Fitzgerald }
72e4961125SRichard Fitzgerald 
cs35l56_readable_reg(struct device * dev,unsigned int reg)73e4961125SRichard Fitzgerald static bool cs35l56_readable_reg(struct device *dev, unsigned int reg)
74e4961125SRichard Fitzgerald {
75e4961125SRichard Fitzgerald 	switch (reg) {
76e4961125SRichard Fitzgerald 	case CS35L56_DEVID:
77e4961125SRichard Fitzgerald 	case CS35L56_REVID:
78e4961125SRichard Fitzgerald 	case CS35L56_RELID:
79e4961125SRichard Fitzgerald 	case CS35L56_OTPID:
80e4961125SRichard Fitzgerald 	case CS35L56_SFT_RESET:
81e4961125SRichard Fitzgerald 	case CS35L56_GLOBAL_ENABLES:
82e4961125SRichard Fitzgerald 	case CS35L56_BLOCK_ENABLES:
83e4961125SRichard Fitzgerald 	case CS35L56_BLOCK_ENABLES2:
84e4961125SRichard Fitzgerald 	case CS35L56_REFCLK_INPUT:
85e4961125SRichard Fitzgerald 	case CS35L56_GLOBAL_SAMPLE_RATE:
86e4961125SRichard Fitzgerald 	case CS35L56_ASP1_ENABLES1:
87e4961125SRichard Fitzgerald 	case CS35L56_ASP1_CONTROL1:
88e4961125SRichard Fitzgerald 	case CS35L56_ASP1_CONTROL2:
89e4961125SRichard Fitzgerald 	case CS35L56_ASP1_CONTROL3:
90e4961125SRichard Fitzgerald 	case CS35L56_ASP1_FRAME_CONTROL1:
91e4961125SRichard Fitzgerald 	case CS35L56_ASP1_FRAME_CONTROL5:
92e4961125SRichard Fitzgerald 	case CS35L56_ASP1_DATA_CONTROL1:
93e4961125SRichard Fitzgerald 	case CS35L56_ASP1_DATA_CONTROL5:
94e4961125SRichard Fitzgerald 	case CS35L56_DACPCM1_INPUT:
95e4961125SRichard Fitzgerald 	case CS35L56_DACPCM2_INPUT:
96e4961125SRichard Fitzgerald 	case CS35L56_ASP1TX1_INPUT:
97e4961125SRichard Fitzgerald 	case CS35L56_ASP1TX2_INPUT:
98e4961125SRichard Fitzgerald 	case CS35L56_ASP1TX3_INPUT:
99e4961125SRichard Fitzgerald 	case CS35L56_ASP1TX4_INPUT:
100e4961125SRichard Fitzgerald 	case CS35L56_DSP1RX1_INPUT:
101e4961125SRichard Fitzgerald 	case CS35L56_DSP1RX2_INPUT:
102e4961125SRichard Fitzgerald 	case CS35L56_SWIRE_DP3_CH1_INPUT:
103e4961125SRichard Fitzgerald 	case CS35L56_SWIRE_DP3_CH2_INPUT:
104e4961125SRichard Fitzgerald 	case CS35L56_SWIRE_DP3_CH3_INPUT:
105e4961125SRichard Fitzgerald 	case CS35L56_SWIRE_DP3_CH4_INPUT:
106e4961125SRichard Fitzgerald 	case CS35L56_IRQ1_CFG:
107e4961125SRichard Fitzgerald 	case CS35L56_IRQ1_STATUS:
108e4961125SRichard Fitzgerald 	case CS35L56_IRQ1_EINT_1 ... CS35L56_IRQ1_EINT_8:
109e4961125SRichard Fitzgerald 	case CS35L56_IRQ1_EINT_18:
110e4961125SRichard Fitzgerald 	case CS35L56_IRQ1_EINT_20:
111e4961125SRichard Fitzgerald 	case CS35L56_IRQ1_MASK_1:
112e4961125SRichard Fitzgerald 	case CS35L56_IRQ1_MASK_2:
113e4961125SRichard Fitzgerald 	case CS35L56_IRQ1_MASK_4:
114e4961125SRichard Fitzgerald 	case CS35L56_IRQ1_MASK_8:
115e4961125SRichard Fitzgerald 	case CS35L56_IRQ1_MASK_18:
116e4961125SRichard Fitzgerald 	case CS35L56_IRQ1_MASK_20:
117e4961125SRichard Fitzgerald 	case CS35L56_DSP_VIRTUAL1_MBOX_1:
118e4961125SRichard Fitzgerald 	case CS35L56_DSP_VIRTUAL1_MBOX_2:
119e4961125SRichard Fitzgerald 	case CS35L56_DSP_VIRTUAL1_MBOX_3:
120e4961125SRichard Fitzgerald 	case CS35L56_DSP_VIRTUAL1_MBOX_4:
121e4961125SRichard Fitzgerald 	case CS35L56_DSP_VIRTUAL1_MBOX_5:
122e4961125SRichard Fitzgerald 	case CS35L56_DSP_VIRTUAL1_MBOX_6:
123e4961125SRichard Fitzgerald 	case CS35L56_DSP_VIRTUAL1_MBOX_7:
124e4961125SRichard Fitzgerald 	case CS35L56_DSP_VIRTUAL1_MBOX_8:
125e4961125SRichard Fitzgerald 	case CS35L56_DSP_RESTRICT_STS1:
126e4961125SRichard Fitzgerald 	case CS35L56_DSP1_SYS_INFO_ID ... CS35L56_DSP1_SYS_INFO_END:
127e4961125SRichard Fitzgerald 	case CS35L56_DSP1_AHBM_WINDOW_DEBUG_0:
128e4961125SRichard Fitzgerald 	case CS35L56_DSP1_AHBM_WINDOW_DEBUG_1:
129e4961125SRichard Fitzgerald 	case CS35L56_DSP1_SCRATCH1:
130e4961125SRichard Fitzgerald 	case CS35L56_DSP1_SCRATCH2:
131e4961125SRichard Fitzgerald 	case CS35L56_DSP1_SCRATCH3:
132e4961125SRichard Fitzgerald 	case CS35L56_DSP1_SCRATCH4:
133e4961125SRichard Fitzgerald 		return true;
134e4961125SRichard Fitzgerald 	default:
135e4961125SRichard Fitzgerald 		return cs35l56_is_dsp_memory(reg);
136e4961125SRichard Fitzgerald 	}
137e4961125SRichard Fitzgerald }
138e4961125SRichard Fitzgerald 
cs35l56_precious_reg(struct device * dev,unsigned int reg)139e4961125SRichard Fitzgerald static bool cs35l56_precious_reg(struct device *dev, unsigned int reg)
140e4961125SRichard Fitzgerald {
141e4961125SRichard Fitzgerald 	switch (reg) {
142e4961125SRichard Fitzgerald 	case CS35L56_DSP1_XMEM_PACKED_0 ... CS35L56_DSP1_XMEM_PACKED_6143:
143e4961125SRichard Fitzgerald 	case CS35L56_DSP1_YMEM_PACKED_0 ... CS35L56_DSP1_YMEM_PACKED_4604:
144e4961125SRichard Fitzgerald 	case CS35L56_DSP1_PMEM_0 ... CS35L56_DSP1_PMEM_5114:
145e4961125SRichard Fitzgerald 		return true;
146e4961125SRichard Fitzgerald 	default:
147e4961125SRichard Fitzgerald 		return false;
148e4961125SRichard Fitzgerald 	}
149e4961125SRichard Fitzgerald }
150e4961125SRichard Fitzgerald 
cs35l56_volatile_reg(struct device * dev,unsigned int reg)151e4961125SRichard Fitzgerald static bool cs35l56_volatile_reg(struct device *dev, unsigned int reg)
152e4961125SRichard Fitzgerald {
153e4961125SRichard Fitzgerald 	switch (reg) {
154e4961125SRichard Fitzgerald 	case CS35L56_DEVID:
155e4961125SRichard Fitzgerald 	case CS35L56_REVID:
156e4961125SRichard Fitzgerald 	case CS35L56_RELID:
157e4961125SRichard Fitzgerald 	case CS35L56_OTPID:
158e4961125SRichard Fitzgerald 	case CS35L56_SFT_RESET:
159e4961125SRichard Fitzgerald 	case CS35L56_GLOBAL_ENABLES:		   /* owned by firmware */
160e4961125SRichard Fitzgerald 	case CS35L56_BLOCK_ENABLES:		   /* owned by firmware */
161e4961125SRichard Fitzgerald 	case CS35L56_BLOCK_ENABLES2:		   /* owned by firmware */
162e4961125SRichard Fitzgerald 	case CS35L56_REFCLK_INPUT:		   /* owned by firmware */
163e4961125SRichard Fitzgerald 	case CS35L56_GLOBAL_SAMPLE_RATE:	   /* owned by firmware */
164e4961125SRichard Fitzgerald 	case CS35L56_DACPCM1_INPUT:		   /* owned by firmware */
165e4961125SRichard Fitzgerald 	case CS35L56_DACPCM2_INPUT:		   /* owned by firmware */
166e4961125SRichard Fitzgerald 	case CS35L56_DSP1RX1_INPUT:		   /* owned by firmware */
167e4961125SRichard Fitzgerald 	case CS35L56_DSP1RX2_INPUT:		   /* owned by firmware */
168e4961125SRichard Fitzgerald 	case CS35L56_IRQ1_STATUS:
169e4961125SRichard Fitzgerald 	case CS35L56_IRQ1_EINT_1 ... CS35L56_IRQ1_EINT_8:
170e4961125SRichard Fitzgerald 	case CS35L56_IRQ1_EINT_18:
171e4961125SRichard Fitzgerald 	case CS35L56_IRQ1_EINT_20:
172e4961125SRichard Fitzgerald 	case CS35L56_DSP_VIRTUAL1_MBOX_1:
173e4961125SRichard Fitzgerald 	case CS35L56_DSP_VIRTUAL1_MBOX_2:
174e4961125SRichard Fitzgerald 	case CS35L56_DSP_VIRTUAL1_MBOX_3:
175e4961125SRichard Fitzgerald 	case CS35L56_DSP_VIRTUAL1_MBOX_4:
176e4961125SRichard Fitzgerald 	case CS35L56_DSP_VIRTUAL1_MBOX_5:
177e4961125SRichard Fitzgerald 	case CS35L56_DSP_VIRTUAL1_MBOX_6:
178e4961125SRichard Fitzgerald 	case CS35L56_DSP_VIRTUAL1_MBOX_7:
179e4961125SRichard Fitzgerald 	case CS35L56_DSP_VIRTUAL1_MBOX_8:
180e4961125SRichard Fitzgerald 	case CS35L56_DSP_RESTRICT_STS1:
181e4961125SRichard Fitzgerald 	case CS35L56_DSP1_SYS_INFO_ID ... CS35L56_DSP1_SYS_INFO_END:
182e4961125SRichard Fitzgerald 	case CS35L56_DSP1_AHBM_WINDOW_DEBUG_0:
183e4961125SRichard Fitzgerald 	case CS35L56_DSP1_AHBM_WINDOW_DEBUG_1:
184e4961125SRichard Fitzgerald 	case CS35L56_DSP1_SCRATCH1:
185e4961125SRichard Fitzgerald 	case CS35L56_DSP1_SCRATCH2:
186e4961125SRichard Fitzgerald 	case CS35L56_DSP1_SCRATCH3:
187e4961125SRichard Fitzgerald 	case CS35L56_DSP1_SCRATCH4:
188e4961125SRichard Fitzgerald 		return true;
189e4961125SRichard Fitzgerald 	case CS35L56_MAIN_RENDER_USER_MUTE:
190e4961125SRichard Fitzgerald 	case CS35L56_MAIN_RENDER_USER_VOLUME:
191e4961125SRichard Fitzgerald 	case CS35L56_MAIN_POSTURE_NUMBER:
192e4961125SRichard Fitzgerald 		return false;
193e4961125SRichard Fitzgerald 	default:
194e4961125SRichard Fitzgerald 		return cs35l56_is_dsp_memory(reg);
195e4961125SRichard Fitzgerald 	}
196e4961125SRichard Fitzgerald }
197e4961125SRichard Fitzgerald 
1983fd715d6SRichard Fitzgerald /*
1993fd715d6SRichard Fitzgerald  * The firmware boot sequence can overwrite the ASP1 config registers so that
2003fd715d6SRichard Fitzgerald  * they don't match regmap's view of their values. Rewrite the values from the
2013fd715d6SRichard Fitzgerald  * regmap cache into the hardware registers.
2023fd715d6SRichard Fitzgerald  */
cs35l56_force_sync_asp1_registers_from_cache(struct cs35l56_base * cs35l56_base)2033fd715d6SRichard Fitzgerald int cs35l56_force_sync_asp1_registers_from_cache(struct cs35l56_base *cs35l56_base)
2043fd715d6SRichard Fitzgerald {
2053fd715d6SRichard Fitzgerald 	struct reg_sequence asp1_regs[] = {
2063fd715d6SRichard Fitzgerald 		{ .reg = CS35L56_ASP1_ENABLES1 },
2073fd715d6SRichard Fitzgerald 		{ .reg = CS35L56_ASP1_CONTROL1 },
2083fd715d6SRichard Fitzgerald 		{ .reg = CS35L56_ASP1_CONTROL2 },
2093fd715d6SRichard Fitzgerald 		{ .reg = CS35L56_ASP1_CONTROL3 },
2103fd715d6SRichard Fitzgerald 		{ .reg = CS35L56_ASP1_FRAME_CONTROL1 },
2113fd715d6SRichard Fitzgerald 		{ .reg = CS35L56_ASP1_FRAME_CONTROL5 },
2123fd715d6SRichard Fitzgerald 		{ .reg = CS35L56_ASP1_DATA_CONTROL1 },
2133fd715d6SRichard Fitzgerald 		{ .reg = CS35L56_ASP1_DATA_CONTROL5 },
2143fd715d6SRichard Fitzgerald 	};
2153fd715d6SRichard Fitzgerald 	int i, ret;
2163fd715d6SRichard Fitzgerald 
2173fd715d6SRichard Fitzgerald 	/* Read values from regmap cache into a write sequence */
2183fd715d6SRichard Fitzgerald 	for (i = 0; i < ARRAY_SIZE(asp1_regs); ++i) {
2193fd715d6SRichard Fitzgerald 		ret = regmap_read(cs35l56_base->regmap, asp1_regs[i].reg, &asp1_regs[i].def);
2203fd715d6SRichard Fitzgerald 		if (ret)
2213fd715d6SRichard Fitzgerald 			goto err;
2223fd715d6SRichard Fitzgerald 	}
2233fd715d6SRichard Fitzgerald 
2243fd715d6SRichard Fitzgerald 	/* Write the values cache-bypassed so that they will be written to silicon */
2253fd715d6SRichard Fitzgerald 	ret = regmap_multi_reg_write_bypassed(cs35l56_base->regmap, asp1_regs,
2263fd715d6SRichard Fitzgerald 					      ARRAY_SIZE(asp1_regs));
2273fd715d6SRichard Fitzgerald 	if (ret)
2283fd715d6SRichard Fitzgerald 		goto err;
2293fd715d6SRichard Fitzgerald 
2303fd715d6SRichard Fitzgerald 	return 0;
2313fd715d6SRichard Fitzgerald 
2323fd715d6SRichard Fitzgerald err:
2333fd715d6SRichard Fitzgerald 	dev_err(cs35l56_base->dev, "Failed to sync ASP1 registers: %d\n", ret);
2343fd715d6SRichard Fitzgerald 
2353fd715d6SRichard Fitzgerald 	return ret;
2363fd715d6SRichard Fitzgerald }
2373fd715d6SRichard Fitzgerald EXPORT_SYMBOL_NS_GPL(cs35l56_force_sync_asp1_registers_from_cache, SND_SOC_CS35L56_SHARED);
2383fd715d6SRichard Fitzgerald 
cs35l56_mbox_send(struct cs35l56_base * cs35l56_base,unsigned int command)2398a731fd3SSimon Trimmer int cs35l56_mbox_send(struct cs35l56_base *cs35l56_base, unsigned int command)
2408a731fd3SSimon Trimmer {
2418a731fd3SSimon Trimmer 	unsigned int val;
2428a731fd3SSimon Trimmer 	int ret;
2438a731fd3SSimon Trimmer 
2448a731fd3SSimon Trimmer 	regmap_write(cs35l56_base->regmap, CS35L56_DSP_VIRTUAL1_MBOX_1, command);
2458a731fd3SSimon Trimmer 	ret = regmap_read_poll_timeout(cs35l56_base->regmap, CS35L56_DSP_VIRTUAL1_MBOX_1,
2468a731fd3SSimon Trimmer 				       val, (val == 0),
2478a731fd3SSimon Trimmer 				       CS35L56_MBOX_POLL_US, CS35L56_MBOX_TIMEOUT_US);
2488a731fd3SSimon Trimmer 	if (ret) {
2498a731fd3SSimon Trimmer 		dev_warn(cs35l56_base->dev, "MBOX command %#x failed: %d\n", command, ret);
2508a731fd3SSimon Trimmer 		return ret;
2518a731fd3SSimon Trimmer 	}
2528a731fd3SSimon Trimmer 
2538a731fd3SSimon Trimmer 	return 0;
2548a731fd3SSimon Trimmer }
2558a731fd3SSimon Trimmer EXPORT_SYMBOL_NS_GPL(cs35l56_mbox_send, SND_SOC_CS35L56_SHARED);
2568a731fd3SSimon Trimmer 
cs35l56_firmware_shutdown(struct cs35l56_base * cs35l56_base)257444dfa09SSimon Trimmer int cs35l56_firmware_shutdown(struct cs35l56_base *cs35l56_base)
258444dfa09SSimon Trimmer {
259444dfa09SSimon Trimmer 	int ret;
260444dfa09SSimon Trimmer 	unsigned int reg;
261444dfa09SSimon Trimmer 	unsigned int val;
262444dfa09SSimon Trimmer 
263444dfa09SSimon Trimmer 	ret = cs35l56_mbox_send(cs35l56_base, CS35L56_MBOX_CMD_SHUTDOWN);
264444dfa09SSimon Trimmer 	if (ret)
265444dfa09SSimon Trimmer 		return ret;
266444dfa09SSimon Trimmer 
267444dfa09SSimon Trimmer 	if (cs35l56_base->rev < CS35L56_REVID_B0)
268444dfa09SSimon Trimmer 		reg = CS35L56_DSP1_PM_CUR_STATE_A1;
269444dfa09SSimon Trimmer 	else
270444dfa09SSimon Trimmer 		reg = CS35L56_DSP1_PM_CUR_STATE;
271444dfa09SSimon Trimmer 
272444dfa09SSimon Trimmer 	ret = regmap_read_poll_timeout(cs35l56_base->regmap,  reg,
273444dfa09SSimon Trimmer 				       val, (val == CS35L56_HALO_STATE_SHUTDOWN),
274444dfa09SSimon Trimmer 				       CS35L56_HALO_STATE_POLL_US,
275444dfa09SSimon Trimmer 				       CS35L56_HALO_STATE_TIMEOUT_US);
276444dfa09SSimon Trimmer 	if (ret < 0)
277444dfa09SSimon Trimmer 		dev_err(cs35l56_base->dev, "Failed to poll PM_CUR_STATE to 1 is %d (ret %d)\n",
278444dfa09SSimon Trimmer 			val, ret);
279444dfa09SSimon Trimmer 	return ret;
280444dfa09SSimon Trimmer }
281444dfa09SSimon Trimmer EXPORT_SYMBOL_NS_GPL(cs35l56_firmware_shutdown, SND_SOC_CS35L56_SHARED);
282444dfa09SSimon Trimmer 
cs35l56_wait_for_firmware_boot(struct cs35l56_base * cs35l56_base)2838a731fd3SSimon Trimmer int cs35l56_wait_for_firmware_boot(struct cs35l56_base *cs35l56_base)
2848a731fd3SSimon Trimmer {
2858a731fd3SSimon Trimmer 	unsigned int reg;
2868a731fd3SSimon Trimmer 	unsigned int val;
28706afec5cSSimon Trimmer 	int read_ret, poll_ret;
2888a731fd3SSimon Trimmer 
2898a731fd3SSimon Trimmer 	if (cs35l56_base->rev < CS35L56_REVID_B0)
2908a731fd3SSimon Trimmer 		reg = CS35L56_DSP1_HALO_STATE_A1;
2918a731fd3SSimon Trimmer 	else
2928a731fd3SSimon Trimmer 		reg = CS35L56_DSP1_HALO_STATE;
2938a731fd3SSimon Trimmer 
29406afec5cSSimon Trimmer 	/*
29506afec5cSSimon Trimmer 	 * This can't be a regmap_read_poll_timeout() because cs35l56 will NAK
29606afec5cSSimon Trimmer 	 * I2C until it has booted which would terminate the poll
29706afec5cSSimon Trimmer 	 */
29806afec5cSSimon Trimmer 	poll_ret = read_poll_timeout(regmap_read, read_ret,
2998a731fd3SSimon Trimmer 				     (val < 0xFFFF) && (val >= CS35L56_HALO_STATE_BOOT_DONE),
3008a731fd3SSimon Trimmer 				     CS35L56_HALO_STATE_POLL_US,
30106afec5cSSimon Trimmer 				     CS35L56_HALO_STATE_TIMEOUT_US,
30206afec5cSSimon Trimmer 				     false,
30306afec5cSSimon Trimmer 				     cs35l56_base->regmap, reg, &val);
3048a731fd3SSimon Trimmer 
30506afec5cSSimon Trimmer 	if (poll_ret) {
30606afec5cSSimon Trimmer 		dev_err(cs35l56_base->dev, "Firmware boot timed out(%d): HALO_STATE=%#x\n",
30706afec5cSSimon Trimmer 			read_ret, val);
3088a731fd3SSimon Trimmer 		return -EIO;
3098a731fd3SSimon Trimmer 	}
3108a731fd3SSimon Trimmer 
3118a731fd3SSimon Trimmer 	return 0;
3128a731fd3SSimon Trimmer }
3138a731fd3SSimon Trimmer EXPORT_SYMBOL_NS_GPL(cs35l56_wait_for_firmware_boot, SND_SOC_CS35L56_SHARED);
3148a731fd3SSimon Trimmer 
cs35l56_wait_control_port_ready(void)315f32a2bcbSSimon Trimmer void cs35l56_wait_control_port_ready(void)
316f32a2bcbSSimon Trimmer {
317f32a2bcbSSimon Trimmer 	/* Wait for control port to be ready (datasheet tIRS). */
318f32a2bcbSSimon Trimmer 	usleep_range(CS35L56_CONTROL_PORT_READY_US, 2 * CS35L56_CONTROL_PORT_READY_US);
319f32a2bcbSSimon Trimmer }
320f32a2bcbSSimon Trimmer EXPORT_SYMBOL_NS_GPL(cs35l56_wait_control_port_ready, SND_SOC_CS35L56_SHARED);
321f32a2bcbSSimon Trimmer 
cs35l56_wait_min_reset_pulse(void)3228a731fd3SSimon Trimmer void cs35l56_wait_min_reset_pulse(void)
3238a731fd3SSimon Trimmer {
3248a731fd3SSimon Trimmer 	/* Satisfy minimum reset pulse width spec */
3258a731fd3SSimon Trimmer 	usleep_range(CS35L56_RESET_PULSE_MIN_US, 2 * CS35L56_RESET_PULSE_MIN_US);
3268a731fd3SSimon Trimmer }
3278a731fd3SSimon Trimmer EXPORT_SYMBOL_NS_GPL(cs35l56_wait_min_reset_pulse, SND_SOC_CS35L56_SHARED);
3288a731fd3SSimon Trimmer 
3298a731fd3SSimon Trimmer static const struct reg_sequence cs35l56_system_reset_seq[] = {
3304a7f5effSRichard Fitzgerald 	REG_SEQ0(CS35L56_DSP1_HALO_STATE, 0),
3318a731fd3SSimon Trimmer 	REG_SEQ0(CS35L56_DSP_VIRTUAL1_MBOX_1, CS35L56_MBOX_CMD_SYSTEM_RESET),
3328a731fd3SSimon Trimmer };
3338a731fd3SSimon Trimmer 
cs35l56_system_reset(struct cs35l56_base * cs35l56_base,bool is_soundwire)3348a731fd3SSimon Trimmer void cs35l56_system_reset(struct cs35l56_base *cs35l56_base, bool is_soundwire)
3358a731fd3SSimon Trimmer {
3368a731fd3SSimon Trimmer 	/*
3378a731fd3SSimon Trimmer 	 * Must enter cache-only first so there can't be any more register
3388a731fd3SSimon Trimmer 	 * accesses other than the controlled system reset sequence below.
3398a731fd3SSimon Trimmer 	 */
3408a731fd3SSimon Trimmer 	regcache_cache_only(cs35l56_base->regmap, true);
3418a731fd3SSimon Trimmer 	regmap_multi_reg_write_bypassed(cs35l56_base->regmap,
3428a731fd3SSimon Trimmer 					cs35l56_system_reset_seq,
3438a731fd3SSimon Trimmer 					ARRAY_SIZE(cs35l56_system_reset_seq));
3448a731fd3SSimon Trimmer 
3458a731fd3SSimon Trimmer 	/* On SoundWire the registers won't be accessible until it re-enumerates. */
3468a731fd3SSimon Trimmer 	if (is_soundwire)
3478a731fd3SSimon Trimmer 		return;
3488a731fd3SSimon Trimmer 
349f32a2bcbSSimon Trimmer 	cs35l56_wait_control_port_ready();
3508a731fd3SSimon Trimmer 	regcache_cache_only(cs35l56_base->regmap, false);
3518a731fd3SSimon Trimmer }
3528a731fd3SSimon Trimmer EXPORT_SYMBOL_NS_GPL(cs35l56_system_reset, SND_SOC_CS35L56_SHARED);
3538a731fd3SSimon Trimmer 
cs35l56_irq_request(struct cs35l56_base * cs35l56_base,int irq)3548a731fd3SSimon Trimmer int cs35l56_irq_request(struct cs35l56_base *cs35l56_base, int irq)
3558a731fd3SSimon Trimmer {
3568a731fd3SSimon Trimmer 	int ret;
3578a731fd3SSimon Trimmer 
3585f7b12dbSSimon Trimmer 	if (irq < 1)
3598a731fd3SSimon Trimmer 		return 0;
3608a731fd3SSimon Trimmer 
3618a731fd3SSimon Trimmer 	ret = devm_request_threaded_irq(cs35l56_base->dev, irq, NULL, cs35l56_irq,
3628a731fd3SSimon Trimmer 					IRQF_ONESHOT | IRQF_SHARED | IRQF_TRIGGER_LOW,
3638a731fd3SSimon Trimmer 					"cs35l56", cs35l56_base);
3648a731fd3SSimon Trimmer 	if (!ret)
3658a731fd3SSimon Trimmer 		cs35l56_base->irq = irq;
3668a731fd3SSimon Trimmer 	else
3678a731fd3SSimon Trimmer 		dev_err(cs35l56_base->dev, "Failed to get IRQ: %d\n", ret);
3688a731fd3SSimon Trimmer 
3698a731fd3SSimon Trimmer 	return ret;
3708a731fd3SSimon Trimmer }
3718a731fd3SSimon Trimmer EXPORT_SYMBOL_NS_GPL(cs35l56_irq_request, SND_SOC_CS35L56_SHARED);
3728a731fd3SSimon Trimmer 
cs35l56_irq(int irq,void * data)3738a731fd3SSimon Trimmer irqreturn_t cs35l56_irq(int irq, void *data)
3748a731fd3SSimon Trimmer {
3758a731fd3SSimon Trimmer 	struct cs35l56_base *cs35l56_base = data;
3768a731fd3SSimon Trimmer 	unsigned int status1 = 0, status8 = 0, status20 = 0;
3778a731fd3SSimon Trimmer 	unsigned int mask1, mask8, mask20;
3788a731fd3SSimon Trimmer 	unsigned int val;
3798a731fd3SSimon Trimmer 	int rv;
3808a731fd3SSimon Trimmer 
3818a731fd3SSimon Trimmer 	irqreturn_t ret = IRQ_NONE;
3828a731fd3SSimon Trimmer 
3838a731fd3SSimon Trimmer 	if (!cs35l56_base->init_done)
3848a731fd3SSimon Trimmer 		return IRQ_NONE;
3858a731fd3SSimon Trimmer 
3868a731fd3SSimon Trimmer 	mutex_lock(&cs35l56_base->irq_lock);
3878a731fd3SSimon Trimmer 
3888a731fd3SSimon Trimmer 	rv = pm_runtime_resume_and_get(cs35l56_base->dev);
3898a731fd3SSimon Trimmer 	if (rv < 0) {
3908a731fd3SSimon Trimmer 		dev_err(cs35l56_base->dev, "irq: failed to get pm_runtime: %d\n", rv);
3918a731fd3SSimon Trimmer 		goto err_unlock;
3928a731fd3SSimon Trimmer 	}
3938a731fd3SSimon Trimmer 
3948a731fd3SSimon Trimmer 	regmap_read(cs35l56_base->regmap, CS35L56_IRQ1_STATUS, &val);
3958a731fd3SSimon Trimmer 	if ((val & CS35L56_IRQ1_STS_MASK) == 0) {
3968a731fd3SSimon Trimmer 		dev_dbg(cs35l56_base->dev, "Spurious IRQ: no pending interrupt\n");
3978a731fd3SSimon Trimmer 		goto err;
3988a731fd3SSimon Trimmer 	}
3998a731fd3SSimon Trimmer 
4008a731fd3SSimon Trimmer 	/* Ack interrupts */
4018a731fd3SSimon Trimmer 	regmap_read(cs35l56_base->regmap, CS35L56_IRQ1_EINT_1, &status1);
4028a731fd3SSimon Trimmer 	regmap_read(cs35l56_base->regmap, CS35L56_IRQ1_MASK_1, &mask1);
4038a731fd3SSimon Trimmer 	status1 &= ~mask1;
4048a731fd3SSimon Trimmer 	regmap_write(cs35l56_base->regmap, CS35L56_IRQ1_EINT_1, status1);
4058a731fd3SSimon Trimmer 
4068a731fd3SSimon Trimmer 	regmap_read(cs35l56_base->regmap, CS35L56_IRQ1_EINT_8, &status8);
4078a731fd3SSimon Trimmer 	regmap_read(cs35l56_base->regmap, CS35L56_IRQ1_MASK_8, &mask8);
4088a731fd3SSimon Trimmer 	status8 &= ~mask8;
4098a731fd3SSimon Trimmer 	regmap_write(cs35l56_base->regmap, CS35L56_IRQ1_EINT_8, status8);
4108a731fd3SSimon Trimmer 
4118a731fd3SSimon Trimmer 	regmap_read(cs35l56_base->regmap, CS35L56_IRQ1_EINT_20, &status20);
4128a731fd3SSimon Trimmer 	regmap_read(cs35l56_base->regmap, CS35L56_IRQ1_MASK_20, &mask20);
4138a731fd3SSimon Trimmer 	status20 &= ~mask20;
4148a731fd3SSimon Trimmer 	/* We don't want EINT20 but they default to unmasked: force mask */
4158a731fd3SSimon Trimmer 	regmap_write(cs35l56_base->regmap, CS35L56_IRQ1_MASK_20, 0xffffffff);
4168a731fd3SSimon Trimmer 
4178a731fd3SSimon Trimmer 	dev_dbg(cs35l56_base->dev, "%s: %#x %#x\n", __func__, status1, status8);
4188a731fd3SSimon Trimmer 
4198a731fd3SSimon Trimmer 	/* Check to see if unmasked bits are active */
4208a731fd3SSimon Trimmer 	if (!status1 && !status8 && !status20)
4218a731fd3SSimon Trimmer 		goto err;
4228a731fd3SSimon Trimmer 
4238a731fd3SSimon Trimmer 	if (status1 & CS35L56_AMP_SHORT_ERR_EINT1_MASK)
4248a731fd3SSimon Trimmer 		dev_crit(cs35l56_base->dev, "Amp short error\n");
4258a731fd3SSimon Trimmer 
4268a731fd3SSimon Trimmer 	if (status8 & CS35L56_TEMP_ERR_EINT1_MASK)
4278a731fd3SSimon Trimmer 		dev_crit(cs35l56_base->dev, "Overtemp error\n");
4288a731fd3SSimon Trimmer 
4298a731fd3SSimon Trimmer 	ret = IRQ_HANDLED;
4308a731fd3SSimon Trimmer 
4318a731fd3SSimon Trimmer err:
4328a731fd3SSimon Trimmer 	pm_runtime_put(cs35l56_base->dev);
4338a731fd3SSimon Trimmer err_unlock:
4348a731fd3SSimon Trimmer 	mutex_unlock(&cs35l56_base->irq_lock);
4358a731fd3SSimon Trimmer 
4368a731fd3SSimon Trimmer 	return ret;
4378a731fd3SSimon Trimmer }
4388a731fd3SSimon Trimmer EXPORT_SYMBOL_NS_GPL(cs35l56_irq, SND_SOC_CS35L56_SHARED);
4398a731fd3SSimon Trimmer 
cs35l56_is_fw_reload_needed(struct cs35l56_base * cs35l56_base)4408a731fd3SSimon Trimmer int cs35l56_is_fw_reload_needed(struct cs35l56_base *cs35l56_base)
4418a731fd3SSimon Trimmer {
4428a731fd3SSimon Trimmer 	unsigned int val;
4438a731fd3SSimon Trimmer 	int ret;
4448a731fd3SSimon Trimmer 
4458a731fd3SSimon Trimmer 	/* Nothing to re-patch if we haven't done any patching yet. */
4468a731fd3SSimon Trimmer 	if (!cs35l56_base->fw_patched)
4478a731fd3SSimon Trimmer 		return false;
4488a731fd3SSimon Trimmer 
4498a731fd3SSimon Trimmer 	/*
4508a731fd3SSimon Trimmer 	 * If we have control of RESET we will have asserted it so the firmware
4518a731fd3SSimon Trimmer 	 * will need re-patching.
4528a731fd3SSimon Trimmer 	 */
4538a731fd3SSimon Trimmer 	if (cs35l56_base->reset_gpio)
4548a731fd3SSimon Trimmer 		return true;
4558a731fd3SSimon Trimmer 
4568a731fd3SSimon Trimmer 	/*
4578a731fd3SSimon Trimmer 	 * In secure mode FIRMWARE_MISSING is cleared by the BIOS loader so
4588a731fd3SSimon Trimmer 	 * can't be used here to test for memory retention.
4598a731fd3SSimon Trimmer 	 * Assume that tuning must be re-loaded.
4608a731fd3SSimon Trimmer 	 */
4618a731fd3SSimon Trimmer 	if (cs35l56_base->secured)
4628a731fd3SSimon Trimmer 		return true;
4638a731fd3SSimon Trimmer 
4648a731fd3SSimon Trimmer 	ret = pm_runtime_resume_and_get(cs35l56_base->dev);
4658a731fd3SSimon Trimmer 	if (ret) {
4668a731fd3SSimon Trimmer 		dev_err(cs35l56_base->dev, "Failed to runtime_get: %d\n", ret);
4678a731fd3SSimon Trimmer 		return ret;
4688a731fd3SSimon Trimmer 	}
4698a731fd3SSimon Trimmer 
4708a731fd3SSimon Trimmer 	ret = regmap_read(cs35l56_base->regmap, CS35L56_PROTECTION_STATUS, &val);
4718a731fd3SSimon Trimmer 	if (ret)
4728a731fd3SSimon Trimmer 		dev_err(cs35l56_base->dev, "Failed to read PROTECTION_STATUS: %d\n", ret);
4738a731fd3SSimon Trimmer 	else
4748a731fd3SSimon Trimmer 		ret = !!(val & CS35L56_FIRMWARE_MISSING);
4758a731fd3SSimon Trimmer 
4768a731fd3SSimon Trimmer 	pm_runtime_put_autosuspend(cs35l56_base->dev);
4778a731fd3SSimon Trimmer 
4788a731fd3SSimon Trimmer 	return ret;
4798a731fd3SSimon Trimmer }
4808a731fd3SSimon Trimmer EXPORT_SYMBOL_NS_GPL(cs35l56_is_fw_reload_needed, SND_SOC_CS35L56_SHARED);
4818a731fd3SSimon Trimmer 
4829974d5b5SRichard Fitzgerald static const struct reg_sequence cs35l56_hibernate_seq[] = {
4839974d5b5SRichard Fitzgerald 	/* This must be the last register access */
4849974d5b5SRichard Fitzgerald 	REG_SEQ0(CS35L56_DSP_VIRTUAL1_MBOX_1, CS35L56_MBOX_CMD_HIBERNATE_NOW),
4859974d5b5SRichard Fitzgerald };
4869974d5b5SRichard Fitzgerald 
4879974d5b5SRichard Fitzgerald static const struct reg_sequence cs35l56_hibernate_wake_seq[] = {
4889974d5b5SRichard Fitzgerald 	REG_SEQ0(CS35L56_DSP_VIRTUAL1_MBOX_1, CS35L56_MBOX_CMD_WAKEUP),
4899974d5b5SRichard Fitzgerald };
4909974d5b5SRichard Fitzgerald 
cs35l56_runtime_suspend_common(struct cs35l56_base * cs35l56_base)4919974d5b5SRichard Fitzgerald int cs35l56_runtime_suspend_common(struct cs35l56_base *cs35l56_base)
4929974d5b5SRichard Fitzgerald {
4939974d5b5SRichard Fitzgerald 	unsigned int val;
4949974d5b5SRichard Fitzgerald 	int ret;
4959974d5b5SRichard Fitzgerald 
4969974d5b5SRichard Fitzgerald 	if (!cs35l56_base->init_done)
4979974d5b5SRichard Fitzgerald 		return 0;
4989974d5b5SRichard Fitzgerald 
4999974d5b5SRichard Fitzgerald 	/* Firmware must have entered a power-save state */
5009974d5b5SRichard Fitzgerald 	ret = regmap_read_poll_timeout(cs35l56_base->regmap,
5019974d5b5SRichard Fitzgerald 				       CS35L56_TRANSDUCER_ACTUAL_PS,
5029974d5b5SRichard Fitzgerald 				       val, (val >= CS35L56_PS3),
5039974d5b5SRichard Fitzgerald 				       CS35L56_PS3_POLL_US,
5049974d5b5SRichard Fitzgerald 				       CS35L56_PS3_TIMEOUT_US);
5059974d5b5SRichard Fitzgerald 	if (ret)
5069974d5b5SRichard Fitzgerald 		dev_warn(cs35l56_base->dev, "PS3 wait failed: %d\n", ret);
5079974d5b5SRichard Fitzgerald 
5089974d5b5SRichard Fitzgerald 	/* Clear BOOT_DONE so it can be used to detect a reboot */
5099974d5b5SRichard Fitzgerald 	regmap_write(cs35l56_base->regmap, CS35L56_IRQ1_EINT_4, CS35L56_OTP_BOOT_DONE_MASK);
5109974d5b5SRichard Fitzgerald 
5119974d5b5SRichard Fitzgerald 	if (!cs35l56_base->can_hibernate) {
5129974d5b5SRichard Fitzgerald 		regcache_cache_only(cs35l56_base->regmap, true);
5139974d5b5SRichard Fitzgerald 		dev_dbg(cs35l56_base->dev, "Suspended: no hibernate");
5149974d5b5SRichard Fitzgerald 
5159974d5b5SRichard Fitzgerald 		return 0;
5169974d5b5SRichard Fitzgerald 	}
5179974d5b5SRichard Fitzgerald 
5189974d5b5SRichard Fitzgerald 	/*
5199974d5b5SRichard Fitzgerald 	 * Enable auto-hibernate. If it is woken by some other wake source
5209974d5b5SRichard Fitzgerald 	 * it will automatically return to hibernate.
5219974d5b5SRichard Fitzgerald 	 */
5229974d5b5SRichard Fitzgerald 	cs35l56_mbox_send(cs35l56_base, CS35L56_MBOX_CMD_ALLOW_AUTO_HIBERNATE);
5239974d5b5SRichard Fitzgerald 
5249974d5b5SRichard Fitzgerald 	/*
5259974d5b5SRichard Fitzgerald 	 * Must enter cache-only first so there can't be any more register
5269974d5b5SRichard Fitzgerald 	 * accesses other than the controlled hibernate sequence below.
5279974d5b5SRichard Fitzgerald 	 */
5289974d5b5SRichard Fitzgerald 	regcache_cache_only(cs35l56_base->regmap, true);
5299974d5b5SRichard Fitzgerald 
5309974d5b5SRichard Fitzgerald 	regmap_multi_reg_write_bypassed(cs35l56_base->regmap,
5319974d5b5SRichard Fitzgerald 					cs35l56_hibernate_seq,
5329974d5b5SRichard Fitzgerald 					ARRAY_SIZE(cs35l56_hibernate_seq));
5339974d5b5SRichard Fitzgerald 
5349974d5b5SRichard Fitzgerald 	dev_dbg(cs35l56_base->dev, "Suspended: hibernate");
5359974d5b5SRichard Fitzgerald 
5369974d5b5SRichard Fitzgerald 	return 0;
5379974d5b5SRichard Fitzgerald }
5389974d5b5SRichard Fitzgerald EXPORT_SYMBOL_NS_GPL(cs35l56_runtime_suspend_common, SND_SOC_CS35L56_SHARED);
5399974d5b5SRichard Fitzgerald 
cs35l56_runtime_resume_common(struct cs35l56_base * cs35l56_base,bool is_soundwire)5409974d5b5SRichard Fitzgerald int cs35l56_runtime_resume_common(struct cs35l56_base *cs35l56_base, bool is_soundwire)
5419974d5b5SRichard Fitzgerald {
5429974d5b5SRichard Fitzgerald 	unsigned int val;
5439974d5b5SRichard Fitzgerald 	int ret;
5449974d5b5SRichard Fitzgerald 
5459974d5b5SRichard Fitzgerald 	if (!cs35l56_base->init_done)
5469974d5b5SRichard Fitzgerald 		return 0;
5479974d5b5SRichard Fitzgerald 
5489974d5b5SRichard Fitzgerald 	if (!cs35l56_base->can_hibernate)
5499974d5b5SRichard Fitzgerald 		goto out_sync;
5509974d5b5SRichard Fitzgerald 
5519974d5b5SRichard Fitzgerald 	if (!is_soundwire) {
5529974d5b5SRichard Fitzgerald 		/*
5539974d5b5SRichard Fitzgerald 		 * Dummy transaction to trigger I2C/SPI auto-wake. This will NAK on I2C.
5549974d5b5SRichard Fitzgerald 		 * Must be done before releasing cache-only.
5559974d5b5SRichard Fitzgerald 		 */
5569974d5b5SRichard Fitzgerald 		regmap_multi_reg_write_bypassed(cs35l56_base->regmap,
5579974d5b5SRichard Fitzgerald 						cs35l56_hibernate_wake_seq,
5589974d5b5SRichard Fitzgerald 						ARRAY_SIZE(cs35l56_hibernate_wake_seq));
5599974d5b5SRichard Fitzgerald 
560f32a2bcbSSimon Trimmer 		cs35l56_wait_control_port_ready();
5619974d5b5SRichard Fitzgerald 	}
5629974d5b5SRichard Fitzgerald 
5639974d5b5SRichard Fitzgerald out_sync:
5649974d5b5SRichard Fitzgerald 	regcache_cache_only(cs35l56_base->regmap, false);
5659974d5b5SRichard Fitzgerald 
5669974d5b5SRichard Fitzgerald 	ret = cs35l56_wait_for_firmware_boot(cs35l56_base);
5679974d5b5SRichard Fitzgerald 	if (ret) {
5689974d5b5SRichard Fitzgerald 		dev_err(cs35l56_base->dev, "Hibernate wake failed: %d\n", ret);
5699974d5b5SRichard Fitzgerald 		goto err;
5709974d5b5SRichard Fitzgerald 	}
5719974d5b5SRichard Fitzgerald 
5729974d5b5SRichard Fitzgerald 	ret = cs35l56_mbox_send(cs35l56_base, CS35L56_MBOX_CMD_PREVENT_AUTO_HIBERNATE);
5739974d5b5SRichard Fitzgerald 	if (ret)
5749974d5b5SRichard Fitzgerald 		goto err;
5759974d5b5SRichard Fitzgerald 
5769974d5b5SRichard Fitzgerald 	/* BOOT_DONE will be 1 if the amp reset */
5779974d5b5SRichard Fitzgerald 	regmap_read(cs35l56_base->regmap, CS35L56_IRQ1_EINT_4, &val);
5789974d5b5SRichard Fitzgerald 	if (val & CS35L56_OTP_BOOT_DONE_MASK) {
5799974d5b5SRichard Fitzgerald 		dev_dbg(cs35l56_base->dev, "Registers reset in suspend\n");
5809974d5b5SRichard Fitzgerald 		regcache_mark_dirty(cs35l56_base->regmap);
5819974d5b5SRichard Fitzgerald 	}
5829974d5b5SRichard Fitzgerald 
5839974d5b5SRichard Fitzgerald 	regcache_sync(cs35l56_base->regmap);
5849974d5b5SRichard Fitzgerald 
5859974d5b5SRichard Fitzgerald 	dev_dbg(cs35l56_base->dev, "Resumed");
5869974d5b5SRichard Fitzgerald 
5879974d5b5SRichard Fitzgerald 	return 0;
5889974d5b5SRichard Fitzgerald 
5899974d5b5SRichard Fitzgerald err:
5909974d5b5SRichard Fitzgerald 	regmap_write(cs35l56_base->regmap, CS35L56_DSP_VIRTUAL1_MBOX_1,
5919974d5b5SRichard Fitzgerald 		     CS35L56_MBOX_CMD_HIBERNATE_NOW);
5929974d5b5SRichard Fitzgerald 
5939974d5b5SRichard Fitzgerald 	regcache_cache_only(cs35l56_base->regmap, true);
5949974d5b5SRichard Fitzgerald 
5959974d5b5SRichard Fitzgerald 	return ret;
5969974d5b5SRichard Fitzgerald }
5979974d5b5SRichard Fitzgerald EXPORT_SYMBOL_NS_GPL(cs35l56_runtime_resume_common, SND_SOC_CS35L56_SHARED);
5989974d5b5SRichard Fitzgerald 
59922e51dbbSRichard Fitzgerald static const struct cs_dsp_region cs35l56_dsp1_regions[] = {
600e4961125SRichard Fitzgerald 	{ .type = WMFW_HALO_PM_PACKED,	.base = CS35L56_DSP1_PMEM_0 },
601e4961125SRichard Fitzgerald 	{ .type = WMFW_HALO_XM_PACKED,	.base = CS35L56_DSP1_XMEM_PACKED_0 },
602e4961125SRichard Fitzgerald 	{ .type = WMFW_HALO_YM_PACKED,	.base = CS35L56_DSP1_YMEM_PACKED_0 },
603e4961125SRichard Fitzgerald 	{ .type = WMFW_ADSP2_XM,	.base = CS35L56_DSP1_XMEM_UNPACKED24_0 },
604e4961125SRichard Fitzgerald 	{ .type = WMFW_ADSP2_YM,	.base = CS35L56_DSP1_YMEM_UNPACKED24_0 },
605e4961125SRichard Fitzgerald };
60622e51dbbSRichard Fitzgerald 
cs35l56_init_cs_dsp(struct cs35l56_base * cs35l56_base,struct cs_dsp * cs_dsp)60722e51dbbSRichard Fitzgerald void cs35l56_init_cs_dsp(struct cs35l56_base *cs35l56_base, struct cs_dsp *cs_dsp)
60822e51dbbSRichard Fitzgerald {
60922e51dbbSRichard Fitzgerald 	cs_dsp->num = 1;
61022e51dbbSRichard Fitzgerald 	cs_dsp->type = WMFW_HALO;
61122e51dbbSRichard Fitzgerald 	cs_dsp->rev = 0;
61222e51dbbSRichard Fitzgerald 	cs_dsp->dev = cs35l56_base->dev;
61322e51dbbSRichard Fitzgerald 	cs_dsp->regmap = cs35l56_base->regmap;
61422e51dbbSRichard Fitzgerald 	cs_dsp->base = CS35L56_DSP1_CORE_BASE;
61522e51dbbSRichard Fitzgerald 	cs_dsp->base_sysinfo = CS35L56_DSP1_SYS_INFO_ID;
61622e51dbbSRichard Fitzgerald 	cs_dsp->mem = cs35l56_dsp1_regions;
61722e51dbbSRichard Fitzgerald 	cs_dsp->num_mems = ARRAY_SIZE(cs35l56_dsp1_regions);
61822e51dbbSRichard Fitzgerald 	cs_dsp->no_core_startstop = true;
61922e51dbbSRichard Fitzgerald }
62022e51dbbSRichard Fitzgerald EXPORT_SYMBOL_NS_GPL(cs35l56_init_cs_dsp, SND_SOC_CS35L56_SHARED);
621e4961125SRichard Fitzgerald 
cs35l56_hw_init(struct cs35l56_base * cs35l56_base)62284851aa0SRichard Fitzgerald int cs35l56_hw_init(struct cs35l56_base *cs35l56_base)
62384851aa0SRichard Fitzgerald {
62484851aa0SRichard Fitzgerald 	int ret;
62584851aa0SRichard Fitzgerald 	unsigned int devid, revid, otpid, secured;
62684851aa0SRichard Fitzgerald 
62784851aa0SRichard Fitzgerald 	/*
62884851aa0SRichard Fitzgerald 	 * If the system is not using a reset_gpio then issue a
62984851aa0SRichard Fitzgerald 	 * dummy read to force a wakeup.
63084851aa0SRichard Fitzgerald 	 */
63184851aa0SRichard Fitzgerald 	if (!cs35l56_base->reset_gpio)
63284851aa0SRichard Fitzgerald 		regmap_read(cs35l56_base->regmap, CS35L56_DSP_VIRTUAL1_MBOX_1, &devid);
63384851aa0SRichard Fitzgerald 
634f32a2bcbSSimon Trimmer 	cs35l56_wait_control_port_ready();
63584851aa0SRichard Fitzgerald 
63684851aa0SRichard Fitzgerald 	/*
63784851aa0SRichard Fitzgerald 	 * The HALO_STATE register is in different locations on Ax and B0
63884851aa0SRichard Fitzgerald 	 * devices so the REVID needs to be determined before waiting for the
63984851aa0SRichard Fitzgerald 	 * firmware to boot.
64084851aa0SRichard Fitzgerald 	 */
64184851aa0SRichard Fitzgerald 	ret = regmap_read(cs35l56_base->regmap, CS35L56_REVID, &revid);
64284851aa0SRichard Fitzgerald 	if (ret < 0) {
64384851aa0SRichard Fitzgerald 		dev_err(cs35l56_base->dev, "Get Revision ID failed\n");
64484851aa0SRichard Fitzgerald 		return ret;
64584851aa0SRichard Fitzgerald 	}
64684851aa0SRichard Fitzgerald 	cs35l56_base->rev = revid & (CS35L56_AREVID_MASK | CS35L56_MTLREVID_MASK);
64784851aa0SRichard Fitzgerald 
64884851aa0SRichard Fitzgerald 	ret = cs35l56_wait_for_firmware_boot(cs35l56_base);
64984851aa0SRichard Fitzgerald 	if (ret)
65084851aa0SRichard Fitzgerald 		return ret;
65184851aa0SRichard Fitzgerald 
65284851aa0SRichard Fitzgerald 	ret = regmap_read(cs35l56_base->regmap, CS35L56_DEVID, &devid);
65384851aa0SRichard Fitzgerald 	if (ret < 0) {
65484851aa0SRichard Fitzgerald 		dev_err(cs35l56_base->dev, "Get Device ID failed\n");
65584851aa0SRichard Fitzgerald 		return ret;
65684851aa0SRichard Fitzgerald 	}
65784851aa0SRichard Fitzgerald 	devid &= CS35L56_DEVID_MASK;
65884851aa0SRichard Fitzgerald 
65984851aa0SRichard Fitzgerald 	switch (devid) {
66084851aa0SRichard Fitzgerald 	case 0x35A56:
66184851aa0SRichard Fitzgerald 		break;
66284851aa0SRichard Fitzgerald 	default:
66384851aa0SRichard Fitzgerald 		dev_err(cs35l56_base->dev, "Unknown device %x\n", devid);
66484851aa0SRichard Fitzgerald 		return ret;
66584851aa0SRichard Fitzgerald 	}
66684851aa0SRichard Fitzgerald 
66784851aa0SRichard Fitzgerald 	ret = regmap_read(cs35l56_base->regmap, CS35L56_DSP_RESTRICT_STS1, &secured);
66884851aa0SRichard Fitzgerald 	if (ret) {
66984851aa0SRichard Fitzgerald 		dev_err(cs35l56_base->dev, "Get Secure status failed\n");
67084851aa0SRichard Fitzgerald 		return ret;
67184851aa0SRichard Fitzgerald 	}
67284851aa0SRichard Fitzgerald 
67384851aa0SRichard Fitzgerald 	/* When any bus is restricted treat the device as secured */
67484851aa0SRichard Fitzgerald 	if (secured & CS35L56_RESTRICTED_MASK)
67584851aa0SRichard Fitzgerald 		cs35l56_base->secured = true;
67684851aa0SRichard Fitzgerald 
67784851aa0SRichard Fitzgerald 	ret = regmap_read(cs35l56_base->regmap, CS35L56_OTPID, &otpid);
67884851aa0SRichard Fitzgerald 	if (ret < 0) {
67984851aa0SRichard Fitzgerald 		dev_err(cs35l56_base->dev, "Get OTP ID failed\n");
68084851aa0SRichard Fitzgerald 		return ret;
68184851aa0SRichard Fitzgerald 	}
68284851aa0SRichard Fitzgerald 
68384851aa0SRichard Fitzgerald 	dev_info(cs35l56_base->dev, "Cirrus Logic CS35L56%s Rev %02X OTP%d\n",
68484851aa0SRichard Fitzgerald 		 cs35l56_base->secured ? "s" : "", cs35l56_base->rev, otpid);
68584851aa0SRichard Fitzgerald 
68684851aa0SRichard Fitzgerald 	/* Wake source and *_BLOCKED interrupts default to unmasked, so mask them */
68784851aa0SRichard Fitzgerald 	regmap_write(cs35l56_base->regmap, CS35L56_IRQ1_MASK_20, 0xffffffff);
68884851aa0SRichard Fitzgerald 	regmap_update_bits(cs35l56_base->regmap, CS35L56_IRQ1_MASK_1,
68984851aa0SRichard Fitzgerald 			   CS35L56_AMP_SHORT_ERR_EINT1_MASK,
69084851aa0SRichard Fitzgerald 			   0);
69184851aa0SRichard Fitzgerald 	regmap_update_bits(cs35l56_base->regmap, CS35L56_IRQ1_MASK_8,
69284851aa0SRichard Fitzgerald 			   CS35L56_TEMP_ERR_EINT1_MASK,
69384851aa0SRichard Fitzgerald 			   0);
69484851aa0SRichard Fitzgerald 
69584851aa0SRichard Fitzgerald 	return 0;
69684851aa0SRichard Fitzgerald }
69784851aa0SRichard Fitzgerald EXPORT_SYMBOL_NS_GPL(cs35l56_hw_init, SND_SOC_CS35L56_SHARED);
69884851aa0SRichard Fitzgerald 
cs35l56_get_speaker_id(struct cs35l56_base * cs35l56_base)699*e905bc71SRichard Fitzgerald int cs35l56_get_speaker_id(struct cs35l56_base *cs35l56_base)
700*e905bc71SRichard Fitzgerald {
701*e905bc71SRichard Fitzgerald 	struct gpio_descs *descs;
702*e905bc71SRichard Fitzgerald 	int speaker_id;
703*e905bc71SRichard Fitzgerald 	int i, ret;
704*e905bc71SRichard Fitzgerald 
705*e905bc71SRichard Fitzgerald 	/* Read the speaker type qualifier from the motherboard GPIOs */
706*e905bc71SRichard Fitzgerald 	descs = gpiod_get_array_optional(cs35l56_base->dev, "spk-id", GPIOD_IN);
707*e905bc71SRichard Fitzgerald 	if (!descs) {
708*e905bc71SRichard Fitzgerald 		return -ENOENT;
709*e905bc71SRichard Fitzgerald 	} else if (IS_ERR(descs)) {
710*e905bc71SRichard Fitzgerald 		ret = PTR_ERR(descs);
711*e905bc71SRichard Fitzgerald 		return dev_err_probe(cs35l56_base->dev, ret, "Failed to get spk-id-gpios\n");
712*e905bc71SRichard Fitzgerald 	}
713*e905bc71SRichard Fitzgerald 
714*e905bc71SRichard Fitzgerald 	speaker_id = 0;
715*e905bc71SRichard Fitzgerald 	for (i = 0; i < descs->ndescs; i++) {
716*e905bc71SRichard Fitzgerald 		ret = gpiod_get_value_cansleep(descs->desc[i]);
717*e905bc71SRichard Fitzgerald 		if (ret < 0) {
718*e905bc71SRichard Fitzgerald 			dev_err_probe(cs35l56_base->dev, ret, "Failed to read spk-id[%d]\n", i);
719*e905bc71SRichard Fitzgerald 			goto err;
720*e905bc71SRichard Fitzgerald 		}
721*e905bc71SRichard Fitzgerald 
722*e905bc71SRichard Fitzgerald 		speaker_id |= (ret << i);
723*e905bc71SRichard Fitzgerald 	}
724*e905bc71SRichard Fitzgerald 
725*e905bc71SRichard Fitzgerald 	dev_dbg(cs35l56_base->dev, "Speaker ID = %d\n", speaker_id);
726*e905bc71SRichard Fitzgerald 	ret = speaker_id;
727*e905bc71SRichard Fitzgerald err:
728*e905bc71SRichard Fitzgerald 	gpiod_put_array(descs);
729*e905bc71SRichard Fitzgerald 
730*e905bc71SRichard Fitzgerald 	return ret;
731*e905bc71SRichard Fitzgerald }
732*e905bc71SRichard Fitzgerald EXPORT_SYMBOL_NS_GPL(cs35l56_get_speaker_id, SND_SOC_CS35L56_SHARED);
733*e905bc71SRichard Fitzgerald 
734e4961125SRichard Fitzgerald static const u32 cs35l56_bclk_valid_for_pll_freq_table[] = {
735e4961125SRichard Fitzgerald 	[0x0C] = 128000,
736e4961125SRichard Fitzgerald 	[0x0F] = 256000,
737e4961125SRichard Fitzgerald 	[0x11] = 384000,
738e4961125SRichard Fitzgerald 	[0x12] = 512000,
739e4961125SRichard Fitzgerald 	[0x15] = 768000,
740e4961125SRichard Fitzgerald 	[0x17] = 1024000,
741e4961125SRichard Fitzgerald 	[0x1A] = 1500000,
742e4961125SRichard Fitzgerald 	[0x1B] = 1536000,
743e4961125SRichard Fitzgerald 	[0x1C] = 2000000,
744e4961125SRichard Fitzgerald 	[0x1D] = 2048000,
745e4961125SRichard Fitzgerald 	[0x1E] = 2400000,
746e4961125SRichard Fitzgerald 	[0x20] = 3000000,
747e4961125SRichard Fitzgerald 	[0x21] = 3072000,
748e4961125SRichard Fitzgerald 	[0x23] = 4000000,
749e4961125SRichard Fitzgerald 	[0x24] = 4096000,
750e4961125SRichard Fitzgerald 	[0x25] = 4800000,
751e4961125SRichard Fitzgerald 	[0x27] = 6000000,
752e4961125SRichard Fitzgerald 	[0x28] = 6144000,
753e4961125SRichard Fitzgerald 	[0x29] = 6250000,
754e4961125SRichard Fitzgerald 	[0x2A] = 6400000,
755e4961125SRichard Fitzgerald 	[0x2E] = 8000000,
756e4961125SRichard Fitzgerald 	[0x2F] = 8192000,
757e4961125SRichard Fitzgerald 	[0x30] = 9600000,
758e4961125SRichard Fitzgerald 	[0x32] = 12000000,
759e4961125SRichard Fitzgerald 	[0x33] = 12288000,
760e4961125SRichard Fitzgerald 	[0x37] = 13500000,
761e4961125SRichard Fitzgerald 	[0x38] = 19200000,
762e4961125SRichard Fitzgerald 	[0x39] = 22579200,
763e4961125SRichard Fitzgerald 	[0x3B] = 24576000,
764e4961125SRichard Fitzgerald };
765e4961125SRichard Fitzgerald 
cs35l56_get_bclk_freq_id(unsigned int freq)766e4961125SRichard Fitzgerald int cs35l56_get_bclk_freq_id(unsigned int freq)
767e4961125SRichard Fitzgerald {
768e4961125SRichard Fitzgerald 	int i;
769e4961125SRichard Fitzgerald 
770e4961125SRichard Fitzgerald 	if (freq == 0)
771e4961125SRichard Fitzgerald 		return -EINVAL;
772e4961125SRichard Fitzgerald 
773e4961125SRichard Fitzgerald 	/* The BCLK frequency must be a valid PLL REFCLK */
774e4961125SRichard Fitzgerald 	for (i = 0; i < ARRAY_SIZE(cs35l56_bclk_valid_for_pll_freq_table); ++i) {
775e4961125SRichard Fitzgerald 		if (cs35l56_bclk_valid_for_pll_freq_table[i] == freq)
776e4961125SRichard Fitzgerald 			return i;
777e4961125SRichard Fitzgerald 	}
778e4961125SRichard Fitzgerald 
779e4961125SRichard Fitzgerald 	return -EINVAL;
780e4961125SRichard Fitzgerald }
781e4961125SRichard Fitzgerald EXPORT_SYMBOL_NS_GPL(cs35l56_get_bclk_freq_id, SND_SOC_CS35L56_SHARED);
782e4961125SRichard Fitzgerald 
783e4961125SRichard Fitzgerald static const char * const cs35l56_supplies[/* auto-sized */] = {
784e4961125SRichard Fitzgerald 	"VDD_P",
785e4961125SRichard Fitzgerald 	"VDD_IO",
786e4961125SRichard Fitzgerald 	"VDD_A",
787e4961125SRichard Fitzgerald };
788e4961125SRichard Fitzgerald 
cs35l56_fill_supply_names(struct regulator_bulk_data * data)789e4961125SRichard Fitzgerald void cs35l56_fill_supply_names(struct regulator_bulk_data *data)
790e4961125SRichard Fitzgerald {
791e4961125SRichard Fitzgerald 	int i;
792e4961125SRichard Fitzgerald 
793e4961125SRichard Fitzgerald 	BUILD_BUG_ON(ARRAY_SIZE(cs35l56_supplies) != CS35L56_NUM_BULK_SUPPLIES);
794e4961125SRichard Fitzgerald 	for (i = 0; i < ARRAY_SIZE(cs35l56_supplies); i++)
795e4961125SRichard Fitzgerald 		data[i].supply = cs35l56_supplies[i];
796e4961125SRichard Fitzgerald }
797e4961125SRichard Fitzgerald EXPORT_SYMBOL_NS_GPL(cs35l56_fill_supply_names, SND_SOC_CS35L56_SHARED);
798e4961125SRichard Fitzgerald 
799e4961125SRichard Fitzgerald const char * const cs35l56_tx_input_texts[] = {
800e4961125SRichard Fitzgerald 	"None", "ASP1RX1", "ASP1RX2", "VMON", "IMON", "ERRVOL", "CLASSH",
801e4961125SRichard Fitzgerald 	"VDDBMON", "VBSTMON", "DSP1TX1", "DSP1TX2", "DSP1TX3", "DSP1TX4",
802e4961125SRichard Fitzgerald 	"DSP1TX5", "DSP1TX6", "DSP1TX7", "DSP1TX8", "TEMPMON",
803d3a4efb3SRichard Fitzgerald 	"INTERPOLATOR", "SDW1RX1", "SDW1RX2",
804e4961125SRichard Fitzgerald };
805e4961125SRichard Fitzgerald EXPORT_SYMBOL_NS_GPL(cs35l56_tx_input_texts, SND_SOC_CS35L56_SHARED);
806e4961125SRichard Fitzgerald 
807e4961125SRichard Fitzgerald const unsigned int cs35l56_tx_input_values[] = {
808e4961125SRichard Fitzgerald 	CS35L56_INPUT_SRC_NONE,
809e4961125SRichard Fitzgerald 	CS35L56_INPUT_SRC_ASP1RX1,
810e4961125SRichard Fitzgerald 	CS35L56_INPUT_SRC_ASP1RX2,
811e4961125SRichard Fitzgerald 	CS35L56_INPUT_SRC_VMON,
812e4961125SRichard Fitzgerald 	CS35L56_INPUT_SRC_IMON,
813e4961125SRichard Fitzgerald 	CS35L56_INPUT_SRC_ERR_VOL,
814e4961125SRichard Fitzgerald 	CS35L56_INPUT_SRC_CLASSH,
815e4961125SRichard Fitzgerald 	CS35L56_INPUT_SRC_VDDBMON,
816e4961125SRichard Fitzgerald 	CS35L56_INPUT_SRC_VBSTMON,
817e4961125SRichard Fitzgerald 	CS35L56_INPUT_SRC_DSP1TX1,
818e4961125SRichard Fitzgerald 	CS35L56_INPUT_SRC_DSP1TX2,
819e4961125SRichard Fitzgerald 	CS35L56_INPUT_SRC_DSP1TX3,
820e4961125SRichard Fitzgerald 	CS35L56_INPUT_SRC_DSP1TX4,
821e4961125SRichard Fitzgerald 	CS35L56_INPUT_SRC_DSP1TX5,
822e4961125SRichard Fitzgerald 	CS35L56_INPUT_SRC_DSP1TX6,
823e4961125SRichard Fitzgerald 	CS35L56_INPUT_SRC_DSP1TX7,
824e4961125SRichard Fitzgerald 	CS35L56_INPUT_SRC_DSP1TX8,
825e4961125SRichard Fitzgerald 	CS35L56_INPUT_SRC_TEMPMON,
826e4961125SRichard Fitzgerald 	CS35L56_INPUT_SRC_INTERPOLATOR,
827d29a966bSRichard Fitzgerald 	CS35L56_INPUT_SRC_SWIRE_DP1_CHANNEL1,
828d29a966bSRichard Fitzgerald 	CS35L56_INPUT_SRC_SWIRE_DP1_CHANNEL2,
829e4961125SRichard Fitzgerald };
830e4961125SRichard Fitzgerald EXPORT_SYMBOL_NS_GPL(cs35l56_tx_input_values, SND_SOC_CS35L56_SHARED);
831e4961125SRichard Fitzgerald 
832e4961125SRichard Fitzgerald struct regmap_config cs35l56_regmap_i2c = {
833e4961125SRichard Fitzgerald 	.reg_bits = 32,
834e4961125SRichard Fitzgerald 	.val_bits = 32,
835e4961125SRichard Fitzgerald 	.reg_stride = 4,
836e4961125SRichard Fitzgerald 	.reg_format_endian = REGMAP_ENDIAN_BIG,
837e4961125SRichard Fitzgerald 	.val_format_endian = REGMAP_ENDIAN_BIG,
838e4961125SRichard Fitzgerald 	.max_register = CS35L56_DSP1_PMEM_5114,
839e4961125SRichard Fitzgerald 	.reg_defaults = cs35l56_reg_defaults,
840e4961125SRichard Fitzgerald 	.num_reg_defaults = ARRAY_SIZE(cs35l56_reg_defaults),
841e4961125SRichard Fitzgerald 	.volatile_reg = cs35l56_volatile_reg,
842e4961125SRichard Fitzgerald 	.readable_reg = cs35l56_readable_reg,
843e4961125SRichard Fitzgerald 	.precious_reg = cs35l56_precious_reg,
844faa48c9bSMark Brown 	.cache_type = REGCACHE_MAPLE,
845e4961125SRichard Fitzgerald };
846e4961125SRichard Fitzgerald EXPORT_SYMBOL_NS_GPL(cs35l56_regmap_i2c, SND_SOC_CS35L56_SHARED);
847e4961125SRichard Fitzgerald 
848e4961125SRichard Fitzgerald struct regmap_config cs35l56_regmap_spi = {
849e4961125SRichard Fitzgerald 	.reg_bits = 32,
850e4961125SRichard Fitzgerald 	.val_bits = 32,
851e4961125SRichard Fitzgerald 	.pad_bits = 16,
852e4961125SRichard Fitzgerald 	.reg_stride = 4,
853e4961125SRichard Fitzgerald 	.reg_format_endian = REGMAP_ENDIAN_BIG,
854e4961125SRichard Fitzgerald 	.val_format_endian = REGMAP_ENDIAN_BIG,
855e4961125SRichard Fitzgerald 	.max_register = CS35L56_DSP1_PMEM_5114,
856e4961125SRichard Fitzgerald 	.reg_defaults = cs35l56_reg_defaults,
857e4961125SRichard Fitzgerald 	.num_reg_defaults = ARRAY_SIZE(cs35l56_reg_defaults),
858e4961125SRichard Fitzgerald 	.volatile_reg = cs35l56_volatile_reg,
859e4961125SRichard Fitzgerald 	.readable_reg = cs35l56_readable_reg,
860e4961125SRichard Fitzgerald 	.precious_reg = cs35l56_precious_reg,
861faa48c9bSMark Brown 	.cache_type = REGCACHE_MAPLE,
862e4961125SRichard Fitzgerald };
863e4961125SRichard Fitzgerald EXPORT_SYMBOL_NS_GPL(cs35l56_regmap_spi, SND_SOC_CS35L56_SHARED);
864e4961125SRichard Fitzgerald 
865e4961125SRichard Fitzgerald struct regmap_config cs35l56_regmap_sdw = {
866e4961125SRichard Fitzgerald 	.reg_bits = 32,
867e4961125SRichard Fitzgerald 	.val_bits = 32,
868e4961125SRichard Fitzgerald 	.reg_stride = 4,
869e4961125SRichard Fitzgerald 	.reg_format_endian = REGMAP_ENDIAN_LITTLE,
870e4961125SRichard Fitzgerald 	.val_format_endian = REGMAP_ENDIAN_BIG,
871e4961125SRichard Fitzgerald 	.max_register = CS35L56_DSP1_PMEM_5114,
872e4961125SRichard Fitzgerald 	.reg_defaults = cs35l56_reg_defaults,
873e4961125SRichard Fitzgerald 	.num_reg_defaults = ARRAY_SIZE(cs35l56_reg_defaults),
874e4961125SRichard Fitzgerald 	.volatile_reg = cs35l56_volatile_reg,
875e4961125SRichard Fitzgerald 	.readable_reg = cs35l56_readable_reg,
876e4961125SRichard Fitzgerald 	.precious_reg = cs35l56_precious_reg,
877faa48c9bSMark Brown 	.cache_type = REGCACHE_MAPLE,
878e4961125SRichard Fitzgerald };
879e4961125SRichard Fitzgerald EXPORT_SYMBOL_NS_GPL(cs35l56_regmap_sdw, SND_SOC_CS35L56_SHARED);
880e4961125SRichard Fitzgerald 
881e4961125SRichard Fitzgerald MODULE_DESCRIPTION("ASoC CS35L56 Shared");
882e4961125SRichard Fitzgerald MODULE_AUTHOR("Richard Fitzgerald <rf@opensource.cirrus.com>");
883e4961125SRichard Fitzgerald MODULE_AUTHOR("Simon Trimmer <simont@opensource.cirrus.com>");
884e4961125SRichard Fitzgerald MODULE_LICENSE("GPL");
885