summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBhalchandra Gajare <gajare@codeaurora.org>2016-10-06 12:06:45 -0700
committerGerrit - the friendly Code Review server <code-review@localhost>2016-10-11 15:38:32 -0700
commitf5c0c7a00bfd43656fa5993e0a9dcd160856c77e (patch)
tree3ed9955dd2f9e254b93ac03c7d5612a7cdbc91b6
parentd0b17cbf01350723aec31d4dcaa203f6955b21d0 (diff)
ASoC: wcd-dsp-mgr: handle codec down and up events
It is possible that codec hardware can be reset in case of subsystem restart scenarios. It is required to reset the codec DSP as well in such cases to make sure the DSP is in usable state after the codec hardware is reset. Change adds support to handle codec down and up events and perform the necessary reset on codec DSP. Change-Id: I79502c043f5e16947c895aab7cd584d72ad1a7dc Signed-off-by: Bhalchandra Gajare <gajare@codeaurora.org>
-rw-r--r--include/sound/wcd-dsp-mgr.h4
-rw-r--r--sound/soc/codecs/wcd-dsp-mgr.c42
2 files changed, 36 insertions, 10 deletions
diff --git a/include/sound/wcd-dsp-mgr.h b/include/sound/wcd-dsp-mgr.h
index 9bd27b4c18b5..2beb9b38a46a 100644
--- a/include/sound/wcd-dsp-mgr.h
+++ b/include/sound/wcd-dsp-mgr.h
@@ -69,6 +69,10 @@ enum wdsp_signal {
/* Hardware generated interrupts signalled to manager */
WDSP_IPC1_INTR,
WDSP_ERR_INTR,
+
+ /* Other signals */
+ WDSP_CDC_DOWN_SIGNAL,
+ WDSP_CDC_UP_SIGNAL,
};
/*
diff --git a/sound/soc/codecs/wcd-dsp-mgr.c b/sound/soc/codecs/wcd-dsp-mgr.c
index a780edc6375b..d9d413f0a80a 100644
--- a/sound/soc/codecs/wcd-dsp-mgr.c
+++ b/sound/soc/codecs/wcd-dsp-mgr.c
@@ -684,17 +684,18 @@ static void wdsp_ssr_work_fn(struct work_struct *work)
WDSP_MGR_MUTEX_LOCK(wdsp, wdsp->ssr_mutex);
- wdsp_collect_ramdumps(wdsp);
-
- /* In case of CDC_DOWN event, the DSP is already shutdown */
- if (wdsp->ssr_type != WDSP_SSR_TYPE_CDC_DOWN) {
+ /* Issue ramdumps and shutdown only if DSP is currently booted */
+ if (WDSP_STATUS_IS_SET(wdsp, WDSP_STATUS_BOOTED)) {
+ wdsp_collect_ramdumps(wdsp);
ret = wdsp_unicast_event(wdsp, WDSP_CMPNT_CONTROL,
WDSP_EVENT_DO_SHUTDOWN, NULL);
if (IS_ERR_VALUE(ret))
WDSP_ERR(wdsp, "Failed WDSP shutdown, err = %d", ret);
+
+ wdsp_broadcast_event_downseq(wdsp, WDSP_EVENT_POST_SHUTDOWN,
+ NULL);
+ WDSP_CLEAR_STATUS(wdsp, WDSP_STATUS_BOOTED);
}
- wdsp_broadcast_event_downseq(wdsp, WDSP_EVENT_POST_SHUTDOWN, NULL);
- WDSP_CLEAR_STATUS(wdsp, WDSP_STATUS_BOOTED);
WDSP_MGR_MUTEX_UNLOCK(wdsp, wdsp->ssr_mutex);
ret = wait_for_completion_timeout(&wdsp->ready_compl,
@@ -761,16 +762,29 @@ static int wdsp_ssr_handler(struct wdsp_mgr_priv *wdsp, void *arg,
switch (ssr_type) {
case WDSP_SSR_TYPE_WDSP_DOWN:
- case WDSP_SSR_TYPE_CDC_DOWN:
__wdsp_clr_ready_locked(wdsp, WDSP_SSR_STATUS_WDSP_READY);
- if (ssr_type == WDSP_SSR_TYPE_CDC_DOWN)
- __wdsp_clr_ready_locked(wdsp,
- WDSP_SSR_STATUS_CDC_READY);
wdsp_broadcast_event_downseq(wdsp, WDSP_EVENT_PRE_SHUTDOWN,
NULL);
schedule_work(&wdsp->ssr_work);
break;
+ case WDSP_SSR_TYPE_CDC_DOWN:
+ __wdsp_clr_ready_locked(wdsp, WDSP_SSR_STATUS_CDC_READY);
+ /*
+ * If DSP is booted when CDC_DOWN is received, it needs
+ * to be shutdown.
+ */
+ if (WDSP_STATUS_IS_SET(wdsp, WDSP_STATUS_BOOTED)) {
+ __wdsp_clr_ready_locked(wdsp,
+ WDSP_SSR_STATUS_WDSP_READY);
+ wdsp_broadcast_event_downseq(wdsp,
+ WDSP_EVENT_PRE_SHUTDOWN,
+ NULL);
+ }
+
+ schedule_work(&wdsp->ssr_work);
+ break;
+
case WDSP_SSR_TYPE_CDC_UP:
__wdsp_set_ready_locked(wdsp, WDSP_SSR_STATUS_CDC_READY, true);
break;
@@ -799,6 +813,8 @@ static int wdsp_signal_handler(struct device *wdsp_dev,
wdsp = dev_get_drvdata(wdsp_dev);
WDSP_MGR_MUTEX_LOCK(wdsp, wdsp->api_mutex);
+ WDSP_DBG(wdsp, "Raised signal %d", signal);
+
switch (signal) {
case WDSP_IPC1_INTR:
ret = wdsp_unicast_event(wdsp, WDSP_CMPNT_IPC,
@@ -807,6 +823,12 @@ static int wdsp_signal_handler(struct device *wdsp_dev,
case WDSP_ERR_INTR:
ret = wdsp_ssr_handler(wdsp, arg, WDSP_SSR_TYPE_WDSP_DOWN);
break;
+ case WDSP_CDC_DOWN_SIGNAL:
+ ret = wdsp_ssr_handler(wdsp, arg, WDSP_SSR_TYPE_CDC_DOWN);
+ break;
+ case WDSP_CDC_UP_SIGNAL:
+ ret = wdsp_ssr_handler(wdsp, arg, WDSP_SSR_TYPE_CDC_UP);
+ break;
default:
ret = -EINVAL;
break;