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