asoc: lpass-cdc: update logic to vote during ssr
After ADSP is up during SSR, core_hw_vote may fail and audio_hw_vote may successed in lpass_cdc_runtime_resume which is caused some timing. When getting slave device_id, as core_hw_vote is 0, it will skip reading swr registers and return 0 which causes fail to read correct device_id. Make this change to avoid calling lpass_cdc_runtime_resume when adsp_up notification doesn't reach lpass_cdc. Change-Id: I90a97e5c47bb95180a96ba1c60b462f1fa0124b7 Signed-off-by: Meng Wang <quic_mengw@quicinc.com> Signed-off-by: Kunlei Zhang <quic_kunleiz@quicinc.com>
This commit is contained in:
@@ -503,6 +503,7 @@ struct lpass_cdc_rx_macro_priv {
|
|||||||
bool is_fir_coeff_written[FIR_PATH_MAX][GRP_MAX];
|
bool is_fir_coeff_written[FIR_PATH_MAX][GRP_MAX];
|
||||||
bool is_fir_capable;
|
bool is_fir_capable;
|
||||||
bool dev_up;
|
bool dev_up;
|
||||||
|
bool pre_dev_up;
|
||||||
bool hph_pwr_mode;
|
bool hph_pwr_mode;
|
||||||
bool hph_hd2_mode;
|
bool hph_hd2_mode;
|
||||||
struct mutex mclk_lock;
|
struct mutex mclk_lock;
|
||||||
@@ -1424,7 +1425,8 @@ static int lpass_cdc_rx_macro_mclk_enable(
|
|||||||
rx_priv->default_clk_id,
|
rx_priv->default_clk_id,
|
||||||
rx_priv->clk_id,
|
rx_priv->clk_id,
|
||||||
false);
|
false);
|
||||||
lpass_cdc_rx_macro_core_vote(rx_priv, false);
|
if (!ret)
|
||||||
|
lpass_cdc_rx_macro_core_vote(rx_priv, false);
|
||||||
rx_priv->clk_id = rx_priv->default_clk_id;
|
rx_priv->clk_id = rx_priv->default_clk_id;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1517,6 +1519,7 @@ static int lpass_cdc_rx_macro_event_handler(struct snd_soc_component *component,
|
|||||||
break;
|
break;
|
||||||
case LPASS_CDC_MACRO_EVT_SSR_DOWN:
|
case LPASS_CDC_MACRO_EVT_SSR_DOWN:
|
||||||
trace_printk("%s, enter SSR down\n", __func__);
|
trace_printk("%s, enter SSR down\n", __func__);
|
||||||
|
rx_priv->pre_dev_up = false;
|
||||||
rx_priv->dev_up = false;
|
rx_priv->dev_up = false;
|
||||||
if (rx_priv->swr_ctrl_data) {
|
if (rx_priv->swr_ctrl_data) {
|
||||||
swrm_wcd_notify(
|
swrm_wcd_notify(
|
||||||
@@ -1534,6 +1537,7 @@ static int lpass_cdc_rx_macro_event_handler(struct snd_soc_component *component,
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case LPASS_CDC_MACRO_EVT_PRE_SSR_UP:
|
case LPASS_CDC_MACRO_EVT_PRE_SSR_UP:
|
||||||
|
rx_priv->pre_dev_up = true;
|
||||||
ret = lpass_cdc_rx_macro_core_vote(rx_priv, true);
|
ret = lpass_cdc_rx_macro_core_vote(rx_priv, true);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
dev_err_ratelimited(rx_priv->dev,
|
dev_err_ratelimited(rx_priv->dev,
|
||||||
@@ -4349,6 +4353,12 @@ static int lpass_cdc_rx_macro_core_vote(void *handle, bool enable)
|
|||||||
pr_err_ratelimited("%s: rx priv data is NULL\n", __func__);
|
pr_err_ratelimited("%s: rx priv data is NULL\n", __func__);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!rx_priv->pre_dev_up && enable) {
|
||||||
|
pr_debug("%s: adsp is not up\n", __func__);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
if (enable) {
|
if (enable) {
|
||||||
pm_runtime_get_sync(rx_priv->dev);
|
pm_runtime_get_sync(rx_priv->dev);
|
||||||
if (lpass_cdc_check_core_votes(rx_priv->dev))
|
if (lpass_cdc_check_core_votes(rx_priv->dev))
|
||||||
@@ -4718,6 +4728,7 @@ static int lpass_cdc_rx_macro_probe(struct platform_device *pdev)
|
|||||||
if (!rx_priv)
|
if (!rx_priv)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
|
rx_priv->pre_dev_up = true;
|
||||||
rx_priv->dev = &pdev->dev;
|
rx_priv->dev = &pdev->dev;
|
||||||
ret = of_property_read_u32(pdev->dev.of_node, "reg",
|
ret = of_property_read_u32(pdev->dev.of_node, "reg",
|
||||||
&rx_base_addr);
|
&rx_base_addr);
|
||||||
|
@@ -176,6 +176,7 @@ struct lpass_cdc_va_macro_priv {
|
|||||||
int dapm_tx_clk_status;
|
int dapm_tx_clk_status;
|
||||||
u16 current_clk_id;
|
u16 current_clk_id;
|
||||||
bool dev_up;
|
bool dev_up;
|
||||||
|
bool pre_dev_up;
|
||||||
bool swr_dmic_enable;
|
bool swr_dmic_enable;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -280,7 +281,8 @@ static int lpass_cdc_va_macro_mclk_enable(
|
|||||||
va_priv->default_clk_id,
|
va_priv->default_clk_id,
|
||||||
va_priv->clk_id,
|
va_priv->clk_id,
|
||||||
false);
|
false);
|
||||||
lpass_cdc_va_macro_core_vote(va_priv, false);
|
if (!ret)
|
||||||
|
lpass_cdc_va_macro_core_vote(va_priv, false);
|
||||||
}
|
}
|
||||||
exit:
|
exit:
|
||||||
mutex_unlock(&va_priv->mclk_lock);
|
mutex_unlock(&va_priv->mclk_lock);
|
||||||
@@ -321,6 +323,7 @@ static int lpass_cdc_va_macro_event_handler(struct snd_soc_component *component,
|
|||||||
__func__);
|
__func__);
|
||||||
break;
|
break;
|
||||||
case LPASS_CDC_MACRO_EVT_PRE_SSR_UP:
|
case LPASS_CDC_MACRO_EVT_PRE_SSR_UP:
|
||||||
|
va_priv->pre_dev_up = true;
|
||||||
/* enable&disable VA_CORE_CLK to reset GFMUX reg */
|
/* enable&disable VA_CORE_CLK to reset GFMUX reg */
|
||||||
ret = lpass_cdc_va_macro_core_vote(va_priv, true);
|
ret = lpass_cdc_va_macro_core_vote(va_priv, true);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
@@ -356,6 +359,7 @@ static int lpass_cdc_va_macro_event_handler(struct snd_soc_component *component,
|
|||||||
lpass_cdc_rsc_clk_reset(va_dev, VA_CORE_CLK);
|
lpass_cdc_rsc_clk_reset(va_dev, VA_CORE_CLK);
|
||||||
break;
|
break;
|
||||||
case LPASS_CDC_MACRO_EVT_SSR_DOWN:
|
case LPASS_CDC_MACRO_EVT_SSR_DOWN:
|
||||||
|
va_priv->pre_dev_up = false;
|
||||||
va_priv->dev_up = false;
|
va_priv->dev_up = false;
|
||||||
if (va_priv->swr_ctrl_data) {
|
if (va_priv->swr_ctrl_data) {
|
||||||
swrm_wcd_notify(
|
swrm_wcd_notify(
|
||||||
@@ -413,6 +417,7 @@ static int lpass_cdc_va_macro_swr_pwr_event(struct snd_soc_dapm_widget *w,
|
|||||||
int ret = 0;
|
int ret = 0;
|
||||||
struct device *va_dev = NULL;
|
struct device *va_dev = NULL;
|
||||||
struct lpass_cdc_va_macro_priv *va_priv = NULL;
|
struct lpass_cdc_va_macro_priv *va_priv = NULL;
|
||||||
|
bool vote_err = false;
|
||||||
|
|
||||||
if (!lpass_cdc_va_macro_get_data(component, &va_dev,
|
if (!lpass_cdc_va_macro_get_data(component, &va_dev,
|
||||||
&va_priv, __func__))
|
&va_priv, __func__))
|
||||||
@@ -496,12 +501,14 @@ static int lpass_cdc_va_macro_swr_pwr_event(struct snd_soc_dapm_widget *w,
|
|||||||
__func__);
|
__func__);
|
||||||
if (va_priv->dev_up)
|
if (va_priv->dev_up)
|
||||||
break;
|
break;
|
||||||
|
vote_err = true;
|
||||||
}
|
}
|
||||||
ret = lpass_cdc_clk_rsc_request_clock(va_priv->dev,
|
ret = lpass_cdc_clk_rsc_request_clock(va_priv->dev,
|
||||||
va_priv->default_clk_id,
|
va_priv->default_clk_id,
|
||||||
VA_CORE_CLK,
|
VA_CORE_CLK,
|
||||||
false);
|
false);
|
||||||
lpass_cdc_va_macro_core_vote(va_priv, false);
|
if (!vote_err)
|
||||||
|
lpass_cdc_va_macro_core_vote(va_priv, false);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
dev_err_ratelimited(component->dev,
|
dev_err_ratelimited(component->dev,
|
||||||
"%s: request clock VA_CLK disable failed\n",
|
"%s: request clock VA_CLK disable failed\n",
|
||||||
@@ -741,6 +748,11 @@ static int lpass_cdc_va_macro_core_vote(void *handle, bool enable)
|
|||||||
pr_err_ratelimited("%s: va priv data is NULL\n", __func__);
|
pr_err_ratelimited("%s: va priv data is NULL\n", __func__);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
if (!va_priv->pre_dev_up && enable) {
|
||||||
|
pr_err("%s: adsp is not up\n", __func__);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
trace_printk("%s, enter: enable %d\n", __func__, enable);
|
trace_printk("%s, enter: enable %d\n", __func__, enable);
|
||||||
if (enable) {
|
if (enable) {
|
||||||
pm_runtime_get_sync(va_priv->dev);
|
pm_runtime_get_sync(va_priv->dev);
|
||||||
@@ -2525,6 +2537,7 @@ static int lpass_cdc_va_macro_probe(struct platform_device *pdev)
|
|||||||
mutex_init(&va_priv->swr_clk_lock);
|
mutex_init(&va_priv->swr_clk_lock);
|
||||||
}
|
}
|
||||||
va_priv->is_used_va_swr_gpio = is_used_va_swr_gpio;
|
va_priv->is_used_va_swr_gpio = is_used_va_swr_gpio;
|
||||||
|
va_priv->pre_dev_up = true;
|
||||||
|
|
||||||
mutex_init(&va_priv->mclk_lock);
|
mutex_init(&va_priv->mclk_lock);
|
||||||
dev_set_drvdata(&pdev->dev, va_priv);
|
dev_set_drvdata(&pdev->dev, va_priv);
|
||||||
|
@@ -315,6 +315,7 @@ struct lpass_cdc_wsa_macro_priv {
|
|||||||
u32 wsa_rload[LPASS_CDC_WSA_MACRO_RX1 + 1];
|
u32 wsa_rload[LPASS_CDC_WSA_MACRO_RX1 + 1];
|
||||||
u8 idle_detect_en;
|
u8 idle_detect_en;
|
||||||
int noise_gate_mode;
|
int noise_gate_mode;
|
||||||
|
bool pre_dev_up;
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct snd_soc_dai_driver lpass_cdc_wsa_macro_dai[];
|
static struct snd_soc_dai_driver lpass_cdc_wsa_macro_dai[];
|
||||||
@@ -1031,6 +1032,7 @@ static int lpass_cdc_wsa_macro_event_handler(struct snd_soc_component *component
|
|||||||
|
|
||||||
switch (event) {
|
switch (event) {
|
||||||
case LPASS_CDC_MACRO_EVT_SSR_DOWN:
|
case LPASS_CDC_MACRO_EVT_SSR_DOWN:
|
||||||
|
wsa_priv->pre_dev_up = false;
|
||||||
trace_printk("%s, enter SSR down\n", __func__);
|
trace_printk("%s, enter SSR down\n", __func__);
|
||||||
if (wsa_priv->swr_ctrl_data) {
|
if (wsa_priv->swr_ctrl_data) {
|
||||||
swrm_wcd_notify(
|
swrm_wcd_notify(
|
||||||
@@ -1051,6 +1053,7 @@ static int lpass_cdc_wsa_macro_event_handler(struct snd_soc_component *component
|
|||||||
break;
|
break;
|
||||||
case LPASS_CDC_MACRO_EVT_SSR_UP:
|
case LPASS_CDC_MACRO_EVT_SSR_UP:
|
||||||
trace_printk("%s, enter SSR up\n", __func__);
|
trace_printk("%s, enter SSR up\n", __func__);
|
||||||
|
wsa_priv->pre_dev_up = true;
|
||||||
/* reset swr after ssr/pdr */
|
/* reset swr after ssr/pdr */
|
||||||
wsa_priv->reset_swr = true;
|
wsa_priv->reset_swr = true;
|
||||||
if (wsa_priv->swr_ctrl_data)
|
if (wsa_priv->swr_ctrl_data)
|
||||||
@@ -3303,6 +3306,11 @@ static int lpass_cdc_wsa_macro_core_vote(void *handle, bool enable)
|
|||||||
pr_err_ratelimited("%s: wsa priv data is NULL\n", __func__);
|
pr_err_ratelimited("%s: wsa priv data is NULL\n", __func__);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
if (!wsa_priv->pre_dev_up && enable) {
|
||||||
|
pr_debug("%s: adsp is not up\n", __func__);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
if (enable) {
|
if (enable) {
|
||||||
pm_runtime_get_sync(wsa_priv->dev);
|
pm_runtime_get_sync(wsa_priv->dev);
|
||||||
if (lpass_cdc_check_core_votes(wsa_priv->dev))
|
if (lpass_cdc_check_core_votes(wsa_priv->dev))
|
||||||
@@ -3761,6 +3769,7 @@ static int lpass_cdc_wsa_macro_probe(struct platform_device *pdev)
|
|||||||
if (!wsa_priv)
|
if (!wsa_priv)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
|
wsa_priv->pre_dev_up = true;
|
||||||
wsa_priv->dev = &pdev->dev;
|
wsa_priv->dev = &pdev->dev;
|
||||||
ret = of_property_read_u32(pdev->dev.of_node, "reg",
|
ret = of_property_read_u32(pdev->dev.of_node, "reg",
|
||||||
&wsa_base_addr);
|
&wsa_base_addr);
|
||||||
|
@@ -315,6 +315,7 @@ struct lpass_cdc_wsa2_macro_priv {
|
|||||||
u32 wsa2_rload[LPASS_CDC_WSA2_MACRO_RX1 + 1];
|
u32 wsa2_rload[LPASS_CDC_WSA2_MACRO_RX1 + 1];
|
||||||
u8 idle_detect_en;
|
u8 idle_detect_en;
|
||||||
int noise_gate_mode;
|
int noise_gate_mode;
|
||||||
|
bool pre_dev_up;
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct snd_soc_dai_driver lpass_cdc_wsa2_macro_dai[];
|
static struct snd_soc_dai_driver lpass_cdc_wsa2_macro_dai[];
|
||||||
@@ -1030,6 +1031,7 @@ static int lpass_cdc_wsa2_macro_event_handler(struct snd_soc_component *componen
|
|||||||
|
|
||||||
switch (event) {
|
switch (event) {
|
||||||
case LPASS_CDC_MACRO_EVT_SSR_DOWN:
|
case LPASS_CDC_MACRO_EVT_SSR_DOWN:
|
||||||
|
wsa2_priv->pre_dev_up = false;
|
||||||
trace_printk("%s, enter SSR down\n", __func__);
|
trace_printk("%s, enter SSR down\n", __func__);
|
||||||
if (wsa2_priv->swr_ctrl_data) {
|
if (wsa2_priv->swr_ctrl_data) {
|
||||||
swrm_wcd_notify(
|
swrm_wcd_notify(
|
||||||
@@ -1050,6 +1052,7 @@ static int lpass_cdc_wsa2_macro_event_handler(struct snd_soc_component *componen
|
|||||||
break;
|
break;
|
||||||
case LPASS_CDC_MACRO_EVT_SSR_UP:
|
case LPASS_CDC_MACRO_EVT_SSR_UP:
|
||||||
trace_printk("%s, enter SSR up\n", __func__);
|
trace_printk("%s, enter SSR up\n", __func__);
|
||||||
|
wsa2_priv->pre_dev_up = true;
|
||||||
/* reset swr after ssr/pdr */
|
/* reset swr after ssr/pdr */
|
||||||
wsa2_priv->reset_swr = true;
|
wsa2_priv->reset_swr = true;
|
||||||
if (wsa2_priv->swr_ctrl_data)
|
if (wsa2_priv->swr_ctrl_data)
|
||||||
@@ -3295,6 +3298,12 @@ static int lpass_cdc_wsa2_macro_core_vote(void *handle, bool enable)
|
|||||||
pr_err_ratelimited("%s: wsa2 priv data is NULL\n", __func__);
|
pr_err_ratelimited("%s: wsa2 priv data is NULL\n", __func__);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!wsa2_priv->pre_dev_up && enable) {
|
||||||
|
pr_debug("%s: adsp is not up\n", __func__);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
if (enable) {
|
if (enable) {
|
||||||
pm_runtime_get_sync(wsa2_priv->dev);
|
pm_runtime_get_sync(wsa2_priv->dev);
|
||||||
if (lpass_cdc_check_core_votes(wsa2_priv->dev))
|
if (lpass_cdc_check_core_votes(wsa2_priv->dev))
|
||||||
@@ -3751,6 +3760,7 @@ static int lpass_cdc_wsa2_macro_probe(struct platform_device *pdev)
|
|||||||
if (!wsa2_priv)
|
if (!wsa2_priv)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
|
wsa2_priv->pre_dev_up = true;
|
||||||
wsa2_priv->dev = &pdev->dev;
|
wsa2_priv->dev = &pdev->dev;
|
||||||
ret = of_property_read_u32(pdev->dev.of_node, "reg",
|
ret = of_property_read_u32(pdev->dev.of_node, "reg",
|
||||||
&wsa2_base_addr);
|
&wsa2_base_addr);
|
||||||
|
@@ -1376,6 +1376,7 @@ int lpass_cdc_runtime_resume(struct device *dev)
|
|||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
trace_printk("%s, enter\n", __func__);
|
trace_printk("%s, enter\n", __func__);
|
||||||
|
dev_dbg(dev,"%s, enter\n", __func__);
|
||||||
mutex_lock(&priv->vote_lock);
|
mutex_lock(&priv->vote_lock);
|
||||||
if (priv->lpass_core_hw_vote == NULL) {
|
if (priv->lpass_core_hw_vote == NULL) {
|
||||||
dev_dbg(dev, "%s: Invalid lpass core hw node\n", __func__);
|
dev_dbg(dev, "%s: Invalid lpass core hw node\n", __func__);
|
||||||
@@ -1415,6 +1416,8 @@ audio_vote:
|
|||||||
done:
|
done:
|
||||||
mutex_unlock(&priv->vote_lock);
|
mutex_unlock(&priv->vote_lock);
|
||||||
trace_printk("%s, leave\n", __func__);
|
trace_printk("%s, leave\n", __func__);
|
||||||
|
dev_dbg(dev,"%s, leave, hw_vote %d, audio_vote %d\n", __func__,
|
||||||
|
priv->core_hw_vote_count, priv->core_audio_vote_count);
|
||||||
pm_runtime_set_autosuspend_delay(priv->dev, LPASS_CDC_AUTO_SUSPEND_DELAY);
|
pm_runtime_set_autosuspend_delay(priv->dev, LPASS_CDC_AUTO_SUSPEND_DELAY);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -1425,6 +1428,7 @@ int lpass_cdc_runtime_suspend(struct device *dev)
|
|||||||
struct lpass_cdc_priv *priv = dev_get_drvdata(dev->parent);
|
struct lpass_cdc_priv *priv = dev_get_drvdata(dev->parent);
|
||||||
|
|
||||||
trace_printk("%s, enter\n", __func__);
|
trace_printk("%s, enter\n", __func__);
|
||||||
|
dev_dbg(dev,"%s, enter\n", __func__);
|
||||||
mutex_lock(&priv->vote_lock);
|
mutex_lock(&priv->vote_lock);
|
||||||
if (priv->lpass_core_hw_vote != NULL) {
|
if (priv->lpass_core_hw_vote != NULL) {
|
||||||
if (--priv->core_hw_vote_count == 0)
|
if (--priv->core_hw_vote_count == 0)
|
||||||
@@ -1454,6 +1458,8 @@ int lpass_cdc_runtime_suspend(struct device *dev)
|
|||||||
|
|
||||||
mutex_unlock(&priv->vote_lock);
|
mutex_unlock(&priv->vote_lock);
|
||||||
trace_printk("%s, leave\n", __func__);
|
trace_printk("%s, leave\n", __func__);
|
||||||
|
dev_dbg(dev,"%s, leave, hw_vote %d, audio_vote %d\n", __func__,
|
||||||
|
priv->core_hw_vote_count, priv->core_audio_vote_count);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(lpass_cdc_runtime_suspend);
|
EXPORT_SYMBOL(lpass_cdc_runtime_suspend);
|
||||||
|
Reference in New Issue
Block a user