diff options
Diffstat (limited to 'sound/soc/codecs/lpass-va-macro.c')
| -rw-r--r-- | sound/soc/codecs/lpass-va-macro.c | 113 |
1 files changed, 74 insertions, 39 deletions
diff --git a/sound/soc/codecs/lpass-va-macro.c b/sound/soc/codecs/lpass-va-macro.c index c781da476240..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) @@ -165,7 +173,6 @@ static const DECLARE_TLV_DB_SCALE(digital_gain, -8400, 100, -8400); enum { - VA_MACRO_AIF_INVALID = 0, VA_MACRO_AIF1_CAP, VA_MACRO_AIF2_CAP, VA_MACRO_AIF3_CAP, @@ -517,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; @@ -557,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 = @@ -578,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; @@ -820,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; @@ -833,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; @@ -1463,37 +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 (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) @@ -1593,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 */ @@ -1637,7 +1671,7 @@ static int va_macro_probe(struct platform_device *pdev) if (ret) goto err_clkout; - va->fsgen = clk_hw_get_clk(&va->hw, "fsgen"); + va->fsgen = devm_clk_hw_get_clk(dev, &va->hw, "fsgen"); if (IS_ERR(va->fsgen)) { ret = PTR_ERR(va->fsgen); goto err_clkout; @@ -1674,7 +1708,7 @@ static void va_macro_remove(struct platform_device *pdev) lpass_macro_pds_exit(va->pds); } -static int __maybe_unused va_macro_runtime_suspend(struct device *dev) +static int va_macro_runtime_suspend(struct device *dev) { struct va_macro *va = dev_get_drvdata(dev); @@ -1689,7 +1723,7 @@ static int __maybe_unused va_macro_runtime_suspend(struct device *dev) return 0; } -static int __maybe_unused va_macro_runtime_resume(struct device *dev) +static int va_macro_runtime_resume(struct device *dev) { struct va_macro *va = dev_get_drvdata(dev); int ret; @@ -1717,11 +1751,12 @@ static int __maybe_unused va_macro_runtime_resume(struct device *dev) static const struct dev_pm_ops va_macro_pm_ops = { - SET_RUNTIME_PM_OPS(va_macro_runtime_suspend, va_macro_runtime_resume, NULL) + RUNTIME_PM_OPS(va_macro_runtime_suspend, va_macro_runtime_resume, NULL) }; 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 }, @@ -1735,7 +1770,7 @@ static struct platform_driver va_macro_driver = { .name = "va_macro", .of_match_table = va_macro_dt_match, .suppress_bind_attrs = true, - .pm = &va_macro_pm_ops, + .pm = pm_ptr(&va_macro_pm_ops), }, .probe = va_macro_probe, .remove = va_macro_remove, |
