xref: /openbmc/linux/sound/soc/codecs/cs35l56-shared.c (revision 65d4d7259bfec376b6b1483b4fe4058a5ba2259b)
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/regmap.h>
9 #include <linux/regulator/consumer.h>
10 #include <linux/types.h>
11 
12 #include "cs35l56.h"
13 
14 static const struct reg_default cs35l56_reg_defaults[] = {
15 	{ CS35L56_ASP1_ENABLES1,		0x00000000 },
16 	{ CS35L56_ASP1_CONTROL1,		0x00000028 },
17 	{ CS35L56_ASP1_CONTROL2,		0x18180200 },
18 	{ CS35L56_ASP1_CONTROL3,		0x00000002 },
19 	{ CS35L56_ASP1_FRAME_CONTROL1,		0x03020100 },
20 	{ CS35L56_ASP1_FRAME_CONTROL5,		0x00020100 },
21 	{ CS35L56_ASP1_DATA_CONTROL1,		0x00000018 },
22 	{ CS35L56_ASP1_DATA_CONTROL5,		0x00000018 },
23 	{ CS35L56_ASP1TX1_INPUT,		0x00000018 },
24 	{ CS35L56_ASP1TX2_INPUT,		0x00000019 },
25 	{ CS35L56_ASP1TX3_INPUT,		0x00000020 },
26 	{ CS35L56_ASP1TX4_INPUT,		0x00000028 },
27 	{ CS35L56_SWIRE_DP3_CH1_INPUT,		0x00000018 },
28 	{ CS35L56_SWIRE_DP3_CH2_INPUT,		0x00000019 },
29 	{ CS35L56_SWIRE_DP3_CH3_INPUT,		0x00000029 },
30 	{ CS35L56_SWIRE_DP3_CH4_INPUT,		0x00000028 },
31 	{ CS35L56_SWIRE_DP3_CH5_INPUT,		0x00000018 },
32 	{ CS35L56_SWIRE_DP3_CH6_INPUT,		0x00000018 },
33 	{ CS35L56_IRQ1_CFG,			0x00000000 },
34 	{ CS35L56_IRQ1_MASK_1,			0x83ffffff },
35 	{ CS35L56_IRQ1_MASK_2,			0xffff7fff },
36 	{ CS35L56_IRQ1_MASK_4,			0xe0ffffff },
37 	{ CS35L56_IRQ1_MASK_8,			0xfc000fff },
38 	{ CS35L56_IRQ1_MASK_18,			0x1f7df0ff },
39 	{ CS35L56_IRQ1_MASK_20,			0x15c00000 },
40 	/* CS35L56_MAIN_RENDER_USER_MUTE - soft register, no default	*/
41 	/* CS35L56_MAIN_RENDER_USER_VOLUME - soft register, no default	*/
42 	/* CS35L56_MAIN_POSTURE_NUMBER - soft register, no default	*/
43 };
44 
45 /*
46  * The Ax devices have different default register values to that of B0,
47  * establish a common set of register defaults.
48  */
49 static const struct reg_sequence cs35l56_reva_patch[] = {
50 	{ CS35L56_SWIRE_DP3_CH5_INPUT,	0x00000018 },
51 	{ CS35L56_SWIRE_DP3_CH6_INPUT,	0x00000018 },
52 };
53 
54 void cs35l56_patch(struct device *dev, struct regmap *regmap, u8 revid)
55 {
56 	int ret;
57 
58 	if (revid >= CS35L56_REVID_B0)
59 		return;
60 
61 	ret = regmap_register_patch(regmap, cs35l56_reva_patch,
62 				    ARRAY_SIZE(cs35l56_reva_patch));
63 	if (ret)
64 		dev_err(dev, "Failed to apply patch: %d\n", ret);
65 }
66 EXPORT_SYMBOL_NS_GPL(cs35l56_patch, SND_SOC_CS35L56_SHARED);
67 
68 static bool cs35l56_is_dsp_memory(unsigned int reg)
69 {
70 	switch (reg) {
71 	case CS35L56_DSP1_XMEM_PACKED_0 ... CS35L56_DSP1_XMEM_PACKED_6143:
72 	case CS35L56_DSP1_XMEM_UNPACKED32_0 ... CS35L56_DSP1_XMEM_UNPACKED32_4095:
73 	case CS35L56_DSP1_XMEM_UNPACKED24_0 ... CS35L56_DSP1_XMEM_UNPACKED24_8191:
74 	case CS35L56_DSP1_YMEM_PACKED_0 ... CS35L56_DSP1_YMEM_PACKED_4604:
75 	case CS35L56_DSP1_YMEM_UNPACKED32_0 ... CS35L56_DSP1_YMEM_UNPACKED32_3070:
76 	case CS35L56_DSP1_YMEM_UNPACKED24_0 ... CS35L56_DSP1_YMEM_UNPACKED24_6141:
77 	case CS35L56_DSP1_PMEM_0 ... CS35L56_DSP1_PMEM_5114:
78 		return true;
79 	default:
80 		return false;
81 	}
82 }
83 
84 static bool cs35l56_readable_reg(struct device *dev, unsigned int reg)
85 {
86 	switch (reg) {
87 	case CS35L56_DEVID:
88 	case CS35L56_REVID:
89 	case CS35L56_RELID:
90 	case CS35L56_OTPID:
91 	case CS35L56_SFT_RESET:
92 	case CS35L56_GLOBAL_ENABLES:
93 	case CS35L56_BLOCK_ENABLES:
94 	case CS35L56_BLOCK_ENABLES2:
95 	case CS35L56_REFCLK_INPUT:
96 	case CS35L56_GLOBAL_SAMPLE_RATE:
97 	case CS35L56_ASP1_ENABLES1:
98 	case CS35L56_ASP1_CONTROL1:
99 	case CS35L56_ASP1_CONTROL2:
100 	case CS35L56_ASP1_CONTROL3:
101 	case CS35L56_ASP1_FRAME_CONTROL1:
102 	case CS35L56_ASP1_FRAME_CONTROL5:
103 	case CS35L56_ASP1_DATA_CONTROL1:
104 	case CS35L56_ASP1_DATA_CONTROL5:
105 	case CS35L56_DACPCM1_INPUT:
106 	case CS35L56_DACPCM2_INPUT:
107 	case CS35L56_ASP1TX1_INPUT:
108 	case CS35L56_ASP1TX2_INPUT:
109 	case CS35L56_ASP1TX3_INPUT:
110 	case CS35L56_ASP1TX4_INPUT:
111 	case CS35L56_DSP1RX1_INPUT:
112 	case CS35L56_DSP1RX2_INPUT:
113 	case CS35L56_SWIRE_DP3_CH1_INPUT:
114 	case CS35L56_SWIRE_DP3_CH2_INPUT:
115 	case CS35L56_SWIRE_DP3_CH3_INPUT:
116 	case CS35L56_SWIRE_DP3_CH4_INPUT:
117 	case CS35L56_SWIRE_DP3_CH5_INPUT:
118 	case CS35L56_SWIRE_DP3_CH6_INPUT:
119 	case CS35L56_IRQ1_CFG:
120 	case CS35L56_IRQ1_STATUS:
121 	case CS35L56_IRQ1_EINT_1 ... CS35L56_IRQ1_EINT_8:
122 	case CS35L56_IRQ1_EINT_18:
123 	case CS35L56_IRQ1_EINT_20:
124 	case CS35L56_IRQ1_MASK_1:
125 	case CS35L56_IRQ1_MASK_2:
126 	case CS35L56_IRQ1_MASK_4:
127 	case CS35L56_IRQ1_MASK_8:
128 	case CS35L56_IRQ1_MASK_18:
129 	case CS35L56_IRQ1_MASK_20:
130 	case CS35L56_DSP_VIRTUAL1_MBOX_1:
131 	case CS35L56_DSP_VIRTUAL1_MBOX_2:
132 	case CS35L56_DSP_VIRTUAL1_MBOX_3:
133 	case CS35L56_DSP_VIRTUAL1_MBOX_4:
134 	case CS35L56_DSP_VIRTUAL1_MBOX_5:
135 	case CS35L56_DSP_VIRTUAL1_MBOX_6:
136 	case CS35L56_DSP_VIRTUAL1_MBOX_7:
137 	case CS35L56_DSP_VIRTUAL1_MBOX_8:
138 	case CS35L56_DSP_RESTRICT_STS1:
139 	case CS35L56_DSP1_SYS_INFO_ID ... CS35L56_DSP1_SYS_INFO_END:
140 	case CS35L56_DSP1_AHBM_WINDOW_DEBUG_0:
141 	case CS35L56_DSP1_AHBM_WINDOW_DEBUG_1:
142 	case CS35L56_DSP1_SCRATCH1:
143 	case CS35L56_DSP1_SCRATCH2:
144 	case CS35L56_DSP1_SCRATCH3:
145 	case CS35L56_DSP1_SCRATCH4:
146 		return true;
147 	default:
148 		return cs35l56_is_dsp_memory(reg);
149 	}
150 }
151 
152 static bool cs35l56_precious_reg(struct device *dev, unsigned int reg)
153 {
154 	switch (reg) {
155 	case CS35L56_DSP1_XMEM_PACKED_0 ... CS35L56_DSP1_XMEM_PACKED_6143:
156 	case CS35L56_DSP1_YMEM_PACKED_0 ... CS35L56_DSP1_YMEM_PACKED_4604:
157 	case CS35L56_DSP1_PMEM_0 ... CS35L56_DSP1_PMEM_5114:
158 		return true;
159 	default:
160 		return false;
161 	}
162 }
163 
164 static bool cs35l56_volatile_reg(struct device *dev, unsigned int reg)
165 {
166 	switch (reg) {
167 	case CS35L56_DEVID:
168 	case CS35L56_REVID:
169 	case CS35L56_RELID:
170 	case CS35L56_OTPID:
171 	case CS35L56_SFT_RESET:
172 	case CS35L56_GLOBAL_ENABLES:		   /* owned by firmware */
173 	case CS35L56_BLOCK_ENABLES:		   /* owned by firmware */
174 	case CS35L56_BLOCK_ENABLES2:		   /* owned by firmware */
175 	case CS35L56_REFCLK_INPUT:		   /* owned by firmware */
176 	case CS35L56_GLOBAL_SAMPLE_RATE:	   /* owned by firmware */
177 	case CS35L56_DACPCM1_INPUT:		   /* owned by firmware */
178 	case CS35L56_DACPCM2_INPUT:		   /* owned by firmware */
179 	case CS35L56_DSP1RX1_INPUT:		   /* owned by firmware */
180 	case CS35L56_DSP1RX2_INPUT:		   /* owned by firmware */
181 	case CS35L56_IRQ1_STATUS:
182 	case CS35L56_IRQ1_EINT_1 ... CS35L56_IRQ1_EINT_8:
183 	case CS35L56_IRQ1_EINT_18:
184 	case CS35L56_IRQ1_EINT_20:
185 	case CS35L56_DSP_VIRTUAL1_MBOX_1:
186 	case CS35L56_DSP_VIRTUAL1_MBOX_2:
187 	case CS35L56_DSP_VIRTUAL1_MBOX_3:
188 	case CS35L56_DSP_VIRTUAL1_MBOX_4:
189 	case CS35L56_DSP_VIRTUAL1_MBOX_5:
190 	case CS35L56_DSP_VIRTUAL1_MBOX_6:
191 	case CS35L56_DSP_VIRTUAL1_MBOX_7:
192 	case CS35L56_DSP_VIRTUAL1_MBOX_8:
193 	case CS35L56_DSP_RESTRICT_STS1:
194 	case CS35L56_DSP1_SYS_INFO_ID ... CS35L56_DSP1_SYS_INFO_END:
195 	case CS35L56_DSP1_AHBM_WINDOW_DEBUG_0:
196 	case CS35L56_DSP1_AHBM_WINDOW_DEBUG_1:
197 	case CS35L56_DSP1_SCRATCH1:
198 	case CS35L56_DSP1_SCRATCH2:
199 	case CS35L56_DSP1_SCRATCH3:
200 	case CS35L56_DSP1_SCRATCH4:
201 		return true;
202 	case CS35L56_MAIN_RENDER_USER_MUTE:
203 	case CS35L56_MAIN_RENDER_USER_VOLUME:
204 	case CS35L56_MAIN_POSTURE_NUMBER:
205 		return false;
206 	default:
207 		return cs35l56_is_dsp_memory(reg);
208 	}
209 }
210 
211 static const u32 cs35l56_firmware_registers[] = {
212 	CS35L56_MAIN_RENDER_USER_MUTE,
213 	CS35L56_MAIN_RENDER_USER_VOLUME,
214 	CS35L56_MAIN_POSTURE_NUMBER,
215 };
216 
217 void cs35l56_reread_firmware_registers(struct device *dev, struct regmap *regmap)
218 {
219 	int i;
220 	unsigned int val;
221 
222 	for (i = 0; i < ARRAY_SIZE(cs35l56_firmware_registers); i++) {
223 		regmap_read(regmap, cs35l56_firmware_registers[i], &val);
224 		dev_dbg(dev, "%s: %d: %#x: %#x\n", __func__,
225 			i, cs35l56_firmware_registers[i], val);
226 	}
227 }
228 EXPORT_SYMBOL_NS_GPL(cs35l56_reread_firmware_registers, SND_SOC_CS35L56_SHARED);
229 
230 const struct cs_dsp_region cs35l56_dsp1_regions[] = {
231 	{ .type = WMFW_HALO_PM_PACKED,	.base = CS35L56_DSP1_PMEM_0 },
232 	{ .type = WMFW_HALO_XM_PACKED,	.base = CS35L56_DSP1_XMEM_PACKED_0 },
233 	{ .type = WMFW_HALO_YM_PACKED,	.base = CS35L56_DSP1_YMEM_PACKED_0 },
234 	{ .type = WMFW_ADSP2_XM,	.base = CS35L56_DSP1_XMEM_UNPACKED24_0 },
235 	{ .type = WMFW_ADSP2_YM,	.base = CS35L56_DSP1_YMEM_UNPACKED24_0 },
236 };
237 EXPORT_SYMBOL_NS_GPL(cs35l56_dsp1_regions, SND_SOC_CS35L56_SHARED);
238 
239 static const u32 cs35l56_bclk_valid_for_pll_freq_table[] = {
240 	[0x0C] = 128000,
241 	[0x0F] = 256000,
242 	[0x11] = 384000,
243 	[0x12] = 512000,
244 	[0x15] = 768000,
245 	[0x17] = 1024000,
246 	[0x1A] = 1500000,
247 	[0x1B] = 1536000,
248 	[0x1C] = 2000000,
249 	[0x1D] = 2048000,
250 	[0x1E] = 2400000,
251 	[0x20] = 3000000,
252 	[0x21] = 3072000,
253 	[0x23] = 4000000,
254 	[0x24] = 4096000,
255 	[0x25] = 4800000,
256 	[0x27] = 6000000,
257 	[0x28] = 6144000,
258 	[0x29] = 6250000,
259 	[0x2A] = 6400000,
260 	[0x2E] = 8000000,
261 	[0x2F] = 8192000,
262 	[0x30] = 9600000,
263 	[0x32] = 12000000,
264 	[0x33] = 12288000,
265 	[0x37] = 13500000,
266 	[0x38] = 19200000,
267 	[0x39] = 22579200,
268 	[0x3B] = 24576000,
269 };
270 
271 int cs35l56_get_bclk_freq_id(unsigned int freq)
272 {
273 	int i;
274 
275 	if (freq == 0)
276 		return -EINVAL;
277 
278 	/* The BCLK frequency must be a valid PLL REFCLK */
279 	for (i = 0; i < ARRAY_SIZE(cs35l56_bclk_valid_for_pll_freq_table); ++i) {
280 		if (cs35l56_bclk_valid_for_pll_freq_table[i] == freq)
281 			return i;
282 	}
283 
284 	return -EINVAL;
285 }
286 EXPORT_SYMBOL_NS_GPL(cs35l56_get_bclk_freq_id, SND_SOC_CS35L56_SHARED);
287 
288 static const char * const cs35l56_supplies[/* auto-sized */] = {
289 	"VDD_P",
290 	"VDD_IO",
291 	"VDD_A",
292 };
293 
294 void cs35l56_fill_supply_names(struct regulator_bulk_data *data)
295 {
296 	int i;
297 
298 	BUILD_BUG_ON(ARRAY_SIZE(cs35l56_supplies) != CS35L56_NUM_BULK_SUPPLIES);
299 	for (i = 0; i < ARRAY_SIZE(cs35l56_supplies); i++)
300 		data[i].supply = cs35l56_supplies[i];
301 }
302 EXPORT_SYMBOL_NS_GPL(cs35l56_fill_supply_names, SND_SOC_CS35L56_SHARED);
303 
304 const char * const cs35l56_tx_input_texts[] = {
305 	"None", "ASP1RX1", "ASP1RX2", "VMON", "IMON", "ERRVOL", "CLASSH",
306 	"VDDBMON", "VBSTMON", "DSP1TX1", "DSP1TX2", "DSP1TX3", "DSP1TX4",
307 	"DSP1TX5", "DSP1TX6", "DSP1TX7", "DSP1TX8", "TEMPMON",
308 	"INTERPOLATOR", "SDW1RX1", "SDW1RX2", "SDW2RX1",
309 };
310 EXPORT_SYMBOL_NS_GPL(cs35l56_tx_input_texts, SND_SOC_CS35L56_SHARED);
311 
312 const unsigned int cs35l56_tx_input_values[] = {
313 	CS35L56_INPUT_SRC_NONE,
314 	CS35L56_INPUT_SRC_ASP1RX1,
315 	CS35L56_INPUT_SRC_ASP1RX2,
316 	CS35L56_INPUT_SRC_VMON,
317 	CS35L56_INPUT_SRC_IMON,
318 	CS35L56_INPUT_SRC_ERR_VOL,
319 	CS35L56_INPUT_SRC_CLASSH,
320 	CS35L56_INPUT_SRC_VDDBMON,
321 	CS35L56_INPUT_SRC_VBSTMON,
322 	CS35L56_INPUT_SRC_DSP1TX1,
323 	CS35L56_INPUT_SRC_DSP1TX2,
324 	CS35L56_INPUT_SRC_DSP1TX3,
325 	CS35L56_INPUT_SRC_DSP1TX4,
326 	CS35L56_INPUT_SRC_DSP1TX5,
327 	CS35L56_INPUT_SRC_DSP1TX6,
328 	CS35L56_INPUT_SRC_DSP1TX7,
329 	CS35L56_INPUT_SRC_DSP1TX8,
330 	CS35L56_INPUT_SRC_TEMPMON,
331 	CS35L56_INPUT_SRC_INTERPOLATOR,
332 	CS35L56_INPUT_SRC_SWIRE_RX1,
333 	CS35L56_INPUT_SRC_SWIRE_RX2,
334 	CS35L56_INPUT_SRC_SWIRE_RX3,
335 };
336 EXPORT_SYMBOL_NS_GPL(cs35l56_tx_input_values, SND_SOC_CS35L56_SHARED);
337 
338 struct regmap_config cs35l56_regmap_i2c = {
339 	.reg_bits = 32,
340 	.val_bits = 32,
341 	.reg_stride = 4,
342 	.reg_format_endian = REGMAP_ENDIAN_BIG,
343 	.val_format_endian = REGMAP_ENDIAN_BIG,
344 	.max_register = CS35L56_DSP1_PMEM_5114,
345 	.reg_defaults = cs35l56_reg_defaults,
346 	.num_reg_defaults = ARRAY_SIZE(cs35l56_reg_defaults),
347 	.volatile_reg = cs35l56_volatile_reg,
348 	.readable_reg = cs35l56_readable_reg,
349 	.precious_reg = cs35l56_precious_reg,
350 	.cache_type = REGCACHE_RBTREE,
351 };
352 EXPORT_SYMBOL_NS_GPL(cs35l56_regmap_i2c, SND_SOC_CS35L56_SHARED);
353 
354 struct regmap_config cs35l56_regmap_spi = {
355 	.reg_bits = 32,
356 	.val_bits = 32,
357 	.pad_bits = 16,
358 	.reg_stride = 4,
359 	.reg_format_endian = REGMAP_ENDIAN_BIG,
360 	.val_format_endian = REGMAP_ENDIAN_BIG,
361 	.max_register = CS35L56_DSP1_PMEM_5114,
362 	.reg_defaults = cs35l56_reg_defaults,
363 	.num_reg_defaults = ARRAY_SIZE(cs35l56_reg_defaults),
364 	.volatile_reg = cs35l56_volatile_reg,
365 	.readable_reg = cs35l56_readable_reg,
366 	.precious_reg = cs35l56_precious_reg,
367 	.cache_type = REGCACHE_RBTREE,
368 };
369 EXPORT_SYMBOL_NS_GPL(cs35l56_regmap_spi, SND_SOC_CS35L56_SHARED);
370 
371 struct regmap_config cs35l56_regmap_sdw = {
372 	.reg_bits = 32,
373 	.val_bits = 32,
374 	.reg_stride = 4,
375 	.reg_format_endian = REGMAP_ENDIAN_LITTLE,
376 	.val_format_endian = REGMAP_ENDIAN_BIG,
377 	.max_register = CS35L56_DSP1_PMEM_5114,
378 	.reg_defaults = cs35l56_reg_defaults,
379 	.num_reg_defaults = ARRAY_SIZE(cs35l56_reg_defaults),
380 	.volatile_reg = cs35l56_volatile_reg,
381 	.readable_reg = cs35l56_readable_reg,
382 	.precious_reg = cs35l56_precious_reg,
383 	.cache_type = REGCACHE_RBTREE,
384 };
385 EXPORT_SYMBOL_NS_GPL(cs35l56_regmap_sdw, SND_SOC_CS35L56_SHARED);
386 
387 MODULE_DESCRIPTION("ASoC CS35L56 Shared");
388 MODULE_AUTHOR("Richard Fitzgerald <rf@opensource.cirrus.com>");
389 MODULE_AUTHOR("Simon Trimmer <simont@opensource.cirrus.com>");
390 MODULE_LICENSE("GPL");
391