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

Commit 09618575 authored by Banajit Goswami's avatar Banajit Goswami
Browse files

dsp: q6core: add support for SSR handling with SND event FWK



Add support for SSR/PDR event handling using SND
event framework.

Change-Id: Ia80c0bc7b99866fbb5c0b8c8ee7cdadeeb0fb0e9
Signed-off-by: default avatarBanajit Goswami <bgoswami@codeaurora.org>
parent 40bdd6b5
Loading
Loading
Loading
Loading
+79 −16
Original line number Diff line number Diff line
@@ -26,6 +26,7 @@
#include <dsp/q6core.h>
#include <dsp/audio_cal_utils.h>
#include <dsp/apr_audio-v2.h>
#include <soc/snd_event.h>
#include <ipc/apr.h>
#include "adsp_err.h"

@@ -79,6 +80,7 @@ struct q6core_str {
	struct cal_type_data *cal_data[CORE_MAX_CAL];
	uint32_t mem_map_cal_handle;
	int32_t adsp_status;
	int32_t avs_state;
	struct q6core_avcs_ver_info q6core_avcs_ver_info;
};

@@ -1448,50 +1450,111 @@ static int q6core_init_cal_data(void)
	return ret;
}

static int q6core_probe(struct platform_device *pdev)
static int q6core_is_avs_up(int32_t *avs_state)
{
	unsigned long timeout;
	int adsp_ready = 0, rc;
	int32_t adsp_ready = 0;
	int ret = 0;

	timeout = jiffies +
		msecs_to_jiffies(ADSP_STATE_READY_TIMEOUT_MS);

	do {
		if (!adsp_ready) {
		adsp_ready = q6core_is_adsp_ready();
			dev_dbg(&pdev->dev, "%s: ADSP Audio is %s\n", __func__,
		pr_debug("%s: ADSP Audio is %s\n", __func__,
			 adsp_ready ? "ready" : "not ready");
		}
		if (adsp_ready)
			break;

		/*
		 * ADSP will be coming up after loading (PD up event) and
		 * it might not be fully up when the control reaches
		 * here. So, wait for 50msec before checking ADSP state
		 * ADSP will be coming up after boot up and AVS might
		 * not be fully up when the control reaches here.
		 * So, wait for 50msec before checking ADSP state again.
		 */
		msleep(50);
	} while (time_after(timeout, jiffies));

	if (!adsp_ready) {
		dev_err(&pdev->dev, "%s: Timeout. ADSP Audio is %s\n",
		       __func__,
	*avs_state = adsp_ready;
	pr_debug("%s: ADSP Audio is %s\n", __func__,
	       adsp_ready ? "ready" : "not ready");
		return -ETIMEDOUT;

	if (!adsp_ready) {
		pr_err_ratelimited("%s: Timeout. ADSP Audio is not ready\n",
				   __func__);
		ret = -ETIMEDOUT;
	}

	return ret;
}

static int q6core_ssr_enable(struct device *dev, void *data)
{
	int32_t avs_state = 0;
	int ret = 0;

	if (!dev) {
		pr_err("%s: dev is NULL\n", __func__);
		return -EINVAL;
	}

	if (!q6core_lcl.avs_state) {
		ret = q6core_is_avs_up(&avs_state);
		if (ret < 0)
			goto err;
		q6core_lcl.avs_state = avs_state;
	}

err:
	return ret;
}

static void q6core_ssr_disable(struct device *dev, void *data)
{
	/* Reset AVS state to 0 */
	q6core_lcl.avs_state = 0;
}

static const struct snd_event_ops q6core_ssr_ops = {
	.enable = q6core_ssr_enable,
	.disable = q6core_ssr_disable,
};

static int q6core_probe(struct platform_device *pdev)
{
	int32_t avs_state = 0;
	int rc = 0;

	rc = q6core_is_avs_up(&avs_state);
	if (rc < 0)
		goto err;
	q6core_lcl.avs_state = avs_state;

	rc = of_platform_populate(pdev->dev.of_node, NULL, NULL, &pdev->dev);
	if (rc) {
		dev_err(&pdev->dev, "%s: failed to add child nodes, rc=%d\n",
			__func__, rc);
		return -EINVAL;
		rc = -EINVAL;
		goto err;
	}
	dev_dbg(&pdev->dev, "%s: added child node\n", __func__);

	return 0;
	rc = snd_event_client_register(&pdev->dev, &q6core_ssr_ops, NULL);
	if (!rc) {
		snd_event_notify(&pdev->dev, SND_EVENT_UP);
	} else {
		dev_err(&pdev->dev,
			"%s: Registration with SND event fwk failed rc = %d\n",
			__func__, rc);
		rc = 0;
	}

err:
	return rc;
}

static int q6core_remove(struct platform_device *pdev)
{
	snd_event_client_deregister(&pdev->dev);
	of_platform_depopulate(&pdev->dev);
	return 0;
}