Merge "soc: vote for LPASS NPA resource from LPI TLMM driver"
Este commit está contenido en:

cometido por
Gerrit - the friendly Code Review server

commit
d72c877e31
@@ -21,6 +21,7 @@
|
||||
#include <linux/platform_device.h>
|
||||
#include <dt-bindings/clock/qcom,audio-ext-clk.h>
|
||||
#include <dsp/q6afe-v2.h>
|
||||
#include <dsp/q6core.h>
|
||||
#include "audio-ext-clk-up.h"
|
||||
|
||||
enum {
|
||||
@@ -33,6 +34,7 @@ enum {
|
||||
AUDIO_EXT_CLK_LPASS5,
|
||||
AUDIO_EXT_CLK_LPASS6,
|
||||
AUDIO_EXT_CLK_LPASS7,
|
||||
AUDIO_EXT_CLK_LPASS_NPA_RSC_ISLAND,
|
||||
AUDIO_EXT_CLK_LPASS_MAX,
|
||||
AUDIO_EXT_CLK_MAX = AUDIO_EXT_CLK_LPASS_MAX,
|
||||
};
|
||||
@@ -55,6 +57,7 @@ struct audio_ext_clk_priv {
|
||||
struct afe_clk_set clk_cfg;
|
||||
struct audio_ext_clk audio_clk;
|
||||
const char *clk_name;
|
||||
uint32_t npa_rsc_client_handle;
|
||||
};
|
||||
|
||||
static inline struct audio_ext_clk_priv *to_audio_clk(struct clk_hw *hw)
|
||||
@@ -141,12 +144,58 @@ static u8 audio_ext_clk_get_parent(struct clk_hw *hw)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lpass_npa_rsc_prepare(struct clk_hw *hw)
|
||||
{
|
||||
struct audio_ext_clk_priv *clk_priv = to_audio_clk(hw);
|
||||
int ret;
|
||||
|
||||
if ((clk_priv->clk_src >= AUDIO_EXT_CLK_LPASS_NPA_RSC_ISLAND) &&
|
||||
(clk_priv->clk_src < AUDIO_EXT_CLK_LPASS_MAX)) {
|
||||
if (q6core_get_avcs_api_version_per_service(
|
||||
APRV2_IDS_SERVICE_ID_ADSP_CORE_V) >= AVCS_API_VERSION_V4) {
|
||||
ret = q6core_request_island_transition(
|
||||
clk_priv->npa_rsc_client_handle, false);
|
||||
if (ret < 0) {
|
||||
pr_err("%s q6core_request_island_transition failed %d\n",
|
||||
__func__, ret);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void lpass_npa_rsc_unprepare(struct clk_hw *hw)
|
||||
{
|
||||
struct audio_ext_clk_priv *clk_priv = to_audio_clk(hw);
|
||||
int ret = 0;
|
||||
|
||||
if ((clk_priv->clk_src >= AUDIO_EXT_CLK_LPASS_NPA_RSC_ISLAND) &&
|
||||
(clk_priv->clk_src < AUDIO_EXT_CLK_LPASS_MAX)) {
|
||||
if (q6core_get_avcs_api_version_per_service(
|
||||
APRV2_IDS_SERVICE_ID_ADSP_CORE_V) >= AVCS_API_VERSION_V4) {
|
||||
ret = q6core_request_island_transition(
|
||||
clk_priv->npa_rsc_client_handle, true);
|
||||
if (ret < 0) {
|
||||
pr_err("%s q6core_request_island_transition failed %d\n",
|
||||
__func__, ret);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static const struct clk_ops audio_ext_clk_ops = {
|
||||
.prepare = audio_ext_clk_prepare,
|
||||
.unprepare = audio_ext_clk_unprepare,
|
||||
.get_parent = audio_ext_clk_get_parent,
|
||||
};
|
||||
|
||||
static const struct clk_ops lpass_npa_rsc_ops = {
|
||||
.prepare = lpass_npa_rsc_prepare,
|
||||
.unprepare = lpass_npa_rsc_unprepare,
|
||||
};
|
||||
|
||||
static const char * const audio_ext_pmi_div_clk[] = {
|
||||
"qpnp_clkdiv_1",
|
||||
"pms405_div_clk1",
|
||||
@@ -274,6 +323,15 @@ static struct audio_ext_clk audio_clk_array[] = {
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
.pnctrl_info = {NULL},
|
||||
.fact = {
|
||||
.hw.init = &(struct clk_init_data){
|
||||
.name = "lpass_npa_rsc_island_clk",
|
||||
.ops = &lpass_npa_rsc_ops,
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
static int audio_get_pinctrl(struct platform_device *pdev)
|
||||
@@ -476,11 +534,34 @@ static int audio_ref_clk_probe(struct platform_device *pdev)
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (clk_priv->clk_src == AUDIO_EXT_CLK_LPASS_NPA_RSC_ISLAND) {
|
||||
if (q6core_get_avcs_api_version_per_service(
|
||||
APRV2_IDS_SERVICE_ID_ADSP_CORE_V) >= AVCS_API_VERSION_V4) {
|
||||
ret = q6core_create_lpass_npa_client(
|
||||
AVCS_SLEEP_NODE_ISLAND_TRANSITION_RESOURCE_ID,
|
||||
"lpass_npa_rsc_mgr",
|
||||
&clk_priv->npa_rsc_client_handle);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "%s: q6core_create_lpass_npa_client is failed %d\n",
|
||||
__func__, ret);
|
||||
audio_put_pinctrl(pdev);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int audio_ref_clk_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct audio_ext_clk_priv *clk_priv = platform_get_drvdata(pdev);
|
||||
|
||||
if (clk_priv->clk_src == AUDIO_EXT_CLK_LPASS_NPA_RSC_ISLAND) {
|
||||
if (q6core_get_avcs_api_version_per_service(
|
||||
APRV2_IDS_SERVICE_ID_ADSP_CORE_V) >= AVCS_API_VERSION_V4)
|
||||
q6core_destroy_lpass_npa_client(
|
||||
clk_priv->npa_rsc_client_handle);
|
||||
}
|
||||
audio_put_pinctrl(pdev);
|
||||
|
||||
return 0;
|
||||
|
@@ -18,7 +18,9 @@
|
||||
#include <linux/printk.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/clk.h>
|
||||
#include <soc/snd_event.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
#include "bolero-cdc.h"
|
||||
#include "internal.h"
|
||||
|
||||
@@ -30,6 +32,9 @@
|
||||
|
||||
static struct snd_soc_codec_driver bolero;
|
||||
|
||||
/* pm runtime auto suspend timer in msecs */
|
||||
#define BOLERO_AUTO_SUSPEND_DELAY 1500 /* delay in msec */
|
||||
|
||||
/* MCLK_MUX table for all macros */
|
||||
static u16 bolero_mclk_mux_tbl[MAX_MACRO][MCLK_MUX_MAX] = {
|
||||
{TX_MACRO, VA_MACRO},
|
||||
@@ -67,6 +72,8 @@ static int __bolero_reg_read(struct bolero_priv *priv,
|
||||
"%s: SSR in progress, exit\n", __func__);
|
||||
goto err;
|
||||
}
|
||||
|
||||
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) {
|
||||
@@ -88,6 +95,8 @@ static int __bolero_reg_read(struct bolero_priv *priv,
|
||||
priv->macro_params[current_mclk_mux_macro].mclk_fn(
|
||||
priv->macro_params[current_mclk_mux_macro].dev, false);
|
||||
err:
|
||||
pm_runtime_mark_last_busy(priv->macro_params[VA_MACRO].dev);
|
||||
pm_runtime_put_autosuspend(priv->macro_params[VA_MACRO].dev);
|
||||
mutex_unlock(&priv->clk_lock);
|
||||
return ret;
|
||||
}
|
||||
@@ -104,6 +113,7 @@ static int __bolero_reg_write(struct bolero_priv *priv,
|
||||
"%s: SSR in progress, exit\n", __func__);
|
||||
goto err;
|
||||
}
|
||||
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) {
|
||||
@@ -125,6 +135,8 @@ static int __bolero_reg_write(struct bolero_priv *priv,
|
||||
priv->macro_params[current_mclk_mux_macro].mclk_fn(
|
||||
priv->macro_params[current_mclk_mux_macro].dev, false);
|
||||
err:
|
||||
pm_runtime_mark_last_busy(priv->macro_params[VA_MACRO].dev);
|
||||
pm_runtime_put_autosuspend(priv->macro_params[VA_MACRO].dev);
|
||||
mutex_unlock(&priv->clk_lock);
|
||||
return ret;
|
||||
}
|
||||
@@ -850,6 +862,7 @@ static int bolero_probe(struct platform_device *pdev)
|
||||
struct bolero_priv *priv;
|
||||
u32 num_macros = 0;
|
||||
int ret;
|
||||
struct clk *lpass_npa_rsc_island = NULL;
|
||||
|
||||
priv = devm_kzalloc(&pdev->dev, sizeof(struct bolero_priv),
|
||||
GFP_KERNEL);
|
||||
@@ -898,6 +911,17 @@ static int bolero_probe(struct platform_device *pdev)
|
||||
bolero_add_child_devices);
|
||||
schedule_work(&priv->bolero_add_child_devices_work);
|
||||
|
||||
/* Register LPASS NPA resource */
|
||||
lpass_npa_rsc_island = devm_clk_get(&pdev->dev, "island_lpass_npa_rsc");
|
||||
if (IS_ERR(lpass_npa_rsc_island)) {
|
||||
ret = PTR_ERR(lpass_npa_rsc_island);
|
||||
dev_dbg(&pdev->dev, "%s: clk get %s failed %d\n",
|
||||
__func__, "island_lpass_npa_rsc", ret);
|
||||
lpass_npa_rsc_island = NULL;
|
||||
ret = 0;
|
||||
}
|
||||
priv->lpass_npa_rsc_island = lpass_npa_rsc_island;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -914,6 +938,41 @@ static int bolero_remove(struct platform_device *pdev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int bolero_runtime_resume(struct device *dev)
|
||||
{
|
||||
struct bolero_priv *priv = dev_get_drvdata(dev->parent);
|
||||
int ret = 0;
|
||||
|
||||
if (priv->lpass_npa_rsc_island == NULL) {
|
||||
dev_dbg(dev, "%s: Invalid lpass npa rsc node\n", __func__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
ret = clk_prepare_enable(priv->lpass_npa_rsc_island);
|
||||
if (ret < 0)
|
||||
dev_err(dev, "%s:lpass npa rsc island enable failed\n",
|
||||
__func__);
|
||||
|
||||
pm_runtime_set_autosuspend_delay(priv->dev, BOLERO_AUTO_SUSPEND_DELAY);
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(bolero_runtime_resume);
|
||||
|
||||
int bolero_runtime_suspend(struct device *dev)
|
||||
{
|
||||
struct bolero_priv *priv = dev_get_drvdata(dev->parent);
|
||||
|
||||
mutex_lock(&priv->clk_lock);
|
||||
if (priv->lpass_npa_rsc_island != NULL)
|
||||
clk_disable_unprepare(priv->lpass_npa_rsc_island);
|
||||
else
|
||||
dev_dbg(dev, "%s: Invalid lpass npa rsc node\n",
|
||||
__func__);
|
||||
mutex_unlock(&priv->clk_lock);
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(bolero_runtime_suspend);
|
||||
|
||||
static const struct of_device_id bolero_dt_match[] = {
|
||||
{.compatible = "qcom,bolero-codec"},
|
||||
{}
|
||||
|
@@ -75,6 +75,8 @@ int bolero_info_create_codec_entry(
|
||||
struct snd_soc_codec *codec);
|
||||
int bolero_register_wake_irq(struct snd_soc_codec *codec, u32 data);
|
||||
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);
|
||||
#else
|
||||
static inline int bolero_register_macro(struct device *dev,
|
||||
u16 macro_id,
|
||||
@@ -113,6 +115,11 @@ static inline void bolero_clear_amic_tx_hold(struct device *dev, u16 adc_n)
|
||||
|
||||
static inline int bolero_register_wake_irq(struct snd_soc_codec *codec,
|
||||
u32 data)
|
||||
static inline int bolero_runtime_resume(struct device *dev)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
static int bolero_runtime_suspend(struct device *dev)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
@@ -64,6 +64,7 @@ struct bolero_priv {
|
||||
u16 current_mclk_mux_macro[MAX_MACRO];
|
||||
struct work_struct bolero_add_child_devices_work;
|
||||
u32 version;
|
||||
struct clk *lpass_npa_rsc_island;
|
||||
|
||||
/* Entry for version info */
|
||||
struct snd_info_entry *entry;
|
||||
|
@@ -20,9 +20,12 @@
|
||||
#include <sound/soc.h>
|
||||
#include <sound/soc-dapm.h>
|
||||
#include <sound/tlv.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
#include "bolero-cdc.h"
|
||||
#include "bolero-cdc-registers.h"
|
||||
|
||||
/* pm runtime auto suspend timer in msecs */
|
||||
#define VA_AUTO_SUSPEND_DELAY 1500 /* delay in msec */
|
||||
#define VA_MACRO_MAX_OFFSET 0x1000
|
||||
|
||||
#define VA_MACRO_NUM_DECIMATORS 8
|
||||
@@ -1617,6 +1620,10 @@ static int va_macro_probe(struct platform_device *pdev)
|
||||
dev_err(&pdev->dev, "%s: register macro failed\n", __func__);
|
||||
goto reg_macro_fail;
|
||||
}
|
||||
pm_runtime_set_autosuspend_delay(&pdev->dev, VA_AUTO_SUSPEND_DELAY);
|
||||
pm_runtime_use_autosuspend(&pdev->dev);
|
||||
pm_runtime_set_suspended(&pdev->dev);
|
||||
pm_runtime_enable(&pdev->dev);
|
||||
return ret;
|
||||
|
||||
reg_macro_fail:
|
||||
@@ -1632,7 +1639,8 @@ static int va_macro_remove(struct platform_device *pdev)
|
||||
|
||||
if (!va_priv)
|
||||
return -EINVAL;
|
||||
|
||||
pm_runtime_disable(&pdev->dev);
|
||||
pm_runtime_set_suspended(&pdev->dev);
|
||||
bolero_unregister_macro(&pdev->dev, VA_MACRO);
|
||||
mutex_destroy(&va_priv->mclk_lock);
|
||||
return 0;
|
||||
@@ -1644,10 +1652,19 @@ static const struct of_device_id va_macro_dt_match[] = {
|
||||
{}
|
||||
};
|
||||
|
||||
static const struct dev_pm_ops bolero_dev_pm_ops = {
|
||||
SET_RUNTIME_PM_OPS(
|
||||
bolero_runtime_suspend,
|
||||
bolero_runtime_resume,
|
||||
NULL
|
||||
)
|
||||
};
|
||||
|
||||
static struct platform_driver va_macro_driver = {
|
||||
.driver = {
|
||||
.name = "va_macro",
|
||||
.owner = THIS_MODULE,
|
||||
.pm = &bolero_dev_pm_ops,
|
||||
.of_match_table = va_macro_dt_match,
|
||||
},
|
||||
.probe = va_macro_probe,
|
||||
|
Referencia en una nueva incidencia
Block a user