diff options
Diffstat (limited to 'sound/soc/codecs/lpass-va-macro.c')
| -rw-r--r-- | sound/soc/codecs/lpass-va-macro.c | 104 |
1 files changed, 69 insertions, 35 deletions
diff --git a/sound/soc/codecs/lpass-va-macro.c b/sound/soc/codecs/lpass-va-macro.c index 92c177b82a02..528d5b167ecf 100644 --- a/sound/soc/codecs/lpass-va-macro.c +++ b/sound/soc/codecs/lpass-va-macro.c @@ -1,6 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-only // Copyright (c) 2018-2020, The Linux Foundation. All rights reserved. +#include <linux/bitfield.h> #include <linux/clk.h> #include <linux/clk-provider.h> #include <linux/init.h> @@ -64,8 +65,15 @@ #define CDC_VA_TOP_CSR_I2S_CLK (0x00A8) #define CDC_VA_TOP_CSR_I2S_RESET (0x00AC) #define CDC_VA_TOP_CSR_CORE_ID_0 (0x00C0) + #define CORE_ID_0_REV_MAJ GENMASK(7, 0) #define CDC_VA_TOP_CSR_CORE_ID_1 (0x00C4) +#define CORE_ID_1_HAS_WSAMACRO BIT(0) +#define CORE_ID_1_HAS_RXMACRO BIT(1) +#define CORE_ID_1_HAS_TXMACRO BIT(2) +#define CORE_ID_1_HAS_VAMACRO BIT(3) #define CDC_VA_TOP_CSR_CORE_ID_2 (0x00C8) + #define CORE_ID_2_REV_MIN GENMASK(7, 4) + #define CORE_ID_2_REV_STEP GENMASK(3, 0) #define CDC_VA_TOP_CSR_CORE_ID_3 (0x00CC) #define CDC_VA_TOP_CSR_SWR_MIC_CTL0 (0x00D0) #define CDC_VA_TOP_CSR_SWR_MIC_CTL1 (0x00D4) @@ -516,8 +524,7 @@ static int va_macro_mclk_event(struct snd_soc_dapm_widget *w, static int va_macro_put_dec_enum(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { - struct snd_soc_dapm_widget *widget = - snd_soc_dapm_kcontrol_widget(kcontrol); + struct snd_soc_dapm_widget *widget = snd_soc_dapm_kcontrol_to_widget(kcontrol); struct snd_soc_component *component = snd_soc_dapm_to_component(widget->dapm); struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; @@ -556,8 +563,7 @@ static int va_macro_put_dec_enum(struct snd_kcontrol *kcontrol, static int va_macro_tx_mixer_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { - struct snd_soc_dapm_widget *widget = - snd_soc_dapm_kcontrol_widget(kcontrol); + struct snd_soc_dapm_widget *widget = snd_soc_dapm_kcontrol_to_widget(kcontrol); struct snd_soc_component *component = snd_soc_dapm_to_component(widget->dapm); struct soc_mixer_control *mc = @@ -577,8 +583,7 @@ static int va_macro_tx_mixer_get(struct snd_kcontrol *kcontrol, static int va_macro_tx_mixer_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { - struct snd_soc_dapm_widget *widget = - snd_soc_dapm_kcontrol_widget(kcontrol); + struct snd_soc_dapm_widget *widget = snd_soc_dapm_kcontrol_to_widget(kcontrol); struct snd_soc_component *component = snd_soc_dapm_to_component(widget->dapm); struct snd_soc_dapm_update *update = NULL; @@ -819,7 +824,7 @@ static int va_macro_enable_dec(struct snd_soc_dapm_widget *w, static int va_macro_dec_mode_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { - struct snd_soc_component *comp = snd_soc_kcontrol_component(kcontrol); + struct snd_soc_component *comp = snd_kcontrol_chip(kcontrol); struct va_macro *va = snd_soc_component_get_drvdata(comp); struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; int path = e->shift_l; @@ -832,7 +837,7 @@ static int va_macro_dec_mode_get(struct snd_kcontrol *kcontrol, static int va_macro_dec_mode_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { - struct snd_soc_component *comp = snd_soc_kcontrol_component(kcontrol); + struct snd_soc_component *comp = snd_kcontrol_chip(kcontrol); int value = ucontrol->value.enumerated.item[0]; struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; int path = e->shift_l; @@ -1462,39 +1467,63 @@ undefined_rate: return dmic_sample_rate; } -static void va_macro_set_lpass_codec_version(struct va_macro *va) +static int va_macro_set_lpass_codec_version(struct va_macro *va) { - int core_id_0 = 0, core_id_1 = 0, core_id_2 = 0; int version = LPASS_CODEC_VERSION_UNKNOWN; + u32 maj, min, step; + u32 val; - regmap_read(va->regmap, CDC_VA_TOP_CSR_CORE_ID_0, &core_id_0); - regmap_read(va->regmap, CDC_VA_TOP_CSR_CORE_ID_1, &core_id_1); - regmap_read(va->regmap, CDC_VA_TOP_CSR_CORE_ID_2, &core_id_2); + regmap_read(va->regmap, CDC_VA_TOP_CSR_CORE_ID_0, &val); + maj = FIELD_GET(CORE_ID_0_REV_MAJ, val); - if ((core_id_0 == 0x01) && (core_id_1 == 0x0F)) - version = LPASS_CODEC_VERSION_2_0; - if ((core_id_0 == 0x02) && (core_id_1 == 0x0F) && core_id_2 == 0x01) + regmap_read(va->regmap, CDC_VA_TOP_CSR_CORE_ID_1, &val); + if (!FIELD_GET(CORE_ID_1_HAS_VAMACRO, val)) { + dev_err(va->dev, "This is not a VA macro instance\n"); + return -ENODEV; + } + + regmap_read(va->regmap, CDC_VA_TOP_CSR_CORE_ID_2, &val); + min = FIELD_GET(CORE_ID_2_REV_MIN, val); + step = FIELD_GET(CORE_ID_2_REV_STEP, val); + + if (maj == 1) { version = LPASS_CODEC_VERSION_2_0; - if ((core_id_0 == 0x02) && (core_id_1 == 0x0E)) - version = LPASS_CODEC_VERSION_2_1; - if ((core_id_0 == 0x02) && (core_id_1 == 0x0F) && (core_id_2 == 0x50 || core_id_2 == 0x51)) - version = LPASS_CODEC_VERSION_2_5; - if ((core_id_0 == 0x02) && (core_id_1 == 0x0F) && (core_id_2 == 0x60 || core_id_2 == 0x61)) - version = LPASS_CODEC_VERSION_2_6; - if ((core_id_0 == 0x02) && (core_id_1 == 0x0F) && (core_id_2 == 0x70 || core_id_2 == 0x71)) - version = LPASS_CODEC_VERSION_2_7; - if ((core_id_0 == 0x02) && (core_id_1 == 0x0F) && (core_id_2 == 0x80 || core_id_2 == 0x81)) - version = LPASS_CODEC_VERSION_2_8; - if ((core_id_0 == 0x02) && (core_id_1 == 0x0F) && (core_id_2 == 0x90 || core_id_2 == 0x91)) - version = LPASS_CODEC_VERSION_2_9; - - if (version == LPASS_CODEC_VERSION_UNKNOWN) - dev_warn(va->dev, "Unknown Codec version, ID: %02x / %02x / %02x\n", - core_id_0, core_id_1, core_id_2); + } else if (maj == 2) { + switch (min) { + case 0: + version = LPASS_CODEC_VERSION_2_0; + break; + case 5: + version = LPASS_CODEC_VERSION_2_5; + break; + case 6: + version = LPASS_CODEC_VERSION_2_6; + break; + case 7: + version = LPASS_CODEC_VERSION_2_7; + break; + case 8: + version = LPASS_CODEC_VERSION_2_8; + break; + case 9: + version = LPASS_CODEC_VERSION_2_9; + break; + default: + break; + } + } + + if (version == LPASS_CODEC_VERSION_UNKNOWN) { + dev_err(va->dev, "VA Macro v%u.%u.%u is not supported\n", + maj, min, step); + return -EOPNOTSUPP; + } lpass_macro_set_codec_version(version); dev_dbg(va->dev, "LPASS Codec Version %s\n", lpass_macro_get_codec_version_string(version)); + + return 0; } static int va_macro_probe(struct platform_device *pdev) @@ -1594,10 +1623,14 @@ static int va_macro_probe(struct platform_device *pdev) * old version of codecs do not have a reliable way to determine the * version from registers, get them from soc specific data */ - if (data->version) + if (data->version) { lpass_macro_set_codec_version(data->version); - else /* read version from register */ - va_macro_set_lpass_codec_version(va); + } else { + /* read version from register */ + ret = va_macro_set_lpass_codec_version(va); + if (ret) + goto err_clkout; + } if (va->has_swr_master) { /* Set default CLK div to 1 */ @@ -1723,6 +1756,7 @@ static const struct dev_pm_ops va_macro_pm_ops = { static const struct of_device_id va_macro_dt_match[] = { { .compatible = "qcom,sc7280-lpass-va-macro", .data = &sm8250_va_data }, + { .compatible = "qcom,sm6115-lpass-va-macro", .data = &sm8450_va_data }, { .compatible = "qcom,sm8250-lpass-va-macro", .data = &sm8250_va_data }, { .compatible = "qcom,sm8450-lpass-va-macro", .data = &sm8450_va_data }, { .compatible = "qcom,sm8550-lpass-va-macro", .data = &sm8550_va_data }, |
