Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 //
0003 // cs35l41-lib.c -- CS35L41 Common functions for HDA and ASoC Audio drivers
0004 //
0005 // Copyright 2017-2021 Cirrus Logic, Inc.
0006 //
0007 // Author: David Rhodes <david.rhodes@cirrus.com>
0008 // Author: Lucas Tanure <lucas.tanure@cirrus.com>
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     /*test regs*/
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     /* addr         shift   size */
0428     { 0x00002030,   0,  4 }, /*TRIM_OSC_FREQ_TRIM*/
0429     { 0x00002030,   7,  1 }, /*TRIM_OSC_TRIM_DONE*/
0430     { 0x0000208c,   24, 6 }, /*TST_DIGREG_VREF_TRIM*/
0431     { 0x00002090,   14, 4 }, /*TST_REF_TRIM*/
0432     { 0x00002090,   10, 4 }, /*TST_REF_TEMPCO_TRIM*/
0433     { 0x0000300C,   11, 4 }, /*PLL_LDOA_TST_VREF_TRIM*/
0434     { 0x0000394C,   23, 2 }, /*BST_ATEST_CM_VOFF*/
0435     { 0x00003950,   0,  7 }, /*BST_ATRIM_IADC_OFFSET*/
0436     { 0x00003950,   8,  7 }, /*BST_ATRIM_IADC_GAIN1*/
0437     { 0x00003950,   16, 8 }, /*BST_ATRIM_IPKCOMP_OFFSET1*/
0438     { 0x00003950,   24, 8 }, /*BST_ATRIM_IPKCOMP_GAIN1*/
0439     { 0x00003954,   0,  7 }, /*BST_ATRIM_IADC_OFFSET2*/
0440     { 0x00003954,   8,  7 }, /*BST_ATRIM_IADC_GAIN2*/
0441     { 0x00003954,   16, 8 }, /*BST_ATRIM_IPKCOMP_OFFSET2*/
0442     { 0x00003954,   24, 8 }, /*BST_ATRIM_IPKCOMP_GAIN2*/
0443     { 0x00003958,   0,  7 }, /*BST_ATRIM_IADC_OFFSET3*/
0444     { 0x00003958,   8,  7 }, /*BST_ATRIM_IADC_GAIN3*/
0445     { 0x00003958,   16, 8 }, /*BST_ATRIM_IPKCOMP_OFFSET3*/
0446     { 0x00003958,   24, 8 }, /*BST_ATRIM_IPKCOMP_GAIN3*/
0447     { 0x0000395C,   0,  7 }, /*BST_ATRIM_IADC_OFFSET4*/
0448     { 0x0000395C,   8,  7 }, /*BST_ATRIM_IADC_GAIN4*/
0449     { 0x0000395C,   16, 8 }, /*BST_ATRIM_IPKCOMP_OFFSET4*/
0450     { 0x0000395C,   24, 8 }, /*BST_ATRIM_IPKCOMP_GAIN4*/
0451     { 0x0000416C,   0,  8 }, /*VMON_GAIN_OTP_VAL*/
0452     { 0x00004160,   0,  7 }, /*VMON_OFFSET_OTP_VAL*/
0453     { 0x0000416C,   8,  8 }, /*IMON_GAIN_OTP_VAL*/
0454     { 0x00004160,   16, 10 }, /*IMON_OFFSET_OTP_VAL*/
0455     { 0x0000416C,   16, 12 }, /*VMON_CM_GAIN_OTP_VAL*/
0456     { 0x0000416C,   28, 1 }, /*VMON_CM_GAIN_SIGN_OTP_VAL*/
0457     { 0x00004170,   0,  6 }, /*IMON_CAL_TEMPCO_OTP_VAL*/
0458     { 0x00004170,   6,  1 }, /*IMON_CAL_TEMPCO_SIGN_OTP*/
0459     { 0x00004170,   8,  6 }, /*IMON_CAL_TEMPCO2_OTP_VAL*/
0460     { 0x00004170,   14, 1 }, /*IMON_CAL_TEMPCO2_DN_UPB_OTP_VAL*/
0461     { 0x00004170,   16, 9 }, /*IMON_CAL_TEMPCO_TBASE_OTP_VAL*/
0462     { 0x00004360,   0,  5 }, /*TEMP_GAIN_OTP_VAL*/
0463     { 0x00004360,   6,  9 }, /*TEMP_OFFSET_OTP_VAL*/
0464     { 0x00004448,   0,  8 }, /*VP_SARADC_OFFSET*/
0465     { 0x00004448,   8,  8 }, /*VP_GAIN_INDEX*/
0466     { 0x00004448,   16, 8 }, /*VBST_SARADC_OFFSET*/
0467     { 0x00004448,   24, 8 }, /*VBST_GAIN_INDEX*/
0468     { 0x0000444C,   0,  3 }, /*ANA_SELINVREF*/
0469     { 0x00006E30,   0,  5 }, /*GAIN_ERR_COEFF_0*/
0470     { 0x00006E30,   8,  5 }, /*GAIN_ERR_COEFF_1*/
0471     { 0x00006E30,   16, 5 }, /*GAIN_ERR_COEFF_2*/
0472     { 0x00006E30,   24, 5 }, /*GAIN_ERR_COEFF_3*/
0473     { 0x00006E34,   0,  5 }, /*GAIN_ERR_COEFF_4*/
0474     { 0x00006E34,   8,  5 }, /*GAIN_ERR_COEFF_5*/
0475     { 0x00006E34,   16, 5 }, /*GAIN_ERR_COEFF_6*/
0476     { 0x00006E34,   24, 5 }, /*GAIN_ERR_COEFF_7*/
0477     { 0x00006E38,   0,  5 }, /*GAIN_ERR_COEFF_8*/
0478     { 0x00006E38,   8,  5 }, /*GAIN_ERR_COEFF_9*/
0479     { 0x00006E38,   16, 5 }, /*GAIN_ERR_COEFF_10*/
0480     { 0x00006E38,   24, 5 }, /*GAIN_ERR_COEFF_11*/
0481     { 0x00006E3C,   0,  5 }, /*GAIN_ERR_COEFF_12*/
0482     { 0x00006E3C,   8,  5 }, /*GAIN_ERR_COEFF_13*/
0483     { 0x00006E3C,   16, 5 }, /*GAIN_ERR_COEFF_14*/
0484     { 0x00006E3C,   24, 5 }, /*GAIN_ERR_COEFF_15*/
0485     { 0x00006E40,   0,  5 }, /*GAIN_ERR_COEFF_16*/
0486     { 0x00006E40,   8,  5 }, /*GAIN_ERR_COEFF_17*/
0487     { 0x00006E40,   16, 5 }, /*GAIN_ERR_COEFF_18*/
0488     { 0x00006E40,   24, 5 }, /*GAIN_ERR_COEFF_19*/
0489     { 0x00006E44,   0,  5 }, /*GAIN_ERR_COEFF_20*/
0490     { 0x00006E48,   0,  10 }, /*VOFF_GAIN_0*/
0491     { 0x00006E48,   10, 10 }, /*VOFF_GAIN_1*/
0492     { 0x00006E48,   20, 10 }, /*VOFF_GAIN_2*/
0493     { 0x00006E4C,   0,  10 }, /*VOFF_GAIN_3*/
0494     { 0x00006E4C,   10, 10 }, /*VOFF_GAIN_4*/
0495     { 0x00006E4C,   20, 10 }, /*VOFF_GAIN_5*/
0496     { 0x00006E50,   0,  10 }, /*VOFF_GAIN_6*/
0497     { 0x00006E50,   10, 10 }, /*VOFF_GAIN_7*/
0498     { 0x00006E50,   20, 10 }, /*VOFF_GAIN_8*/
0499     { 0x00006E54,   0,  10 }, /*VOFF_GAIN_9*/
0500     { 0x00006E54,   10, 10 }, /*VOFF_GAIN_10*/
0501     { 0x00006E54,   20, 10 }, /*VOFF_GAIN_11*/
0502     { 0x00006E58,   0,  10 }, /*VOFF_GAIN_12*/
0503     { 0x00006E58,   10, 10 }, /*VOFF_GAIN_13*/
0504     { 0x00006E58,   20, 10 }, /*VOFF_GAIN_14*/
0505     { 0x00006E5C,   0,  10 }, /*VOFF_GAIN_15*/
0506     { 0x00006E5C,   10, 10 }, /*VOFF_GAIN_16*/
0507     { 0x00006E5C,   20, 10 }, /*VOFF_GAIN_17*/
0508     { 0x00006E60,   0,  10 }, /*VOFF_GAIN_18*/
0509     { 0x00006E60,   10, 10 }, /*VOFF_GAIN_19*/
0510     { 0x00006E60,   20, 10 }, /*VOFF_GAIN_20*/
0511     { 0x00006E64,   0,  10 }, /*VOFF_INT1*/
0512     { 0x00007418,   7,  5 }, /*DS_SPK_INT1_CAP_TRIM*/
0513     { 0x0000741C,   0,  5 }, /*DS_SPK_INT2_CAP_TRIM*/
0514     { 0x0000741C,   11, 4 }, /*DS_SPK_LPF_CAP_TRIM*/
0515     { 0x0000741C,   19, 4 }, /*DS_SPK_QUAN_CAP_TRIM*/
0516     { 0x00007434,   17, 1 }, /*FORCE_CAL*/
0517     { 0x00007434,   18, 7 }, /*CAL_OVERRIDE*/
0518     { 0x00007068,   0,  9 }, /*MODIX*/
0519     { 0x0000410C,   7,  1 }, /*VIMON_DLY_NOT_COMB*/
0520     { 0x0000400C,   0,  7 }, /*VIMON_DLY*/
0521     { 0x00000000,   0,  1 }, /*extra bit*/
0522     { 0x00017040,   0,  8 }, /*X_COORDINATE*/
0523     { 0x00017040,   8,  8 }, /*Y_COORDINATE*/
0524     { 0x00017040,   16, 8 }, /*WAFER_ID*/
0525     { 0x00017040,   24, 8 }, /*DVS*/
0526     { 0x00017044,   0,  24 }, /*LOT_NUMBER*/
0527 };
0528 
0529 static const struct cs35l41_otp_packed_element_t otp_map_2[] = {
0530     /* addr         shift   size */
0531     { 0x00002030,   0,  4 }, /*TRIM_OSC_FREQ_TRIM*/
0532     { 0x00002030,   7,  1 }, /*TRIM_OSC_TRIM_DONE*/
0533     { 0x0000208c,   24, 6 }, /*TST_DIGREG_VREF_TRIM*/
0534     { 0x00002090,   14, 4 }, /*TST_REF_TRIM*/
0535     { 0x00002090,   10, 4 }, /*TST_REF_TEMPCO_TRIM*/
0536     { 0x0000300C,   11, 4 }, /*PLL_LDOA_TST_VREF_TRIM*/
0537     { 0x0000394C,   23, 2 }, /*BST_ATEST_CM_VOFF*/
0538     { 0x00003950,   0,  7 }, /*BST_ATRIM_IADC_OFFSET*/
0539     { 0x00003950,   8,  7 }, /*BST_ATRIM_IADC_GAIN1*/
0540     { 0x00003950,   16, 8 }, /*BST_ATRIM_IPKCOMP_OFFSET1*/
0541     { 0x00003950,   24, 8 }, /*BST_ATRIM_IPKCOMP_GAIN1*/
0542     { 0x00003954,   0,  7 }, /*BST_ATRIM_IADC_OFFSET2*/
0543     { 0x00003954,   8,  7 }, /*BST_ATRIM_IADC_GAIN2*/
0544     { 0x00003954,   16, 8 }, /*BST_ATRIM_IPKCOMP_OFFSET2*/
0545     { 0x00003954,   24, 8 }, /*BST_ATRIM_IPKCOMP_GAIN2*/
0546     { 0x00003958,   0,  7 }, /*BST_ATRIM_IADC_OFFSET3*/
0547     { 0x00003958,   8,  7 }, /*BST_ATRIM_IADC_GAIN3*/
0548     { 0x00003958,   16, 8 }, /*BST_ATRIM_IPKCOMP_OFFSET3*/
0549     { 0x00003958,   24, 8 }, /*BST_ATRIM_IPKCOMP_GAIN3*/
0550     { 0x0000395C,   0,  7 }, /*BST_ATRIM_IADC_OFFSET4*/
0551     { 0x0000395C,   8,  7 }, /*BST_ATRIM_IADC_GAIN4*/
0552     { 0x0000395C,   16, 8 }, /*BST_ATRIM_IPKCOMP_OFFSET4*/
0553     { 0x0000395C,   24, 8 }, /*BST_ATRIM_IPKCOMP_GAIN4*/
0554     { 0x0000416C,   0,  8 }, /*VMON_GAIN_OTP_VAL*/
0555     { 0x00004160,   0,  7 }, /*VMON_OFFSET_OTP_VAL*/
0556     { 0x0000416C,   8,  8 }, /*IMON_GAIN_OTP_VAL*/
0557     { 0x00004160,   16, 10 }, /*IMON_OFFSET_OTP_VAL*/
0558     { 0x0000416C,   16, 12 }, /*VMON_CM_GAIN_OTP_VAL*/
0559     { 0x0000416C,   28, 1 }, /*VMON_CM_GAIN_SIGN_OTP_VAL*/
0560     { 0x00004170,   0,  6 }, /*IMON_CAL_TEMPCO_OTP_VAL*/
0561     { 0x00004170,   6,  1 }, /*IMON_CAL_TEMPCO_SIGN_OTP*/
0562     { 0x00004170,   8,  6 }, /*IMON_CAL_TEMPCO2_OTP_VAL*/
0563     { 0x00004170,   14, 1 }, /*IMON_CAL_TEMPCO2_DN_UPB_OTP_VAL*/
0564     { 0x00004170,   16, 9 }, /*IMON_CAL_TEMPCO_TBASE_OTP_VAL*/
0565     { 0x00004360,   0,  5 }, /*TEMP_GAIN_OTP_VAL*/
0566     { 0x00004360,   6,  9 }, /*TEMP_OFFSET_OTP_VAL*/
0567     { 0x00004448,   0,  8 }, /*VP_SARADC_OFFSET*/
0568     { 0x00004448,   8,  8 }, /*VP_GAIN_INDEX*/
0569     { 0x00004448,   16, 8 }, /*VBST_SARADC_OFFSET*/
0570     { 0x00004448,   24, 8 }, /*VBST_GAIN_INDEX*/
0571     { 0x0000444C,   0,  3 }, /*ANA_SELINVREF*/
0572     { 0x00006E30,   0,  5 }, /*GAIN_ERR_COEFF_0*/
0573     { 0x00006E30,   8,  5 }, /*GAIN_ERR_COEFF_1*/
0574     { 0x00006E30,   16, 5 }, /*GAIN_ERR_COEFF_2*/
0575     { 0x00006E30,   24, 5 }, /*GAIN_ERR_COEFF_3*/
0576     { 0x00006E34,   0,  5 }, /*GAIN_ERR_COEFF_4*/
0577     { 0x00006E34,   8,  5 }, /*GAIN_ERR_COEFF_5*/
0578     { 0x00006E34,   16, 5 }, /*GAIN_ERR_COEFF_6*/
0579     { 0x00006E34,   24, 5 }, /*GAIN_ERR_COEFF_7*/
0580     { 0x00006E38,   0,  5 }, /*GAIN_ERR_COEFF_8*/
0581     { 0x00006E38,   8,  5 }, /*GAIN_ERR_COEFF_9*/
0582     { 0x00006E38,   16, 5 }, /*GAIN_ERR_COEFF_10*/
0583     { 0x00006E38,   24, 5 }, /*GAIN_ERR_COEFF_11*/
0584     { 0x00006E3C,   0,  5 }, /*GAIN_ERR_COEFF_12*/
0585     { 0x00006E3C,   8,  5 }, /*GAIN_ERR_COEFF_13*/
0586     { 0x00006E3C,   16, 5 }, /*GAIN_ERR_COEFF_14*/
0587     { 0x00006E3C,   24, 5 }, /*GAIN_ERR_COEFF_15*/
0588     { 0x00006E40,   0,  5 }, /*GAIN_ERR_COEFF_16*/
0589     { 0x00006E40,   8,  5 }, /*GAIN_ERR_COEFF_17*/
0590     { 0x00006E40,   16, 5 }, /*GAIN_ERR_COEFF_18*/
0591     { 0x00006E40,   24, 5 }, /*GAIN_ERR_COEFF_19*/
0592     { 0x00006E44,   0,  5 }, /*GAIN_ERR_COEFF_20*/
0593     { 0x00006E48,   0,  10 }, /*VOFF_GAIN_0*/
0594     { 0x00006E48,   10, 10 }, /*VOFF_GAIN_1*/
0595     { 0x00006E48,   20, 10 }, /*VOFF_GAIN_2*/
0596     { 0x00006E4C,   0,  10 }, /*VOFF_GAIN_3*/
0597     { 0x00006E4C,   10, 10 }, /*VOFF_GAIN_4*/
0598     { 0x00006E4C,   20, 10 }, /*VOFF_GAIN_5*/
0599     { 0x00006E50,   0,  10 }, /*VOFF_GAIN_6*/
0600     { 0x00006E50,   10, 10 }, /*VOFF_GAIN_7*/
0601     { 0x00006E50,   20, 10 }, /*VOFF_GAIN_8*/
0602     { 0x00006E54,   0,  10 }, /*VOFF_GAIN_9*/
0603     { 0x00006E54,   10, 10 }, /*VOFF_GAIN_10*/
0604     { 0x00006E54,   20, 10 }, /*VOFF_GAIN_11*/
0605     { 0x00006E58,   0,  10 }, /*VOFF_GAIN_12*/
0606     { 0x00006E58,   10, 10 }, /*VOFF_GAIN_13*/
0607     { 0x00006E58,   20, 10 }, /*VOFF_GAIN_14*/
0608     { 0x00006E5C,   0,  10 }, /*VOFF_GAIN_15*/
0609     { 0x00006E5C,   10, 10 }, /*VOFF_GAIN_16*/
0610     { 0x00006E5C,   20, 10 }, /*VOFF_GAIN_17*/
0611     { 0x00006E60,   0,  10 }, /*VOFF_GAIN_18*/
0612     { 0x00006E60,   10, 10 }, /*VOFF_GAIN_19*/
0613     { 0x00006E60,   20, 10 }, /*VOFF_GAIN_20*/
0614     { 0x00006E64,   0,  10 }, /*VOFF_INT1*/
0615     { 0x00007418,   7,  5 }, /*DS_SPK_INT1_CAP_TRIM*/
0616     { 0x0000741C,   0,  5 }, /*DS_SPK_INT2_CAP_TRIM*/
0617     { 0x0000741C,   11, 4 }, /*DS_SPK_LPF_CAP_TRIM*/
0618     { 0x0000741C,   19, 4 }, /*DS_SPK_QUAN_CAP_TRIM*/
0619     { 0x00007434,   17, 1 }, /*FORCE_CAL*/
0620     { 0x00007434,   18, 7 }, /*CAL_OVERRIDE*/
0621     { 0x00007068,   0,  9 }, /*MODIX*/
0622     { 0x0000410C,   7,  1 }, /*VIMON_DLY_NOT_COMB*/
0623     { 0x0000400C,   0,  7 }, /*VIMON_DLY*/
0624     { 0x00004000,   11, 1 }, /*VMON_POL*/
0625     { 0x00017040,   0,  8 }, /*X_COORDINATE*/
0626     { 0x00017040,   8,  8 }, /*Y_COORDINATE*/
0627     { 0x00017040,   16, 8 }, /*WAFER_ID*/
0628     { 0x00017040,   24, 8 }, /*DVS*/
0629     { 0x00017044,   0,  24 }, /*LOT_NUMBER*/
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 /* Must be called with the TEST_KEY unlocked */
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 /* both bit_offset and otp_map[i].size are 0 */
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 /* Must be called with the TEST_KEY unlocked */
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:  /* 1.0 uH */
0993         bst_lbst_val = 0;
0994         break;
0995     case 1200:  /* 1.2 uH */
0996         bst_lbst_val = 1;
0997         break;
0998     case 1500:  /* 1.5 uH */
0999         bst_lbst_val = 2;
1000         break;
1001     case 2200:  /* 2.2 uH */
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         /* 201 uF and greater */
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 }, // GLOBAL_EN = 1
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         /* Only CLSA0100 doesn't use GPIO as VSPK switch, but even on that laptop we can
1132          * toggle GPIO1 as is not connected to anything.
1133          * There will be no other device without VSPK switch.
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     /* There is only one laptop that doesn't have VSPK switch. */
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     // Set mailbox cmd
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     // Read mailbox status and verify it is appropriate for the given cmd
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     // Don't wait for ACK since bus activity would wake the device
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");