0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #include <linux/dev_printk.h>
0011 #include <linux/module.h>
0012 #include <linux/regmap.h>
0013 #include <linux/regulator/consumer.h>
0014 #include <linux/slab.h>
0015 #include <linux/firmware/cirrus/wmfw.h>
0016
0017 #include <sound/cs35l41.h>
0018
0019 static const struct reg_default cs35l41_reg[] = {
0020 { CS35L41_PWR_CTRL1, 0x00000000 },
0021 { CS35L41_PWR_CTRL2, 0x00000000 },
0022 { CS35L41_PWR_CTRL3, 0x01000010 },
0023 { CS35L41_GPIO_PAD_CONTROL, 0x00000000 },
0024 { CS35L41_GLOBAL_CLK_CTRL, 0x00000003 },
0025 { CS35L41_TST_FS_MON0, 0x00020016 },
0026 { CS35L41_BSTCVRT_COEFF, 0x00002424 },
0027 { CS35L41_BSTCVRT_SLOPE_LBST, 0x00007500 },
0028 { CS35L41_BSTCVRT_PEAK_CUR, 0x0000004A },
0029 { CS35L41_SP_ENABLES, 0x00000000 },
0030 { CS35L41_SP_RATE_CTRL, 0x00000028 },
0031 { CS35L41_SP_FORMAT, 0x18180200 },
0032 { CS35L41_SP_HIZ_CTRL, 0x00000002 },
0033 { CS35L41_SP_FRAME_TX_SLOT, 0x03020100 },
0034 { CS35L41_SP_FRAME_RX_SLOT, 0x00000100 },
0035 { CS35L41_SP_TX_WL, 0x00000018 },
0036 { CS35L41_SP_RX_WL, 0x00000018 },
0037 { CS35L41_DAC_PCM1_SRC, 0x00000008 },
0038 { CS35L41_ASP_TX1_SRC, 0x00000018 },
0039 { CS35L41_ASP_TX2_SRC, 0x00000019 },
0040 { CS35L41_ASP_TX3_SRC, 0x00000000 },
0041 { CS35L41_ASP_TX4_SRC, 0x00000000 },
0042 { CS35L41_DSP1_RX1_SRC, 0x00000008 },
0043 { CS35L41_DSP1_RX2_SRC, 0x00000009 },
0044 { CS35L41_DSP1_RX3_SRC, 0x00000018 },
0045 { CS35L41_DSP1_RX4_SRC, 0x00000019 },
0046 { CS35L41_DSP1_RX5_SRC, 0x00000020 },
0047 { CS35L41_DSP1_RX6_SRC, 0x00000021 },
0048 { CS35L41_DSP1_RX7_SRC, 0x0000003A },
0049 { CS35L41_DSP1_RX8_SRC, 0x00000001 },
0050 { CS35L41_NGATE1_SRC, 0x00000008 },
0051 { CS35L41_NGATE2_SRC, 0x00000009 },
0052 { CS35L41_AMP_DIG_VOL_CTRL, 0x00008000 },
0053 { CS35L41_CLASSH_CFG, 0x000B0405 },
0054 { CS35L41_WKFET_CFG, 0x00000111 },
0055 { CS35L41_NG_CFG, 0x00000033 },
0056 { CS35L41_AMP_GAIN_CTRL, 0x00000000 },
0057 { CS35L41_IRQ1_MASK1, 0xFFFFFFFF },
0058 { CS35L41_IRQ1_MASK2, 0xFFFFFFFF },
0059 { CS35L41_IRQ1_MASK3, 0xFFFF87FF },
0060 { CS35L41_IRQ1_MASK4, 0xFEFFFFFF },
0061 { CS35L41_GPIO1_CTRL1, 0xE1000001 },
0062 { CS35L41_GPIO2_CTRL1, 0xE1000001 },
0063 { CS35L41_MIXER_NGATE_CFG, 0x00000000 },
0064 { CS35L41_MIXER_NGATE_CH1_CFG, 0x00000303 },
0065 { CS35L41_MIXER_NGATE_CH2_CFG, 0x00000303 },
0066 { CS35L41_DSP1_CCM_CORE_CTRL, 0x00000101 },
0067 };
0068
0069 static bool cs35l41_readable_reg(struct device *dev, unsigned int reg)
0070 {
0071 switch (reg) {
0072 case CS35L41_DEVID:
0073 case CS35L41_REVID:
0074 case CS35L41_FABID:
0075 case CS35L41_RELID:
0076 case CS35L41_OTPID:
0077 case CS35L41_TEST_KEY_CTL:
0078 case CS35L41_USER_KEY_CTL:
0079 case CS35L41_OTP_CTRL0:
0080 case CS35L41_OTP_CTRL3:
0081 case CS35L41_OTP_CTRL4:
0082 case CS35L41_OTP_CTRL5:
0083 case CS35L41_OTP_CTRL6:
0084 case CS35L41_OTP_CTRL7:
0085 case CS35L41_OTP_CTRL8:
0086 case CS35L41_PWR_CTRL1:
0087 case CS35L41_PWR_CTRL2:
0088 case CS35L41_PWR_CTRL3:
0089 case CS35L41_CTRL_OVRRIDE:
0090 case CS35L41_AMP_OUT_MUTE:
0091 case CS35L41_PROTECT_REL_ERR_IGN:
0092 case CS35L41_GPIO_PAD_CONTROL:
0093 case CS35L41_JTAG_CONTROL:
0094 case CS35L41_PWRMGT_CTL:
0095 case CS35L41_WAKESRC_CTL:
0096 case CS35L41_PWRMGT_STS:
0097 case CS35L41_PLL_CLK_CTRL:
0098 case CS35L41_DSP_CLK_CTRL:
0099 case CS35L41_GLOBAL_CLK_CTRL:
0100 case CS35L41_DATA_FS_SEL:
0101 case CS35L41_TST_FS_MON0:
0102 case CS35L41_MDSYNC_EN:
0103 case CS35L41_MDSYNC_TX_ID:
0104 case CS35L41_MDSYNC_PWR_CTRL:
0105 case CS35L41_MDSYNC_DATA_TX:
0106 case CS35L41_MDSYNC_TX_STATUS:
0107 case CS35L41_MDSYNC_DATA_RX:
0108 case CS35L41_MDSYNC_RX_STATUS:
0109 case CS35L41_MDSYNC_ERR_STATUS:
0110 case CS35L41_MDSYNC_SYNC_PTE2:
0111 case CS35L41_MDSYNC_SYNC_PTE3:
0112 case CS35L41_MDSYNC_SYNC_MSM_STATUS:
0113 case CS35L41_BSTCVRT_VCTRL1:
0114 case CS35L41_BSTCVRT_VCTRL2:
0115 case CS35L41_BSTCVRT_PEAK_CUR:
0116 case CS35L41_BSTCVRT_SFT_RAMP:
0117 case CS35L41_BSTCVRT_COEFF:
0118 case CS35L41_BSTCVRT_SLOPE_LBST:
0119 case CS35L41_BSTCVRT_SW_FREQ:
0120 case CS35L41_BSTCVRT_DCM_CTRL:
0121 case CS35L41_BSTCVRT_DCM_MODE_FORCE:
0122 case CS35L41_BSTCVRT_OVERVOLT_CTRL:
0123 case CS35L41_VI_VOL_POL:
0124 case CS35L41_DTEMP_WARN_THLD:
0125 case CS35L41_DTEMP_CFG:
0126 case CS35L41_DTEMP_EN:
0127 case CS35L41_VPVBST_FS_SEL:
0128 case CS35L41_SP_ENABLES:
0129 case CS35L41_SP_RATE_CTRL:
0130 case CS35L41_SP_FORMAT:
0131 case CS35L41_SP_HIZ_CTRL:
0132 case CS35L41_SP_FRAME_TX_SLOT:
0133 case CS35L41_SP_FRAME_RX_SLOT:
0134 case CS35L41_SP_TX_WL:
0135 case CS35L41_SP_RX_WL:
0136 case CS35L41_DAC_PCM1_SRC:
0137 case CS35L41_ASP_TX1_SRC:
0138 case CS35L41_ASP_TX2_SRC:
0139 case CS35L41_ASP_TX3_SRC:
0140 case CS35L41_ASP_TX4_SRC:
0141 case CS35L41_DSP1_RX1_SRC:
0142 case CS35L41_DSP1_RX2_SRC:
0143 case CS35L41_DSP1_RX3_SRC:
0144 case CS35L41_DSP1_RX4_SRC:
0145 case CS35L41_DSP1_RX5_SRC:
0146 case CS35L41_DSP1_RX6_SRC:
0147 case CS35L41_DSP1_RX7_SRC:
0148 case CS35L41_DSP1_RX8_SRC:
0149 case CS35L41_NGATE1_SRC:
0150 case CS35L41_NGATE2_SRC:
0151 case CS35L41_AMP_DIG_VOL_CTRL:
0152 case CS35L41_VPBR_CFG:
0153 case CS35L41_VBBR_CFG:
0154 case CS35L41_VPBR_STATUS:
0155 case CS35L41_VBBR_STATUS:
0156 case CS35L41_OVERTEMP_CFG:
0157 case CS35L41_AMP_ERR_VOL:
0158 case CS35L41_VOL_STATUS_TO_DSP:
0159 case CS35L41_CLASSH_CFG:
0160 case CS35L41_WKFET_CFG:
0161 case CS35L41_NG_CFG:
0162 case CS35L41_AMP_GAIN_CTRL:
0163 case CS35L41_DAC_MSM_CFG:
0164 case CS35L41_IRQ1_CFG:
0165 case CS35L41_IRQ1_STATUS:
0166 case CS35L41_IRQ1_STATUS1:
0167 case CS35L41_IRQ1_STATUS2:
0168 case CS35L41_IRQ1_STATUS3:
0169 case CS35L41_IRQ1_STATUS4:
0170 case CS35L41_IRQ1_RAW_STATUS1:
0171 case CS35L41_IRQ1_RAW_STATUS2:
0172 case CS35L41_IRQ1_RAW_STATUS3:
0173 case CS35L41_IRQ1_RAW_STATUS4:
0174 case CS35L41_IRQ1_MASK1:
0175 case CS35L41_IRQ1_MASK2:
0176 case CS35L41_IRQ1_MASK3:
0177 case CS35L41_IRQ1_MASK4:
0178 case CS35L41_IRQ1_FRC1:
0179 case CS35L41_IRQ1_FRC2:
0180 case CS35L41_IRQ1_FRC3:
0181 case CS35L41_IRQ1_FRC4:
0182 case CS35L41_IRQ1_EDGE1:
0183 case CS35L41_IRQ1_EDGE4:
0184 case CS35L41_IRQ1_POL1:
0185 case CS35L41_IRQ1_POL2:
0186 case CS35L41_IRQ1_POL3:
0187 case CS35L41_IRQ1_POL4:
0188 case CS35L41_IRQ1_DB3:
0189 case CS35L41_IRQ2_CFG:
0190 case CS35L41_IRQ2_STATUS:
0191 case CS35L41_IRQ2_STATUS1:
0192 case CS35L41_IRQ2_STATUS2:
0193 case CS35L41_IRQ2_STATUS3:
0194 case CS35L41_IRQ2_STATUS4:
0195 case CS35L41_IRQ2_RAW_STATUS1:
0196 case CS35L41_IRQ2_RAW_STATUS2:
0197 case CS35L41_IRQ2_RAW_STATUS3:
0198 case CS35L41_IRQ2_RAW_STATUS4:
0199 case CS35L41_IRQ2_MASK1:
0200 case CS35L41_IRQ2_MASK2:
0201 case CS35L41_IRQ2_MASK3:
0202 case CS35L41_IRQ2_MASK4:
0203 case CS35L41_IRQ2_FRC1:
0204 case CS35L41_IRQ2_FRC2:
0205 case CS35L41_IRQ2_FRC3:
0206 case CS35L41_IRQ2_FRC4:
0207 case CS35L41_IRQ2_EDGE1:
0208 case CS35L41_IRQ2_EDGE4:
0209 case CS35L41_IRQ2_POL1:
0210 case CS35L41_IRQ2_POL2:
0211 case CS35L41_IRQ2_POL3:
0212 case CS35L41_IRQ2_POL4:
0213 case CS35L41_IRQ2_DB3:
0214 case CS35L41_GPIO_STATUS1:
0215 case CS35L41_GPIO1_CTRL1:
0216 case CS35L41_GPIO2_CTRL1:
0217 case CS35L41_MIXER_NGATE_CFG:
0218 case CS35L41_MIXER_NGATE_CH1_CFG:
0219 case CS35L41_MIXER_NGATE_CH2_CFG:
0220 case CS35L41_DSP_MBOX_1 ... CS35L41_DSP_VIRT2_MBOX_8:
0221 case CS35L41_CLOCK_DETECT_1:
0222 case CS35L41_DIE_STS1:
0223 case CS35L41_DIE_STS2:
0224 case CS35L41_TEMP_CAL1:
0225 case CS35L41_TEMP_CAL2:
0226 case CS35L41_DSP1_TIMESTAMP_COUNT:
0227 case CS35L41_DSP1_SYS_ID:
0228 case CS35L41_DSP1_SYS_VERSION:
0229 case CS35L41_DSP1_SYS_CORE_ID:
0230 case CS35L41_DSP1_SYS_AHB_ADDR:
0231 case CS35L41_DSP1_SYS_XSRAM_SIZE:
0232 case CS35L41_DSP1_SYS_YSRAM_SIZE:
0233 case CS35L41_DSP1_SYS_PSRAM_SIZE:
0234 case CS35L41_DSP1_SYS_PM_BOOT_SIZE:
0235 case CS35L41_DSP1_SYS_FEATURES:
0236 case CS35L41_DSP1_SYS_FIR_FILTERS:
0237 case CS35L41_DSP1_SYS_LMS_FILTERS:
0238 case CS35L41_DSP1_SYS_XM_BANK_SIZE:
0239 case CS35L41_DSP1_SYS_YM_BANK_SIZE:
0240 case CS35L41_DSP1_SYS_PM_BANK_SIZE:
0241 case CS35L41_DSP1_RX1_RATE:
0242 case CS35L41_DSP1_RX2_RATE:
0243 case CS35L41_DSP1_RX3_RATE:
0244 case CS35L41_DSP1_RX4_RATE:
0245 case CS35L41_DSP1_RX5_RATE:
0246 case CS35L41_DSP1_RX6_RATE:
0247 case CS35L41_DSP1_RX7_RATE:
0248 case CS35L41_DSP1_RX8_RATE:
0249 case CS35L41_DSP1_TX1_RATE:
0250 case CS35L41_DSP1_TX2_RATE:
0251 case CS35L41_DSP1_TX3_RATE:
0252 case CS35L41_DSP1_TX4_RATE:
0253 case CS35L41_DSP1_TX5_RATE:
0254 case CS35L41_DSP1_TX6_RATE:
0255 case CS35L41_DSP1_TX7_RATE:
0256 case CS35L41_DSP1_TX8_RATE:
0257 case CS35L41_DSP1_SCRATCH1:
0258 case CS35L41_DSP1_SCRATCH2:
0259 case CS35L41_DSP1_SCRATCH3:
0260 case CS35L41_DSP1_SCRATCH4:
0261 case CS35L41_DSP1_CCM_CORE_CTRL:
0262 case CS35L41_DSP1_CCM_CLK_OVERRIDE:
0263 case CS35L41_DSP1_XM_MSTR_EN:
0264 case CS35L41_DSP1_XM_CORE_PRI:
0265 case CS35L41_DSP1_XM_AHB_PACK_PL_PRI:
0266 case CS35L41_DSP1_XM_AHB_UP_PL_PRI:
0267 case CS35L41_DSP1_XM_ACCEL_PL0_PRI:
0268 case CS35L41_DSP1_XM_NPL0_PRI:
0269 case CS35L41_DSP1_YM_MSTR_EN:
0270 case CS35L41_DSP1_YM_CORE_PRI:
0271 case CS35L41_DSP1_YM_AHB_PACK_PL_PRI:
0272 case CS35L41_DSP1_YM_AHB_UP_PL_PRI:
0273 case CS35L41_DSP1_YM_ACCEL_PL0_PRI:
0274 case CS35L41_DSP1_YM_NPL0_PRI:
0275 case CS35L41_DSP1_MPU_XM_ACCESS0:
0276 case CS35L41_DSP1_MPU_YM_ACCESS0:
0277 case CS35L41_DSP1_MPU_WNDW_ACCESS0:
0278 case CS35L41_DSP1_MPU_XREG_ACCESS0:
0279 case CS35L41_DSP1_MPU_YREG_ACCESS0:
0280 case CS35L41_DSP1_MPU_XM_ACCESS1:
0281 case CS35L41_DSP1_MPU_YM_ACCESS1:
0282 case CS35L41_DSP1_MPU_WNDW_ACCESS1:
0283 case CS35L41_DSP1_MPU_XREG_ACCESS1:
0284 case CS35L41_DSP1_MPU_YREG_ACCESS1:
0285 case CS35L41_DSP1_MPU_XM_ACCESS2:
0286 case CS35L41_DSP1_MPU_YM_ACCESS2:
0287 case CS35L41_DSP1_MPU_WNDW_ACCESS2:
0288 case CS35L41_DSP1_MPU_XREG_ACCESS2:
0289 case CS35L41_DSP1_MPU_YREG_ACCESS2:
0290 case CS35L41_DSP1_MPU_XM_ACCESS3:
0291 case CS35L41_DSP1_MPU_YM_ACCESS3:
0292 case CS35L41_DSP1_MPU_WNDW_ACCESS3:
0293 case CS35L41_DSP1_MPU_XREG_ACCESS3:
0294 case CS35L41_DSP1_MPU_YREG_ACCESS3:
0295 case CS35L41_DSP1_MPU_XM_VIO_ADDR:
0296 case CS35L41_DSP1_MPU_XM_VIO_STATUS:
0297 case CS35L41_DSP1_MPU_YM_VIO_ADDR:
0298 case CS35L41_DSP1_MPU_YM_VIO_STATUS:
0299 case CS35L41_DSP1_MPU_PM_VIO_ADDR:
0300 case CS35L41_DSP1_MPU_PM_VIO_STATUS:
0301 case CS35L41_DSP1_MPU_LOCK_CONFIG:
0302 case CS35L41_DSP1_MPU_WDT_RST_CTRL:
0303 case CS35L41_OTP_TRIM_1:
0304 case CS35L41_OTP_TRIM_2:
0305 case CS35L41_OTP_TRIM_3:
0306 case CS35L41_OTP_TRIM_4:
0307 case CS35L41_OTP_TRIM_5:
0308 case CS35L41_OTP_TRIM_6:
0309 case CS35L41_OTP_TRIM_7:
0310 case CS35L41_OTP_TRIM_8:
0311 case CS35L41_OTP_TRIM_9:
0312 case CS35L41_OTP_TRIM_10:
0313 case CS35L41_OTP_TRIM_11:
0314 case CS35L41_OTP_TRIM_12:
0315 case CS35L41_OTP_TRIM_13:
0316 case CS35L41_OTP_TRIM_14:
0317 case CS35L41_OTP_TRIM_15:
0318 case CS35L41_OTP_TRIM_16:
0319 case CS35L41_OTP_TRIM_17:
0320 case CS35L41_OTP_TRIM_18:
0321 case CS35L41_OTP_TRIM_19:
0322 case CS35L41_OTP_TRIM_20:
0323 case CS35L41_OTP_TRIM_21:
0324 case CS35L41_OTP_TRIM_22:
0325 case CS35L41_OTP_TRIM_23:
0326 case CS35L41_OTP_TRIM_24:
0327 case CS35L41_OTP_TRIM_25:
0328 case CS35L41_OTP_TRIM_26:
0329 case CS35L41_OTP_TRIM_27:
0330 case CS35L41_OTP_TRIM_28:
0331 case CS35L41_OTP_TRIM_29:
0332 case CS35L41_OTP_TRIM_30:
0333 case CS35L41_OTP_TRIM_31:
0334 case CS35L41_OTP_TRIM_32:
0335 case CS35L41_OTP_TRIM_33:
0336 case CS35L41_OTP_TRIM_34:
0337 case CS35L41_OTP_TRIM_35:
0338 case CS35L41_OTP_TRIM_36:
0339 case CS35L41_OTP_MEM0 ... CS35L41_OTP_MEM31:
0340 case CS35L41_DSP1_XMEM_PACK_0 ... CS35L41_DSP1_XMEM_PACK_3068:
0341 case CS35L41_DSP1_XMEM_UNPACK32_0 ... CS35L41_DSP1_XMEM_UNPACK32_2046:
0342 case CS35L41_DSP1_XMEM_UNPACK24_0 ... CS35L41_DSP1_XMEM_UNPACK24_4093:
0343 case CS35L41_DSP1_YMEM_PACK_0 ... CS35L41_DSP1_YMEM_PACK_1532:
0344 case CS35L41_DSP1_YMEM_UNPACK32_0 ... CS35L41_DSP1_YMEM_UNPACK32_1022:
0345 case CS35L41_DSP1_YMEM_UNPACK24_0 ... CS35L41_DSP1_YMEM_UNPACK24_2045:
0346 case CS35L41_DSP1_PMEM_0 ... CS35L41_DSP1_PMEM_5114:
0347
0348 case CS35L41_PLL_OVR:
0349 case CS35L41_BST_TEST_DUTY:
0350 case CS35L41_DIGPWM_IOCTRL:
0351 return true;
0352 default:
0353 return false;
0354 }
0355 }
0356
0357 static bool cs35l41_precious_reg(struct device *dev, unsigned int reg)
0358 {
0359 switch (reg) {
0360 case CS35L41_TEST_KEY_CTL:
0361 case CS35L41_USER_KEY_CTL:
0362 case CS35L41_OTP_MEM0 ... CS35L41_OTP_MEM31:
0363 case CS35L41_TST_FS_MON0:
0364 case CS35L41_DSP1_XMEM_PACK_0 ... CS35L41_DSP1_XMEM_PACK_3068:
0365 case CS35L41_DSP1_YMEM_PACK_0 ... CS35L41_DSP1_YMEM_PACK_1532:
0366 case CS35L41_DSP1_PMEM_0 ... CS35L41_DSP1_PMEM_5114:
0367 return true;
0368 default:
0369 return false;
0370 }
0371 }
0372
0373 static bool cs35l41_volatile_reg(struct device *dev, unsigned int reg)
0374 {
0375 switch (reg) {
0376 case CS35L41_DEVID:
0377 case CS35L41_SFT_RESET:
0378 case CS35L41_FABID:
0379 case CS35L41_REVID:
0380 case CS35L41_OTPID:
0381 case CS35L41_TEST_KEY_CTL:
0382 case CS35L41_USER_KEY_CTL:
0383 case CS35L41_PWRMGT_CTL:
0384 case CS35L41_WAKESRC_CTL:
0385 case CS35L41_PWRMGT_STS:
0386 case CS35L41_DTEMP_EN:
0387 case CS35L41_IRQ1_STATUS:
0388 case CS35L41_IRQ1_STATUS1:
0389 case CS35L41_IRQ1_STATUS2:
0390 case CS35L41_IRQ1_STATUS3:
0391 case CS35L41_IRQ1_STATUS4:
0392 case CS35L41_IRQ1_RAW_STATUS1:
0393 case CS35L41_IRQ1_RAW_STATUS2:
0394 case CS35L41_IRQ1_RAW_STATUS3:
0395 case CS35L41_IRQ1_RAW_STATUS4:
0396 case CS35L41_IRQ2_STATUS:
0397 case CS35L41_IRQ2_STATUS1:
0398 case CS35L41_IRQ2_STATUS2:
0399 case CS35L41_IRQ2_STATUS3:
0400 case CS35L41_IRQ2_STATUS4:
0401 case CS35L41_IRQ2_RAW_STATUS1:
0402 case CS35L41_IRQ2_RAW_STATUS2:
0403 case CS35L41_IRQ2_RAW_STATUS3:
0404 case CS35L41_IRQ2_RAW_STATUS4:
0405 case CS35L41_GPIO_STATUS1:
0406 case CS35L41_DSP_MBOX_1 ... CS35L41_DSP_VIRT2_MBOX_8:
0407 case CS35L41_DSP1_XMEM_PACK_0 ... CS35L41_DSP1_XMEM_PACK_3068:
0408 case CS35L41_DSP1_XMEM_UNPACK32_0 ... CS35L41_DSP1_XMEM_UNPACK32_2046:
0409 case CS35L41_DSP1_XMEM_UNPACK24_0 ... CS35L41_DSP1_XMEM_UNPACK24_4093:
0410 case CS35L41_DSP1_YMEM_PACK_0 ... CS35L41_DSP1_YMEM_PACK_1532:
0411 case CS35L41_DSP1_YMEM_UNPACK32_0 ... CS35L41_DSP1_YMEM_UNPACK32_1022:
0412 case CS35L41_DSP1_YMEM_UNPACK24_0 ... CS35L41_DSP1_YMEM_UNPACK24_2045:
0413 case CS35L41_DSP1_PMEM_0 ... CS35L41_DSP1_PMEM_5114:
0414 case CS35L41_DSP1_SCRATCH1:
0415 case CS35L41_DSP1_SCRATCH2:
0416 case CS35L41_DSP1_SCRATCH3:
0417 case CS35L41_DSP1_SCRATCH4:
0418 case CS35L41_DSP1_CCM_CLK_OVERRIDE ... CS35L41_DSP1_WDT_STATUS:
0419 case CS35L41_OTP_MEM0 ... CS35L41_OTP_MEM31:
0420 return true;
0421 default:
0422 return false;
0423 }
0424 }
0425
0426 static const struct cs35l41_otp_packed_element_t otp_map_1[] = {
0427
0428 { 0x00002030, 0, 4 },
0429 { 0x00002030, 7, 1 },
0430 { 0x0000208c, 24, 6 },
0431 { 0x00002090, 14, 4 },
0432 { 0x00002090, 10, 4 },
0433 { 0x0000300C, 11, 4 },
0434 { 0x0000394C, 23, 2 },
0435 { 0x00003950, 0, 7 },
0436 { 0x00003950, 8, 7 },
0437 { 0x00003950, 16, 8 },
0438 { 0x00003950, 24, 8 },
0439 { 0x00003954, 0, 7 },
0440 { 0x00003954, 8, 7 },
0441 { 0x00003954, 16, 8 },
0442 { 0x00003954, 24, 8 },
0443 { 0x00003958, 0, 7 },
0444 { 0x00003958, 8, 7 },
0445 { 0x00003958, 16, 8 },
0446 { 0x00003958, 24, 8 },
0447 { 0x0000395C, 0, 7 },
0448 { 0x0000395C, 8, 7 },
0449 { 0x0000395C, 16, 8 },
0450 { 0x0000395C, 24, 8 },
0451 { 0x0000416C, 0, 8 },
0452 { 0x00004160, 0, 7 },
0453 { 0x0000416C, 8, 8 },
0454 { 0x00004160, 16, 10 },
0455 { 0x0000416C, 16, 12 },
0456 { 0x0000416C, 28, 1 },
0457 { 0x00004170, 0, 6 },
0458 { 0x00004170, 6, 1 },
0459 { 0x00004170, 8, 6 },
0460 { 0x00004170, 14, 1 },
0461 { 0x00004170, 16, 9 },
0462 { 0x00004360, 0, 5 },
0463 { 0x00004360, 6, 9 },
0464 { 0x00004448, 0, 8 },
0465 { 0x00004448, 8, 8 },
0466 { 0x00004448, 16, 8 },
0467 { 0x00004448, 24, 8 },
0468 { 0x0000444C, 0, 3 },
0469 { 0x00006E30, 0, 5 },
0470 { 0x00006E30, 8, 5 },
0471 { 0x00006E30, 16, 5 },
0472 { 0x00006E30, 24, 5 },
0473 { 0x00006E34, 0, 5 },
0474 { 0x00006E34, 8, 5 },
0475 { 0x00006E34, 16, 5 },
0476 { 0x00006E34, 24, 5 },
0477 { 0x00006E38, 0, 5 },
0478 { 0x00006E38, 8, 5 },
0479 { 0x00006E38, 16, 5 },
0480 { 0x00006E38, 24, 5 },
0481 { 0x00006E3C, 0, 5 },
0482 { 0x00006E3C, 8, 5 },
0483 { 0x00006E3C, 16, 5 },
0484 { 0x00006E3C, 24, 5 },
0485 { 0x00006E40, 0, 5 },
0486 { 0x00006E40, 8, 5 },
0487 { 0x00006E40, 16, 5 },
0488 { 0x00006E40, 24, 5 },
0489 { 0x00006E44, 0, 5 },
0490 { 0x00006E48, 0, 10 },
0491 { 0x00006E48, 10, 10 },
0492 { 0x00006E48, 20, 10 },
0493 { 0x00006E4C, 0, 10 },
0494 { 0x00006E4C, 10, 10 },
0495 { 0x00006E4C, 20, 10 },
0496 { 0x00006E50, 0, 10 },
0497 { 0x00006E50, 10, 10 },
0498 { 0x00006E50, 20, 10 },
0499 { 0x00006E54, 0, 10 },
0500 { 0x00006E54, 10, 10 },
0501 { 0x00006E54, 20, 10 },
0502 { 0x00006E58, 0, 10 },
0503 { 0x00006E58, 10, 10 },
0504 { 0x00006E58, 20, 10 },
0505 { 0x00006E5C, 0, 10 },
0506 { 0x00006E5C, 10, 10 },
0507 { 0x00006E5C, 20, 10 },
0508 { 0x00006E60, 0, 10 },
0509 { 0x00006E60, 10, 10 },
0510 { 0x00006E60, 20, 10 },
0511 { 0x00006E64, 0, 10 },
0512 { 0x00007418, 7, 5 },
0513 { 0x0000741C, 0, 5 },
0514 { 0x0000741C, 11, 4 },
0515 { 0x0000741C, 19, 4 },
0516 { 0x00007434, 17, 1 },
0517 { 0x00007434, 18, 7 },
0518 { 0x00007068, 0, 9 },
0519 { 0x0000410C, 7, 1 },
0520 { 0x0000400C, 0, 7 },
0521 { 0x00000000, 0, 1 },
0522 { 0x00017040, 0, 8 },
0523 { 0x00017040, 8, 8 },
0524 { 0x00017040, 16, 8 },
0525 { 0x00017040, 24, 8 },
0526 { 0x00017044, 0, 24 },
0527 };
0528
0529 static const struct cs35l41_otp_packed_element_t otp_map_2[] = {
0530
0531 { 0x00002030, 0, 4 },
0532 { 0x00002030, 7, 1 },
0533 { 0x0000208c, 24, 6 },
0534 { 0x00002090, 14, 4 },
0535 { 0x00002090, 10, 4 },
0536 { 0x0000300C, 11, 4 },
0537 { 0x0000394C, 23, 2 },
0538 { 0x00003950, 0, 7 },
0539 { 0x00003950, 8, 7 },
0540 { 0x00003950, 16, 8 },
0541 { 0x00003950, 24, 8 },
0542 { 0x00003954, 0, 7 },
0543 { 0x00003954, 8, 7 },
0544 { 0x00003954, 16, 8 },
0545 { 0x00003954, 24, 8 },
0546 { 0x00003958, 0, 7 },
0547 { 0x00003958, 8, 7 },
0548 { 0x00003958, 16, 8 },
0549 { 0x00003958, 24, 8 },
0550 { 0x0000395C, 0, 7 },
0551 { 0x0000395C, 8, 7 },
0552 { 0x0000395C, 16, 8 },
0553 { 0x0000395C, 24, 8 },
0554 { 0x0000416C, 0, 8 },
0555 { 0x00004160, 0, 7 },
0556 { 0x0000416C, 8, 8 },
0557 { 0x00004160, 16, 10 },
0558 { 0x0000416C, 16, 12 },
0559 { 0x0000416C, 28, 1 },
0560 { 0x00004170, 0, 6 },
0561 { 0x00004170, 6, 1 },
0562 { 0x00004170, 8, 6 },
0563 { 0x00004170, 14, 1 },
0564 { 0x00004170, 16, 9 },
0565 { 0x00004360, 0, 5 },
0566 { 0x00004360, 6, 9 },
0567 { 0x00004448, 0, 8 },
0568 { 0x00004448, 8, 8 },
0569 { 0x00004448, 16, 8 },
0570 { 0x00004448, 24, 8 },
0571 { 0x0000444C, 0, 3 },
0572 { 0x00006E30, 0, 5 },
0573 { 0x00006E30, 8, 5 },
0574 { 0x00006E30, 16, 5 },
0575 { 0x00006E30, 24, 5 },
0576 { 0x00006E34, 0, 5 },
0577 { 0x00006E34, 8, 5 },
0578 { 0x00006E34, 16, 5 },
0579 { 0x00006E34, 24, 5 },
0580 { 0x00006E38, 0, 5 },
0581 { 0x00006E38, 8, 5 },
0582 { 0x00006E38, 16, 5 },
0583 { 0x00006E38, 24, 5 },
0584 { 0x00006E3C, 0, 5 },
0585 { 0x00006E3C, 8, 5 },
0586 { 0x00006E3C, 16, 5 },
0587 { 0x00006E3C, 24, 5 },
0588 { 0x00006E40, 0, 5 },
0589 { 0x00006E40, 8, 5 },
0590 { 0x00006E40, 16, 5 },
0591 { 0x00006E40, 24, 5 },
0592 { 0x00006E44, 0, 5 },
0593 { 0x00006E48, 0, 10 },
0594 { 0x00006E48, 10, 10 },
0595 { 0x00006E48, 20, 10 },
0596 { 0x00006E4C, 0, 10 },
0597 { 0x00006E4C, 10, 10 },
0598 { 0x00006E4C, 20, 10 },
0599 { 0x00006E50, 0, 10 },
0600 { 0x00006E50, 10, 10 },
0601 { 0x00006E50, 20, 10 },
0602 { 0x00006E54, 0, 10 },
0603 { 0x00006E54, 10, 10 },
0604 { 0x00006E54, 20, 10 },
0605 { 0x00006E58, 0, 10 },
0606 { 0x00006E58, 10, 10 },
0607 { 0x00006E58, 20, 10 },
0608 { 0x00006E5C, 0, 10 },
0609 { 0x00006E5C, 10, 10 },
0610 { 0x00006E5C, 20, 10 },
0611 { 0x00006E60, 0, 10 },
0612 { 0x00006E60, 10, 10 },
0613 { 0x00006E60, 20, 10 },
0614 { 0x00006E64, 0, 10 },
0615 { 0x00007418, 7, 5 },
0616 { 0x0000741C, 0, 5 },
0617 { 0x0000741C, 11, 4 },
0618 { 0x0000741C, 19, 4 },
0619 { 0x00007434, 17, 1 },
0620 { 0x00007434, 18, 7 },
0621 { 0x00007068, 0, 9 },
0622 { 0x0000410C, 7, 1 },
0623 { 0x0000400C, 0, 7 },
0624 { 0x00004000, 11, 1 },
0625 { 0x00017040, 0, 8 },
0626 { 0x00017040, 8, 8 },
0627 { 0x00017040, 16, 8 },
0628 { 0x00017040, 24, 8 },
0629 { 0x00017044, 0, 24 },
0630 };
0631
0632 static const struct reg_sequence cs35l41_reva0_errata_patch[] = {
0633 { 0x00003854, 0x05180240 },
0634 { CS35L41_VIMON_SPKMON_RESYNC, 0x00000000 },
0635 { 0x00004310, 0x00000000 },
0636 { CS35L41_VPVBST_FS_SEL, 0x00000000 },
0637 { CS35L41_OTP_TRIM_30, 0x9091A1C8 },
0638 { 0x00003014, 0x0200EE0E },
0639 { CS35L41_BSTCVRT_DCM_CTRL, 0x00000051 },
0640 { 0x00000054, 0x00000004 },
0641 { CS35L41_IRQ1_DB3, 0x00000000 },
0642 { CS35L41_IRQ2_DB3, 0x00000000 },
0643 { CS35L41_DSP1_YM_ACCEL_PL0_PRI, 0x00000000 },
0644 { CS35L41_DSP1_XM_ACCEL_PL0_PRI, 0x00000000 },
0645 { CS35L41_PWR_CTRL2, 0x00000000 },
0646 { CS35L41_AMP_GAIN_CTRL, 0x00000000 },
0647 { CS35L41_ASP_TX3_SRC, 0x00000000 },
0648 { CS35L41_ASP_TX4_SRC, 0x00000000 },
0649 };
0650
0651 static const struct reg_sequence cs35l41_revb0_errata_patch[] = {
0652 { CS35L41_VIMON_SPKMON_RESYNC, 0x00000000 },
0653 { 0x00004310, 0x00000000 },
0654 { CS35L41_VPVBST_FS_SEL, 0x00000000 },
0655 { CS35L41_BSTCVRT_DCM_CTRL, 0x00000051 },
0656 { CS35L41_DSP1_YM_ACCEL_PL0_PRI, 0x00000000 },
0657 { CS35L41_DSP1_XM_ACCEL_PL0_PRI, 0x00000000 },
0658 { CS35L41_PWR_CTRL2, 0x00000000 },
0659 { CS35L41_AMP_GAIN_CTRL, 0x00000000 },
0660 { CS35L41_ASP_TX3_SRC, 0x00000000 },
0661 { CS35L41_ASP_TX4_SRC, 0x00000000 },
0662 };
0663
0664 static const struct reg_sequence cs35l41_revb2_errata_patch[] = {
0665 { CS35L41_VIMON_SPKMON_RESYNC, 0x00000000 },
0666 { 0x00004310, 0x00000000 },
0667 { CS35L41_VPVBST_FS_SEL, 0x00000000 },
0668 { CS35L41_BSTCVRT_DCM_CTRL, 0x00000051 },
0669 { CS35L41_DSP1_YM_ACCEL_PL0_PRI, 0x00000000 },
0670 { CS35L41_DSP1_XM_ACCEL_PL0_PRI, 0x00000000 },
0671 { CS35L41_PWR_CTRL2, 0x00000000 },
0672 { CS35L41_AMP_GAIN_CTRL, 0x00000000 },
0673 { CS35L41_ASP_TX3_SRC, 0x00000000 },
0674 { CS35L41_ASP_TX4_SRC, 0x00000000 },
0675 };
0676
0677 static const struct reg_sequence cs35l41_fs_errata_patch[] = {
0678 { CS35L41_DSP1_RX1_RATE, 0x00000001 },
0679 { CS35L41_DSP1_RX2_RATE, 0x00000001 },
0680 { CS35L41_DSP1_RX3_RATE, 0x00000001 },
0681 { CS35L41_DSP1_RX4_RATE, 0x00000001 },
0682 { CS35L41_DSP1_RX5_RATE, 0x00000001 },
0683 { CS35L41_DSP1_RX6_RATE, 0x00000001 },
0684 { CS35L41_DSP1_RX7_RATE, 0x00000001 },
0685 { CS35L41_DSP1_RX8_RATE, 0x00000001 },
0686 { CS35L41_DSP1_TX1_RATE, 0x00000001 },
0687 { CS35L41_DSP1_TX2_RATE, 0x00000001 },
0688 { CS35L41_DSP1_TX3_RATE, 0x00000001 },
0689 { CS35L41_DSP1_TX4_RATE, 0x00000001 },
0690 { CS35L41_DSP1_TX5_RATE, 0x00000001 },
0691 { CS35L41_DSP1_TX6_RATE, 0x00000001 },
0692 { CS35L41_DSP1_TX7_RATE, 0x00000001 },
0693 { CS35L41_DSP1_TX8_RATE, 0x00000001 },
0694 };
0695
0696 static const struct cs35l41_otp_map_element_t cs35l41_otp_map_map[] = {
0697 {
0698 .id = 0x01,
0699 .map = otp_map_1,
0700 .num_elements = ARRAY_SIZE(otp_map_1),
0701 .bit_offset = 16,
0702 .word_offset = 2,
0703 },
0704 {
0705 .id = 0x02,
0706 .map = otp_map_2,
0707 .num_elements = ARRAY_SIZE(otp_map_2),
0708 .bit_offset = 16,
0709 .word_offset = 2,
0710 },
0711 {
0712 .id = 0x03,
0713 .map = otp_map_2,
0714 .num_elements = ARRAY_SIZE(otp_map_2),
0715 .bit_offset = 16,
0716 .word_offset = 2,
0717 },
0718 {
0719 .id = 0x06,
0720 .map = otp_map_2,
0721 .num_elements = ARRAY_SIZE(otp_map_2),
0722 .bit_offset = 16,
0723 .word_offset = 2,
0724 },
0725 {
0726 .id = 0x08,
0727 .map = otp_map_1,
0728 .num_elements = ARRAY_SIZE(otp_map_1),
0729 .bit_offset = 16,
0730 .word_offset = 2,
0731 },
0732 };
0733
0734 struct regmap_config cs35l41_regmap_i2c = {
0735 .reg_bits = 32,
0736 .val_bits = 32,
0737 .reg_stride = CS35L41_REGSTRIDE,
0738 .reg_format_endian = REGMAP_ENDIAN_BIG,
0739 .val_format_endian = REGMAP_ENDIAN_BIG,
0740 .max_register = CS35L41_LASTREG,
0741 .reg_defaults = cs35l41_reg,
0742 .num_reg_defaults = ARRAY_SIZE(cs35l41_reg),
0743 .volatile_reg = cs35l41_volatile_reg,
0744 .readable_reg = cs35l41_readable_reg,
0745 .precious_reg = cs35l41_precious_reg,
0746 .cache_type = REGCACHE_RBTREE,
0747 };
0748 EXPORT_SYMBOL_GPL(cs35l41_regmap_i2c);
0749
0750 struct regmap_config cs35l41_regmap_spi = {
0751 .reg_bits = 32,
0752 .val_bits = 32,
0753 .pad_bits = 16,
0754 .reg_stride = CS35L41_REGSTRIDE,
0755 .reg_format_endian = REGMAP_ENDIAN_BIG,
0756 .val_format_endian = REGMAP_ENDIAN_BIG,
0757 .max_register = CS35L41_LASTREG,
0758 .reg_defaults = cs35l41_reg,
0759 .num_reg_defaults = ARRAY_SIZE(cs35l41_reg),
0760 .volatile_reg = cs35l41_volatile_reg,
0761 .readable_reg = cs35l41_readable_reg,
0762 .precious_reg = cs35l41_precious_reg,
0763 .cache_type = REGCACHE_RBTREE,
0764 };
0765 EXPORT_SYMBOL_GPL(cs35l41_regmap_spi);
0766
0767 static const struct cs35l41_otp_map_element_t *cs35l41_find_otp_map(u32 otp_id)
0768 {
0769 int i;
0770
0771 for (i = 0; i < ARRAY_SIZE(cs35l41_otp_map_map); i++) {
0772 if (cs35l41_otp_map_map[i].id == otp_id)
0773 return &cs35l41_otp_map_map[i];
0774 }
0775
0776 return NULL;
0777 }
0778
0779 int cs35l41_test_key_unlock(struct device *dev, struct regmap *regmap)
0780 {
0781 static const struct reg_sequence unlock[] = {
0782 { CS35L41_TEST_KEY_CTL, 0x00000055 },
0783 { CS35L41_TEST_KEY_CTL, 0x000000AA },
0784 };
0785 int ret;
0786
0787 ret = regmap_multi_reg_write(regmap, unlock, ARRAY_SIZE(unlock));
0788 if (ret)
0789 dev_err(dev, "Failed to unlock test key: %d\n", ret);
0790
0791 return ret;
0792 }
0793 EXPORT_SYMBOL_GPL(cs35l41_test_key_unlock);
0794
0795 int cs35l41_test_key_lock(struct device *dev, struct regmap *regmap)
0796 {
0797 static const struct reg_sequence unlock[] = {
0798 { CS35L41_TEST_KEY_CTL, 0x000000CC },
0799 { CS35L41_TEST_KEY_CTL, 0x00000033 },
0800 };
0801 int ret;
0802
0803 ret = regmap_multi_reg_write(regmap, unlock, ARRAY_SIZE(unlock));
0804 if (ret)
0805 dev_err(dev, "Failed to lock test key: %d\n", ret);
0806
0807 return ret;
0808 }
0809 EXPORT_SYMBOL_GPL(cs35l41_test_key_lock);
0810
0811
0812 int cs35l41_otp_unpack(struct device *dev, struct regmap *regmap)
0813 {
0814 const struct cs35l41_otp_map_element_t *otp_map_match;
0815 const struct cs35l41_otp_packed_element_t *otp_map;
0816 int bit_offset, word_offset, ret, i;
0817 unsigned int bit_sum = 8;
0818 u32 otp_val, otp_id_reg;
0819 u32 *otp_mem;
0820
0821 otp_mem = kmalloc_array(CS35L41_OTP_SIZE_WORDS, sizeof(*otp_mem), GFP_KERNEL);
0822 if (!otp_mem)
0823 return -ENOMEM;
0824
0825 ret = regmap_read(regmap, CS35L41_OTPID, &otp_id_reg);
0826 if (ret) {
0827 dev_err(dev, "Read OTP ID failed: %d\n", ret);
0828 goto err_otp_unpack;
0829 }
0830
0831 otp_map_match = cs35l41_find_otp_map(otp_id_reg);
0832
0833 if (!otp_map_match) {
0834 dev_err(dev, "OTP Map matching ID %d not found\n", otp_id_reg);
0835 ret = -EINVAL;
0836 goto err_otp_unpack;
0837 }
0838
0839 ret = regmap_bulk_read(regmap, CS35L41_OTP_MEM0, otp_mem, CS35L41_OTP_SIZE_WORDS);
0840 if (ret) {
0841 dev_err(dev, "Read OTP Mem failed: %d\n", ret);
0842 goto err_otp_unpack;
0843 }
0844
0845 otp_map = otp_map_match->map;
0846
0847 bit_offset = otp_map_match->bit_offset;
0848 word_offset = otp_map_match->word_offset;
0849
0850 for (i = 0; i < otp_map_match->num_elements; i++) {
0851 dev_dbg(dev, "bitoffset= %d, word_offset=%d, bit_sum mod 32=%d, otp_map[i].size = %u\n",
0852 bit_offset, word_offset, bit_sum % 32, otp_map[i].size);
0853 if (bit_offset + otp_map[i].size - 1 >= 32) {
0854 otp_val = (otp_mem[word_offset] &
0855 GENMASK(31, bit_offset)) >> bit_offset;
0856 otp_val |= (otp_mem[++word_offset] &
0857 GENMASK(bit_offset + otp_map[i].size - 33, 0)) <<
0858 (32 - bit_offset);
0859 bit_offset += otp_map[i].size - 32;
0860 } else if (bit_offset + otp_map[i].size - 1 >= 0) {
0861 otp_val = (otp_mem[word_offset] &
0862 GENMASK(bit_offset + otp_map[i].size - 1, bit_offset)
0863 ) >> bit_offset;
0864 bit_offset += otp_map[i].size;
0865 } else
0866 otp_val = 0;
0867
0868 bit_sum += otp_map[i].size;
0869
0870 if (bit_offset == 32) {
0871 bit_offset = 0;
0872 word_offset++;
0873 }
0874
0875 if (otp_map[i].reg != 0) {
0876 ret = regmap_update_bits(regmap, otp_map[i].reg,
0877 GENMASK(otp_map[i].shift + otp_map[i].size - 1,
0878 otp_map[i].shift),
0879 otp_val << otp_map[i].shift);
0880 if (ret < 0) {
0881 dev_err(dev, "Write OTP val failed: %d\n", ret);
0882 goto err_otp_unpack;
0883 }
0884 }
0885 }
0886
0887 ret = 0;
0888
0889 err_otp_unpack:
0890 kfree(otp_mem);
0891
0892 return ret;
0893 }
0894 EXPORT_SYMBOL_GPL(cs35l41_otp_unpack);
0895
0896
0897 int cs35l41_register_errata_patch(struct device *dev, struct regmap *reg, unsigned int reg_revid)
0898 {
0899 char *rev;
0900 int ret;
0901
0902 switch (reg_revid) {
0903 case CS35L41_REVID_A0:
0904 ret = regmap_register_patch(reg, cs35l41_reva0_errata_patch,
0905 ARRAY_SIZE(cs35l41_reva0_errata_patch));
0906 rev = "A0";
0907 break;
0908 case CS35L41_REVID_B0:
0909 ret = regmap_register_patch(reg, cs35l41_revb0_errata_patch,
0910 ARRAY_SIZE(cs35l41_revb0_errata_patch));
0911 rev = "B0";
0912 break;
0913 case CS35L41_REVID_B2:
0914 ret = regmap_register_patch(reg, cs35l41_revb2_errata_patch,
0915 ARRAY_SIZE(cs35l41_revb2_errata_patch));
0916 rev = "B2";
0917 break;
0918 default:
0919 ret = -EINVAL;
0920 rev = "XX";
0921 break;
0922 }
0923
0924 if (ret)
0925 dev_err(dev, "Failed to apply %s errata patch: %d\n", rev, ret);
0926
0927 ret = regmap_write(reg, CS35L41_DSP1_CCM_CORE_CTRL, 0);
0928 if (ret < 0)
0929 dev_err(dev, "Write CCM_CORE_CTRL failed: %d\n", ret);
0930
0931 return ret;
0932 }
0933 EXPORT_SYMBOL_GPL(cs35l41_register_errata_patch);
0934
0935 int cs35l41_set_channels(struct device *dev, struct regmap *reg,
0936 unsigned int tx_num, unsigned int *tx_slot,
0937 unsigned int rx_num, unsigned int *rx_slot)
0938 {
0939 unsigned int val, mask;
0940 int i;
0941
0942 if (tx_num > 4 || rx_num > 2)
0943 return -EINVAL;
0944
0945 val = 0;
0946 mask = 0;
0947 for (i = 0; i < rx_num; i++) {
0948 dev_dbg(dev, "rx slot %d position = %d\n", i, rx_slot[i]);
0949 val |= rx_slot[i] << (i * 8);
0950 mask |= 0x3F << (i * 8);
0951 }
0952 regmap_update_bits(reg, CS35L41_SP_FRAME_RX_SLOT, mask, val);
0953
0954 val = 0;
0955 mask = 0;
0956 for (i = 0; i < tx_num; i++) {
0957 dev_dbg(dev, "tx slot %d position = %d\n", i, tx_slot[i]);
0958 val |= tx_slot[i] << (i * 8);
0959 mask |= 0x3F << (i * 8);
0960 }
0961 regmap_update_bits(reg, CS35L41_SP_FRAME_TX_SLOT, mask, val);
0962
0963 return 0;
0964 }
0965 EXPORT_SYMBOL_GPL(cs35l41_set_channels);
0966
0967 static const unsigned char cs35l41_bst_k1_table[4][5] = {
0968 { 0x24, 0x32, 0x32, 0x4F, 0x57 },
0969 { 0x24, 0x32, 0x32, 0x4F, 0x57 },
0970 { 0x40, 0x32, 0x32, 0x4F, 0x57 },
0971 { 0x40, 0x32, 0x32, 0x4F, 0x57 }
0972 };
0973
0974 static const unsigned char cs35l41_bst_k2_table[4][5] = {
0975 { 0x24, 0x49, 0x66, 0xA3, 0xEA },
0976 { 0x24, 0x49, 0x66, 0xA3, 0xEA },
0977 { 0x48, 0x49, 0x66, 0xA3, 0xEA },
0978 { 0x48, 0x49, 0x66, 0xA3, 0xEA }
0979 };
0980
0981 static const unsigned char cs35l41_bst_slope_table[4] = {
0982 0x75, 0x6B, 0x3B, 0x28
0983 };
0984
0985 static int cs35l41_boost_config(struct device *dev, struct regmap *regmap, int boost_ind,
0986 int boost_cap, int boost_ipk)
0987 {
0988 unsigned char bst_lbst_val, bst_cbst_range, bst_ipk_scaled;
0989 int ret;
0990
0991 switch (boost_ind) {
0992 case 1000:
0993 bst_lbst_val = 0;
0994 break;
0995 case 1200:
0996 bst_lbst_val = 1;
0997 break;
0998 case 1500:
0999 bst_lbst_val = 2;
1000 break;
1001 case 2200:
1002 bst_lbst_val = 3;
1003 break;
1004 default:
1005 dev_err(dev, "Invalid boost inductor value: %d nH\n", boost_ind);
1006 return -EINVAL;
1007 }
1008
1009 switch (boost_cap) {
1010 case 0 ... 19:
1011 bst_cbst_range = 0;
1012 break;
1013 case 20 ... 50:
1014 bst_cbst_range = 1;
1015 break;
1016 case 51 ... 100:
1017 bst_cbst_range = 2;
1018 break;
1019 case 101 ... 200:
1020 bst_cbst_range = 3;
1021 break;
1022 default:
1023 if (boost_cap < 0) {
1024 dev_err(dev, "Invalid boost capacitor value: %d nH\n", boost_cap);
1025 return -EINVAL;
1026 }
1027
1028 bst_cbst_range = 4;
1029 }
1030
1031 if (boost_ipk < 1600 || boost_ipk > 4500) {
1032 dev_err(dev, "Invalid boost inductor peak current: %d mA\n", boost_ipk);
1033 return -EINVAL;
1034 }
1035
1036 ret = regmap_update_bits(regmap, CS35L41_BSTCVRT_COEFF,
1037 CS35L41_BST_K1_MASK | CS35L41_BST_K2_MASK,
1038 cs35l41_bst_k1_table[bst_lbst_val][bst_cbst_range]
1039 << CS35L41_BST_K1_SHIFT |
1040 cs35l41_bst_k2_table[bst_lbst_val][bst_cbst_range]
1041 << CS35L41_BST_K2_SHIFT);
1042 if (ret) {
1043 dev_err(dev, "Failed to write boost coefficients: %d\n", ret);
1044 return ret;
1045 }
1046
1047 ret = regmap_update_bits(regmap, CS35L41_BSTCVRT_SLOPE_LBST,
1048 CS35L41_BST_SLOPE_MASK | CS35L41_BST_LBST_VAL_MASK,
1049 cs35l41_bst_slope_table[bst_lbst_val]
1050 << CS35L41_BST_SLOPE_SHIFT |
1051 bst_lbst_val << CS35L41_BST_LBST_VAL_SHIFT);
1052 if (ret) {
1053 dev_err(dev, "Failed to write boost slope/inductor value: %d\n", ret);
1054 return ret;
1055 }
1056
1057 bst_ipk_scaled = ((boost_ipk - 1600) / 50) + 0x10;
1058
1059 ret = regmap_update_bits(regmap, CS35L41_BSTCVRT_PEAK_CUR, CS35L41_BST_IPK_MASK,
1060 bst_ipk_scaled << CS35L41_BST_IPK_SHIFT);
1061 if (ret) {
1062 dev_err(dev, "Failed to write boost inductor peak current: %d\n", ret);
1063 return ret;
1064 }
1065
1066 regmap_update_bits(regmap, CS35L41_PWR_CTRL2, CS35L41_BST_EN_MASK,
1067 CS35L41_BST_EN_DEFAULT << CS35L41_BST_EN_SHIFT);
1068
1069 return 0;
1070 }
1071
1072 static const struct reg_sequence cs35l41_safe_to_reset[] = {
1073 { 0x00000040, 0x00000055 },
1074 { 0x00000040, 0x000000AA },
1075 { 0x0000393C, 0x000000C0, 6000},
1076 { 0x0000393C, 0x00000000 },
1077 { 0x00007414, 0x00C82222 },
1078 { 0x0000742C, 0x00000000 },
1079 { 0x00000040, 0x000000CC },
1080 { 0x00000040, 0x00000033 },
1081 };
1082
1083 static const struct reg_sequence cs35l41_active_to_safe[] = {
1084 { 0x00000040, 0x00000055 },
1085 { 0x00000040, 0x000000AA },
1086 { 0x00007438, 0x00585941 },
1087 { CS35L41_PWR_CTRL1, 0x00000000 },
1088 { 0x0000742C, 0x00000009, 3000 },
1089 { 0x00007438, 0x00580941 },
1090 { 0x00000040, 0x000000CC },
1091 { 0x00000040, 0x00000033 },
1092 };
1093
1094 static const struct reg_sequence cs35l41_safe_to_active[] = {
1095 { 0x00000040, 0x00000055 },
1096 { 0x00000040, 0x000000AA },
1097 { 0x0000742C, 0x0000000F },
1098 { 0x0000742C, 0x00000079 },
1099 { 0x00007438, 0x00585941 },
1100 { CS35L41_PWR_CTRL1, 0x00000001, 3000 },
1101 { 0x0000742C, 0x000000F9 },
1102 { 0x00007438, 0x00580941 },
1103 { 0x00000040, 0x000000CC },
1104 { 0x00000040, 0x00000033 },
1105 };
1106
1107 static const struct reg_sequence cs35l41_reset_to_safe[] = {
1108 { 0x00000040, 0x00000055 },
1109 { 0x00000040, 0x000000AA },
1110 { 0x00007438, 0x00585941 },
1111 { 0x00007414, 0x08C82222 },
1112 { 0x0000742C, 0x00000009 },
1113 { 0x00000040, 0x000000CC },
1114 { 0x00000040, 0x00000033 },
1115 };
1116
1117 int cs35l41_init_boost(struct device *dev, struct regmap *regmap,
1118 struct cs35l41_hw_cfg *hw_cfg)
1119 {
1120 int ret;
1121
1122 switch (hw_cfg->bst_type) {
1123 case CS35L41_INT_BOOST:
1124 ret = cs35l41_boost_config(dev, regmap, hw_cfg->bst_ind,
1125 hw_cfg->bst_cap, hw_cfg->bst_ipk);
1126 if (ret)
1127 dev_err(dev, "Error in Boost DT config: %d\n", ret);
1128 break;
1129 case CS35L41_EXT_BOOST:
1130 case CS35L41_EXT_BOOST_NO_VSPK_SWITCH:
1131
1132
1133
1134
1135 regmap_write(regmap, CS35L41_GPIO1_CTRL1, 0x00000001);
1136 regmap_multi_reg_write(regmap, cs35l41_reset_to_safe,
1137 ARRAY_SIZE(cs35l41_reset_to_safe));
1138 ret = regmap_update_bits(regmap, CS35L41_PWR_CTRL2, CS35L41_BST_EN_MASK,
1139 CS35L41_BST_DIS_FET_OFF << CS35L41_BST_EN_SHIFT);
1140 break;
1141 default:
1142 dev_err(dev, "Boost type %d not supported\n", hw_cfg->bst_type);
1143 ret = -EINVAL;
1144 break;
1145 }
1146
1147 return ret;
1148 }
1149 EXPORT_SYMBOL_GPL(cs35l41_init_boost);
1150
1151 bool cs35l41_safe_reset(struct regmap *regmap, enum cs35l41_boost_type b_type)
1152 {
1153 switch (b_type) {
1154
1155 case CS35L41_EXT_BOOST_NO_VSPK_SWITCH:
1156 return false;
1157 case CS35L41_EXT_BOOST:
1158 regmap_write(regmap, CS35L41_GPIO1_CTRL1, 0x00000001);
1159 regmap_multi_reg_write(regmap, cs35l41_safe_to_reset,
1160 ARRAY_SIZE(cs35l41_safe_to_reset));
1161 return true;
1162 default:
1163 return true;
1164 }
1165 }
1166 EXPORT_SYMBOL_GPL(cs35l41_safe_reset);
1167
1168 int cs35l41_global_enable(struct regmap *regmap, enum cs35l41_boost_type b_type, int enable)
1169 {
1170 int ret;
1171
1172 switch (b_type) {
1173 case CS35L41_INT_BOOST:
1174 ret = regmap_update_bits(regmap, CS35L41_PWR_CTRL1, CS35L41_GLOBAL_EN_MASK,
1175 enable << CS35L41_GLOBAL_EN_SHIFT);
1176 usleep_range(3000, 3100);
1177 break;
1178 case CS35L41_EXT_BOOST:
1179 case CS35L41_EXT_BOOST_NO_VSPK_SWITCH:
1180 if (enable)
1181 ret = regmap_multi_reg_write(regmap, cs35l41_safe_to_active,
1182 ARRAY_SIZE(cs35l41_safe_to_active));
1183 else
1184 ret = regmap_multi_reg_write(regmap, cs35l41_active_to_safe,
1185 ARRAY_SIZE(cs35l41_active_to_safe));
1186 break;
1187 default:
1188 ret = -EINVAL;
1189 break;
1190 }
1191
1192 return ret;
1193 }
1194 EXPORT_SYMBOL_GPL(cs35l41_global_enable);
1195
1196 int cs35l41_gpio_config(struct regmap *regmap, struct cs35l41_hw_cfg *hw_cfg)
1197 {
1198 struct cs35l41_gpio_cfg *gpio1 = &hw_cfg->gpio1;
1199 struct cs35l41_gpio_cfg *gpio2 = &hw_cfg->gpio2;
1200 int irq_pol = IRQF_TRIGGER_NONE;
1201
1202 regmap_update_bits(regmap, CS35L41_GPIO1_CTRL1,
1203 CS35L41_GPIO_POL_MASK | CS35L41_GPIO_DIR_MASK,
1204 gpio1->pol_inv << CS35L41_GPIO_POL_SHIFT |
1205 !gpio1->out_en << CS35L41_GPIO_DIR_SHIFT);
1206
1207 regmap_update_bits(regmap, CS35L41_GPIO2_CTRL1,
1208 CS35L41_GPIO_POL_MASK | CS35L41_GPIO_DIR_MASK,
1209 gpio2->pol_inv << CS35L41_GPIO_POL_SHIFT |
1210 !gpio2->out_en << CS35L41_GPIO_DIR_SHIFT);
1211
1212 if (gpio1->valid)
1213 regmap_update_bits(regmap, CS35L41_GPIO_PAD_CONTROL, CS35L41_GPIO1_CTRL_MASK,
1214 gpio1->func << CS35L41_GPIO1_CTRL_SHIFT);
1215
1216 if (gpio2->valid) {
1217 regmap_update_bits(regmap, CS35L41_GPIO_PAD_CONTROL, CS35L41_GPIO2_CTRL_MASK,
1218 gpio2->func << CS35L41_GPIO2_CTRL_SHIFT);
1219
1220 switch (gpio2->func) {
1221 case CS35L41_GPIO2_INT_PUSH_PULL_LOW:
1222 case CS35L41_GPIO2_INT_OPEN_DRAIN:
1223 irq_pol = IRQF_TRIGGER_LOW;
1224 break;
1225 case CS35L41_GPIO2_INT_PUSH_PULL_HIGH:
1226 irq_pol = IRQF_TRIGGER_HIGH;
1227 break;
1228 default:
1229 break;
1230 }
1231 }
1232
1233 return irq_pol;
1234 }
1235 EXPORT_SYMBOL_GPL(cs35l41_gpio_config);
1236
1237 static const struct cs_dsp_region cs35l41_dsp1_regions[] = {
1238 { .type = WMFW_HALO_PM_PACKED, .base = CS35L41_DSP1_PMEM_0 },
1239 { .type = WMFW_HALO_XM_PACKED, .base = CS35L41_DSP1_XMEM_PACK_0 },
1240 { .type = WMFW_HALO_YM_PACKED, .base = CS35L41_DSP1_YMEM_PACK_0 },
1241 {. type = WMFW_ADSP2_XM, .base = CS35L41_DSP1_XMEM_UNPACK24_0},
1242 {. type = WMFW_ADSP2_YM, .base = CS35L41_DSP1_YMEM_UNPACK24_0},
1243 };
1244
1245 void cs35l41_configure_cs_dsp(struct device *dev, struct regmap *reg, struct cs_dsp *dsp)
1246 {
1247 dsp->num = 1;
1248 dsp->type = WMFW_HALO;
1249 dsp->rev = 0;
1250 dsp->dev = dev;
1251 dsp->regmap = reg;
1252 dsp->base = CS35L41_DSP1_CTRL_BASE;
1253 dsp->base_sysinfo = CS35L41_DSP1_SYS_ID;
1254 dsp->mem = cs35l41_dsp1_regions;
1255 dsp->num_mems = ARRAY_SIZE(cs35l41_dsp1_regions);
1256 dsp->lock_regions = 0xFFFFFFFF;
1257 }
1258 EXPORT_SYMBOL_GPL(cs35l41_configure_cs_dsp);
1259
1260 static bool cs35l41_check_cspl_mbox_sts(enum cs35l41_cspl_mbox_cmd cmd,
1261 enum cs35l41_cspl_mbox_status sts)
1262 {
1263 switch (cmd) {
1264 case CSPL_MBOX_CMD_NONE:
1265 case CSPL_MBOX_CMD_UNKNOWN_CMD:
1266 return true;
1267 case CSPL_MBOX_CMD_PAUSE:
1268 case CSPL_MBOX_CMD_OUT_OF_HIBERNATE:
1269 return (sts == CSPL_MBOX_STS_PAUSED);
1270 case CSPL_MBOX_CMD_RESUME:
1271 return (sts == CSPL_MBOX_STS_RUNNING);
1272 case CSPL_MBOX_CMD_REINIT:
1273 return (sts == CSPL_MBOX_STS_RUNNING);
1274 case CSPL_MBOX_CMD_STOP_PRE_REINIT:
1275 return (sts == CSPL_MBOX_STS_RDY_FOR_REINIT);
1276 default:
1277 return false;
1278 }
1279 }
1280
1281 int cs35l41_set_cspl_mbox_cmd(struct device *dev, struct regmap *regmap,
1282 enum cs35l41_cspl_mbox_cmd cmd)
1283 {
1284 unsigned int sts = 0, i;
1285 int ret;
1286
1287
1288 ret = regmap_write(regmap, CS35L41_DSP_VIRT1_MBOX_1, cmd);
1289 if (ret < 0) {
1290 if (cmd != CSPL_MBOX_CMD_OUT_OF_HIBERNATE)
1291 dev_err(dev, "Failed to write MBOX: %d\n", ret);
1292 return ret;
1293 }
1294
1295
1296 for (i = 0; i < 5; i++) {
1297 usleep_range(1000, 1100);
1298
1299 ret = regmap_read(regmap, CS35L41_DSP_MBOX_2, &sts);
1300 if (ret < 0) {
1301 dev_err(dev, "Failed to read MBOX STS: %d\n", ret);
1302 continue;
1303 }
1304
1305 if (!cs35l41_check_cspl_mbox_sts(cmd, sts))
1306 dev_dbg(dev, "[%u] cmd %u returned invalid sts %u", i, cmd, sts);
1307 else
1308 return 0;
1309 }
1310
1311 if (cmd != CSPL_MBOX_CMD_OUT_OF_HIBERNATE)
1312 dev_err(dev, "Failed to set mailbox cmd %u (status %u)\n", cmd, sts);
1313
1314 return -ENOMSG;
1315 }
1316 EXPORT_SYMBOL_GPL(cs35l41_set_cspl_mbox_cmd);
1317
1318 int cs35l41_write_fs_errata(struct device *dev, struct regmap *regmap)
1319 {
1320 int ret;
1321
1322 ret = regmap_multi_reg_write(regmap, cs35l41_fs_errata_patch,
1323 ARRAY_SIZE(cs35l41_fs_errata_patch));
1324 if (ret < 0)
1325 dev_err(dev, "Failed to write fs errata: %d\n", ret);
1326
1327 return ret;
1328 }
1329 EXPORT_SYMBOL_GPL(cs35l41_write_fs_errata);
1330
1331 int cs35l41_enter_hibernate(struct device *dev, struct regmap *regmap,
1332 enum cs35l41_boost_type b_type)
1333 {
1334 if (!cs35l41_safe_reset(regmap, b_type)) {
1335 dev_dbg(dev, "System does not support Suspend\n");
1336 return -EINVAL;
1337 }
1338
1339 dev_dbg(dev, "Enter hibernate\n");
1340 regmap_write(regmap, CS35L41_WAKESRC_CTL, 0x0088);
1341 regmap_write(regmap, CS35L41_WAKESRC_CTL, 0x0188);
1342
1343
1344 regmap_write(regmap, CS35L41_DSP_VIRT1_MBOX_1, CSPL_MBOX_CMD_HIBERNATE);
1345
1346 return 0;
1347 }
1348 EXPORT_SYMBOL_GPL(cs35l41_enter_hibernate);
1349
1350 static void cs35l41_wait_for_pwrmgt_sts(struct device *dev, struct regmap *regmap)
1351 {
1352 const int pwrmgt_retries = 10;
1353 unsigned int sts;
1354 int i, ret;
1355
1356 for (i = 0; i < pwrmgt_retries; i++) {
1357 ret = regmap_read(regmap, CS35L41_PWRMGT_STS, &sts);
1358 if (ret)
1359 dev_err(dev, "Failed to read PWRMGT_STS: %d\n", ret);
1360 else if (!(sts & CS35L41_WR_PEND_STS_MASK))
1361 return;
1362
1363 udelay(20);
1364 }
1365
1366 dev_err(dev, "Timed out reading PWRMGT_STS\n");
1367 }
1368
1369 int cs35l41_exit_hibernate(struct device *dev, struct regmap *regmap)
1370 {
1371 const int wake_retries = 20;
1372 const int sleep_retries = 5;
1373 int ret, i, j;
1374
1375 for (i = 0; i < sleep_retries; i++) {
1376 dev_dbg(dev, "Exit hibernate\n");
1377
1378 for (j = 0; j < wake_retries; j++) {
1379 ret = cs35l41_set_cspl_mbox_cmd(dev, regmap,
1380 CSPL_MBOX_CMD_OUT_OF_HIBERNATE);
1381 if (!ret)
1382 break;
1383
1384 usleep_range(100, 200);
1385 }
1386
1387 if (j < wake_retries) {
1388 dev_dbg(dev, "Wake success at cycle: %d\n", j);
1389 return 0;
1390 }
1391
1392 dev_err(dev, "Wake failed, re-enter hibernate: %d\n", ret);
1393
1394 cs35l41_wait_for_pwrmgt_sts(dev, regmap);
1395 regmap_write(regmap, CS35L41_WAKESRC_CTL, 0x0088);
1396
1397 cs35l41_wait_for_pwrmgt_sts(dev, regmap);
1398 regmap_write(regmap, CS35L41_WAKESRC_CTL, 0x0188);
1399
1400 cs35l41_wait_for_pwrmgt_sts(dev, regmap);
1401 regmap_write(regmap, CS35L41_PWRMGT_CTL, 0x3);
1402 }
1403
1404 dev_err(dev, "Timed out waking device\n");
1405
1406 return -ETIMEDOUT;
1407 }
1408 EXPORT_SYMBOL_GPL(cs35l41_exit_hibernate);
1409
1410 MODULE_DESCRIPTION("CS35L41 library");
1411 MODULE_AUTHOR("David Rhodes, Cirrus Logic Inc, <david.rhodes@cirrus.com>");
1412 MODULE_AUTHOR("Lucas Tanure, Cirrus Logic Inc, <tanureal@opensource.cirrus.com>");
1413 MODULE_LICENSE("GPL");