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