From 50ef13eca627cf44ad28e9946680b114930b41af Mon Sep 17 00:00:00 2001 From: Aditya Bavanari Date: Fri, 9 Aug 2019 15:14:43 +0530 Subject: [PATCH] asoc: codecs: Fix LPI TLMM GPIO invalid access issue Runtime suspend gets called multiple times during SSR scenarios leading to clock count mismatch. Add logic to prevent this in all macros and pinctrl lpi driver. Change-Id: I380631c1db8cd7d94a8909affd8c96c87f24817c Signed-off-by: Aditya Bavanari --- asoc/codecs/bolero/rx-macro.c | 11 +++++- asoc/codecs/bolero/tx-macro.c | 12 +++++- asoc/codecs/bolero/va-macro.c | 11 +++++- asoc/codecs/bolero/wsa-macro.c | 11 +++++- soc/pinctrl-lpi.c | 68 +++++++++++++++++----------------- 5 files changed, 71 insertions(+), 42 deletions(-) diff --git a/asoc/codecs/bolero/rx-macro.c b/asoc/codecs/bolero/rx-macro.c index 0137c9f52bdb..03dea2093639 100644 --- a/asoc/codecs/bolero/rx-macro.c +++ b/asoc/codecs/bolero/rx-macro.c @@ -1235,8 +1235,15 @@ static int rx_macro_event_handler(struct snd_soc_component *component, rx_priv->swr_ctrl_data[0].rx_swr_pdev, SWR_DEVICE_SSR_DOWN, NULL); } - if (!pm_runtime_status_suspended(rx_dev)) - bolero_runtime_suspend(rx_dev); + if ((!pm_runtime_enabled(rx_dev) || + !pm_runtime_suspended(rx_dev))) { + ret = bolero_runtime_suspend(rx_dev); + if (!ret) { + pm_runtime_disable(rx_dev); + pm_runtime_set_suspended(rx_dev); + pm_runtime_enable(rx_dev); + } + } break; case BOLERO_MACRO_EVT_SSR_UP: rx_priv->dev_up = true; diff --git a/asoc/codecs/bolero/tx-macro.c b/asoc/codecs/bolero/tx-macro.c index db1129c8321b..fda01e1304f5 100644 --- a/asoc/codecs/bolero/tx-macro.c +++ b/asoc/codecs/bolero/tx-macro.c @@ -342,6 +342,7 @@ static int tx_macro_event_handler(struct snd_soc_component *component, { struct device *tx_dev = NULL; struct tx_macro_priv *tx_priv = NULL; + int ret = 0; if (!tx_macro_get_data(component, &tx_dev, &tx_priv, __func__)) return -EINVAL; @@ -356,8 +357,15 @@ static int tx_macro_event_handler(struct snd_soc_component *component, tx_priv->swr_ctrl_data[0].tx_swr_pdev, SWR_DEVICE_SSR_DOWN, NULL); } - if (!pm_runtime_status_suspended(tx_dev)) - bolero_runtime_suspend(tx_dev); + if ((!pm_runtime_enabled(tx_dev) || + !pm_runtime_suspended(tx_dev))) { + ret = bolero_runtime_suspend(tx_dev); + if (!ret) { + pm_runtime_disable(tx_dev); + pm_runtime_set_suspended(tx_dev); + pm_runtime_enable(tx_dev); + } + } break; case BOLERO_MACRO_EVT_SSR_UP: /* reset swr after ssr/pdr */ diff --git a/asoc/codecs/bolero/va-macro.c b/asoc/codecs/bolero/va-macro.c index 3c625a5a9ef9..4c1631942a36 100644 --- a/asoc/codecs/bolero/va-macro.c +++ b/asoc/codecs/bolero/va-macro.c @@ -252,8 +252,15 @@ static int va_macro_event_handler(struct snd_soc_component *component, bolero_rsc_clk_reset(va_dev, VA_CORE_CLK); break; case BOLERO_MACRO_EVT_SSR_DOWN: - if (!pm_runtime_status_suspended(va_dev)) - bolero_runtime_suspend(va_dev); + if ((!pm_runtime_enabled(va_dev) || + !pm_runtime_suspended(va_dev))) { + ret = bolero_runtime_suspend(va_dev); + if (!ret) { + pm_runtime_disable(va_dev); + pm_runtime_set_suspended(va_dev); + pm_runtime_enable(va_dev); + } + } break; default: break; diff --git a/asoc/codecs/bolero/wsa-macro.c b/asoc/codecs/bolero/wsa-macro.c index d7f9478b5bd6..928aec0d5e0d 100644 --- a/asoc/codecs/bolero/wsa-macro.c +++ b/asoc/codecs/bolero/wsa-macro.c @@ -920,8 +920,15 @@ static int wsa_macro_event_handler(struct snd_soc_component *component, wsa_priv->swr_ctrl_data[0].wsa_swr_pdev, SWR_DEVICE_SSR_DOWN, NULL); } - if (!pm_runtime_status_suspended(wsa_dev)) - bolero_runtime_suspend(wsa_dev); + if ((!pm_runtime_enabled(wsa_dev) || + !pm_runtime_suspended(wsa_dev))) { + ret = bolero_runtime_suspend(wsa_dev); + if (!ret) { + pm_runtime_disable(wsa_dev); + pm_runtime_set_suspended(wsa_dev); + pm_runtime_enable(wsa_dev); + } + } break; case BOLERO_MACRO_EVT_SSR_UP: /* reset swr after ssr/pdr */ diff --git a/soc/pinctrl-lpi.c b/soc/pinctrl-lpi.c index e11ba6e2be96..157e2c54a17b 100644 --- a/soc/pinctrl-lpi.c +++ b/soc/pinctrl-lpi.c @@ -481,6 +481,39 @@ static int lpi_notifier_service_cb(struct notifier_block *this, return NOTIFY_OK; } +int lpi_pinctrl_suspend(struct device *dev) +{ + int ret = 0; + + dev_dbg(dev, "%s: system suspend\n", __func__); + + if ((!pm_runtime_enabled(dev) || !pm_runtime_suspended(dev))) { + ret = lpi_pinctrl_runtime_suspend(dev); + if (!ret) { + /* + * Synchronize runtime-pm and system-pm states: + * At this point, we are already suspended. If + * runtime-pm still thinks its active, then + * make sure its status is in sync with HW + * status. The three below calls let the + * runtime-pm know that we are suspended + * already without re-invoking the suspend + * callback + */ + pm_runtime_disable(dev); + pm_runtime_set_suspended(dev); + pm_runtime_enable(dev); + } + } + + return ret; +} + +int lpi_pinctrl_resume(struct device *dev) +{ + return 0; +} + static struct notifier_block service_nb = { .notifier_call = lpi_notifier_service_cb, .priority = -INT_MAX, @@ -489,7 +522,7 @@ static struct notifier_block service_nb = { static void lpi_pinctrl_ssr_disable(struct device *dev, void *data) { lpi_dev_up = false; - lpi_pinctrl_runtime_suspend(dev); + lpi_pinctrl_suspend(dev); } static const struct snd_event_ops lpi_pinctrl_ssr_ops = { @@ -820,39 +853,6 @@ int lpi_pinctrl_runtime_suspend(struct device *dev) return 0; } -int lpi_pinctrl_suspend(struct device *dev) -{ - int ret = 0; - - dev_dbg(dev, "%s: system suspend\n", __func__); - - if ((!pm_runtime_enabled(dev) || !pm_runtime_suspended(dev))) { - ret = lpi_pinctrl_runtime_suspend(dev); - if (!ret) { - /* - * Synchronize runtime-pm and system-pm states: - * At this point, we are already suspended. If - * runtime-pm still thinks its active, then - * make sure its status is in sync with HW - * status. The three below calls let the - * runtime-pm know that we are suspended - * already without re-invoking the suspend - * callback - */ - pm_runtime_disable(dev); - pm_runtime_set_suspended(dev); - pm_runtime_enable(dev); - } - } - - return ret; -} - -int lpi_pinctrl_resume(struct device *dev) -{ - return 0; -} - static const struct dev_pm_ops lpi_pinctrl_dev_pm_ops = { SET_SYSTEM_SLEEP_PM_OPS( lpi_pinctrl_suspend,