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