Loading 4.0/asoc/codecs/audio-ext-clk-up.c +12 −0 Original line number Diff line number Diff line Loading @@ -70,6 +70,8 @@ static int audio_ext_clk_prepare(struct clk_hw *hw) if ((clk_priv->clk_src >= AUDIO_EXT_CLK_LPASS) && (clk_priv->clk_src < AUDIO_EXT_CLK_LPASS_MAX)) { clk_priv->clk_cfg.enable = 1; trace_printk("%s: vote for %d clock\n", __func__, clk_priv->clk_src); ret = afe_set_lpass_clk_cfg(IDX_RSVD_3, &clk_priv->clk_cfg); if (ret < 0) { pr_err_ratelimited("%s afe_set_digital_codec_core_clock failed\n", Loading Loading @@ -112,6 +114,8 @@ static void audio_ext_clk_unprepare(struct clk_hw *hw) if ((clk_priv->clk_src >= AUDIO_EXT_CLK_LPASS) && (clk_priv->clk_src < AUDIO_EXT_CLK_LPASS_MAX)) { clk_priv->clk_cfg.enable = 0; trace_printk("%s: unvote for %d clock\n", __func__, clk_priv->clk_src); ret = afe_set_lpass_clk_cfg(IDX_RSVD_3, &clk_priv->clk_cfg); if (ret < 0) pr_err_ratelimited("%s: afe_set_lpass_clk_cfg failed, ret = %d\n", Loading Loading @@ -146,6 +150,8 @@ static int lpass_hw_vote_prepare(struct clk_hw *hw) int ret; if (clk_priv->clk_src == AUDIO_EXT_CLK_LPASS_CORE_HW_VOTE) { trace_printk("%s: vote for %d clock\n", __func__, clk_priv->clk_src); ret = afe_vote_lpass_core_hw(AFE_LPASS_CORE_HW_MACRO_BLOCK, "LPASS_HW_MACRO", &clk_priv->lpass_core_hwvote_client_handle); Loading @@ -157,6 +163,8 @@ static int lpass_hw_vote_prepare(struct clk_hw *hw) } if (clk_priv->clk_src == AUDIO_EXT_CLK_LPASS_AUDIO_HW_VOTE) { trace_printk("%s: vote for %d clock\n", __func__, clk_priv->clk_src); ret = afe_vote_lpass_core_hw(AFE_LPASS_CORE_HW_DCODEC_BLOCK, "LPASS_HW_DCODEC", &clk_priv->lpass_audio_hwvote_client_handle); Loading @@ -176,6 +184,8 @@ static void lpass_hw_vote_unprepare(struct clk_hw *hw) int ret = 0; if (clk_priv->clk_src == AUDIO_EXT_CLK_LPASS_CORE_HW_VOTE) { trace_printk("%s: unvote for %d clock\n", __func__, clk_priv->clk_src); ret = afe_unvote_lpass_core_hw( AFE_LPASS_CORE_HW_MACRO_BLOCK, clk_priv->lpass_core_hwvote_client_handle); Loading @@ -186,6 +196,8 @@ static void lpass_hw_vote_unprepare(struct clk_hw *hw) } if (clk_priv->clk_src == AUDIO_EXT_CLK_LPASS_AUDIO_HW_VOTE) { trace_printk("%s: unvote for %d clock\n", __func__, clk_priv->clk_src); ret = afe_unvote_lpass_core_hw( AFE_LPASS_CORE_HW_DCODEC_BLOCK, clk_priv->lpass_audio_hwvote_client_handle); Loading 4.0/asoc/codecs/bolero/bolero-cdc-regmap.c +9 −1 Original line number Diff line number Diff line // SPDX-License-Identifier: GPL-2.0-only /* Copyright (c) 2018, The Linux Foundation. All rights reserved. /* Copyright (c) 2018, 2020, The Linux Foundation. All rights reserved. */ #include <linux/regmap.h> Loading Loading @@ -797,6 +797,14 @@ static bool bolero_is_volatile_register(struct device *dev, case BOLERO_CDC_VA_TOP_CSR_CORE_ID_1: case BOLERO_CDC_VA_TOP_CSR_CORE_ID_2: case BOLERO_CDC_VA_TOP_CSR_CORE_ID_3: case BOLERO_CDC_VA_TOP_CSR_DMIC0_CTL: case BOLERO_CDC_VA_TOP_CSR_DMIC1_CTL: case BOLERO_CDC_VA_TOP_CSR_DMIC2_CTL: case BOLERO_CDC_VA_TOP_CSR_DMIC3_CTL: case BOLERO_CDC_TX_TOP_CSR_SWR_DMIC0_CTL: case BOLERO_CDC_TX_TOP_CSR_SWR_DMIC1_CTL: case BOLERO_CDC_TX_TOP_CSR_SWR_DMIC2_CTL: case BOLERO_CDC_TX_TOP_CSR_SWR_DMIC3_CTL: case BOLERO_CDC_WSA_VBAT_BCL_VBAT_GAIN_MON_VAL: case BOLERO_CDC_WSA_VBAT_BCL_VBAT_DECODE_ST: case BOLERO_CDC_WSA_INTR_CTRL_PIN1_STATUS0: Loading 4.0/asoc/codecs/bolero/bolero-cdc.c +180 −3 Original line number Diff line number Diff line // SPDX-License-Identifier: GPL-2.0-only /* Copyright (c) 2018-2019, The Linux Foundation. All rights reserved. /* Copyright (c) 2018-2020, The Linux Foundation. All rights reserved. */ #include <linux/of_platform.h> Loading Loading @@ -457,6 +457,129 @@ void bolero_unregister_res_clk(struct device *dev) } EXPORT_SYMBOL(bolero_unregister_res_clk); static u8 bolero_dmic_clk_div_get(struct snd_soc_codec *codec, int mode) { struct bolero_priv* priv = snd_soc_codec_get_drvdata(codec); int macro = (mode ? VA_MACRO : TX_MACRO); int ret = 0; if (priv->macro_params[macro].clk_div_get) { ret = priv->macro_params[macro].clk_div_get(codec); if (ret > 0) return ret; } return 1; } int bolero_dmic_clk_enable(struct snd_soc_codec *codec, u32 dmic, u32 tx_mode, bool enable) { struct bolero_priv* priv = snd_soc_codec_get_drvdata(codec); u8 dmic_clk_en = 0x01; u16 dmic_clk_reg = 0; s32 *dmic_clk_cnt = NULL; u8 *dmic_clk_div = NULL; u8 freq_change_mask = 0; u8 clk_div = 0; dev_dbg(codec->dev, "%s: enable: %d, tx_mode:%d, dmic: %d\n", __func__, enable, tx_mode, dmic); switch (dmic) { case 0: case 1: dmic_clk_cnt = &(priv->dmic_0_1_clk_cnt); dmic_clk_div = &(priv->dmic_0_1_clk_div); dmic_clk_reg = BOLERO_CDC_VA_TOP_CSR_DMIC0_CTL; freq_change_mask = 0x01; break; case 2: case 3: dmic_clk_cnt = &(priv->dmic_2_3_clk_cnt); dmic_clk_div = &(priv->dmic_2_3_clk_div); dmic_clk_reg = BOLERO_CDC_VA_TOP_CSR_DMIC1_CTL; freq_change_mask = 0x02; break; case 4: case 5: dmic_clk_cnt = &(priv->dmic_4_5_clk_cnt); dmic_clk_div = &(priv->dmic_4_5_clk_div); dmic_clk_reg = BOLERO_CDC_VA_TOP_CSR_DMIC2_CTL; freq_change_mask = 0x04; break; case 6: case 7: dmic_clk_cnt = &(priv->dmic_6_7_clk_cnt); dmic_clk_div = &(priv->dmic_6_7_clk_div); dmic_clk_reg = BOLERO_CDC_VA_TOP_CSR_DMIC3_CTL; freq_change_mask = 0x08; break; default: dev_err(codec->dev, "%s: Invalid DMIC Selection\n", __func__); return -EINVAL; } dev_dbg(codec->dev, "%s: DMIC%d dmic_clk_cnt %d\n", __func__, dmic, *dmic_clk_cnt); if (enable) { clk_div = bolero_dmic_clk_div_get(codec, tx_mode); (*dmic_clk_cnt)++; if (*dmic_clk_cnt == 1) { snd_soc_update_bits(codec, BOLERO_CDC_VA_TOP_CSR_DMIC_CFG, 0x80, 0x00); snd_soc_update_bits(codec, dmic_clk_reg, 0x0E, clk_div << 0x1); snd_soc_update_bits(codec, dmic_clk_reg, dmic_clk_en, dmic_clk_en); } else { if (*dmic_clk_div > clk_div) { snd_soc_update_bits(codec, BOLERO_CDC_VA_TOP_CSR_DMIC_CFG, freq_change_mask, freq_change_mask); snd_soc_update_bits(codec, dmic_clk_reg, 0x0E, clk_div << 0x1); snd_soc_update_bits(codec, BOLERO_CDC_VA_TOP_CSR_DMIC_CFG, freq_change_mask, 0x00); } else { clk_div = *dmic_clk_div; } } *dmic_clk_div = clk_div; } else { (*dmic_clk_cnt)--; if (*dmic_clk_cnt == 0) { snd_soc_update_bits(codec, dmic_clk_reg, dmic_clk_en, 0); clk_div = 0; snd_soc_update_bits(codec, dmic_clk_reg, 0x0E, clk_div << 0x1); } else { clk_div = bolero_dmic_clk_div_get(codec, tx_mode); if (*dmic_clk_div > clk_div) { clk_div = bolero_dmic_clk_div_get(codec, !tx_mode); snd_soc_update_bits(codec, BOLERO_CDC_VA_TOP_CSR_DMIC_CFG, freq_change_mask, freq_change_mask); snd_soc_update_bits(codec, dmic_clk_reg, 0x0E, clk_div << 0x1); snd_soc_update_bits(codec, BOLERO_CDC_VA_TOP_CSR_DMIC_CFG, freq_change_mask, 0x00); } else { clk_div = *dmic_clk_div; } } *dmic_clk_div = clk_div; } return 0; } EXPORT_SYMBOL(bolero_dmic_clk_enable); /** * bolero_register_macro - Registers macro to bolero * Loading Loading @@ -504,7 +627,11 @@ int bolero_register_macro(struct device *dev, u16 macro_id, priv->macro_params[macro_id].clk_switch = ops->clk_switch; priv->macro_params[macro_id].reg_evt_listener = ops->reg_evt_listener; priv->macro_params[macro_id].clk_enable = ops->clk_enable; } if (macro_id == TX_MACRO || macro_id == VA_MACRO) priv->macro_params[macro_id].clk_div_get = ops->clk_div_get; if (priv->version == BOLERO_VERSION_2_1) { if (macro_id == VA_MACRO) priv->macro_params[macro_id].reg_wake_irq = Loading Loading @@ -574,7 +701,10 @@ void bolero_unregister_macro(struct device *dev, u16 macro_id) priv->macro_params[macro_id].reg_wake_irq = NULL; priv->macro_params[macro_id].clk_switch = NULL; priv->macro_params[macro_id].reg_evt_listener = NULL; priv->macro_params[macro_id].clk_enable = NULL; } if (macro_id == TX_MACRO || macro_id == VA_MACRO) priv->macro_params[macro_id].clk_div_get = NULL; priv->num_dais -= priv->macro_params[macro_id].num_dais; priv->num_macros_registered--; Loading Loading @@ -685,6 +815,7 @@ static int bolero_ssr_enable(struct device *dev, void *data) priv->codec, BOLERO_MACRO_EVT_CLK_RESET, 0x0); } trace_printk("%s: clk count reset\n", __func__); regcache_cache_only(priv->regmap, false); mutex_lock(&priv->clk_lock); priv->dev_up = true; Loading @@ -695,6 +826,7 @@ static int bolero_ssr_enable(struct device *dev, void *data) /* Add a 100usec sleep to ensure last register write is done */ usleep_range(100,110); bolero_clk_rsc_enable_all_clocks(priv->clk_dev, false); trace_printk("%s: regcache_sync done\n", __func__); /* call ssr event for supported macros */ for (macro_idx = START_MACRO; macro_idx < MAX_MACRO; macro_idx++) { if (!priv->macro_params[macro_idx].event_handler) Loading @@ -702,6 +834,7 @@ static int bolero_ssr_enable(struct device *dev, void *data) priv->macro_params[macro_idx].event_handler(priv->codec, BOLERO_MACRO_EVT_SSR_UP, 0x0); } trace_printk("%s: SSR up events processed by all macros\n", __func__); bolero_cdc_notifier_call(priv, BOLERO_WCD_EVT_SSR_UP); return 0; } Loading Loading @@ -845,9 +978,11 @@ EXPORT_SYMBOL(bolero_register_wake_irq); * * @codec: pointer to codec instance. * * @clk_src: 0 for TX_RCG and 1 for VA_RCG 994 * * Returns 0 on success or -EINVAL on error. */ int bolero_tx_clk_switch(struct snd_soc_codec *codec) int bolero_tx_clk_switch(struct snd_soc_codec *codec, int clk_src) { struct bolero_priv *priv = NULL; int ret = 0; Loading @@ -865,12 +1000,46 @@ int bolero_tx_clk_switch(struct snd_soc_codec *codec) } if (priv->macro_params[TX_MACRO].clk_switch) ret = priv->macro_params[TX_MACRO].clk_switch(codec); ret = priv->macro_params[TX_MACRO].clk_switch(codec, clk_src); return ret; } EXPORT_SYMBOL(bolero_tx_clk_switch); /** * bolero_tx_mclk_enable - Enable/Disable TX Macro mclk * * @component: pointer to codec component instance. * @enable: set true to enable, otherwise false. * * Returns 0 on success or -EINVAL on error. */ int bolero_tx_mclk_enable(struct snd_soc_codec *codec, bool enable) { struct bolero_priv *priv = NULL; int ret = 0; if (!codec) return -EINVAL; priv = snd_soc_codec_get_drvdata(codec); if (!priv) return -EINVAL; if (!bolero_is_valid_codec_dev(priv->dev)) { dev_err(codec->dev, "%s: invalid codec\n", __func__); return -EINVAL; } if (priv->macro_params[TX_MACRO].clk_enable) ret = priv->macro_params[TX_MACRO].clk_enable(codec, enable); return ret; } EXPORT_SYMBOL(bolero_tx_mclk_enable); /** * bolero_register_event_listener - Register/Deregister to event listener * Loading Loading @@ -1189,6 +1358,8 @@ int bolero_runtime_resume(struct device *dev) } } priv->core_hw_vote_count++; trace_printk("%s: hw vote count %d\n", __func__, priv->core_hw_vote_count); audio_vote: if (priv->lpass_audio_hw_vote == NULL) { Loading @@ -1205,6 +1376,8 @@ int bolero_runtime_resume(struct device *dev) } } priv->core_audio_vote_count++; trace_printk("%s: audio vote count %d\n", __func__, priv->core_audio_vote_count); done: mutex_unlock(&priv->vote_lock); Loading @@ -1227,6 +1400,8 @@ int bolero_runtime_suspend(struct device *dev) dev_dbg(dev, "%s: Invalid lpass core hw node\n", __func__); } trace_printk("%s: hw vote count %d\n", __func__, priv->core_hw_vote_count); if (priv->lpass_audio_hw_vote != NULL) { if (--priv->core_audio_vote_count == 0) Loading @@ -1237,6 +1412,8 @@ int bolero_runtime_suspend(struct device *dev) dev_dbg(dev, "%s: Invalid lpass audio hw node\n", __func__); } trace_printk("%s: audio vote count %d\n", __func__, priv->core_audio_vote_count); mutex_unlock(&priv->vote_lock); return 0; Loading 4.0/asoc/codecs/bolero/bolero-cdc.h +43 −4 Original line number Diff line number Diff line /* SPDX-License-Identifier: GPL-2.0-only */ /* Copyright (c) 2018-2019, The Linux Foundation. All rights reserved. /* Copyright (c) 2018-2020, The Linux Foundation. All rights reserved. */ #ifndef BOLERO_CDC_H Loading Loading @@ -37,6 +37,11 @@ enum { BOLERO_ADC_MAX }; enum { CLK_SRC_TX_RCG = 0, CLK_SRC_VA_RCG, }; enum { BOLERO_MACRO_EVT_RX_MUTE = 1, /* for RX mute/unmute */ BOLERO_MACRO_EVT_IMPED_TRUE, /* for imped true */ Loading @@ -50,6 +55,24 @@ enum { BOLERO_MACRO_EVT_BCS_CLK_OFF }; enum { DMIC_TX = 0, DMIC_VA = 1, }; enum { DMIC0 = 0, DMIC1, DMIC2, DMIC3, DMIC4, DMIC5, DMIC6, DMIC7, DMIC_MAX }; struct macro_ops { int (*init)(struct snd_soc_codec *codec); int (*exit)(struct snd_soc_codec *codec); Loading @@ -62,8 +85,10 @@ struct macro_ops { int (*reg_wake_irq)(struct snd_soc_codec *codec, u32 data); int (*set_port_map)(struct snd_soc_codec *codec, u32 uc, u32 size, void *data); int (*clk_switch)(struct snd_soc_codec *codec); int (*clk_div_get)(struct snd_soc_codec *codec); int (*clk_switch)(struct snd_soc_codec *codec, int clk_src); int (*reg_evt_listener)(struct snd_soc_codec *codec, bool en); int (*clk_enable)(struct snd_soc_codec *c, bool en); char __iomem *io_base; u16 clk_id_req; u16 default_clk_id; Loading @@ -87,12 +112,15 @@ void bolero_clear_amic_tx_hold(struct device *dev, u16 adc_n); int bolero_runtime_resume(struct device *dev); int bolero_runtime_suspend(struct device *dev); int bolero_set_port_map(struct snd_soc_codec *codec, u32 size, void *data); int bolero_tx_clk_switch(struct snd_soc_codec *codec); int bolero_tx_clk_switch(struct snd_soc_codec *codec, int clk_src); int bolero_register_event_listener(struct snd_soc_codec *codec, bool enable); void bolero_wsa_pa_on(struct device *dev); bool bolero_check_core_votes(struct device *dev); int bolero_tx_mclk_enable(struct snd_soc_codec *c, bool enable); int bolero_get_version(struct device *dev); int bolero_dmic_clk_enable(struct snd_soc_codec *codec, u32 dmic, u32 tx_mode, bool enable); #else static inline int bolero_register_res_clk(struct device *dev, rsc_clk_cb_t cb) { Loading Loading @@ -152,7 +180,8 @@ static inline int bolero_set_port_map(struct snd_soc_codec codec, return 0; } static inline int bolero_tx_clk_switch(struct snd_soc_codec *codec) static inline int bolero_tx_clk_switch(struct snd_soc_codec *codec, int clk_src) { return 0; } Loading @@ -177,5 +206,15 @@ static int bolero_get_version(struct device *dev) { return 0; } static int bolero_dmic_clk_enable(struct snd_soc_codec *codec, u32 dmic, u32 tx_mode, bool enable) { return 0; } static int bolero_tx_mclk_enable(struct snd_soc_codec *c, bool enable) { return 0; } #endif /* CONFIG_SND_SOC_BOLERO */ #endif /* BOLERO_CDC_H */ 4.0/asoc/codecs/bolero/bolero-clk-rsc.c +20 −1 Original line number Diff line number Diff line // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (c) 2019, The Linux Foundation. All rights reserved. * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved. */ #include <linux/of_platform.h> Loading Loading @@ -32,6 +32,7 @@ static char clk_src_name[MAX_CLK][BOLERO_CLK_NAME_LENGTH] = { struct bolero_clk_rsc { struct device *dev; struct mutex rsc_clk_lock; struct mutex fs_gen_lock; struct clk *clk[MAX_CLK]; int clk_cnt[MAX_CLK]; int reg_seq_en_cnt; Loading Loading @@ -128,6 +129,8 @@ int bolero_rsc_clk_reset(struct device *dev, int clk_id) } dev_dbg(priv->dev, "%s: clock reset after ssr, count %d\n", __func__, count); trace_printk("%s: clock reset after ssr, count %d\n", __func__, count); while (count--) { clk_prepare_enable(priv->clk[clk_id]); clk_prepare_enable(priv->clk[clk_id + NPL_CLK_OFFSET]); Loading Loading @@ -237,6 +240,7 @@ static int bolero_clk_rsc_mux1_clk_request(struct bolero_clk_rsc *priv, char __iomem *clk_muxsel = NULL; int ret = 0; int default_clk_id = priv->default_clk_id[clk_id]; u32 muxsel = 0; clk_muxsel = bolero_clk_rsc_get_clk_muxsel(priv, clk_id); if (!clk_muxsel) { Loading Loading @@ -268,6 +272,9 @@ static int bolero_clk_rsc_mux1_clk_request(struct bolero_clk_rsc *priv, } } iowrite32(0x1, clk_muxsel); muxsel = ioread32(clk_muxsel); trace_printk("%s: muxsel value after enable: %d\n", __func__, muxsel); bolero_clk_rsc_mux0_clk_request(priv, default_clk_id, false); } Loading @@ -287,6 +294,9 @@ static int bolero_clk_rsc_mux1_clk_request(struct bolero_clk_rsc *priv, if (!ret) iowrite32(0x0, clk_muxsel); muxsel = ioread32(clk_muxsel); trace_printk("%s: muxsel value after disable: %d\n", __func__, muxsel); if (priv->clk[clk_id + NPL_CLK_OFFSET]) clk_disable_unprepare( priv->clk[clk_id + NPL_CLK_OFFSET]); Loading Loading @@ -422,6 +432,7 @@ void bolero_clk_rsc_fs_gen_request(struct device *dev, bool enable) pr_err("%s: regmap is null\n", __func__); return; } mutex_lock(&priv->fs_gen_lock); if (enable) { if (priv->reg_seq_en_cnt++ == 0) { for (i = 0; i < (priv->num_fs_reg * 2); i += 2) { Loading @@ -439,6 +450,7 @@ void bolero_clk_rsc_fs_gen_request(struct device *dev, bool enable) dev_err_ratelimited(priv->dev, "%s: req_seq_cnt: %d is already disabled\n", __func__, priv->reg_seq_en_cnt); priv->reg_seq_en_cnt = 0; mutex_unlock(&priv->fs_gen_lock); return; } if (--priv->reg_seq_en_cnt == 0) { Loading @@ -451,6 +463,7 @@ void bolero_clk_rsc_fs_gen_request(struct device *dev, bool enable) } } } mutex_unlock(&priv->fs_gen_lock); } EXPORT_SYMBOL(bolero_clk_rsc_fs_gen_request); Loading Loading @@ -500,6 +513,7 @@ int bolero_clk_rsc_request_clock(struct device *dev, if (!priv->dev_up && enable) { dev_err_ratelimited(priv->dev, "%s: SSR is in progress..\n", __func__); trace_printk("%s: SSR is in progress..\n", __func__); ret = -EINVAL; goto err; } Loading Loading @@ -529,6 +543,9 @@ int bolero_clk_rsc_request_clock(struct device *dev, dev_dbg(priv->dev, "%s: clk_cnt: %d for requested clk: %d, enable: %d\n", __func__, priv->clk_cnt[clk_id_req], clk_id_req, enable); trace_printk("%s: clk_cnt: %d for requested clk: %d, enable: %d\n", __func__, priv->clk_cnt[clk_id_req], clk_id_req, enable); mutex_unlock(&priv->rsc_clk_lock); Loading Loading @@ -665,6 +682,7 @@ static int bolero_clk_rsc_probe(struct platform_device *pdev) priv->dev = &pdev->dev; priv->dev_up = true; mutex_init(&priv->rsc_clk_lock); mutex_init(&priv->fs_gen_lock); dev_set_drvdata(&pdev->dev, priv); err: Loading @@ -680,6 +698,7 @@ static int bolero_clk_rsc_remove(struct platform_device *pdev) if (!priv) return -EINVAL; mutex_destroy(&priv->rsc_clk_lock); mutex_destroy(&priv->fs_gen_lock); return 0; } Loading Loading
4.0/asoc/codecs/audio-ext-clk-up.c +12 −0 Original line number Diff line number Diff line Loading @@ -70,6 +70,8 @@ static int audio_ext_clk_prepare(struct clk_hw *hw) if ((clk_priv->clk_src >= AUDIO_EXT_CLK_LPASS) && (clk_priv->clk_src < AUDIO_EXT_CLK_LPASS_MAX)) { clk_priv->clk_cfg.enable = 1; trace_printk("%s: vote for %d clock\n", __func__, clk_priv->clk_src); ret = afe_set_lpass_clk_cfg(IDX_RSVD_3, &clk_priv->clk_cfg); if (ret < 0) { pr_err_ratelimited("%s afe_set_digital_codec_core_clock failed\n", Loading Loading @@ -112,6 +114,8 @@ static void audio_ext_clk_unprepare(struct clk_hw *hw) if ((clk_priv->clk_src >= AUDIO_EXT_CLK_LPASS) && (clk_priv->clk_src < AUDIO_EXT_CLK_LPASS_MAX)) { clk_priv->clk_cfg.enable = 0; trace_printk("%s: unvote for %d clock\n", __func__, clk_priv->clk_src); ret = afe_set_lpass_clk_cfg(IDX_RSVD_3, &clk_priv->clk_cfg); if (ret < 0) pr_err_ratelimited("%s: afe_set_lpass_clk_cfg failed, ret = %d\n", Loading Loading @@ -146,6 +150,8 @@ static int lpass_hw_vote_prepare(struct clk_hw *hw) int ret; if (clk_priv->clk_src == AUDIO_EXT_CLK_LPASS_CORE_HW_VOTE) { trace_printk("%s: vote for %d clock\n", __func__, clk_priv->clk_src); ret = afe_vote_lpass_core_hw(AFE_LPASS_CORE_HW_MACRO_BLOCK, "LPASS_HW_MACRO", &clk_priv->lpass_core_hwvote_client_handle); Loading @@ -157,6 +163,8 @@ static int lpass_hw_vote_prepare(struct clk_hw *hw) } if (clk_priv->clk_src == AUDIO_EXT_CLK_LPASS_AUDIO_HW_VOTE) { trace_printk("%s: vote for %d clock\n", __func__, clk_priv->clk_src); ret = afe_vote_lpass_core_hw(AFE_LPASS_CORE_HW_DCODEC_BLOCK, "LPASS_HW_DCODEC", &clk_priv->lpass_audio_hwvote_client_handle); Loading @@ -176,6 +184,8 @@ static void lpass_hw_vote_unprepare(struct clk_hw *hw) int ret = 0; if (clk_priv->clk_src == AUDIO_EXT_CLK_LPASS_CORE_HW_VOTE) { trace_printk("%s: unvote for %d clock\n", __func__, clk_priv->clk_src); ret = afe_unvote_lpass_core_hw( AFE_LPASS_CORE_HW_MACRO_BLOCK, clk_priv->lpass_core_hwvote_client_handle); Loading @@ -186,6 +196,8 @@ static void lpass_hw_vote_unprepare(struct clk_hw *hw) } if (clk_priv->clk_src == AUDIO_EXT_CLK_LPASS_AUDIO_HW_VOTE) { trace_printk("%s: unvote for %d clock\n", __func__, clk_priv->clk_src); ret = afe_unvote_lpass_core_hw( AFE_LPASS_CORE_HW_DCODEC_BLOCK, clk_priv->lpass_audio_hwvote_client_handle); Loading
4.0/asoc/codecs/bolero/bolero-cdc-regmap.c +9 −1 Original line number Diff line number Diff line // SPDX-License-Identifier: GPL-2.0-only /* Copyright (c) 2018, The Linux Foundation. All rights reserved. /* Copyright (c) 2018, 2020, The Linux Foundation. All rights reserved. */ #include <linux/regmap.h> Loading Loading @@ -797,6 +797,14 @@ static bool bolero_is_volatile_register(struct device *dev, case BOLERO_CDC_VA_TOP_CSR_CORE_ID_1: case BOLERO_CDC_VA_TOP_CSR_CORE_ID_2: case BOLERO_CDC_VA_TOP_CSR_CORE_ID_3: case BOLERO_CDC_VA_TOP_CSR_DMIC0_CTL: case BOLERO_CDC_VA_TOP_CSR_DMIC1_CTL: case BOLERO_CDC_VA_TOP_CSR_DMIC2_CTL: case BOLERO_CDC_VA_TOP_CSR_DMIC3_CTL: case BOLERO_CDC_TX_TOP_CSR_SWR_DMIC0_CTL: case BOLERO_CDC_TX_TOP_CSR_SWR_DMIC1_CTL: case BOLERO_CDC_TX_TOP_CSR_SWR_DMIC2_CTL: case BOLERO_CDC_TX_TOP_CSR_SWR_DMIC3_CTL: case BOLERO_CDC_WSA_VBAT_BCL_VBAT_GAIN_MON_VAL: case BOLERO_CDC_WSA_VBAT_BCL_VBAT_DECODE_ST: case BOLERO_CDC_WSA_INTR_CTRL_PIN1_STATUS0: Loading
4.0/asoc/codecs/bolero/bolero-cdc.c +180 −3 Original line number Diff line number Diff line // SPDX-License-Identifier: GPL-2.0-only /* Copyright (c) 2018-2019, The Linux Foundation. All rights reserved. /* Copyright (c) 2018-2020, The Linux Foundation. All rights reserved. */ #include <linux/of_platform.h> Loading Loading @@ -457,6 +457,129 @@ void bolero_unregister_res_clk(struct device *dev) } EXPORT_SYMBOL(bolero_unregister_res_clk); static u8 bolero_dmic_clk_div_get(struct snd_soc_codec *codec, int mode) { struct bolero_priv* priv = snd_soc_codec_get_drvdata(codec); int macro = (mode ? VA_MACRO : TX_MACRO); int ret = 0; if (priv->macro_params[macro].clk_div_get) { ret = priv->macro_params[macro].clk_div_get(codec); if (ret > 0) return ret; } return 1; } int bolero_dmic_clk_enable(struct snd_soc_codec *codec, u32 dmic, u32 tx_mode, bool enable) { struct bolero_priv* priv = snd_soc_codec_get_drvdata(codec); u8 dmic_clk_en = 0x01; u16 dmic_clk_reg = 0; s32 *dmic_clk_cnt = NULL; u8 *dmic_clk_div = NULL; u8 freq_change_mask = 0; u8 clk_div = 0; dev_dbg(codec->dev, "%s: enable: %d, tx_mode:%d, dmic: %d\n", __func__, enable, tx_mode, dmic); switch (dmic) { case 0: case 1: dmic_clk_cnt = &(priv->dmic_0_1_clk_cnt); dmic_clk_div = &(priv->dmic_0_1_clk_div); dmic_clk_reg = BOLERO_CDC_VA_TOP_CSR_DMIC0_CTL; freq_change_mask = 0x01; break; case 2: case 3: dmic_clk_cnt = &(priv->dmic_2_3_clk_cnt); dmic_clk_div = &(priv->dmic_2_3_clk_div); dmic_clk_reg = BOLERO_CDC_VA_TOP_CSR_DMIC1_CTL; freq_change_mask = 0x02; break; case 4: case 5: dmic_clk_cnt = &(priv->dmic_4_5_clk_cnt); dmic_clk_div = &(priv->dmic_4_5_clk_div); dmic_clk_reg = BOLERO_CDC_VA_TOP_CSR_DMIC2_CTL; freq_change_mask = 0x04; break; case 6: case 7: dmic_clk_cnt = &(priv->dmic_6_7_clk_cnt); dmic_clk_div = &(priv->dmic_6_7_clk_div); dmic_clk_reg = BOLERO_CDC_VA_TOP_CSR_DMIC3_CTL; freq_change_mask = 0x08; break; default: dev_err(codec->dev, "%s: Invalid DMIC Selection\n", __func__); return -EINVAL; } dev_dbg(codec->dev, "%s: DMIC%d dmic_clk_cnt %d\n", __func__, dmic, *dmic_clk_cnt); if (enable) { clk_div = bolero_dmic_clk_div_get(codec, tx_mode); (*dmic_clk_cnt)++; if (*dmic_clk_cnt == 1) { snd_soc_update_bits(codec, BOLERO_CDC_VA_TOP_CSR_DMIC_CFG, 0x80, 0x00); snd_soc_update_bits(codec, dmic_clk_reg, 0x0E, clk_div << 0x1); snd_soc_update_bits(codec, dmic_clk_reg, dmic_clk_en, dmic_clk_en); } else { if (*dmic_clk_div > clk_div) { snd_soc_update_bits(codec, BOLERO_CDC_VA_TOP_CSR_DMIC_CFG, freq_change_mask, freq_change_mask); snd_soc_update_bits(codec, dmic_clk_reg, 0x0E, clk_div << 0x1); snd_soc_update_bits(codec, BOLERO_CDC_VA_TOP_CSR_DMIC_CFG, freq_change_mask, 0x00); } else { clk_div = *dmic_clk_div; } } *dmic_clk_div = clk_div; } else { (*dmic_clk_cnt)--; if (*dmic_clk_cnt == 0) { snd_soc_update_bits(codec, dmic_clk_reg, dmic_clk_en, 0); clk_div = 0; snd_soc_update_bits(codec, dmic_clk_reg, 0x0E, clk_div << 0x1); } else { clk_div = bolero_dmic_clk_div_get(codec, tx_mode); if (*dmic_clk_div > clk_div) { clk_div = bolero_dmic_clk_div_get(codec, !tx_mode); snd_soc_update_bits(codec, BOLERO_CDC_VA_TOP_CSR_DMIC_CFG, freq_change_mask, freq_change_mask); snd_soc_update_bits(codec, dmic_clk_reg, 0x0E, clk_div << 0x1); snd_soc_update_bits(codec, BOLERO_CDC_VA_TOP_CSR_DMIC_CFG, freq_change_mask, 0x00); } else { clk_div = *dmic_clk_div; } } *dmic_clk_div = clk_div; } return 0; } EXPORT_SYMBOL(bolero_dmic_clk_enable); /** * bolero_register_macro - Registers macro to bolero * Loading Loading @@ -504,7 +627,11 @@ int bolero_register_macro(struct device *dev, u16 macro_id, priv->macro_params[macro_id].clk_switch = ops->clk_switch; priv->macro_params[macro_id].reg_evt_listener = ops->reg_evt_listener; priv->macro_params[macro_id].clk_enable = ops->clk_enable; } if (macro_id == TX_MACRO || macro_id == VA_MACRO) priv->macro_params[macro_id].clk_div_get = ops->clk_div_get; if (priv->version == BOLERO_VERSION_2_1) { if (macro_id == VA_MACRO) priv->macro_params[macro_id].reg_wake_irq = Loading Loading @@ -574,7 +701,10 @@ void bolero_unregister_macro(struct device *dev, u16 macro_id) priv->macro_params[macro_id].reg_wake_irq = NULL; priv->macro_params[macro_id].clk_switch = NULL; priv->macro_params[macro_id].reg_evt_listener = NULL; priv->macro_params[macro_id].clk_enable = NULL; } if (macro_id == TX_MACRO || macro_id == VA_MACRO) priv->macro_params[macro_id].clk_div_get = NULL; priv->num_dais -= priv->macro_params[macro_id].num_dais; priv->num_macros_registered--; Loading Loading @@ -685,6 +815,7 @@ static int bolero_ssr_enable(struct device *dev, void *data) priv->codec, BOLERO_MACRO_EVT_CLK_RESET, 0x0); } trace_printk("%s: clk count reset\n", __func__); regcache_cache_only(priv->regmap, false); mutex_lock(&priv->clk_lock); priv->dev_up = true; Loading @@ -695,6 +826,7 @@ static int bolero_ssr_enable(struct device *dev, void *data) /* Add a 100usec sleep to ensure last register write is done */ usleep_range(100,110); bolero_clk_rsc_enable_all_clocks(priv->clk_dev, false); trace_printk("%s: regcache_sync done\n", __func__); /* call ssr event for supported macros */ for (macro_idx = START_MACRO; macro_idx < MAX_MACRO; macro_idx++) { if (!priv->macro_params[macro_idx].event_handler) Loading @@ -702,6 +834,7 @@ static int bolero_ssr_enable(struct device *dev, void *data) priv->macro_params[macro_idx].event_handler(priv->codec, BOLERO_MACRO_EVT_SSR_UP, 0x0); } trace_printk("%s: SSR up events processed by all macros\n", __func__); bolero_cdc_notifier_call(priv, BOLERO_WCD_EVT_SSR_UP); return 0; } Loading Loading @@ -845,9 +978,11 @@ EXPORT_SYMBOL(bolero_register_wake_irq); * * @codec: pointer to codec instance. * * @clk_src: 0 for TX_RCG and 1 for VA_RCG 994 * * Returns 0 on success or -EINVAL on error. */ int bolero_tx_clk_switch(struct snd_soc_codec *codec) int bolero_tx_clk_switch(struct snd_soc_codec *codec, int clk_src) { struct bolero_priv *priv = NULL; int ret = 0; Loading @@ -865,12 +1000,46 @@ int bolero_tx_clk_switch(struct snd_soc_codec *codec) } if (priv->macro_params[TX_MACRO].clk_switch) ret = priv->macro_params[TX_MACRO].clk_switch(codec); ret = priv->macro_params[TX_MACRO].clk_switch(codec, clk_src); return ret; } EXPORT_SYMBOL(bolero_tx_clk_switch); /** * bolero_tx_mclk_enable - Enable/Disable TX Macro mclk * * @component: pointer to codec component instance. * @enable: set true to enable, otherwise false. * * Returns 0 on success or -EINVAL on error. */ int bolero_tx_mclk_enable(struct snd_soc_codec *codec, bool enable) { struct bolero_priv *priv = NULL; int ret = 0; if (!codec) return -EINVAL; priv = snd_soc_codec_get_drvdata(codec); if (!priv) return -EINVAL; if (!bolero_is_valid_codec_dev(priv->dev)) { dev_err(codec->dev, "%s: invalid codec\n", __func__); return -EINVAL; } if (priv->macro_params[TX_MACRO].clk_enable) ret = priv->macro_params[TX_MACRO].clk_enable(codec, enable); return ret; } EXPORT_SYMBOL(bolero_tx_mclk_enable); /** * bolero_register_event_listener - Register/Deregister to event listener * Loading Loading @@ -1189,6 +1358,8 @@ int bolero_runtime_resume(struct device *dev) } } priv->core_hw_vote_count++; trace_printk("%s: hw vote count %d\n", __func__, priv->core_hw_vote_count); audio_vote: if (priv->lpass_audio_hw_vote == NULL) { Loading @@ -1205,6 +1376,8 @@ int bolero_runtime_resume(struct device *dev) } } priv->core_audio_vote_count++; trace_printk("%s: audio vote count %d\n", __func__, priv->core_audio_vote_count); done: mutex_unlock(&priv->vote_lock); Loading @@ -1227,6 +1400,8 @@ int bolero_runtime_suspend(struct device *dev) dev_dbg(dev, "%s: Invalid lpass core hw node\n", __func__); } trace_printk("%s: hw vote count %d\n", __func__, priv->core_hw_vote_count); if (priv->lpass_audio_hw_vote != NULL) { if (--priv->core_audio_vote_count == 0) Loading @@ -1237,6 +1412,8 @@ int bolero_runtime_suspend(struct device *dev) dev_dbg(dev, "%s: Invalid lpass audio hw node\n", __func__); } trace_printk("%s: audio vote count %d\n", __func__, priv->core_audio_vote_count); mutex_unlock(&priv->vote_lock); return 0; Loading
4.0/asoc/codecs/bolero/bolero-cdc.h +43 −4 Original line number Diff line number Diff line /* SPDX-License-Identifier: GPL-2.0-only */ /* Copyright (c) 2018-2019, The Linux Foundation. All rights reserved. /* Copyright (c) 2018-2020, The Linux Foundation. All rights reserved. */ #ifndef BOLERO_CDC_H Loading Loading @@ -37,6 +37,11 @@ enum { BOLERO_ADC_MAX }; enum { CLK_SRC_TX_RCG = 0, CLK_SRC_VA_RCG, }; enum { BOLERO_MACRO_EVT_RX_MUTE = 1, /* for RX mute/unmute */ BOLERO_MACRO_EVT_IMPED_TRUE, /* for imped true */ Loading @@ -50,6 +55,24 @@ enum { BOLERO_MACRO_EVT_BCS_CLK_OFF }; enum { DMIC_TX = 0, DMIC_VA = 1, }; enum { DMIC0 = 0, DMIC1, DMIC2, DMIC3, DMIC4, DMIC5, DMIC6, DMIC7, DMIC_MAX }; struct macro_ops { int (*init)(struct snd_soc_codec *codec); int (*exit)(struct snd_soc_codec *codec); Loading @@ -62,8 +85,10 @@ struct macro_ops { int (*reg_wake_irq)(struct snd_soc_codec *codec, u32 data); int (*set_port_map)(struct snd_soc_codec *codec, u32 uc, u32 size, void *data); int (*clk_switch)(struct snd_soc_codec *codec); int (*clk_div_get)(struct snd_soc_codec *codec); int (*clk_switch)(struct snd_soc_codec *codec, int clk_src); int (*reg_evt_listener)(struct snd_soc_codec *codec, bool en); int (*clk_enable)(struct snd_soc_codec *c, bool en); char __iomem *io_base; u16 clk_id_req; u16 default_clk_id; Loading @@ -87,12 +112,15 @@ void bolero_clear_amic_tx_hold(struct device *dev, u16 adc_n); int bolero_runtime_resume(struct device *dev); int bolero_runtime_suspend(struct device *dev); int bolero_set_port_map(struct snd_soc_codec *codec, u32 size, void *data); int bolero_tx_clk_switch(struct snd_soc_codec *codec); int bolero_tx_clk_switch(struct snd_soc_codec *codec, int clk_src); int bolero_register_event_listener(struct snd_soc_codec *codec, bool enable); void bolero_wsa_pa_on(struct device *dev); bool bolero_check_core_votes(struct device *dev); int bolero_tx_mclk_enable(struct snd_soc_codec *c, bool enable); int bolero_get_version(struct device *dev); int bolero_dmic_clk_enable(struct snd_soc_codec *codec, u32 dmic, u32 tx_mode, bool enable); #else static inline int bolero_register_res_clk(struct device *dev, rsc_clk_cb_t cb) { Loading Loading @@ -152,7 +180,8 @@ static inline int bolero_set_port_map(struct snd_soc_codec codec, return 0; } static inline int bolero_tx_clk_switch(struct snd_soc_codec *codec) static inline int bolero_tx_clk_switch(struct snd_soc_codec *codec, int clk_src) { return 0; } Loading @@ -177,5 +206,15 @@ static int bolero_get_version(struct device *dev) { return 0; } static int bolero_dmic_clk_enable(struct snd_soc_codec *codec, u32 dmic, u32 tx_mode, bool enable) { return 0; } static int bolero_tx_mclk_enable(struct snd_soc_codec *c, bool enable) { return 0; } #endif /* CONFIG_SND_SOC_BOLERO */ #endif /* BOLERO_CDC_H */
4.0/asoc/codecs/bolero/bolero-clk-rsc.c +20 −1 Original line number Diff line number Diff line // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (c) 2019, The Linux Foundation. All rights reserved. * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved. */ #include <linux/of_platform.h> Loading Loading @@ -32,6 +32,7 @@ static char clk_src_name[MAX_CLK][BOLERO_CLK_NAME_LENGTH] = { struct bolero_clk_rsc { struct device *dev; struct mutex rsc_clk_lock; struct mutex fs_gen_lock; struct clk *clk[MAX_CLK]; int clk_cnt[MAX_CLK]; int reg_seq_en_cnt; Loading Loading @@ -128,6 +129,8 @@ int bolero_rsc_clk_reset(struct device *dev, int clk_id) } dev_dbg(priv->dev, "%s: clock reset after ssr, count %d\n", __func__, count); trace_printk("%s: clock reset after ssr, count %d\n", __func__, count); while (count--) { clk_prepare_enable(priv->clk[clk_id]); clk_prepare_enable(priv->clk[clk_id + NPL_CLK_OFFSET]); Loading Loading @@ -237,6 +240,7 @@ static int bolero_clk_rsc_mux1_clk_request(struct bolero_clk_rsc *priv, char __iomem *clk_muxsel = NULL; int ret = 0; int default_clk_id = priv->default_clk_id[clk_id]; u32 muxsel = 0; clk_muxsel = bolero_clk_rsc_get_clk_muxsel(priv, clk_id); if (!clk_muxsel) { Loading Loading @@ -268,6 +272,9 @@ static int bolero_clk_rsc_mux1_clk_request(struct bolero_clk_rsc *priv, } } iowrite32(0x1, clk_muxsel); muxsel = ioread32(clk_muxsel); trace_printk("%s: muxsel value after enable: %d\n", __func__, muxsel); bolero_clk_rsc_mux0_clk_request(priv, default_clk_id, false); } Loading @@ -287,6 +294,9 @@ static int bolero_clk_rsc_mux1_clk_request(struct bolero_clk_rsc *priv, if (!ret) iowrite32(0x0, clk_muxsel); muxsel = ioread32(clk_muxsel); trace_printk("%s: muxsel value after disable: %d\n", __func__, muxsel); if (priv->clk[clk_id + NPL_CLK_OFFSET]) clk_disable_unprepare( priv->clk[clk_id + NPL_CLK_OFFSET]); Loading Loading @@ -422,6 +432,7 @@ void bolero_clk_rsc_fs_gen_request(struct device *dev, bool enable) pr_err("%s: regmap is null\n", __func__); return; } mutex_lock(&priv->fs_gen_lock); if (enable) { if (priv->reg_seq_en_cnt++ == 0) { for (i = 0; i < (priv->num_fs_reg * 2); i += 2) { Loading @@ -439,6 +450,7 @@ void bolero_clk_rsc_fs_gen_request(struct device *dev, bool enable) dev_err_ratelimited(priv->dev, "%s: req_seq_cnt: %d is already disabled\n", __func__, priv->reg_seq_en_cnt); priv->reg_seq_en_cnt = 0; mutex_unlock(&priv->fs_gen_lock); return; } if (--priv->reg_seq_en_cnt == 0) { Loading @@ -451,6 +463,7 @@ void bolero_clk_rsc_fs_gen_request(struct device *dev, bool enable) } } } mutex_unlock(&priv->fs_gen_lock); } EXPORT_SYMBOL(bolero_clk_rsc_fs_gen_request); Loading Loading @@ -500,6 +513,7 @@ int bolero_clk_rsc_request_clock(struct device *dev, if (!priv->dev_up && enable) { dev_err_ratelimited(priv->dev, "%s: SSR is in progress..\n", __func__); trace_printk("%s: SSR is in progress..\n", __func__); ret = -EINVAL; goto err; } Loading Loading @@ -529,6 +543,9 @@ int bolero_clk_rsc_request_clock(struct device *dev, dev_dbg(priv->dev, "%s: clk_cnt: %d for requested clk: %d, enable: %d\n", __func__, priv->clk_cnt[clk_id_req], clk_id_req, enable); trace_printk("%s: clk_cnt: %d for requested clk: %d, enable: %d\n", __func__, priv->clk_cnt[clk_id_req], clk_id_req, enable); mutex_unlock(&priv->rsc_clk_lock); Loading Loading @@ -665,6 +682,7 @@ static int bolero_clk_rsc_probe(struct platform_device *pdev) priv->dev = &pdev->dev; priv->dev_up = true; mutex_init(&priv->rsc_clk_lock); mutex_init(&priv->fs_gen_lock); dev_set_drvdata(&pdev->dev, priv); err: Loading @@ -680,6 +698,7 @@ static int bolero_clk_rsc_remove(struct platform_device *pdev) if (!priv) return -EINVAL; mutex_destroy(&priv->rsc_clk_lock); mutex_destroy(&priv->fs_gen_lock); return 0; } Loading