diff --git a/sound/soc/codecs/lpass-wsa-macro.c b/sound/soc/codecs/lpass-wsa-macro.c index 1a36a384cc886..8cdf8f7f64b17 100644 --- a/sound/soc/codecs/lpass-wsa-macro.c +++ b/sound/soc/codecs/lpass-wsa-macro.c @@ -44,11 +44,7 @@ #define CDC_WSA_TOP_I2S_CLK (0x00A4) #define CDC_WSA_TOP_I2S_RESET (0x00A8) #define CDC_WSA_RX_INP_MUX_RX_INT0_CFG0 (0x0100) -#define CDC_WSA_RX_INTX_1_MIX_INP0_SEL_MASK GENMASK(2, 0) -#define CDC_WSA_RX_INTX_1_MIX_INP1_SEL_MASK GENMASK(5, 3) #define CDC_WSA_RX_INP_MUX_RX_INT0_CFG1 (0x0104) -#define CDC_WSA_RX_INTX_2_SEL_MASK GENMASK(2, 0) -#define CDC_WSA_RX_INTX_1_MIX_INP2_SEL_MASK GENMASK(5, 3) #define CDC_WSA_RX_INP_MUX_RX_INT1_CFG0 (0x0108) #define CDC_WSA_RX_INP_MUX_RX_INT1_CFG1 (0x010C) #define CDC_WSA_RX_INP_MUX_RX_MIX_CFG0 (0x0110) @@ -173,22 +169,7 @@ #define CDC_WSA_COMPANDER0_CTL5 (0x0594) #define CDC_WSA_COMPANDER0_CTL6 (0x0598) #define CDC_WSA_COMPANDER0_CTL7 (0x059C) -#define CDC_WSA_COMPANDER1_CTL0 (0x05C0) -#define CDC_WSA_COMPANDER1_CTL1 (0x05C4) -#define CDC_WSA_COMPANDER1_CTL2 (0x05C8) -#define CDC_WSA_COMPANDER1_CTL3 (0x05CC) -#define CDC_WSA_COMPANDER1_CTL4 (0x05D0) -#define CDC_WSA_COMPANDER1_CTL5 (0x05D4) -#define CDC_WSA_COMPANDER1_CTL6 (0x05D8) -#define CDC_WSA_COMPANDER1_CTL7 (0x05DC) -#define CDC_WSA_SOFTCLIP0_CRC (0x0600) -#define CDC_WSA_SOFTCLIP_CLK_EN_MASK BIT(0) -#define CDC_WSA_SOFTCLIP_CLK_ENABLE BIT(0) -#define CDC_WSA_SOFTCLIP0_SOFTCLIP_CTRL (0x0604) -#define CDC_WSA_SOFTCLIP_EN_MASK BIT(0) -#define CDC_WSA_SOFTCLIP_ENABLE BIT(0) -#define CDC_WSA_SOFTCLIP1_CRC (0x0640) -#define CDC_WSA_SOFTCLIP1_SOFTCLIP_CTRL (0x0644) +/* CDC_WSA_COMPANDER1_CTLx and CDC_WSA_SOFTCLIPx differ per LPASS codec versions */ #define CDC_WSA_EC_HQ0_EC_REF_HQ_PATH_CTL (0x0680) #define CDC_WSA_EC_HQ_EC_CLK_EN_MASK BIT(0) #define CDC_WSA_EC_HQ_EC_CLK_ENABLE BIT(0) @@ -217,6 +198,24 @@ #define CDC_WSA_SPLINE_ASRC1_STATUS_FIFO (0x0760) #define WSA_MAX_OFFSET (0x0760) +/* LPASS codec version <=2.4 register offsets */ +#define CDC_WSA_COMPANDER1_CTL0 (0x05C0) +#define CDC_WSA_COMPANDER1_CTL1 (0x05C4) +#define CDC_WSA_COMPANDER1_CTL2 (0x05C8) +#define CDC_WSA_COMPANDER1_CTL3 (0x05CC) +#define CDC_WSA_COMPANDER1_CTL4 (0x05D0) +#define CDC_WSA_COMPANDER1_CTL5 (0x05D4) +#define CDC_WSA_COMPANDER1_CTL6 (0x05D8) +#define CDC_WSA_COMPANDER1_CTL7 (0x05DC) +#define CDC_WSA_SOFTCLIP0_CRC (0x0600) +#define CDC_WSA_SOFTCLIP_CLK_EN_MASK BIT(0) +#define CDC_WSA_SOFTCLIP_CLK_ENABLE BIT(0) +#define CDC_WSA_SOFTCLIP0_SOFTCLIP_CTRL (0x0604) +#define CDC_WSA_SOFTCLIP_EN_MASK BIT(0) +#define CDC_WSA_SOFTCLIP_ENABLE BIT(0) +#define CDC_WSA_SOFTCLIP1_CRC (0x0640) +#define CDC_WSA_SOFTCLIP1_SOFTCLIP_CTRL (0x0644) + #define WSA_MACRO_RX_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 |\ SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000 |\ SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_192000) @@ -237,8 +236,6 @@ #define WSA_MACRO_MCLK_FREQ 19200000 #define WSA_MACRO_MUX_CFG_OFFSET 0x8 #define WSA_MACRO_MUX_CFG1_OFFSET 0x4 -#define WSA_MACRO_RX_COMP_OFFSET 0x40 -#define WSA_MACRO_RX_SOFTCLIP_OFFSET 0x40 #define WSA_MACRO_RX_PATH_OFFSET 0x80 #define WSA_MACRO_RX_PATH_CFG3_OFFSET 0x10 #define WSA_MACRO_RX_PATH_DSMDEM_OFFSET 0x4C @@ -334,12 +331,34 @@ enum { WSA_MACRO_MAX_DAIS, }; +/** + * struct wsa_reg_layout - Register layout differences + * @rx_intx_1_mix_inp0_sel_mask: register mask for RX_INTX_1_MIX_INP0_SEL_MASK + * @rx_intx_1_mix_inp1_sel_mask: register mask for RX_INTX_1_MIX_INP1_SEL_MASK + * @rx_intx_1_mix_inp2_sel_mask: register mask for RX_INTX_1_MIX_INP2_SEL_MASK + * @rx_intx_2_sel_mask: register mask for RX_INTX_2_SEL_MASK + * @compander1_reg_offset: offset between compander registers (compander1 - compander0) + * @softclip0_reg_base: base address of softclip0 register + * @softclip1_reg_offset: offset between compander registers (softclip1 - softclip0) + */ +struct wsa_reg_layout { + unsigned int rx_intx_1_mix_inp0_sel_mask; + unsigned int rx_intx_1_mix_inp1_sel_mask; + unsigned int rx_intx_1_mix_inp2_sel_mask; + unsigned int rx_intx_2_sel_mask; + unsigned int compander1_reg_offset; + unsigned int softclip0_reg_base; + unsigned int softclip1_reg_offset; +}; + struct wsa_macro { struct device *dev; int comp_enabled[WSA_MACRO_COMP_MAX]; int ec_hq[WSA_MACRO_RX1 + 1]; u16 prim_int_users[WSA_MACRO_RX1 + 1]; u16 wsa_mclk_users; + enum lpass_codec_version codec_version; + const struct wsa_reg_layout *reg_layout; unsigned long active_ch_mask[WSA_MACRO_MAX_DAIS]; unsigned long active_ch_cnt[WSA_MACRO_MAX_DAIS]; int rx_port_value[WSA_MACRO_RX_MAX]; @@ -358,13 +377,23 @@ struct wsa_macro { }; #define to_wsa_macro(_hw) container_of(_hw, struct wsa_macro, hw) +static const struct wsa_reg_layout wsa_codec_v2_1 = { + .rx_intx_1_mix_inp0_sel_mask = GENMASK(2, 0), + .rx_intx_1_mix_inp1_sel_mask = GENMASK(5, 3), + .rx_intx_1_mix_inp2_sel_mask = GENMASK(5, 3), + .rx_intx_2_sel_mask = GENMASK(2, 0), + .compander1_reg_offset = 0x40, + .softclip0_reg_base = 0x600, + .softclip1_reg_offset = 0x40, +}; + static const DECLARE_TLV_DB_SCALE(digital_gain, -8400, 100, -8400); -static const char *const rx_text[] = { +static const char *const rx_text_v2_1[] = { "ZERO", "RX0", "RX1", "RX_MIX0", "RX_MIX1", "DEC0", "DEC1" }; -static const char *const rx_mix_text[] = { +static const char *const rx_mix_text_v2_1[] = { "ZERO", "RX0", "RX1", "RX_MIX0", "RX_MIX1" }; @@ -389,68 +418,68 @@ static SOC_ENUM_SINGLE_EXT_DECL(wsa_macro_ear_spkr_pa_gain_enum, wsa_macro_ear_spkr_pa_gain_text); /* RX INT0 */ -static const struct soc_enum rx0_prim_inp0_chain_enum = +static const struct soc_enum rx0_prim_inp0_chain_enum_v2_1 = SOC_ENUM_SINGLE(CDC_WSA_RX_INP_MUX_RX_INT0_CFG0, - 0, 7, rx_text); + 0, 7, rx_text_v2_1); -static const struct soc_enum rx0_prim_inp1_chain_enum = +static const struct soc_enum rx0_prim_inp1_chain_enum_v2_1 = SOC_ENUM_SINGLE(CDC_WSA_RX_INP_MUX_RX_INT0_CFG0, - 3, 7, rx_text); + 3, 7, rx_text_v2_1); -static const struct soc_enum rx0_prim_inp2_chain_enum = +static const struct soc_enum rx0_prim_inp2_chain_enum_v2_1 = SOC_ENUM_SINGLE(CDC_WSA_RX_INP_MUX_RX_INT0_CFG1, - 3, 7, rx_text); + 3, 7, rx_text_v2_1); -static const struct soc_enum rx0_mix_chain_enum = +static const struct soc_enum rx0_mix_chain_enum_v2_1 = SOC_ENUM_SINGLE(CDC_WSA_RX_INP_MUX_RX_INT0_CFG1, - 0, 5, rx_mix_text); + 0, 5, rx_mix_text_v2_1); static const struct soc_enum rx0_sidetone_mix_enum = SOC_ENUM_SINGLE(SND_SOC_NOPM, 0, 2, rx_sidetone_mix_text); -static const struct snd_kcontrol_new rx0_prim_inp0_mux = - SOC_DAPM_ENUM("WSA_RX0 INP0 Mux", rx0_prim_inp0_chain_enum); +static const struct snd_kcontrol_new rx0_prim_inp0_mux_v2_1 = + SOC_DAPM_ENUM("WSA_RX0 INP0 Mux", rx0_prim_inp0_chain_enum_v2_1); -static const struct snd_kcontrol_new rx0_prim_inp1_mux = - SOC_DAPM_ENUM("WSA_RX0 INP1 Mux", rx0_prim_inp1_chain_enum); +static const struct snd_kcontrol_new rx0_prim_inp1_mux_v2_1 = + SOC_DAPM_ENUM("WSA_RX0 INP1 Mux", rx0_prim_inp1_chain_enum_v2_1); -static const struct snd_kcontrol_new rx0_prim_inp2_mux = - SOC_DAPM_ENUM("WSA_RX0 INP2 Mux", rx0_prim_inp2_chain_enum); +static const struct snd_kcontrol_new rx0_prim_inp2_mux_v2_1 = + SOC_DAPM_ENUM("WSA_RX0 INP2 Mux", rx0_prim_inp2_chain_enum_v2_1); -static const struct snd_kcontrol_new rx0_mix_mux = - SOC_DAPM_ENUM("WSA_RX0 MIX Mux", rx0_mix_chain_enum); +static const struct snd_kcontrol_new rx0_mix_mux_v2_1 = + SOC_DAPM_ENUM("WSA_RX0 MIX Mux", rx0_mix_chain_enum_v2_1); static const struct snd_kcontrol_new rx0_sidetone_mix_mux = SOC_DAPM_ENUM("WSA_RX0 SIDETONE MIX Mux", rx0_sidetone_mix_enum); /* RX INT1 */ -static const struct soc_enum rx1_prim_inp0_chain_enum = +static const struct soc_enum rx1_prim_inp0_chain_enum_v2_1 = SOC_ENUM_SINGLE(CDC_WSA_RX_INP_MUX_RX_INT1_CFG0, - 0, 7, rx_text); + 0, 7, rx_text_v2_1); -static const struct soc_enum rx1_prim_inp1_chain_enum = +static const struct soc_enum rx1_prim_inp1_chain_enum_v2_1 = SOC_ENUM_SINGLE(CDC_WSA_RX_INP_MUX_RX_INT1_CFG0, - 3, 7, rx_text); + 3, 7, rx_text_v2_1); -static const struct soc_enum rx1_prim_inp2_chain_enum = +static const struct soc_enum rx1_prim_inp2_chain_enum_v2_1 = SOC_ENUM_SINGLE(CDC_WSA_RX_INP_MUX_RX_INT1_CFG1, - 3, 7, rx_text); + 3, 7, rx_text_v2_1); -static const struct soc_enum rx1_mix_chain_enum = +static const struct soc_enum rx1_mix_chain_enum_v2_1 = SOC_ENUM_SINGLE(CDC_WSA_RX_INP_MUX_RX_INT1_CFG1, - 0, 5, rx_mix_text); + 0, 5, rx_mix_text_v2_1); -static const struct snd_kcontrol_new rx1_prim_inp0_mux = - SOC_DAPM_ENUM("WSA_RX1 INP0 Mux", rx1_prim_inp0_chain_enum); +static const struct snd_kcontrol_new rx1_prim_inp0_mux_v2_1 = + SOC_DAPM_ENUM("WSA_RX1 INP0 Mux", rx1_prim_inp0_chain_enum_v2_1); -static const struct snd_kcontrol_new rx1_prim_inp1_mux = - SOC_DAPM_ENUM("WSA_RX1 INP1 Mux", rx1_prim_inp1_chain_enum); +static const struct snd_kcontrol_new rx1_prim_inp1_mux_v2_1 = + SOC_DAPM_ENUM("WSA_RX1 INP1 Mux", rx1_prim_inp1_chain_enum_v2_1); -static const struct snd_kcontrol_new rx1_prim_inp2_mux = - SOC_DAPM_ENUM("WSA_RX1 INP2 Mux", rx1_prim_inp2_chain_enum); +static const struct snd_kcontrol_new rx1_prim_inp2_mux_v2_1 = + SOC_DAPM_ENUM("WSA_RX1 INP2 Mux", rx1_prim_inp2_chain_enum_v2_1); -static const struct snd_kcontrol_new rx1_mix_mux = - SOC_DAPM_ENUM("WSA_RX1 MIX Mux", rx1_mix_chain_enum); +static const struct snd_kcontrol_new rx1_mix_mux_v2_1 = + SOC_DAPM_ENUM("WSA_RX1 MIX Mux", rx1_mix_chain_enum_v2_1); static const struct soc_enum rx_mix_ec0_enum = SOC_ENUM_SINGLE(CDC_WSA_RX_INP_MUX_RX_MIX_CFG0, @@ -489,14 +518,6 @@ static const struct reg_default wsa_defaults[] = { { CDC_WSA_RX_INP_MUX_RX_MIX_CFG0, 0x00}, { CDC_WSA_RX_INP_MUX_RX_EC_CFG0, 0x00}, { CDC_WSA_RX_INP_MUX_SOFTCLIP_CFG0, 0x00}, - { CDC_WSA_TX0_SPKR_PROT_PATH_CTL, 0x02}, - { CDC_WSA_TX0_SPKR_PROT_PATH_CFG0, 0x00}, - { CDC_WSA_TX1_SPKR_PROT_PATH_CTL, 0x02}, - { CDC_WSA_TX1_SPKR_PROT_PATH_CFG0, 0x00}, - { CDC_WSA_TX2_SPKR_PROT_PATH_CTL, 0x02}, - { CDC_WSA_TX2_SPKR_PROT_PATH_CFG0, 0x00}, - { CDC_WSA_TX3_SPKR_PROT_PATH_CTL, 0x02}, - { CDC_WSA_TX3_SPKR_PROT_PATH_CFG0, 0x00}, { CDC_WSA_INTR_CTRL_CFG, 0x00}, { CDC_WSA_INTR_CTRL_CLR_COMMIT, 0x00}, { CDC_WSA_INTR_CTRL_PIN1_MASK0, 0xFF}, @@ -561,18 +582,6 @@ static const struct reg_default wsa_defaults[] = { { CDC_WSA_COMPANDER0_CTL5, 0x00}, { CDC_WSA_COMPANDER0_CTL6, 0x01}, { CDC_WSA_COMPANDER0_CTL7, 0x28}, - { CDC_WSA_COMPANDER1_CTL0, 0x60}, - { CDC_WSA_COMPANDER1_CTL1, 0xDB}, - { CDC_WSA_COMPANDER1_CTL2, 0xFF}, - { CDC_WSA_COMPANDER1_CTL3, 0x35}, - { CDC_WSA_COMPANDER1_CTL4, 0xFF}, - { CDC_WSA_COMPANDER1_CTL5, 0x00}, - { CDC_WSA_COMPANDER1_CTL6, 0x01}, - { CDC_WSA_COMPANDER1_CTL7, 0x28}, - { CDC_WSA_SOFTCLIP0_CRC, 0x00}, - { CDC_WSA_SOFTCLIP0_SOFTCLIP_CTRL, 0x38}, - { CDC_WSA_SOFTCLIP1_CRC, 0x00}, - { CDC_WSA_SOFTCLIP1_SOFTCLIP_CTRL, 0x38}, { CDC_WSA_EC_HQ0_EC_REF_HQ_PATH_CTL, 0x00}, { CDC_WSA_EC_HQ0_EC_REF_HQ_CFG0, 0x01}, { CDC_WSA_EC_HQ1_EC_REF_HQ_PATH_CTL, 0x00}, @@ -597,6 +606,29 @@ static const struct reg_default wsa_defaults[] = { { CDC_WSA_SPLINE_ASRC1_STATUS_FIFO, 0x00}, }; +static const struct reg_default wsa_defaults_v2_1[] = { + { CDC_WSA_TX0_SPKR_PROT_PATH_CTL, 0x02}, + { CDC_WSA_TX0_SPKR_PROT_PATH_CFG0, 0x00}, + { CDC_WSA_TX1_SPKR_PROT_PATH_CTL, 0x02}, + { CDC_WSA_TX1_SPKR_PROT_PATH_CFG0, 0x00}, + { CDC_WSA_TX2_SPKR_PROT_PATH_CTL, 0x02}, + { CDC_WSA_TX2_SPKR_PROT_PATH_CFG0, 0x00}, + { CDC_WSA_TX3_SPKR_PROT_PATH_CTL, 0x02}, + { CDC_WSA_TX3_SPKR_PROT_PATH_CFG0, 0x00}, + { CDC_WSA_COMPANDER1_CTL0, 0x60}, + { CDC_WSA_COMPANDER1_CTL1, 0xDB}, + { CDC_WSA_COMPANDER1_CTL2, 0xFF}, + { CDC_WSA_COMPANDER1_CTL3, 0x35}, + { CDC_WSA_COMPANDER1_CTL4, 0xFF}, + { CDC_WSA_COMPANDER1_CTL5, 0x00}, + { CDC_WSA_COMPANDER1_CTL6, 0x01}, + { CDC_WSA_COMPANDER1_CTL7, 0x28}, + { CDC_WSA_SOFTCLIP0_CRC, 0x00}, + { CDC_WSA_SOFTCLIP0_SOFTCLIP_CTRL, 0x38}, + { CDC_WSA_SOFTCLIP1_CRC, 0x00}, + { CDC_WSA_SOFTCLIP1_SOFTCLIP_CTRL, 0x38}, +}; + static bool wsa_is_wronly_register(struct device *dev, unsigned int reg) { @@ -610,6 +642,26 @@ static bool wsa_is_wronly_register(struct device *dev, return false; } +static bool wsa_is_rw_register_v2_1(struct device *dev, unsigned int reg) +{ + switch (reg) { + case CDC_WSA_COMPANDER1_CTL0: + case CDC_WSA_COMPANDER1_CTL1: + case CDC_WSA_COMPANDER1_CTL2: + case CDC_WSA_COMPANDER1_CTL3: + case CDC_WSA_COMPANDER1_CTL4: + case CDC_WSA_COMPANDER1_CTL5: + case CDC_WSA_COMPANDER1_CTL7: + case CDC_WSA_SOFTCLIP0_CRC: + case CDC_WSA_SOFTCLIP0_SOFTCLIP_CTRL: + case CDC_WSA_SOFTCLIP1_CRC: + case CDC_WSA_SOFTCLIP1_SOFTCLIP_CTRL: + return true; + } + + return false; +} + static bool wsa_is_rw_register(struct device *dev, unsigned int reg) { switch (reg) { @@ -701,17 +753,6 @@ static bool wsa_is_rw_register(struct device *dev, unsigned int reg) case CDC_WSA_COMPANDER0_CTL4: case CDC_WSA_COMPANDER0_CTL5: case CDC_WSA_COMPANDER0_CTL7: - case CDC_WSA_COMPANDER1_CTL0: - case CDC_WSA_COMPANDER1_CTL1: - case CDC_WSA_COMPANDER1_CTL2: - case CDC_WSA_COMPANDER1_CTL3: - case CDC_WSA_COMPANDER1_CTL4: - case CDC_WSA_COMPANDER1_CTL5: - case CDC_WSA_COMPANDER1_CTL7: - case CDC_WSA_SOFTCLIP0_CRC: - case CDC_WSA_SOFTCLIP0_SOFTCLIP_CTRL: - case CDC_WSA_SOFTCLIP1_CRC: - case CDC_WSA_SOFTCLIP1_SOFTCLIP_CTRL: case CDC_WSA_EC_HQ0_EC_REF_HQ_PATH_CTL: case CDC_WSA_EC_HQ0_EC_REF_HQ_CFG0: case CDC_WSA_EC_HQ1_EC_REF_HQ_PATH_CTL: @@ -727,7 +768,7 @@ static bool wsa_is_rw_register(struct device *dev, unsigned int reg) return true; } - return false; + return wsa_is_rw_register_v2_1(dev, reg); } static bool wsa_is_writeable_register(struct device *dev, unsigned int reg) @@ -741,6 +782,16 @@ static bool wsa_is_writeable_register(struct device *dev, unsigned int reg) return ret; } +static bool wsa_is_readable_register_v2_1(struct device *dev, unsigned int reg) +{ + switch (reg) { + case CDC_WSA_COMPANDER1_CTL6: + return true; + } + + return wsa_is_rw_register(dev, reg); +} + static bool wsa_is_readable_register(struct device *dev, unsigned int reg) { switch (reg) { @@ -750,7 +801,6 @@ static bool wsa_is_readable_register(struct device *dev, unsigned int reg) case CDC_WSA_INTR_CTRL_PIN1_STATUS0: case CDC_WSA_INTR_CTRL_PIN2_STATUS0: case CDC_WSA_COMPANDER0_CTL6: - case CDC_WSA_COMPANDER1_CTL6: case CDC_WSA_SPLINE_ASRC0_STATUS_FMIN_CNTR_LSB: case CDC_WSA_SPLINE_ASRC0_STATUS_FMIN_CNTR_MSB: case CDC_WSA_SPLINE_ASRC0_STATUS_FMAX_CNTR_LSB: @@ -764,7 +814,17 @@ static bool wsa_is_readable_register(struct device *dev, unsigned int reg) return true; } - return wsa_is_rw_register(dev, reg); + return wsa_is_readable_register_v2_1(dev, reg); +} + +static bool wsa_is_volatile_register_v2_1(struct device *dev, unsigned int reg) +{ + switch (reg) { + case CDC_WSA_COMPANDER1_CTL6: + return true; + } + + return false; } static bool wsa_is_volatile_register(struct device *dev, unsigned int reg) @@ -774,7 +834,6 @@ static bool wsa_is_volatile_register(struct device *dev, unsigned int reg) case CDC_WSA_INTR_CTRL_PIN1_STATUS0: case CDC_WSA_INTR_CTRL_PIN2_STATUS0: case CDC_WSA_COMPANDER0_CTL6: - case CDC_WSA_COMPANDER1_CTL6: case CDC_WSA_SPLINE_ASRC0_STATUS_FMIN_CNTR_LSB: case CDC_WSA_SPLINE_ASRC0_STATUS_FMIN_CNTR_MSB: case CDC_WSA_SPLINE_ASRC0_STATUS_FMAX_CNTR_LSB: @@ -787,7 +846,8 @@ static bool wsa_is_volatile_register(struct device *dev, unsigned int reg) case CDC_WSA_SPLINE_ASRC1_STATUS_FIFO: return true; } - return false; + + return wsa_is_volatile_register_v2_1(dev, reg); } static const struct regmap_config wsa_regmap_config = { @@ -796,8 +856,7 @@ static const struct regmap_config wsa_regmap_config = { .val_bits = 32, /* 8 but with 32 bit read/write */ .reg_stride = 4, .cache_type = REGCACHE_FLAT, - .reg_defaults = wsa_defaults, - .num_reg_defaults = ARRAY_SIZE(wsa_defaults), + /* .reg_defaults and .num_reg_defaults set in probe() */ .max_register = WSA_MAX_OFFSET, .writeable_reg = wsa_is_writeable_register, .volatile_reg = wsa_is_volatile_register, @@ -871,11 +930,11 @@ static int wsa_macro_set_prim_interpolator_rate(struct snd_soc_dai *dai, for (j = 0; j < NUM_INTERPOLATORS; j++) { int_mux_cfg1 = int_mux_cfg0 + WSA_MACRO_MUX_CFG1_OFFSET; inp0_sel = snd_soc_component_read_field(component, int_mux_cfg0, - CDC_WSA_RX_INTX_1_MIX_INP0_SEL_MASK); - inp1_sel = snd_soc_component_read_field(component, int_mux_cfg0, - CDC_WSA_RX_INTX_1_MIX_INP1_SEL_MASK); + wsa->reg_layout->rx_intx_1_mix_inp0_sel_mask); + inp1_sel = snd_soc_component_read_field(component, int_mux_cfg0, + wsa->reg_layout->rx_intx_1_mix_inp1_sel_mask); inp2_sel = snd_soc_component_read_field(component, int_mux_cfg1, - CDC_WSA_RX_INTX_1_MIX_INP2_SEL_MASK); + wsa->reg_layout->rx_intx_1_mix_inp2_sel_mask); if ((inp0_sel == int_1_mix1_inp + INTn_1_INP_SEL_RX0) || (inp1_sel == int_1_mix1_inp + INTn_1_INP_SEL_RX0) || @@ -916,7 +975,7 @@ static int wsa_macro_set_mix_interpolator_rate(struct snd_soc_dai *dai, int_mux_cfg1 = CDC_WSA_RX_INP_MUX_RX_INT0_CFG1; for (j = 0; j < NUM_INTERPOLATORS; j++) { int_mux_cfg1_val = snd_soc_component_read_field(component, int_mux_cfg1, - CDC_WSA_RX_INTX_2_SEL_MASK); + wsa->reg_layout->rx_intx_2_sel_mask); if (int_mux_cfg1_val == int_2_inp + INTn_2_INP_SEL_RX0) { int_fs_reg = CDC_WSA_RX0_RX_PATH_MIX_CTL + @@ -1299,7 +1358,7 @@ static int wsa_macro_config_compander(struct snd_soc_component *component, return 0; comp_ctl0_reg = CDC_WSA_COMPANDER0_CTL0 + - (comp * WSA_MACRO_RX_COMP_OFFSET); + (comp * wsa->reg_layout->compander1_reg_offset); rx_path_cfg0_reg = CDC_WSA_RX0_RX_PATH_CFG0 + (comp * WSA_MACRO_RX_PATH_OFFSET); @@ -1345,8 +1404,8 @@ static void wsa_macro_enable_softclip_clk(struct snd_soc_component *component, int path, bool enable) { - u16 softclip_clk_reg = CDC_WSA_SOFTCLIP0_CRC + - (path * WSA_MACRO_RX_SOFTCLIP_OFFSET); + u16 softclip_clk_reg = wsa->reg_layout->softclip0_reg_base + + (path * wsa->reg_layout->softclip1_reg_offset); u8 softclip_mux_mask = (1 << path); u8 softclip_mux_value = (1 << path); @@ -1391,7 +1450,7 @@ static int wsa_macro_config_softclip(struct snd_soc_component *component, return 0; softclip_ctrl_reg = CDC_WSA_SOFTCLIP0_SOFTCLIP_CTRL + - (softclip_path * WSA_MACRO_RX_SOFTCLIP_OFFSET); + (softclip_path * wsa->reg_layout->softclip1_reg_offset); if (SND_SOC_DAPM_EVENT_ON(event)) { /* Enable Softclip clock and mux */ @@ -1416,6 +1475,7 @@ static int wsa_macro_config_softclip(struct snd_soc_component *component, static bool wsa_macro_adie_lb(struct snd_soc_component *component, int interp_idx) { + struct wsa_macro *wsa = snd_soc_component_get_drvdata(component); u16 int_mux_cfg0, int_mux_cfg1; u8 int_n_inp0, int_n_inp1, int_n_inp2; @@ -1423,19 +1483,19 @@ static bool wsa_macro_adie_lb(struct snd_soc_component *component, int_mux_cfg1 = int_mux_cfg0 + 4; int_n_inp0 = snd_soc_component_read_field(component, int_mux_cfg0, - CDC_WSA_RX_INTX_1_MIX_INP0_SEL_MASK); + wsa->reg_layout->rx_intx_1_mix_inp0_sel_mask); if (int_n_inp0 == INTn_1_INP_SEL_DEC0 || int_n_inp0 == INTn_1_INP_SEL_DEC1) return true; int_n_inp1 = snd_soc_component_read_field(component, int_mux_cfg0, - CDC_WSA_RX_INTX_1_MIX_INP1_SEL_MASK); + wsa->reg_layout->rx_intx_1_mix_inp1_sel_mask); if (int_n_inp1 == INTn_1_INP_SEL_DEC0 || int_n_inp1 == INTn_1_INP_SEL_DEC1) return true; int_n_inp2 = snd_soc_component_read_field(component, int_mux_cfg1, - CDC_WSA_RX_INTX_1_MIX_INP2_SEL_MASK); + wsa->reg_layout->rx_intx_1_mix_inp2_sel_mask); if (int_n_inp2 == INTn_1_INP_SEL_DEC0 || int_n_inp2 == INTn_1_INP_SEL_DEC1) return true; @@ -2073,19 +2133,6 @@ static const struct snd_soc_dapm_widget wsa_macro_dapm_widgets[] = { SND_SOC_DAPM_MIXER("WSA RX_MIX0", SND_SOC_NOPM, 0, 0, NULL, 0), SND_SOC_DAPM_MIXER("WSA RX_MIX1", SND_SOC_NOPM, 0, 0, NULL, 0), - SND_SOC_DAPM_MUX("WSA_RX0 INP0", SND_SOC_NOPM, 0, 0, &rx0_prim_inp0_mux), - SND_SOC_DAPM_MUX("WSA_RX0 INP1", SND_SOC_NOPM, 0, 0, &rx0_prim_inp1_mux), - SND_SOC_DAPM_MUX("WSA_RX0 INP2", SND_SOC_NOPM, 0, 0, &rx0_prim_inp2_mux), - SND_SOC_DAPM_MUX_E("WSA_RX0 MIX INP", SND_SOC_NOPM, WSA_MACRO_RX_MIX0, - 0, &rx0_mix_mux, wsa_macro_enable_mix_path, - SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), - SND_SOC_DAPM_MUX("WSA_RX1 INP0", SND_SOC_NOPM, 0, 0, &rx1_prim_inp0_mux), - SND_SOC_DAPM_MUX("WSA_RX1 INP1", SND_SOC_NOPM, 0, 0, &rx1_prim_inp1_mux), - SND_SOC_DAPM_MUX("WSA_RX1 INP2", SND_SOC_NOPM, 0, 0, &rx1_prim_inp2_mux), - SND_SOC_DAPM_MUX_E("WSA_RX1 MIX INP", SND_SOC_NOPM, WSA_MACRO_RX_MIX1, - 0, &rx1_mix_mux, wsa_macro_enable_mix_path, - SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), - SND_SOC_DAPM_MIXER_E("WSA_RX INT0 MIX", SND_SOC_NOPM, 0, 0, NULL, 0, wsa_macro_enable_main_path, SND_SOC_DAPM_PRE_PMU), SND_SOC_DAPM_MIXER_E("WSA_RX INT1 MIX", SND_SOC_NOPM, 1, 0, NULL, 0, @@ -2136,6 +2183,21 @@ static const struct snd_soc_dapm_widget wsa_macro_dapm_widgets[] = { SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), }; +static const struct snd_soc_dapm_widget wsa_macro_dapm_widgets_v2_1[] = { + SND_SOC_DAPM_MUX("WSA_RX0 INP0", SND_SOC_NOPM, 0, 0, &rx0_prim_inp0_mux_v2_1), + SND_SOC_DAPM_MUX("WSA_RX0 INP1", SND_SOC_NOPM, 0, 0, &rx0_prim_inp1_mux_v2_1), + SND_SOC_DAPM_MUX("WSA_RX0 INP2", SND_SOC_NOPM, 0, 0, &rx0_prim_inp2_mux_v2_1), + SND_SOC_DAPM_MUX_E("WSA_RX0 MIX INP", SND_SOC_NOPM, WSA_MACRO_RX_MIX0, + 0, &rx0_mix_mux_v2_1, wsa_macro_enable_mix_path, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), + SND_SOC_DAPM_MUX("WSA_RX1 INP0", SND_SOC_NOPM, 0, 0, &rx1_prim_inp0_mux_v2_1), + SND_SOC_DAPM_MUX("WSA_RX1 INP1", SND_SOC_NOPM, 0, 0, &rx1_prim_inp1_mux_v2_1), + SND_SOC_DAPM_MUX("WSA_RX1 INP2", SND_SOC_NOPM, 0, 0, &rx1_prim_inp2_mux_v2_1), + SND_SOC_DAPM_MUX_E("WSA_RX1 MIX INP", SND_SOC_NOPM, WSA_MACRO_RX_MIX1, + 0, &rx1_mix_mux_v2_1, wsa_macro_enable_mix_path, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), +}; + static const struct snd_soc_dapm_route wsa_audio_map[] = { /* VI Feedback */ {"WSA_AIF_VI Mixer", "WSA_SPKR_VI_1", "VIINPUT_WSA"}, @@ -2281,7 +2343,10 @@ static int wsa_swrm_clock(struct wsa_macro *wsa, bool enable) static int wsa_macro_component_probe(struct snd_soc_component *comp) { + struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(comp); struct wsa_macro *wsa = snd_soc_component_get_drvdata(comp); + const struct snd_soc_dapm_widget *widgets; + unsigned int num_widgets; snd_soc_component_init_regmap(comp, wsa->regmap); @@ -2298,7 +2363,10 @@ static int wsa_macro_component_probe(struct snd_soc_component *comp) wsa_macro_set_spkr_mode(comp, WSA_MACRO_SPKR_MODE_1); - return 0; + widgets = wsa_macro_dapm_widgets_v2_1; + num_widgets = ARRAY_SIZE(wsa_macro_dapm_widgets_v2_1); + + return snd_soc_dapm_new_controls(dapm, widgets, num_widgets); } static int swclk_gate_enable(struct clk_hw *hw) @@ -2378,10 +2446,12 @@ static const struct snd_soc_component_driver wsa_macro_component_drv = { static int wsa_macro_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; + struct reg_default *reg_defaults; + struct regmap_config *reg_config; struct wsa_macro *wsa; kernel_ulong_t flags; void __iomem *base; - int ret; + int ret, def_count; flags = (kernel_ulong_t)device_get_match_data(dev); @@ -2415,10 +2485,36 @@ static int wsa_macro_probe(struct platform_device *pdev) if (IS_ERR(base)) return PTR_ERR(base); - wsa->regmap = devm_regmap_init_mmio(dev, base, &wsa_regmap_config); + wsa->codec_version = lpass_macro_get_codec_version(); + switch (wsa->codec_version) { + default: + wsa->reg_layout = &wsa_codec_v2_1; + def_count = ARRAY_SIZE(wsa_defaults) + ARRAY_SIZE(wsa_defaults_v2_1); + reg_defaults = devm_kmalloc_array(dev, def_count, + sizeof(*reg_defaults), + GFP_KERNEL); + if (!reg_defaults) + return -ENOMEM; + memcpy(®_defaults[0], wsa_defaults, sizeof(wsa_defaults)); + memcpy(®_defaults[ARRAY_SIZE(wsa_defaults)], + wsa_defaults_v2_1, sizeof(wsa_defaults_v2_1)); + break; + } + + reg_config = devm_kmemdup(dev, &wsa_regmap_config, + sizeof(*reg_config), GFP_KERNEL); + if (!reg_config) + return -ENOMEM; + + reg_config->reg_defaults = reg_defaults; + reg_config->num_reg_defaults = def_count; + + wsa->regmap = devm_regmap_init_mmio(dev, base, reg_config); if (IS_ERR(wsa->regmap)) return PTR_ERR(wsa->regmap); + devm_kfree(dev, reg_config); + devm_kfree(dev, reg_defaults); dev_set_drvdata(dev, wsa); wsa->dev = dev;