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