From 5d45f4c865153ab4a52a42a9cc42bb899600e4ed Mon Sep 17 00:00:00 2001 From: Vidyakumar Athota Date: Sun, 10 Mar 2019 22:35:07 -0700 Subject: [PATCH] asoc: codecs: bolero: add clk resource manager driver Add Bolero clock resource manager driver to handle/manage bolero clocks for all the concurrency usecases like record + voice activation. Change-Id: I970a05d96fc9060b44bfe670d465f0b9d72cc53b Signed-off-by: Vidyakumar Athota --- asoc/codecs/bolero/Kbuild | 1 + asoc/codecs/bolero/bolero-cdc.c | 361 ++++++++-------- asoc/codecs/bolero/bolero-cdc.h | 27 +- asoc/codecs/bolero/bolero-clk-rsc.c | 613 ++++++++++++++++++++++++++++ asoc/codecs/bolero/bolero-clk-rsc.h | 42 ++ asoc/codecs/bolero/internal.h | 5 +- asoc/codecs/bolero/rx-macro.c | 129 +++--- asoc/codecs/bolero/tx-macro.c | 70 +--- asoc/codecs/bolero/va-macro.c | 110 ++--- asoc/codecs/bolero/wsa-macro.c | 83 ++-- 10 files changed, 964 insertions(+), 477 deletions(-) create mode 100644 asoc/codecs/bolero/bolero-clk-rsc.c create mode 100644 asoc/codecs/bolero/bolero-clk-rsc.h diff --git a/asoc/codecs/bolero/Kbuild b/asoc/codecs/bolero/Kbuild index f01f523dcfb0..25d788170f4c 100644 --- a/asoc/codecs/bolero/Kbuild +++ b/asoc/codecs/bolero/Kbuild @@ -70,6 +70,7 @@ ifdef CONFIG_SND_SOC_BOLERO BOLERO_OBJS += bolero-cdc-utils.o BOLERO_OBJS += bolero-cdc-regmap.o BOLERO_OBJS += bolero-cdc-tables.o + BOLERO_OBJS += bolero-clk-rsc.o endif ifdef CONFIG_WSA_MACRO diff --git a/asoc/codecs/bolero/bolero-cdc.c b/asoc/codecs/bolero/bolero-cdc.c index 217fa5f41d10..d805126b2254 100644 --- a/asoc/codecs/bolero/bolero-cdc.c +++ b/asoc/codecs/bolero/bolero-cdc.c @@ -16,6 +16,7 @@ #include #include "bolero-cdc.h" #include "internal.h" +#include "bolero-clk-rsc.h" #define DRV_NAME "bolero_codec" @@ -93,43 +94,44 @@ static void bolero_ahb_read_device(char __iomem *io_base, static int __bolero_reg_read(struct bolero_priv *priv, u16 macro_id, u16 reg, u8 *val) { - int ret = -EINVAL; - u16 current_mclk_mux_macro; + int ret = 0; mutex_lock(&priv->clk_lock); if (!priv->dev_up) { dev_dbg_ratelimited(priv->dev, "%s: SSR in progress, exit\n", __func__); - goto err; + ret = -EINVAL; + goto ssr_err; } if (priv->macro_params[VA_MACRO].dev) pm_runtime_get_sync(priv->macro_params[VA_MACRO].dev); - current_mclk_mux_macro = - priv->current_mclk_mux_macro[macro_id]; - if (!priv->macro_params[current_mclk_mux_macro].mclk_fn) { - dev_dbg_ratelimited(priv->dev, - "%s: mclk_fn not init for macro-id:%d, current_mclk_mux_macro:%d\n", - __func__, macro_id, current_mclk_mux_macro); - goto err; - } - ret = priv->macro_params[current_mclk_mux_macro].mclk_fn( - priv->macro_params[current_mclk_mux_macro].dev, true); - if (ret) { - dev_dbg_ratelimited(priv->dev, - "%s: clock enable failed for macro-id:%d, current_mclk_mux_macro:%d\n", - __func__, macro_id, current_mclk_mux_macro); + + /* Request Clk before register access */ + ret = bolero_clk_rsc_request_clock(priv->macro_params[macro_id].dev, + priv->macro_params[macro_id].default_clk_id, + priv->macro_params[macro_id].clk_id_req, + true); + if (ret < 0) { + dev_err_ratelimited(priv->dev, + "%s: Failed to enable clock, ret:%d\n", __func__, ret); goto err; } + bolero_ahb_read_device( priv->macro_params[macro_id].io_base, reg, val); - priv->macro_params[current_mclk_mux_macro].mclk_fn( - priv->macro_params[current_mclk_mux_macro].dev, false); + + bolero_clk_rsc_request_clock(priv->macro_params[macro_id].dev, + priv->macro_params[macro_id].default_clk_id, + priv->macro_params[macro_id].clk_id_req, + false); + err: if (priv->macro_params[VA_MACRO].dev) { pm_runtime_mark_last_busy(priv->macro_params[VA_MACRO].dev); pm_runtime_put_autosuspend(priv->macro_params[VA_MACRO].dev); } +ssr_err: mutex_unlock(&priv->clk_lock); return ret; } @@ -137,42 +139,43 @@ err: static int __bolero_reg_write(struct bolero_priv *priv, u16 macro_id, u16 reg, u8 val) { - int ret = -EINVAL; - u16 current_mclk_mux_macro; + int ret = 0; mutex_lock(&priv->clk_lock); if (!priv->dev_up) { dev_dbg_ratelimited(priv->dev, "%s: SSR in progress, exit\n", __func__); - goto err; + ret = -EINVAL; + goto ssr_err; } if (priv->macro_params[VA_MACRO].dev) - ret = pm_runtime_get_sync(priv->macro_params[VA_MACRO].dev); - current_mclk_mux_macro = - priv->current_mclk_mux_macro[macro_id]; - if (!priv->macro_params[current_mclk_mux_macro].mclk_fn) { - dev_dbg_ratelimited(priv->dev, - "%s: mclk_fn not init for macro-id:%d, current_mclk_mux_macro:%d\n", - __func__, macro_id, current_mclk_mux_macro); - goto err; - } - ret = priv->macro_params[current_mclk_mux_macro].mclk_fn( - priv->macro_params[current_mclk_mux_macro].dev, true); - if (ret) { - dev_dbg_ratelimited(priv->dev, - "%s: clock enable failed for macro-id:%d, current_mclk_mux_macro:%d\n", - __func__, macro_id, current_mclk_mux_macro); + pm_runtime_get_sync(priv->macro_params[VA_MACRO].dev); + + /* Request Clk before register access */ + ret = bolero_clk_rsc_request_clock(priv->macro_params[macro_id].dev, + priv->macro_params[macro_id].default_clk_id, + priv->macro_params[macro_id].clk_id_req, + true); + if (ret < 0) { + dev_err_ratelimited(priv->dev, + "%s: Failed to enable clock, ret:%d\n", __func__, ret); goto err; } + bolero_ahb_write_device( - priv->macro_params[macro_id].io_base, reg, val); - priv->macro_params[current_mclk_mux_macro].mclk_fn( - priv->macro_params[current_mclk_mux_macro].dev, false); + priv->macro_params[macro_id].io_base, reg, val); + + bolero_clk_rsc_request_clock(priv->macro_params[macro_id].dev, + priv->macro_params[macro_id].default_clk_id, + priv->macro_params[macro_id].clk_id_req, + false); + err: if (priv->macro_params[VA_MACRO].dev) { pm_runtime_mark_last_busy(priv->macro_params[VA_MACRO].dev); pm_runtime_put_autosuspend(priv->macro_params[VA_MACRO].dev); } +ssr_err: mutex_unlock(&priv->clk_lock); return ret; } @@ -239,7 +242,7 @@ static void bolero_cdc_notifier_call(struct bolero_priv *priv, data, (void *)priv->wcd_dev); } -static bool bolero_is_valid_macro_dev(struct device *dev) +static bool bolero_is_valid_child_dev(struct device *dev) { if (of_device_is_compatible(dev->parent->of_node, "qcom,bolero-codec")) return true; @@ -326,6 +329,36 @@ struct device *bolero_get_device_ptr(struct device *dev, u16 macro_id) } EXPORT_SYMBOL(bolero_get_device_ptr); +/** + * bolero_get_rsc_clk_device_ptr - Get rsc clk device ptr + * + * @dev: bolero device ptr. + * + * Returns dev ptr on success or NULL on error. + */ +struct device *bolero_get_rsc_clk_device_ptr(struct device *dev) +{ + struct bolero_priv *priv; + + if (!dev) { + pr_err("%s: dev is null\n", __func__); + return NULL; + } + + if (!bolero_is_valid_codec_dev(dev)) { + pr_err("%s: invalid codec\n", __func__); + return NULL; + } + priv = dev_get_drvdata(dev); + if (!priv) { + dev_err(dev, "%s: priv is null\n", __func__); + return NULL; + } + + return priv->clk_dev; +} +EXPORT_SYMBOL(bolero_get_rsc_clk_device_ptr); + static int bolero_copy_dais_from_macro(struct bolero_priv *priv) { struct snd_soc_dai_driver *dai_ptr; @@ -355,6 +388,69 @@ static int bolero_copy_dais_from_macro(struct bolero_priv *priv) return 0; } +/** + * bolero_register_res_clk - Registers rsc clk driver to bolero + * + * @dev: rsc clk device ptr. + * @rsc_clk_cb: event handler callback for notifications like SSR + * + * Returns 0 on success or -EINVAL on error. + */ +int bolero_register_res_clk(struct device *dev, rsc_clk_cb_t rsc_clk_cb) +{ + struct bolero_priv *priv; + + if (!dev || !rsc_clk_cb) { + pr_err("%s: dev or rsc_clk_cb is null\n", __func__); + return -EINVAL; + } + if (!bolero_is_valid_child_dev(dev)) { + dev_err(dev, "%s: child device :%pK not added yet\n", + __func__, dev); + return -EINVAL; + } + priv = dev_get_drvdata(dev->parent); + if (!priv) { + dev_err(dev, "%s: priv is null\n", __func__); + return -EINVAL; + } + + priv->clk_dev = dev; + priv->rsc_clk_cb = rsc_clk_cb; + + return 0; +} +EXPORT_SYMBOL(bolero_register_res_clk); + +/** + * bolero_unregister_res_clk - Unregisters rsc clk driver from bolero + * + * @dev: resource clk device ptr. + */ +void bolero_unregister_res_clk(struct device *dev) +{ + struct bolero_priv *priv; + + if (!dev) { + pr_err("%s: dev is NULL\n", __func__); + return; + } + if (!bolero_is_valid_child_dev(dev)) { + dev_err(dev, "%s: child device :%pK not added\n", + __func__, dev); + return; + } + priv = dev_get_drvdata(dev->parent); + if (!priv) { + dev_err(dev, "%s: priv is null\n", __func__); + return; + } + + priv->clk_dev = NULL; + priv->rsc_clk_cb = NULL; +} +EXPORT_SYMBOL(bolero_unregister_res_clk); + /** * bolero_register_macro - Registers macro to bolero * @@ -374,7 +470,7 @@ int bolero_register_macro(struct device *dev, u16 macro_id, pr_err("%s: dev or ops is null\n", __func__); return -EINVAL; } - if (!bolero_is_valid_macro_dev(dev)) { + if (!bolero_is_valid_child_dev(dev)) { dev_err(dev, "%s: child device for macro:%d not added yet\n", __func__, macro_id); return -EINVAL; @@ -385,12 +481,13 @@ int bolero_register_macro(struct device *dev, u16 macro_id, return -EINVAL; } + priv->macro_params[macro_id].clk_id_req = ops->clk_id_req; + priv->macro_params[macro_id].default_clk_id = ops->default_clk_id; priv->macro_params[macro_id].init = ops->init; priv->macro_params[macro_id].exit = ops->exit; priv->macro_params[macro_id].io_base = ops->io_base; priv->macro_params[macro_id].num_dais = ops->num_dais; priv->macro_params[macro_id].dai_ptr = ops->dai_ptr; - priv->macro_params[macro_id].mclk_fn = ops->mclk_fn; priv->macro_params[macro_id].event_handler = ops->event_handler; priv->macro_params[macro_id].set_port_map = ops->set_port_map; priv->macro_params[macro_id].dev = dev; @@ -441,7 +538,7 @@ void bolero_unregister_macro(struct device *dev, u16 macro_id) pr_err("%s: dev is null\n", __func__); return; } - if (!bolero_is_valid_macro_dev(dev)) { + if (!bolero_is_valid_child_dev(dev)) { dev_err(dev, "%s: macro:%d not in valid registered macro-list\n", __func__, macro_id); return; @@ -455,7 +552,6 @@ void bolero_unregister_macro(struct device *dev, u16 macro_id) priv->macro_params[macro_id].init = NULL; priv->macro_params[macro_id].num_dais = 0; priv->macro_params[macro_id].dai_ptr = NULL; - priv->macro_params[macro_id].mclk_fn = NULL; priv->macro_params[macro_id].event_handler = NULL; priv->macro_params[macro_id].dev = NULL; if (macro_id == TX_MACRO) @@ -470,150 +566,6 @@ void bolero_unregister_macro(struct device *dev, u16 macro_id) } EXPORT_SYMBOL(bolero_unregister_macro); -static void bolero_fs_gen_enable(struct bolero_priv *priv, bool enable) -{ - if (enable) { - if (++priv->clk_users == 1) { - mutex_unlock(&priv->clk_lock); - regmap_update_bits(priv->regmap, - BOLERO_CDC_VA_CLK_RST_CTRL_MCLK_CONTROL, - 0x01, 0x01); - regmap_update_bits(priv->regmap, - BOLERO_CDC_VA_CLK_RST_CTRL_FS_CNT_CONTROL, - 0x01, 0x01); - regmap_update_bits(priv->regmap, - BOLERO_CDC_VA_TOP_CSR_TOP_CFG0, - 0x02, 0x02); - mutex_lock(&priv->clk_lock); - } - } else { - if (priv->clk_users <= 0) { - dev_err(priv->dev, - "%s:clock already disabled\n", - __func__); - priv->clk_users = 0; - return; - } - if (--priv->clk_users == 0) { - mutex_unlock(&priv->clk_lock); - regmap_update_bits(priv->regmap, - BOLERO_CDC_VA_TOP_CSR_TOP_CFG0, - 0x02, 0x00); - regmap_update_bits(priv->regmap, - BOLERO_CDC_VA_CLK_RST_CTRL_FS_CNT_CONTROL, - 0x01, 0x00); - regmap_update_bits(priv->regmap, - BOLERO_CDC_VA_CLK_RST_CTRL_MCLK_CONTROL, - 0x01, 0x00); - mutex_lock(&priv->clk_lock); - } - } -} - -/** - * bolero_request_clock - request for clock enable/disable - * - * @dev: macro device ptr. - * @macro_id: ID of macro calling this API. - * @mclk_mux_id: MCLK_MUX ID. - * @enable: enable or disable clock flag - * - * Returns 0 on success or -EINVAL on error. - */ -int bolero_request_clock(struct device *dev, u16 macro_id, - enum mclk_mux mclk_mux_id, - bool enable) -{ - struct bolero_priv *priv; - u16 mclk_mux0_macro, mclk_mux1_macro; - int ret = 0, ret1 = 0; - - if (!dev) { - pr_err("%s: dev is null\n", __func__); - return -EINVAL; - } - if (!bolero_is_valid_macro_dev(dev)) { - dev_err(dev, "%s: macro:%d not in valid registered macro-list\n", - __func__, macro_id); - return -EINVAL; - } - priv = dev_get_drvdata(dev->parent); - if (!priv || (macro_id >= MAX_MACRO)) { - dev_err(dev, "%s: priv is null or invalid macro\n", __func__); - return -EINVAL; - } - mclk_mux0_macro = bolero_mclk_mux_tbl[macro_id][MCLK_MUX0]; - mutex_lock(&priv->clk_lock); - switch (mclk_mux_id) { - case MCLK_MUX0: - ret = priv->macro_params[mclk_mux0_macro].mclk_fn( - priv->macro_params[mclk_mux0_macro].dev, enable); - if (ret < 0) { - dev_err(dev, - "%s: MCLK_MUX0 %s failed for macro:%d, mclk_mux0_macro:%d\n", - __func__, - enable ? "enable" : "disable", - macro_id, mclk_mux0_macro); - goto err; - } - bolero_fs_gen_enable(priv, enable); - break; - case MCLK_MUX1: - mclk_mux1_macro = bolero_mclk_mux_tbl[macro_id][MCLK_MUX1]; - ret = priv->macro_params[mclk_mux0_macro].mclk_fn( - priv->macro_params[mclk_mux0_macro].dev, - true); - if (ret < 0) { - dev_err(dev, - "%s: MCLK_MUX0 en failed for macro:%d mclk_mux0_macro:%d\n", - __func__, macro_id, mclk_mux0_macro); - /* - * for disable case, need to proceed still for mclk_mux1 - * counter to decrement - */ - if (enable) - goto err; - } - bolero_fs_gen_enable(priv, enable); - /* - * need different return value as ret variable - * is used to track mclk_mux0 enable success or fail - */ - ret1 = priv->macro_params[mclk_mux1_macro].mclk_fn( - priv->macro_params[mclk_mux1_macro].dev, enable); - if (ret1 < 0) - dev_err(dev, - "%s: MCLK_MUX1 %s failed for macro:%d, mclk_mux1_macro:%d\n", - __func__, - enable ? "enable" : "disable", - macro_id, mclk_mux1_macro); - /* disable mclk_mux0 only if ret is success(0) */ - if (!ret) - priv->macro_params[mclk_mux0_macro].mclk_fn( - priv->macro_params[mclk_mux0_macro].dev, - false); - if (enable && ret1) - goto err; - break; - case MCLK_MUX_MAX: - default: - dev_err(dev, "%s: invalid mclk_mux_id: %d\n", - __func__, mclk_mux_id); - ret = -EINVAL; - goto err; - } - if (enable) - priv->current_mclk_mux_macro[macro_id] = - bolero_mclk_mux_tbl[macro_id][mclk_mux_id]; - else - priv->current_mclk_mux_macro[macro_id] = - bolero_mclk_mux_tbl[macro_id][MCLK_MUX0]; -err: - mutex_unlock(&priv->clk_lock); - return ret; -} -EXPORT_SYMBOL(bolero_request_clock); - static ssize_t bolero_version_read(struct snd_info_entry *entry, void *file_private_data, struct file *file, @@ -657,6 +609,9 @@ static int bolero_ssr_enable(struct device *dev, void *data) return 0; } + if (priv->rsc_clk_cb) + priv->rsc_clk_cb(priv->clk_dev, BOLERO_MACRO_EVT_SSR_UP); + if (priv->macro_params[VA_MACRO].event_handler) priv->macro_params[VA_MACRO].event_handler( priv->component, @@ -683,6 +638,9 @@ static void bolero_ssr_disable(struct device *dev, void *data) struct bolero_priv *priv = data; int macro_idx; + if (priv->rsc_clk_cb) + priv->rsc_clk_cb(priv->clk_dev, BOLERO_MACRO_EVT_SSR_DOWN); + bolero_cdc_notifier_call(priv, BOLERO_WCD_EVT_PA_OFF_PRE_SSR); regcache_cache_only(priv->regmap, true); @@ -1074,7 +1032,30 @@ static struct platform_driver bolero_drv = { .remove = bolero_remove, }; -module_platform_driver(bolero_drv); +static int bolero_drv_init(void) +{ + return platform_driver_register(&bolero_drv); +} + +static void bolero_drv_exit(void) +{ + platform_driver_unregister(&bolero_drv); +} + +static int __init bolero_init(void) +{ + bolero_drv_init(); + bolero_clk_rsc_mgr_init(); + return 0; +} +module_init(bolero_init); + +static void __exit bolero_exit(void) +{ + bolero_clk_rsc_mgr_exit(); + bolero_drv_exit(); +} +module_exit(bolero_exit); MODULE_DESCRIPTION("Bolero driver"); MODULE_LICENSE("GPL v2"); diff --git a/asoc/codecs/bolero/bolero-cdc.h b/asoc/codecs/bolero/bolero-cdc.h index 524225e795dd..e533eb85731c 100644 --- a/asoc/codecs/bolero/bolero-cdc.h +++ b/asoc/codecs/bolero/bolero-cdc.h @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-2.0-only */ -/* Copyright (c) 2018, The Linux Foundation. All rights reserved. +/* Copyright (c) 2018-2019, The Linux Foundation. All rights reserved. */ #ifndef BOLERO_CDC_H @@ -54,16 +54,20 @@ struct macro_ops { int (*set_port_map)(struct snd_soc_component *component, u32 uc, u32 size, void *data); char __iomem *io_base; + u16 clk_id_req; + u16 default_clk_id; }; +typedef int (*rsc_clk_cb_t)(struct device *dev, u16 event); + #if IS_ENABLED(CONFIG_SND_SOC_BOLERO) +int bolero_register_res_clk(struct device *dev, rsc_clk_cb_t cb); +void bolero_unregister_res_clk(struct device *dev); int bolero_register_macro(struct device *dev, u16 macro_id, struct macro_ops *ops); void bolero_unregister_macro(struct device *dev, u16 macro_id); struct device *bolero_get_device_ptr(struct device *dev, u16 macro_id); -int bolero_request_clock(struct device *dev, u16 macro_id, - enum mclk_mux mclk_mux_id, - bool enable); +struct device *bolero_get_rsc_clk_device_ptr(struct device *dev); int bolero_info_create_codec_entry( struct snd_info_entry *codec_root, struct snd_soc_component *component); @@ -73,6 +77,14 @@ int bolero_runtime_resume(struct device *dev); int bolero_runtime_suspend(struct device *dev); int bolero_set_port_map(struct snd_soc_component *component, u32 size, void *data); #else +static inline int bolero_register_res_clk(struct device *dev, rsc_clk_cb_t cb) +{ + return 0; +} +static inline void bolero_unregister_res_clk(struct device *dev) +{ +} + static inline int bolero_register_macro(struct device *dev, u16 macro_id, struct macro_ops *ops) @@ -90,13 +102,6 @@ static inline struct device *bolero_get_device_ptr(struct device *dev, return NULL; } -static inline int bolero_request_clock(struct device *dev, u16 macro_id, - enum mclk_mux mclk_mux_id, - bool enable) -{ - return 0; -} - static int bolero_info_create_codec_entry( struct snd_info_entry *codec_root, struct snd_soc_component *component) diff --git a/asoc/codecs/bolero/bolero-clk-rsc.c b/asoc/codecs/bolero/bolero-clk-rsc.c new file mode 100644 index 000000000000..03befde80a27 --- /dev/null +++ b/asoc/codecs/bolero/bolero-clk-rsc.c @@ -0,0 +1,613 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2019, The Linux Foundation. All rights reserved. + */ + +#include +#include +#include +#include +#include +#include +#include +#include "bolero-cdc.h" +#include "bolero-clk-rsc.h" + +#define DRV_NAME "bolero-clk-rsc" +#define BOLERO_CLK_NAME_LENGTH 30 +#define NPL_CLK_OFFSET (TX_NPL_CLK - TX_CORE_CLK) + +static char clk_src_name[MAX_CLK][BOLERO_CLK_NAME_LENGTH] = { + "tx_core_clk", + "rx_core_clk", + "wsa_core_clk", + "va_core_clk", + "tx_npl_clk", + "rx_npl_clk", + "wsa_npl_clk", + "va_npl_clk", +}; + +struct bolero_clk_rsc { + struct device *dev; + struct mutex rsc_clk_lock; + struct clk *clk[MAX_CLK]; + int clk_cnt[MAX_CLK]; + int reg_seq_en_cnt; + int va_tx_clk_cnt; + bool dev_up; + u32 num_fs_reg; + u32 *fs_gen_seq; + int default_clk_id[MAX_CLK]; + struct regmap *regmap; + char __iomem *rx_clk_muxsel; + char __iomem *wsa_clk_muxsel; + char __iomem *va_clk_muxsel; +}; + +static int bolero_clk_rsc_cb(struct device *dev, u16 event) +{ + struct bolero_clk_rsc *priv; + + if (!dev) { + pr_err("%s: Invalid device pointer\n", + __func__); + return -EINVAL; + } + + priv = dev_get_drvdata(dev); + if (!priv) { + pr_err("%s: Invalid clk rsc priviate data\n", + __func__); + return -EINVAL; + } + + mutex_lock(&priv->rsc_clk_lock); + if (event == BOLERO_MACRO_EVT_SSR_UP) + priv->dev_up = true; + else if (event == BOLERO_MACRO_EVT_SSR_DOWN) + priv->dev_up = false; + mutex_unlock(&priv->rsc_clk_lock); + + return 0; +} + +static char __iomem *bolero_clk_rsc_get_clk_muxsel(struct bolero_clk_rsc *priv, + int clk_id) +{ + switch (clk_id) { + case RX_CORE_CLK: + return priv->rx_clk_muxsel; + case WSA_CORE_CLK: + return priv->wsa_clk_muxsel; + case VA_CORE_CLK: + return priv->va_clk_muxsel; + case TX_CORE_CLK: + default: + dev_err_ratelimited(priv->dev, "%s: Invalid case\n", __func__); + break; + } + + return NULL; +} + +static int bolero_clk_rsc_mux0_clk_request(struct bolero_clk_rsc *priv, + int clk_id, + bool enable) +{ + int ret = 0; + + if (enable) { + /* Enable Requested Core clk */ + if (priv->clk_cnt[clk_id] == 0) { + ret = clk_prepare_enable(priv->clk[clk_id]); + if (ret < 0) { + dev_err_ratelimited(priv->dev, "%s:clk_id %d enable failed\n", + __func__, clk_id); + goto done; + } + if (priv->clk[clk_id + NPL_CLK_OFFSET]) { + ret = clk_prepare_enable( + priv->clk[clk_id + NPL_CLK_OFFSET]); + if (ret < 0) { + dev_err_ratelimited(priv->dev, "%s:clk_id %d enable failed\n", + __func__, + clk_id + NPL_CLK_OFFSET); + goto err; + } + } + } + priv->clk_cnt[clk_id]++; + } else { + if (priv->clk_cnt[clk_id] <= 0) { + dev_err_ratelimited(priv->dev, "%s: clk_id: %d is already disabled\n", + __func__, clk_id); + priv->clk_cnt[clk_id] = 0; + goto done; + } + priv->clk_cnt[clk_id]--; + if (priv->clk_cnt[clk_id] == 0) { + if (priv->clk[clk_id + NPL_CLK_OFFSET]) + clk_disable_unprepare( + priv->clk[clk_id + NPL_CLK_OFFSET]); + clk_disable_unprepare(priv->clk[clk_id]); + } + } + return ret; + +err: + clk_disable_unprepare(priv->clk[clk_id]); +done: + return ret; +} + +static int bolero_clk_rsc_mux1_clk_request(struct bolero_clk_rsc *priv, + int clk_id, + bool enable) +{ + char __iomem *clk_muxsel = NULL; + int ret = 0; + int default_clk_id = priv->default_clk_id[clk_id]; + + clk_muxsel = bolero_clk_rsc_get_clk_muxsel(priv, clk_id); + if (!clk_muxsel) { + ret = -EINVAL; + goto done; + } + + if (enable) { + if (priv->clk_cnt[clk_id] == 0) { + ret = bolero_clk_rsc_mux0_clk_request(priv, default_clk_id, + true); + if (ret < 0) + goto done; + + ret = clk_prepare_enable(priv->clk[clk_id]); + if (ret < 0) { + dev_err_ratelimited(priv->dev, "%s:clk_id %d enable failed\n", + __func__, clk_id); + goto err_clk; + } + if (priv->clk[clk_id + NPL_CLK_OFFSET]) { + ret = clk_prepare_enable( + priv->clk[clk_id + NPL_CLK_OFFSET]); + if (ret < 0) { + dev_err_ratelimited(priv->dev, "%s:clk_id %d enable failed\n", + __func__, + clk_id + NPL_CLK_OFFSET); + goto err_npl_clk; + } + } + iowrite32(0x1, clk_muxsel); + bolero_clk_rsc_mux0_clk_request(priv, default_clk_id, + false); + } + priv->clk_cnt[clk_id]++; + } else { + if (priv->clk_cnt[clk_id] <= 0) { + dev_err_ratelimited(priv->dev, "%s: clk_id: %d is already disabled\n", + __func__, clk_id); + priv->clk_cnt[clk_id] = 0; + goto done; + } + priv->clk_cnt[clk_id]--; + if (priv->clk_cnt[clk_id] == 0) { + bolero_clk_rsc_mux0_clk_request(priv, default_clk_id, + true); + + iowrite32(0x0, clk_muxsel); + if (priv->clk[clk_id + NPL_CLK_OFFSET]) + clk_disable_unprepare( + priv->clk[clk_id + NPL_CLK_OFFSET]); + clk_disable_unprepare(priv->clk[clk_id]); + + bolero_clk_rsc_mux0_clk_request(priv, default_clk_id, + false); + } + } + return ret; + +err_npl_clk: + clk_disable_unprepare(priv->clk[clk_id]); + +err_clk: + bolero_clk_rsc_mux0_clk_request(priv, default_clk_id, false); +done: + return ret; +} + +static int bolero_clk_rsc_check_and_update_va_clk(struct bolero_clk_rsc *priv, + bool mux_switch, + int clk_id, + bool enable) +{ + int ret = 0; + + if (enable) { + if (clk_id == VA_CORE_CLK && mux_switch) { + /* + * Handle the following usecase scenarios during enable + * 1. VA only, Active clk is VA_CORE_CLK + * 2. record -> record + VA, Active clk is TX_CORE_CLK + */ + if (priv->clk_cnt[TX_CORE_CLK] == 0) { + ret = bolero_clk_rsc_mux1_clk_request(priv, + VA_CORE_CLK, enable); + if (ret < 0) + goto err; + } else { + ret = bolero_clk_rsc_mux0_clk_request(priv, + TX_CORE_CLK, enable); + if (ret < 0) + goto err; + priv->va_tx_clk_cnt++; + } + } else if ((priv->clk_cnt[TX_CORE_CLK] > 0) && + (priv->clk_cnt[VA_CORE_CLK] > 0)) { + /* + * Handle following concurrency scenario during enable + * 1. VA-> Record+VA, Increment TX CLK and Disable VA + * 2. VA-> Playback+VA, Increment TX CLK and Disable VA + */ + while (priv->clk_cnt[VA_CORE_CLK] > 0) { + ret = bolero_clk_rsc_mux0_clk_request(priv, + TX_CORE_CLK, true); + if (ret < 0) + goto err; + + bolero_clk_rsc_mux1_clk_request(priv, + VA_CORE_CLK, false); + priv->va_tx_clk_cnt++; + } + } + } else { + if (clk_id == VA_CORE_CLK && mux_switch) { + /* + * Handle the following usecase scenarios during disable + * 1. VA only, disable VA_CORE_CLK + * 2. Record + VA -> Record, decrement TX CLK count + */ + if (priv->clk_cnt[VA_CORE_CLK]) { + bolero_clk_rsc_mux1_clk_request(priv, + VA_CORE_CLK, enable); + } else if (priv->va_tx_clk_cnt) { + bolero_clk_rsc_mux0_clk_request(priv, + TX_CORE_CLK, enable); + priv->va_tx_clk_cnt--; + } + } else if (priv->va_tx_clk_cnt == priv->clk_cnt[TX_CORE_CLK]) { + /* + * Handle the following usecase scenarios during disable + * Record+VA-> VA: enable VA CLK, decrement TX CLK count + */ + while (priv->va_tx_clk_cnt) { + ret = bolero_clk_rsc_mux1_clk_request(priv, + VA_CORE_CLK, true); + if (ret < 0) + goto err; + + bolero_clk_rsc_mux0_clk_request(priv, + TX_CORE_CLK, false); + priv->va_tx_clk_cnt--; + } + } + } + +err: + return ret; +} + +/** + * bolero_clk_rsc_fs_gen_request - request to enable/disable fs generation + * sequence + * + * @dev: Macro device pointer + * @enable: enable or disable flag + */ +void bolero_clk_rsc_fs_gen_request(struct device *dev, bool enable) +{ + int i; + struct regmap *regmap; + struct device *clk_dev = NULL; + struct bolero_clk_rsc *priv = NULL; + + if (!dev) { + pr_err("%s: dev is null %d\n", __func__); + return; + } + clk_dev = bolero_get_rsc_clk_device_ptr(dev->parent); + if (!clk_dev) { + pr_err("%s: Invalid rsc clk device\n", __func__); + return; + } + priv = dev_get_drvdata(clk_dev); + if (!priv) { + pr_err("%s: Invalid rsc clk priviate data\n", __func__); + return; + } + regmap = dev_get_regmap(priv->dev->parent, NULL); + if (enable) { + if (priv->reg_seq_en_cnt++ == 0) { + for (i = 0; i < (priv->num_fs_reg * 2); i += 2) { + dev_dbg(priv->dev, "%s: Register: %d, value: %d\n", + __func__, priv->fs_gen_seq[i], + priv->fs_gen_seq[i + 1]); + regmap_update_bits(regmap, + priv->fs_gen_seq[i], + priv->fs_gen_seq[i + 1], + priv->fs_gen_seq[i + 1]); + } + } + } else { + if (priv->reg_seq_en_cnt <= 0) { + 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; + return; + } + if (--priv->reg_seq_en_cnt == 0) { + for (i = ((priv->num_fs_reg - 1) * 2); i >= 0; i -= 2) { + dev_dbg(priv->dev, "%s: Register: %d, value: %d\n", + __func__, priv->fs_gen_seq[i], + priv->fs_gen_seq[i + 1]); + regmap_update_bits(regmap, priv->fs_gen_seq[i], + priv->fs_gen_seq[i + 1], 0x0); + } + } + } +} +EXPORT_SYMBOL(bolero_clk_rsc_fs_gen_request); + +/** + * bolero_clk_rsc_request_clock - request for clock to + * enable/disable + * + * @dev: Macro device pointer. + * @default_clk_id: mux0 Core clock ID input. + * @clk_id_req: Core clock ID requested to enable/disable + * @enable: enable or disable clock flag + * + * Returns 0 on success or -EINVAL on error. + */ +int bolero_clk_rsc_request_clock(struct device *dev, + int default_clk_id, + int clk_id_req, + bool enable) +{ + int ret = 0; + struct device *clk_dev = NULL; + struct bolero_clk_rsc *priv = NULL; + bool mux_switch = false; + + if (!dev) { + pr_err("%s: dev is null %d\n", __func__); + return -EINVAL; + } + if ((clk_id_req < 0 || clk_id_req >= MAX_CLK) && + (default_clk_id < 0 || default_clk_id >= MAX_CLK)) { + pr_err("%s: Invalid clk_id_req: %d or default_clk_id: %d\n", + __func__, clk_id_req, default_clk_id); + return -EINVAL; + } + clk_dev = bolero_get_rsc_clk_device_ptr(dev->parent); + if (!clk_dev) { + pr_err("%s: Invalid rsc clk device\n", __func__); + return -EINVAL; + } + priv = dev_get_drvdata(clk_dev); + if (!priv) { + pr_err("%s: Invalid rsc clk priviate data\n", __func__); + return -EINVAL; + } + + mutex_lock(&priv->rsc_clk_lock); + if (!priv->dev_up) { + dev_err_ratelimited(priv->dev, "%s: SSR is in progress..\n", + __func__); + ret = -EINVAL; + goto err; + } + priv->default_clk_id[clk_id_req] = default_clk_id; + if (default_clk_id != clk_id_req) + mux_switch = true; + + if (mux_switch) { + if (clk_id_req != VA_CORE_CLK) { + ret = bolero_clk_rsc_mux1_clk_request(priv, clk_id_req, + enable); + if (ret < 0) + goto err; + } + } else { + ret = bolero_clk_rsc_mux0_clk_request(priv, clk_id_req, enable); + if (ret < 0) + goto err; + } + + ret = bolero_clk_rsc_check_and_update_va_clk(priv, mux_switch, + clk_id_req, + enable); + if (ret < 0) + goto err; + + 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); + + mutex_unlock(&priv->rsc_clk_lock); + + return 0; + +err: + mutex_unlock(&priv->rsc_clk_lock); + return ret; +} +EXPORT_SYMBOL(bolero_clk_rsc_request_clock); + + +static int bolero_clk_rsc_probe(struct platform_device *pdev) +{ + int ret = 0, fs_gen_size, i, j; + const char **clk_name_array; + int clk_cnt; + struct clk *clk; + struct bolero_clk_rsc *priv = NULL; + u32 muxsel = 0; + + priv = devm_kzalloc(&pdev->dev, sizeof(struct bolero_clk_rsc), + GFP_KERNEL); + if (!priv) + return -ENOMEM; + + /* Get clk fs gen sequence from device tree */ + if (!of_find_property(pdev->dev.of_node, "qcom,fs-gen-sequence", + &fs_gen_size)) { + dev_err(&pdev->dev, "%s: unable to find qcom,fs-gen-sequence property\n", + __func__); + ret = -EINVAL; + goto err; + } + priv->num_fs_reg = fs_gen_size/(2 * sizeof(u32)); + priv->fs_gen_seq = devm_kzalloc(&pdev->dev, fs_gen_size, GFP_KERNEL); + if (!priv->fs_gen_seq) { + ret = -ENOMEM; + goto err; + } + dev_dbg(&pdev->dev, "%s: num_fs_reg %d\n", __func__, priv->num_fs_reg); + /* Parse fs-gen-sequence */ + ret = of_property_read_u32_array(pdev->dev.of_node, + "qcom,fs-gen-sequence", + priv->fs_gen_seq, + priv->num_fs_reg * 2); + if (ret < 0) { + dev_err(&pdev->dev, "%s: unable to parse fs-gen-sequence, ret = %d\n", + __func__, ret); + goto err; + } + + /* Get clk details from device tree */ + clk_cnt = of_property_count_strings(pdev->dev.of_node, "clock-names"); + if (clk_cnt <= 0 || clk_cnt > MAX_CLK) { + dev_err(&pdev->dev, "%s: Invalid number of clocks %d", + __func__, clk_cnt); + ret = -EINVAL; + goto err; + } + clk_name_array = devm_kzalloc(&pdev->dev, clk_cnt * sizeof(char *), + GFP_KERNEL); + + ret = of_property_read_string_array(pdev->dev.of_node, "clock-names", + clk_name_array, clk_cnt); + + for (i = 0; i < MAX_CLK; i++) { + priv->clk[i] = NULL; + for (j = 0; j < clk_cnt; j++) { + if (!strcmp(clk_src_name[i], clk_name_array[j])) { + clk = devm_clk_get(&pdev->dev, clk_src_name[i]); + if (IS_ERR(clk)) { + ret = PTR_ERR(clk); + dev_err(&pdev->dev, "%s: clk get failed for %s with ret %d\n", + __func__, clk_src_name[i], ret); + goto err; + } + priv->clk[i] = clk; + dev_dbg(&pdev->dev, "%s: clk get success for clk name %s\n", + __func__, clk_src_name[i]); + } + } + } + ret = of_property_read_u32(pdev->dev.of_node, + "qcom,rx_mclk_mode_muxsel", &muxsel); + if (ret) { + dev_dbg(&pdev->dev, "%s: could not find qcom,rx_mclk_mode_muxsel entry in dt\n", + __func__); + } else { + priv->rx_clk_muxsel = devm_ioremap(&pdev->dev, muxsel, 0x4); + if (!priv->rx_clk_muxsel) { + dev_err(&pdev->dev, "%s: ioremap failed for rx muxsel\n", + __func__); + return -ENOMEM; + } + } + ret = of_property_read_u32(pdev->dev.of_node, + "qcom,wsa_mclk_mode_muxsel", &muxsel); + if (ret) { + dev_dbg(&pdev->dev, "%s: could not find qcom,wsa_mclk_mode_muxsel entry in dt\n", + __func__); + } else { + priv->wsa_clk_muxsel = devm_ioremap(&pdev->dev, muxsel, 0x4); + if (!priv->wsa_clk_muxsel) { + dev_err(&pdev->dev, "%s: ioremap failed for wsa muxsel\n", + __func__); + return -ENOMEM; + } + } + ret = of_property_read_u32(pdev->dev.of_node, + "qcom,va_mclk_mode_muxsel", &muxsel); + if (ret) { + dev_dbg(&pdev->dev, "%s: could not find qcom,va_mclk_mode_muxsel entry in dt\n", + __func__); + } else { + priv->va_clk_muxsel = devm_ioremap(&pdev->dev, muxsel, 0x4); + if (!priv->va_clk_muxsel) { + dev_err(&pdev->dev, "%s: ioremap failed for va muxsel\n", + __func__); + return -ENOMEM; + } + } + + ret = bolero_register_res_clk(&pdev->dev, bolero_clk_rsc_cb); + if (ret < 0) { + dev_err(&pdev->dev, "%s: Failed to register cb %d", + __func__, ret); + goto err; + } + priv->dev = &pdev->dev; + priv->dev_up = true; + mutex_init(&priv->rsc_clk_lock); + dev_set_drvdata(&pdev->dev, priv); + +err: + return ret; +} + +static int bolero_clk_rsc_remove(struct platform_device *pdev) +{ + struct bolero_clk_rsc *priv = dev_get_drvdata(&pdev->dev); + + bolero_unregister_res_clk(&pdev->dev); + of_platform_depopulate(&pdev->dev); + if (!priv) + return -EINVAL; + mutex_destroy(&priv->rsc_clk_lock); + + return 0; +} + +static const struct of_device_id bolero_clk_rsc_dt_match[] = { + {.compatible = "qcom,bolero-clk-rsc-mngr"}, + {} +}; +MODULE_DEVICE_TABLE(of, bolero_clk_rsc_dt_match); + +static struct platform_driver bolero_clk_rsc_mgr = { + .driver = { + .name = "bolero-clk-rsc-mngr", + .owner = THIS_MODULE, + .of_match_table = bolero_clk_rsc_dt_match, + }, + .probe = bolero_clk_rsc_probe, + .remove = bolero_clk_rsc_remove, +}; + +int bolero_clk_rsc_mgr_init(void) +{ + return platform_driver_register(&bolero_clk_rsc_mgr); +} + +void bolero_clk_rsc_mgr_exit(void) +{ + platform_driver_unregister(&bolero_clk_rsc_mgr); +} +MODULE_DESCRIPTION("Bolero clock resource manager driver"); +MODULE_LICENSE("GPL v2"); diff --git a/asoc/codecs/bolero/bolero-clk-rsc.h b/asoc/codecs/bolero/bolero-clk-rsc.h new file mode 100644 index 000000000000..b378f73b34d4 --- /dev/null +++ b/asoc/codecs/bolero/bolero-clk-rsc.h @@ -0,0 +1,42 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2019, The Linux Foundation. All rights reserved. + */ + +#ifndef BOLERO_CLK_RSC_H +#define BOLERO_CLK_RSC_H + +#include +#include + +#if IS_ENABLED(CONFIG_SND_SOC_BOLERO) +int bolero_clk_rsc_mgr_init(void); +void bolero_clk_rsc_mgr_exit(void); +void bolero_clk_rsc_fs_gen_request(struct device *dev, + bool enable); +int bolero_clk_rsc_request_clock(struct device *dev, + int default_clk_id, + int clk_id_req, + bool enable); +#else +static inline void bolero_clk_rsc_fs_gen_request(struct device *dev, + bool enable) +{ +} +static inline int bolero_clk_rsc_mgr_init(void) +{ + return 0; +} +static inline void bolero_clk_rsc_mgr_exit(void) +{ +} +static inline int bolero_clk_rsc_request_clock(struct device *dev, + int default_clk_id, + int clk_id_req, + bool enable) +{ + return 0; +} + +#endif /* CONFIG_SND_SOC_BOLERO */ +#endif /* BOLERO_CLK_RSC_H */ diff --git a/asoc/codecs/bolero/internal.h b/asoc/codecs/bolero/internal.h index 2749b0b0d324..734afbc06b51 100644 --- a/asoc/codecs/bolero/internal.h +++ b/asoc/codecs/bolero/internal.h @@ -7,7 +7,7 @@ #include "bolero-cdc-registers.h" -#define BOLERO_CDC_CHILD_DEVICES_MAX 5 +#define BOLERO_CDC_CHILD_DEVICES_MAX 6 /* from bolero to WCD events */ enum { @@ -73,7 +73,8 @@ struct bolero_priv { struct wcd_ctrl_platform_data plat_data; struct device *wcd_dev; struct blocking_notifier_head notifier; - int clk_users; + struct device *clk_dev; + rsc_clk_cb_t rsc_clk_cb; }; struct regmap *bolero_regmap_init(struct device *dev, diff --git a/asoc/codecs/bolero/rx-macro.c b/asoc/codecs/bolero/rx-macro.c index 035215275621..0fc13eec41bf 100644 --- a/asoc/codecs/bolero/rx-macro.c +++ b/asoc/codecs/bolero/rx-macro.c @@ -18,6 +18,7 @@ #include #include "bolero-cdc.h" #include "bolero-cdc-registers.h" +#include "bolero-clk-rsc.h" #define RX_MACRO_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 |\ SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000 |\ @@ -331,8 +332,6 @@ enum { * @swr_plat_data: Soundwire platform data * @rx_macro_add_child_devices_work: work for adding child devices * @rx_swr_gpio_p: used by pinctrl API - * @rx_core_clk: MCLK for rx macro - * @rx_npl_clk: NPL clock for RX soundwire * @component: codec handle */ struct rx_macro_priv { @@ -353,15 +352,12 @@ struct rx_macro_priv { bool dev_up; bool hph_pwr_mode; bool hph_hd2_mode; - u16 mclk_mux; struct mutex mclk_lock; struct mutex swr_clk_lock; struct rx_swr_ctrl_data *swr_ctrl_data; struct rx_swr_ctrl_platform_data swr_plat_data; struct work_struct rx_macro_add_child_devices_work; struct device_node *rx_swr_gpio_p; - struct clk *rx_core_clk; - struct clk *rx_npl_clk; struct snd_soc_component *component; unsigned long active_ch_mask[RX_MACRO_MAX_DAIS]; unsigned long active_ch_cnt[RX_MACRO_MAX_DAIS]; @@ -378,6 +374,8 @@ struct rx_macro_priv { int is_softclip_on; int softclip_clk_users; struct rx_macro_bcl_pmic_params bcl_pmic_params; + u16 clk_id; + u16 default_clk_id; }; static struct snd_soc_dai_driver rx_macro_dai[]; @@ -1059,7 +1057,7 @@ static int rx_macro_mclk_enable(struct rx_macro_priv *rx_priv, bool mclk_enable, bool dapm) { struct regmap *regmap = dev_get_regmap(rx_priv->dev->parent, NULL); - int ret = 0, mclk_mux = MCLK_MUX0; + int ret = 0; if (regmap == NULL) { dev_err(rx_priv->dev, "%s: regmap is NULL\n", __func__); @@ -1073,16 +1071,19 @@ static int rx_macro_mclk_enable(struct rx_macro_priv *rx_priv, if (mclk_enable) { if (rx_priv->rx_mclk_users == 0) { if (rx_priv->is_native_on) - mclk_mux = MCLK_MUX1; - ret = bolero_request_clock(rx_priv->dev, - RX_MACRO, mclk_mux, true); + rx_priv->clk_id = RX_CORE_CLK; + ret = bolero_clk_rsc_request_clock(rx_priv->dev, + rx_priv->default_clk_id, + rx_priv->clk_id, + true); if (ret < 0) { dev_err(rx_priv->dev, "%s: rx request clock enable failed\n", __func__); goto exit; } - rx_priv->mclk_mux = mclk_mux; + bolero_clk_rsc_fs_gen_request(rx_priv->dev, + true); regcache_mark_dirty(regmap); regcache_sync_region(regmap, RX_START_OFFSET, @@ -1113,10 +1114,13 @@ static int rx_macro_mclk_enable(struct rx_macro_priv *rx_priv, regmap_update_bits(regmap, BOLERO_CDC_RX_CLK_RST_CTRL_MCLK_CONTROL, 0x01, 0x00); - mclk_mux = rx_priv->mclk_mux; - bolero_request_clock(rx_priv->dev, - RX_MACRO, mclk_mux, false); - rx_priv->mclk_mux = MCLK_MUX0; + bolero_clk_rsc_fs_gen_request(rx_priv->dev, + false); + bolero_clk_rsc_request_clock(rx_priv->dev, + rx_priv->default_clk_id, + rx_priv->clk_id, + false); + rx_priv->clk_id = rx_priv->default_clk_id; } } exit: @@ -1142,9 +1146,9 @@ static int rx_macro_mclk_event(struct snd_soc_dapm_widget *w, case SND_SOC_DAPM_PRE_PMU: /* if swr_clk_users > 0, call device down */ if (rx_priv->swr_clk_users > 0) { - if ((rx_priv->mclk_mux == MCLK_MUX0 && + if ((rx_priv->clk_id == rx_priv->default_clk_id && rx_priv->is_native_on) || - (rx_priv->mclk_mux == MCLK_MUX1 && + (rx_priv->clk_id == RX_CORE_CLK && !rx_priv->is_native_on)) { swrm_wcd_notify( rx_priv->swr_ctrl_data[0].rx_swr_pdev, @@ -1174,51 +1178,13 @@ static int rx_macro_mclk_event(struct snd_soc_dapm_widget *w, return ret; } -static int rx_macro_mclk_ctrl(struct device *dev, bool enable) -{ - struct rx_macro_priv *rx_priv = dev_get_drvdata(dev); - int ret = 0; - - if (enable) { - ret = clk_prepare_enable(rx_priv->rx_core_clk); - if (ret < 0) { - dev_err(dev, "%s:rx mclk enable failed\n", __func__); - return ret; - } - ret = clk_prepare_enable(rx_priv->rx_npl_clk); - if (ret < 0) { - clk_disable_unprepare(rx_priv->rx_core_clk); - dev_err(dev, "%s:rx npl_clk enable failed\n", - __func__); - return ret; - } - if (rx_priv->rx_mclk_cnt++ == 0) { - if (rx_priv->dev_up) - iowrite32(0x1, rx_priv->rx_mclk_mode_muxsel); - } - } else { - if (rx_priv->rx_mclk_cnt <= 0) { - dev_dbg(dev, "%s:rx mclk already disabled\n", __func__); - rx_priv->rx_mclk_cnt = 0; - return 0; - } - if (--rx_priv->rx_mclk_cnt == 0) { - if (rx_priv->dev_up) - iowrite32(0x0, rx_priv->rx_mclk_mode_muxsel); - } - clk_disable_unprepare(rx_priv->rx_npl_clk); - clk_disable_unprepare(rx_priv->rx_core_clk); - } - - return 0; -} - static int rx_macro_event_handler(struct snd_soc_component *component, u16 event, u32 data) { u16 reg = 0, reg_mix = 0, rx_idx = 0, mute = 0x0, val = 0; struct device *rx_dev = NULL; struct rx_macro_priv *rx_priv = NULL; + int ret = 0; if (!rx_macro_get_data(component, &rx_dev, &rx_priv, __func__)) return -EINVAL; @@ -1256,17 +1222,25 @@ static int rx_macro_event_handler(struct snd_soc_component *component, rx_priv->dev_up = true; /* reset swr after ssr/pdr */ rx_priv->reset_swr = true; - /* enable&disable MCLK_MUX1 to reset GFMUX reg */ - bolero_request_clock(rx_priv->dev, - RX_MACRO, MCLK_MUX1, true); - bolero_request_clock(rx_priv->dev, - RX_MACRO, MCLK_MUX1, false); + /* enable&disable RX_CORE_CLK to reset GFMUX reg */ + ret = bolero_clk_rsc_request_clock(rx_priv->dev, + rx_priv->default_clk_id, + RX_CORE_CLK, true); + if (ret < 0) + dev_err_ratelimited(rx_priv->dev, + "%s, failed to enable clk, ret:%d\n", + __func__, ret); + else + bolero_clk_rsc_request_clock(rx_priv->dev, + rx_priv->default_clk_id, + RX_CORE_CLK, false); + swrm_wcd_notify( rx_priv->swr_ctrl_data[0].rx_swr_pdev, SWR_DEVICE_SSR_UP, NULL); break; } - return 0; + return ret; } static int rx_macro_find_playback_dai_id_for_port(int port_id, @@ -3573,7 +3547,6 @@ static void rx_macro_init_ops(struct macro_ops *ops, char __iomem *rx_io_base) ops->io_base = rx_io_base; ops->dai_ptr = rx_macro_dai; ops->num_dais = ARRAY_SIZE(rx_macro_dai); - ops->mclk_fn = rx_macro_mclk_ctrl; ops->event_handler = rx_macro_event_handler; ops->set_port_map = rx_macro_set_port_map; } @@ -3585,8 +3558,8 @@ static int rx_macro_probe(struct platform_device *pdev) u32 rx_base_addr = 0, muxsel = 0; char __iomem *rx_io_base = NULL, *muxsel_io = NULL; int ret = 0; - struct clk *rx_core_clk = NULL, *rx_npl_clk = NULL; u8 bcl_pmic_params[3]; + u32 default_clk_id = 0; rx_priv = devm_kzalloc(&pdev->dev, sizeof(struct rx_macro_priv), GFP_KERNEL); @@ -3608,6 +3581,13 @@ static int rx_macro_probe(struct platform_device *pdev) __func__, "reg"); return ret; } + ret = of_property_read_u32(pdev->dev.of_node, "qcom,default-clk-id", + &default_clk_id); + if (ret) { + dev_err(&pdev->dev, "%s: could not find %s entry in dt\n", + __func__, "qcom,default-clk-id"); + default_clk_id = RX_CORE_CLK; + } rx_priv->rx_swr_gpio_p = of_parse_phandle(pdev->dev.of_node, "qcom,rx-swr-gpios", 0); if (!rx_priv->rx_swr_gpio_p) { @@ -3639,25 +3619,6 @@ static int rx_macro_probe(struct platform_device *pdev) rx_priv->swr_plat_data.clk = rx_swrm_clock; rx_priv->swr_plat_data.handle_irq = NULL; - /* Register MCLK for rx macro */ - rx_core_clk = devm_clk_get(&pdev->dev, "rx_core_clk"); - if (IS_ERR(rx_core_clk)) { - ret = PTR_ERR(rx_core_clk); - dev_err(&pdev->dev, "%s: clk get %s failed %d\n", - __func__, "rx_core_clk", ret); - return ret; - } - rx_priv->rx_core_clk = rx_core_clk; - /* Register npl clk for soundwire */ - rx_npl_clk = devm_clk_get(&pdev->dev, "rx_npl_clk"); - if (IS_ERR(rx_npl_clk)) { - ret = PTR_ERR(rx_npl_clk); - dev_err(&pdev->dev, "%s: clk get %s failed %d\n", - __func__, "rx_npl_clk", ret); - return ret; - } - rx_priv->rx_npl_clk = rx_npl_clk; - ret = of_property_read_u8_array(pdev->dev.of_node, "qcom,rx-bcl-pmic-params", bcl_pmic_params, sizeof(bcl_pmic_params)); @@ -3669,6 +3630,10 @@ static int rx_macro_probe(struct platform_device *pdev) rx_priv->bcl_pmic_params.sid = bcl_pmic_params[1]; rx_priv->bcl_pmic_params.ppid = bcl_pmic_params[2]; } + rx_priv->clk_id = default_clk_id; + rx_priv->default_clk_id = default_clk_id; + ops.clk_id_req = rx_priv->clk_id; + ops.default_clk_id = default_clk_id; dev_set_drvdata(&pdev->dev, rx_priv); mutex_init(&rx_priv->mclk_lock); diff --git a/asoc/codecs/bolero/tx-macro.c b/asoc/codecs/bolero/tx-macro.c index 98ee1e72d611..32b85a94e865 100644 --- a/asoc/codecs/bolero/tx-macro.c +++ b/asoc/codecs/bolero/tx-macro.c @@ -16,6 +16,7 @@ #include #include "bolero-cdc.h" #include "bolero-cdc-registers.h" +#include "bolero-clk-rsc.h" #define TX_MACRO_MAX_OFFSET 0x1000 @@ -129,8 +130,6 @@ struct tx_macro_priv { int swr_clk_users; bool dapm_mclk_enable; bool reset_swr; - struct clk *tx_core_clk; - struct clk *tx_npl_clk; struct mutex mclk_lock; struct mutex swr_clk_lock; struct snd_soc_component *component; @@ -198,14 +197,18 @@ static int tx_macro_mclk_enable(struct tx_macro_priv *tx_priv, mutex_lock(&tx_priv->mclk_lock); if (mclk_enable) { if (tx_priv->tx_mclk_users == 0) { - ret = bolero_request_clock(tx_priv->dev, - TX_MACRO, MCLK_MUX0, true); + ret = bolero_clk_rsc_request_clock(tx_priv->dev, + TX_CORE_CLK, + TX_CORE_CLK, + true); if (ret < 0) { dev_err(tx_priv->dev, "%s: request clock enable failed\n", __func__); goto exit; } + bolero_clk_rsc_fs_gen_request(tx_priv->dev, + true); regcache_mark_dirty(regmap); regcache_sync_region(regmap, TX_START_OFFSET, @@ -236,8 +239,13 @@ static int tx_macro_mclk_enable(struct tx_macro_priv *tx_priv, regmap_update_bits(regmap, BOLERO_CDC_TX_CLK_RST_CTRL_MCLK_CONTROL, 0x01, 0x00); - bolero_request_clock(tx_priv->dev, - TX_MACRO, MCLK_MUX0, false); + bolero_clk_rsc_fs_gen_request(tx_priv->dev, + false); + + bolero_clk_rsc_request_clock(tx_priv->dev, + TX_CORE_CLK, + TX_CORE_CLK, + false); } } exit: @@ -278,33 +286,6 @@ static int tx_macro_mclk_event(struct snd_soc_dapm_widget *w, return ret; } -static int tx_macro_mclk_ctrl(struct device *dev, bool enable) -{ - struct tx_macro_priv *tx_priv = dev_get_drvdata(dev); - int ret = 0; - - if (enable) { - ret = clk_prepare_enable(tx_priv->tx_core_clk); - if (ret < 0) { - dev_err(dev, "%s:tx mclk enable failed\n", __func__); - goto exit; - } - ret = clk_prepare_enable(tx_priv->tx_npl_clk); - if (ret < 0) { - dev_err(dev, "%s:tx npl_clk enable failed\n", - __func__); - clk_disable_unprepare(tx_priv->tx_core_clk); - goto exit; - } - } else { - clk_disable_unprepare(tx_priv->tx_npl_clk); - clk_disable_unprepare(tx_priv->tx_core_clk); - } - -exit: - return ret; -} - static int tx_macro_event_handler(struct snd_soc_component *component, u16 event, u32 data) { @@ -1769,7 +1750,6 @@ static void tx_macro_init_ops(struct macro_ops *ops, ops->io_base = tx_io_base; ops->dai_ptr = tx_macro_dai; ops->num_dais = ARRAY_SIZE(tx_macro_dai); - ops->mclk_fn = tx_macro_mclk_ctrl; ops->event_handler = tx_macro_event_handler; ops->reg_wake_irq = tx_macro_reg_wake_irq; ops->set_port_map = tx_macro_set_port_map; @@ -1781,7 +1761,6 @@ static int tx_macro_probe(struct platform_device *pdev) struct tx_macro_priv *tx_priv = NULL; u32 tx_base_addr = 0, sample_rate = 0; char __iomem *tx_io_base = NULL; - struct clk *tx_core_clk = NULL, *tx_npl_clk = NULL; int ret = 0; const char *dmic_sample_rate = "qcom,tx-dmic-sample-rate"; @@ -1835,34 +1814,19 @@ static int tx_macro_probe(struct platform_device *pdev) tx_priv->swr_plat_data.bulk_write = NULL; tx_priv->swr_plat_data.clk = tx_macro_swrm_clock; tx_priv->swr_plat_data.handle_irq = NULL; - /* Register MCLK for tx macro */ - tx_core_clk = devm_clk_get(&pdev->dev, "tx_core_clk"); - if (IS_ERR(tx_core_clk)) { - ret = PTR_ERR(tx_core_clk); - dev_err(&pdev->dev, "%s: clk get %s failed %d\n", - __func__, "tx_core_clk", ret); - return ret; - } - tx_priv->tx_core_clk = tx_core_clk; - /* Register npl clk for soundwire */ - tx_npl_clk = devm_clk_get(&pdev->dev, "tx_npl_clk"); - if (IS_ERR(tx_npl_clk)) { - ret = PTR_ERR(tx_npl_clk); - dev_err(&pdev->dev, "%s: clk get %s failed %d\n", - __func__, "tx_npl_clk", ret); - return ret; - } - tx_priv->tx_npl_clk = tx_npl_clk; mutex_init(&tx_priv->mclk_lock); mutex_init(&tx_priv->swr_clk_lock); tx_macro_init_ops(&ops, tx_io_base); + ops.clk_id_req = TX_CORE_CLK; + ops.default_clk_id = TX_CORE_CLK; ret = bolero_register_macro(&pdev->dev, TX_MACRO, &ops); if (ret) { dev_err(&pdev->dev, "%s: register macro failed\n", __func__); goto err_reg_macro; } + schedule_work(&tx_priv->tx_macro_add_child_devices_work); return 0; err_reg_macro: diff --git a/asoc/codecs/bolero/va-macro.c b/asoc/codecs/bolero/va-macro.c index 8789fce4fb5d..217800adcaa3 100644 --- a/asoc/codecs/bolero/va-macro.c +++ b/asoc/codecs/bolero/va-macro.c @@ -15,6 +15,7 @@ #include #include "bolero-cdc.h" #include "bolero-cdc-registers.h" +#include "bolero-clk-rsc.h" /* pm runtime auto suspend timer in msecs */ #define VA_AUTO_SUSPEND_DELAY 100 /* delay in msec */ @@ -94,7 +95,6 @@ struct va_macro_priv { struct device *dev; bool dec_active[VA_MACRO_NUM_DECIMATORS]; bool va_without_decimation; - struct clk *va_core_clk; struct mutex mclk_lock; struct snd_soc_component *component; struct hpf_work va_hpf_work[VA_MACRO_NUM_DECIMATORS]; @@ -114,6 +114,8 @@ struct va_macro_priv { u32 micb_voltage; u32 micb_current; int micb_users; + u16 default_clk_id; + u16 clk_id; }; static bool va_macro_get_data(struct snd_soc_component *component, @@ -153,15 +155,18 @@ static int va_macro_mclk_enable(struct va_macro_priv *va_priv, mutex_lock(&va_priv->mclk_lock); if (mclk_enable) { if (va_priv->va_mclk_users == 0) { - ret = bolero_request_clock(va_priv->dev, - VA_MACRO, - va_priv->mclk_mux_sel, true); + ret = bolero_clk_rsc_request_clock(va_priv->dev, + va_priv->default_clk_id, + va_priv->clk_id, + true); if (ret < 0) { dev_err(va_priv->dev, "%s: va request clock en failed\n", __func__); goto exit; } + bolero_clk_rsc_fs_gen_request(va_priv->dev, + true); regcache_mark_dirty(regmap); regcache_sync_region(regmap, VA_START_OFFSET, @@ -177,9 +182,12 @@ static int va_macro_mclk_enable(struct va_macro_priv *va_priv, } va_priv->va_mclk_users--; if (va_priv->va_mclk_users == 0) { - bolero_request_clock(va_priv->dev, - VA_MACRO, - va_priv->mclk_mux_sel, false); + bolero_clk_rsc_fs_gen_request(va_priv->dev, + false); + bolero_clk_rsc_request_clock(va_priv->dev, + va_priv->default_clk_id, + va_priv->clk_id, + false); } } exit: @@ -252,29 +260,6 @@ static int va_macro_mclk_event(struct snd_soc_dapm_widget *w, return ret; } -static int va_macro_mclk_ctrl(struct device *dev, bool enable) -{ - struct va_macro_priv *va_priv = dev_get_drvdata(dev); - int ret = 0; - - if (enable) { - ret = clk_prepare_enable(va_priv->va_core_clk); - if (ret < 0) { - dev_err(dev, "%s:va mclk enable failed\n", __func__); - goto exit; - } - if (va_priv->mclk_mux_sel == MCLK_MUX1) - iowrite32(0x1, va_priv->va_island_mode_muxsel); - } else { - if (va_priv->mclk_mux_sel == MCLK_MUX1) - iowrite32(0x0, va_priv->va_island_mode_muxsel); - clk_disable_unprepare(va_priv->va_core_clk); - } - -exit: - return ret; -} - static void va_macro_tx_hpf_corner_freq_callback(struct work_struct *work) { struct delayed_work *hpf_delayed_work; @@ -1581,7 +1566,6 @@ static void va_macro_init_ops(struct macro_ops *ops, ops->init = va_macro_init; ops->exit = va_macro_deinit; ops->io_base = va_io_base; - ops->mclk_fn = va_macro_mclk_ctrl; ops->event_handler = va_macro_event_handler; } @@ -1589,10 +1573,8 @@ static int va_macro_probe(struct platform_device *pdev) { struct macro_ops ops; struct va_macro_priv *va_priv; - u32 va_base_addr, sample_rate = 0, island_sel = 0; + u32 va_base_addr, sample_rate = 0; char __iomem *va_io_base; - char __iomem *va_muxsel_io = NULL; - struct clk *va_core_clk; bool va_without_decimation = false; const char *micb_supply_str = "va-vdd-micb-supply"; const char *micb_supply_str1 = "va-vdd-micb"; @@ -1600,7 +1582,7 @@ static int va_macro_probe(struct platform_device *pdev) const char *micb_current_str = "qcom,va-vdd-micb-current"; int ret = 0; const char *dmic_sample_rate = "qcom,va-dmic-sample-rate"; - u16 mclk_mux_sel = MCLK_MUX0; + u32 default_clk_id = 0; va_priv = devm_kzalloc(&pdev->dev, sizeof(struct va_macro_priv), GFP_KERNEL); @@ -1639,53 +1621,6 @@ static int va_macro_probe(struct platform_device *pdev) } va_priv->va_io_base = va_io_base; - ret = of_property_read_u16(va_priv->dev->of_node, - "qcom,va-clk-mux-select", &mclk_mux_sel); - if (ret) { - dev_dbg(&pdev->dev, - "%s: could not find %s entry in dt, use default\n", - __func__, "qcom,va-clk-mux-select"); - } else { - if (mclk_mux_sel != MCLK_MUX0 && mclk_mux_sel != MCLK_MUX1) { - dev_err(&pdev->dev, - "%s: mclk_mux_sel: %d is invalid\n", - __func__, mclk_mux_sel); - return -EINVAL; - } - } - va_priv->mclk_mux_sel = mclk_mux_sel; - - if (va_priv->mclk_mux_sel == MCLK_MUX1) { - ret = of_property_read_u32(pdev->dev.of_node, - "qcom,va-island-mode-muxsel", - &island_sel); - if (ret) { - dev_err(&pdev->dev, - "%s: could not find %s entry in dt\n", - __func__, "qcom,va-island-mode-muxsel"); - return ret; - } else { - va_muxsel_io = devm_ioremap(&pdev->dev, - island_sel, 0x4); - if (!va_muxsel_io) { - dev_err(&pdev->dev, - "%s: ioremap failed for island_sel\n", - __func__); - return -ENOMEM; - } - } - va_priv->va_island_mode_muxsel = va_muxsel_io; - } - /* Register MCLK for va macro */ - va_core_clk = devm_clk_get(&pdev->dev, "va_core_clk"); - if (IS_ERR(va_core_clk)) { - ret = PTR_ERR(va_core_clk); - dev_err(&pdev->dev, "%s: clk get %s failed\n", - __func__, "va_core_clk"); - return ret; - } - va_priv->va_core_clk = va_core_clk; - if (of_parse_phandle(pdev->dev.of_node, micb_supply_str, 0)) { va_priv->micb_supply = devm_regulator_get(&pdev->dev, micb_supply_str1); @@ -1717,10 +1652,21 @@ static int va_macro_probe(struct platform_device *pdev) return ret; } } + ret = of_property_read_u32(pdev->dev.of_node, "qcom,default-clk-id", + &default_clk_id); + if (ret) { + dev_err(&pdev->dev, "%s: could not find %s entry in dt\n", + __func__, "qcom,default-clk-id"); + default_clk_id = VA_CORE_CLK; + } + va_priv->clk_id = VA_CORE_CLK; + va_priv->default_clk_id = default_clk_id; mutex_init(&va_priv->mclk_lock); dev_set_drvdata(&pdev->dev, va_priv); va_macro_init_ops(&ops, va_io_base, va_without_decimation); + ops.clk_id_req = va_priv->default_clk_id; + ops.default_clk_id = va_priv->default_clk_id; ret = bolero_register_macro(&pdev->dev, VA_MACRO, &ops); if (ret < 0) { dev_err(&pdev->dev, "%s: register macro failed\n", __func__); diff --git a/asoc/codecs/bolero/wsa-macro.c b/asoc/codecs/bolero/wsa-macro.c index b0a4b1e0f42d..dd3f4feba4ae 100644 --- a/asoc/codecs/bolero/wsa-macro.c +++ b/asoc/codecs/bolero/wsa-macro.c @@ -17,6 +17,7 @@ #include "bolero-cdc.h" #include "bolero-cdc-registers.h" #include "wsa-macro.h" +#include "bolero-clk-rsc.h" #define WSA_MACRO_MAX_OFFSET 0x1000 @@ -175,8 +176,6 @@ enum { * @swr_plat_data: Soundwire platform data * @wsa_macro_add_child_devices_work: work for adding child devices * @wsa_swr_gpio_p: used by pinctrl API - * @wsa_core_clk: MCLK for wsa macro - * @wsa_npl_clk: NPL clock for WSA soundwire * @component: codec handle * @rx_0_count: RX0 interpolation users * @rx_1_count: RX1 interpolation users @@ -201,8 +200,6 @@ struct wsa_macro_priv { struct wsa_macro_swr_ctrl_platform_data swr_plat_data; struct work_struct wsa_macro_add_child_devices_work; struct device_node *wsa_swr_gpio_p; - struct clk *wsa_core_clk; - struct clk *wsa_npl_clk; struct snd_soc_component *component; int rx_0_count; int rx_1_count; @@ -219,6 +216,8 @@ struct wsa_macro_priv { int is_softclip_on[WSA_MACRO_SOFTCLIP_MAX]; int softclip_clk_users[WSA_MACRO_SOFTCLIP_MAX]; struct wsa_macro_bcl_pmic_params bcl_pmic_params; + char __iomem *mclk_mode_muxsel; + u16 default_clk_id; }; static int wsa_macro_config_ear_spkr_gain(struct snd_soc_component *component, @@ -808,14 +807,18 @@ static int wsa_macro_mclk_enable(struct wsa_macro_priv *wsa_priv, mutex_lock(&wsa_priv->mclk_lock); if (mclk_enable) { if (wsa_priv->wsa_mclk_users == 0) { - ret = bolero_request_clock(wsa_priv->dev, - WSA_MACRO, MCLK_MUX0, true); + ret = bolero_clk_rsc_request_clock(wsa_priv->dev, + wsa_priv->default_clk_id, + wsa_priv->default_clk_id, + true); if (ret < 0) { dev_err(wsa_priv->dev, "%s: wsa request clock enable failed\n", __func__); goto exit; } + bolero_clk_rsc_fs_gen_request(wsa_priv->dev, + true); regcache_mark_dirty(regmap); regcache_sync_region(regmap, WSA_START_OFFSET, @@ -846,8 +849,13 @@ static int wsa_macro_mclk_enable(struct wsa_macro_priv *wsa_priv, regmap_update_bits(regmap, BOLERO_CDC_WSA_CLK_RST_CTRL_MCLK_CONTROL, 0x01, 0x00); - bolero_request_clock(wsa_priv->dev, - WSA_MACRO, MCLK_MUX0, false); + bolero_clk_rsc_fs_gen_request(wsa_priv->dev, + false); + + bolero_clk_rsc_request_clock(wsa_priv->dev, + wsa_priv->default_clk_id, + wsa_priv->default_clk_id, + false); } } exit: @@ -888,35 +896,6 @@ static int wsa_macro_mclk_event(struct snd_soc_dapm_widget *w, return ret; } -static int wsa_macro_mclk_ctrl(struct device *dev, bool enable) -{ - struct wsa_macro_priv *wsa_priv = dev_get_drvdata(dev); - int ret = 0; - - if (!wsa_priv) - return -EINVAL; - - if (enable) { - ret = clk_prepare_enable(wsa_priv->wsa_core_clk); - if (ret < 0) { - dev_err(dev, "%s:wsa mclk enable failed\n", __func__); - goto exit; - } - ret = clk_prepare_enable(wsa_priv->wsa_npl_clk); - if (ret < 0) { - dev_err(dev, "%s:wsa npl_clk enable failed\n", - __func__); - clk_disable_unprepare(wsa_priv->wsa_core_clk); - goto exit; - } - } else { - clk_disable_unprepare(wsa_priv->wsa_npl_clk); - clk_disable_unprepare(wsa_priv->wsa_core_clk); - } -exit: - return ret; -} - static int wsa_macro_event_handler(struct snd_soc_component *component, u16 event, u32 data) { @@ -2809,7 +2788,6 @@ static void wsa_macro_init_ops(struct macro_ops *ops, ops->io_base = wsa_io_base; ops->dai_ptr = wsa_macro_dai; ops->num_dais = ARRAY_SIZE(wsa_macro_dai); - ops->mclk_fn = wsa_macro_mclk_ctrl; ops->event_handler = wsa_macro_event_handler; ops->set_port_map = wsa_macro_set_port_map; } @@ -2818,10 +2796,9 @@ static int wsa_macro_probe(struct platform_device *pdev) { struct macro_ops ops; struct wsa_macro_priv *wsa_priv; - u32 wsa_base_addr; + u32 wsa_base_addr, default_clk_id; char __iomem *wsa_io_base; int ret = 0; - struct clk *wsa_core_clk, *wsa_npl_clk; u8 bcl_pmic_params[3]; wsa_priv = devm_kzalloc(&pdev->dev, sizeof(struct wsa_macro_priv), @@ -2861,24 +2838,13 @@ static int wsa_macro_probe(struct platform_device *pdev) wsa_priv->swr_plat_data.clk = wsa_swrm_clock; wsa_priv->swr_plat_data.handle_irq = NULL; - /* Register MCLK for wsa macro */ - wsa_core_clk = devm_clk_get(&pdev->dev, "wsa_core_clk"); - if (IS_ERR(wsa_core_clk)) { - ret = PTR_ERR(wsa_core_clk); - dev_err(&pdev->dev, "%s: clk get %s failed\n", - __func__, "wsa_core_clk"); - return ret; + ret = of_property_read_u32(pdev->dev.of_node, "qcom,default-clk-id", + &default_clk_id); + if (ret) { + dev_err(&pdev->dev, "%s: could not find %s entry in dt\n", + __func__, "qcom,mux0-clk-id"); + default_clk_id = WSA_CORE_CLK; } - wsa_priv->wsa_core_clk = wsa_core_clk; - /* Register npl clk for soundwire */ - wsa_npl_clk = devm_clk_get(&pdev->dev, "wsa_npl_clk"); - if (IS_ERR(wsa_npl_clk)) { - ret = PTR_ERR(wsa_npl_clk); - dev_err(&pdev->dev, "%s: clk get %s failed\n", - __func__, "wsa_npl_clk"); - return ret; - } - wsa_priv->wsa_npl_clk = wsa_npl_clk; ret = of_property_read_u8_array(pdev->dev.of_node, "qcom,wsa-bcl-pmic-params", bcl_pmic_params, @@ -2891,11 +2857,14 @@ static int wsa_macro_probe(struct platform_device *pdev) wsa_priv->bcl_pmic_params.sid = bcl_pmic_params[1]; wsa_priv->bcl_pmic_params.ppid = bcl_pmic_params[2]; } + wsa_priv->default_clk_id = default_clk_id; dev_set_drvdata(&pdev->dev, wsa_priv); mutex_init(&wsa_priv->mclk_lock); mutex_init(&wsa_priv->swr_clk_lock); wsa_macro_init_ops(&ops, wsa_io_base); + ops.clk_id_req = wsa_priv->default_clk_id; + ops.default_clk_id = wsa_priv->default_clk_id; ret = bolero_register_macro(&pdev->dev, WSA_MACRO, &ops); if (ret < 0) { dev_err(&pdev->dev, "%s: register macro failed\n", __func__);