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