Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit de9bfef0 authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "ASoC: wcd-dsp-mgr: handle codec down and up events"

parents 3e806839 f5c0c7a0
Loading
Loading
Loading
Loading
+12 −6
Original line number Diff line number Diff line
@@ -65,9 +65,14 @@ enum wdsp_event_type {
	WDSP_EVENT_RESUME,
};

enum wdsp_intr {
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,
};

/*
@@ -92,7 +97,7 @@ struct wdsp_img_section {
	u8 *data;
};

struct wdsp_err_intr_arg {
struct wdsp_err_signal_arg {
	bool mem_dumps_enabled;
	u32 remote_start_addr;
	size_t dump_size;
@@ -104,8 +109,9 @@ struct wdsp_err_intr_arg {
 *			their own ops to manager driver
 * @get_dev_for_cmpnt: components can use this to get handle
 *		       to struct device * of any other component
 * @intr_handler: callback to notify manager driver that interrupt
 *		  has occurred.
 * @signal_handler: callback to notify manager driver that signal
 *		    has occurred. Cannot be called from interrupt
 *		    context as this can sleep
 * @vote_for_dsp: notifies manager that dsp should be booted up
 * @suspend: notifies manager that one component wants to suspend.
 *	     Manager will make sure to suspend all components in order
@@ -120,8 +126,8 @@ struct wdsp_mgr_ops {
				  struct wdsp_cmpnt_ops *ops);
	struct device *(*get_dev_for_cmpnt)(struct device *wdsp_dev,
					    enum wdsp_cmpnt_type type);
	int (*intr_handler)(struct device *wdsp_dev,
			      enum wdsp_intr intr, void *arg);
	int (*signal_handler)(struct device *wdsp_dev,
			      enum wdsp_signal signal, void *arg);
	int (*vote_for_dsp)(struct device *wdsp_dev, bool vote);
	int (*suspend)(struct device *wdsp_dev);
	int (*resume)(struct device *wdsp_dev);
+42 −20
Original line number Diff line number Diff line
@@ -136,7 +136,7 @@ struct wdsp_ramdump_data {
	void *rd_v_addr;

	/* Data provided through error interrupt */
	struct wdsp_err_intr_arg err_data;
	struct wdsp_err_signal_arg err_data;
};

struct wdsp_mgr_priv {
@@ -608,7 +608,7 @@ static struct device *wdsp_get_dev_for_cmpnt(struct device *wdsp_dev,
static void wdsp_collect_ramdumps(struct wdsp_mgr_priv *wdsp)
{
	struct wdsp_img_section img_section;
	struct wdsp_err_intr_arg *data = &wdsp->dump_data.err_data;
	struct wdsp_err_signal_arg *data = &wdsp->dump_data.err_data;
	struct ramdump_segment rd_seg;
	int ret = 0;

@@ -684,17 +684,18 @@ static void wdsp_ssr_work_fn(struct work_struct *work)

	WDSP_MGR_MUTEX_LOCK(wdsp, wdsp->ssr_mutex);

	/* Issue ramdumps and shutdown only if DSP is currently booted */
	if (WDSP_STATUS_IS_SET(wdsp, WDSP_STATUS_BOOTED)) {
		wdsp_collect_ramdumps(wdsp);

	/* In case of CDC_DOWN event, the DSP is already shutdown */
	if (wdsp->ssr_type != WDSP_SSR_TYPE_CDC_DOWN) {
		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_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,
@@ -739,7 +740,7 @@ static int wdsp_ssr_handler(struct wdsp_mgr_priv *wdsp, void *arg,
			    enum wdsp_ssr_type ssr_type)
{
	enum wdsp_ssr_type current_ssr_type;
	struct wdsp_err_intr_arg *err_data;
	struct wdsp_err_signal_arg *err_data;

	WDSP_MGR_MUTEX_LOCK(wdsp, wdsp->ssr_mutex);

@@ -750,7 +751,7 @@ static int wdsp_ssr_handler(struct wdsp_mgr_priv *wdsp, void *arg,
	wdsp->ssr_type = ssr_type;

	if (arg) {
		err_data = (struct wdsp_err_intr_arg *) arg;
		err_data = (struct wdsp_err_signal_arg *) arg;
		memcpy(&wdsp->dump_data.err_data, err_data,
		       sizeof(*err_data));
	} else {
@@ -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;
@@ -787,8 +801,8 @@ static int wdsp_ssr_handler(struct wdsp_mgr_priv *wdsp, void *arg,
	return 0;
}

static int wdsp_intr_handler(struct device *wdsp_dev,
			     enum wdsp_intr intr, void *arg)
static int wdsp_signal_handler(struct device *wdsp_dev,
			       enum wdsp_signal signal, void *arg)
{
	struct wdsp_mgr_priv *wdsp;
	int ret;
@@ -799,7 +813,9 @@ static int wdsp_intr_handler(struct device *wdsp_dev,
	wdsp = dev_get_drvdata(wdsp_dev);
	WDSP_MGR_MUTEX_LOCK(wdsp, wdsp->api_mutex);

	switch (intr) {
	WDSP_DBG(wdsp, "Raised signal %d", signal);

	switch (signal) {
	case WDSP_IPC1_INTR:
		ret = wdsp_unicast_event(wdsp, WDSP_CMPNT_IPC,
					 WDSP_EVENT_IPC1_INTR, NULL);
@@ -807,14 +823,20 @@ static int wdsp_intr_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;
	}

	if (IS_ERR_VALUE(ret))
		WDSP_ERR(wdsp, "handling intr %d failed with error %d",
			 intr, ret);
		WDSP_ERR(wdsp, "handling signal %d failed with error %d",
			 signal, ret);
	WDSP_MGR_MUTEX_UNLOCK(wdsp, wdsp->api_mutex);

	return ret;
@@ -870,7 +892,7 @@ static int wdsp_resume(struct device *wdsp_dev)
static struct wdsp_mgr_ops wdsp_ops = {
	.register_cmpnt_ops = wdsp_register_cmpnt_ops,
	.get_dev_for_cmpnt = wdsp_get_dev_for_cmpnt,
	.intr_handler = wdsp_intr_handler,
	.signal_handler = wdsp_signal_handler,
	.vote_for_dsp = wdsp_vote_for_dsp,
	.suspend = wdsp_suspend,
	.resume = wdsp_resume,
+8 −8
Original line number Diff line number Diff line
@@ -646,8 +646,8 @@ static irqreturn_t wcd_cntl_ipc_irq(int irq, void *data)
	complete(&cntl->boot_complete);

	if (cntl->m_dev && cntl->m_ops &&
	    cntl->m_ops->intr_handler)
		ret = cntl->m_ops->intr_handler(cntl->m_dev, WDSP_IPC1_INTR,
	    cntl->m_ops->signal_handler)
		ret = cntl->m_ops->signal_handler(cntl->m_dev, WDSP_IPC1_INTR,
						  NULL);
	else
		ret = -EINVAL;
@@ -663,7 +663,7 @@ static irqreturn_t wcd_cntl_err_irq(int irq, void *data)
{
	struct wcd_dsp_cntl *cntl = data;
	struct snd_soc_codec *codec = cntl->codec;
	struct wdsp_err_intr_arg arg;
	struct wdsp_err_signal_arg arg;
	u16 status = 0;
	u8 reg_val;
	int ret = 0;
@@ -678,11 +678,11 @@ static irqreturn_t wcd_cntl_err_irq(int irq, void *data)
		__func__, status);

	if ((status & cntl->irqs.fatal_irqs) &&
	    (cntl->m_dev && cntl->m_ops && cntl->m_ops->intr_handler)) {
	    (cntl->m_dev && cntl->m_ops && cntl->m_ops->signal_handler)) {
		arg.mem_dumps_enabled = cntl->ramdump_enable;
		arg.remote_start_addr = WCD_934X_RAMDUMP_START_ADDR;
		arg.dump_size = WCD_934X_RAMDUMP_SIZE;
		ret = cntl->m_ops->intr_handler(cntl->m_dev, WDSP_ERR_INTR,
		ret = cntl->m_ops->signal_handler(cntl->m_dev, WDSP_ERR_INTR,
						  &arg);
		if (IS_ERR_VALUE(ret))
			dev_err(cntl->codec->dev,
@@ -690,7 +690,7 @@ static irqreturn_t wcd_cntl_err_irq(int irq, void *data)
				__func__, status & cntl->irqs.fatal_irqs);
		wcd_cntl_change_online_state(cntl, 0);
	} else {
		dev_err(cntl->codec->dev, "%s: Invalid intr_handler\n",
		dev_err(cntl->codec->dev, "%s: Invalid signal_handler\n",
			__func__);
	}