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

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

Merge "ASoC: msmcobalt: Enable msmcobalt to use audio notifier"

parents f5b72281 dec2bc73
Loading
Loading
Loading
Loading
+70 −114
Original line number Diff line number Diff line
@@ -27,16 +27,15 @@
#include <linux/device.h>
#include <linux/slab.h>
#include <soc/qcom/subsystem_restart.h>
#include <soc/qcom/subsystem_notif.h>
#include <soc/qcom/scm.h>
#include <sound/apr_audio-v2.h>
#include <soc/qcom/smd.h>
#include <linux/qdsp6v2/apr.h>
#include <linux/qdsp6v2/apr_tal.h>
#include <linux/qdsp6v2/dsp_debug.h>
#include <linux/qdsp6v2/audio_notifier.h>
#include <linux/ipc_logging.h>

#define SCM_Q6_NMI_CMD 0x1
#define APR_PKT_IPC_LOG_PAGE_CNT 2

static struct apr_q6 q6;
@@ -45,9 +44,11 @@ static void *apr_pkt_ctx;
static wait_queue_head_t dsp_wait;
static wait_queue_head_t modem_wait;
static bool is_modem_up;
static bool is_initial_boot;
/* Subsystem restart: QDSP6 data, functions */
static struct workqueue_struct *apr_reset_workqueue;
static void apr_reset_deregister(struct work_struct *work);
static void dispatch_event(unsigned long code, uint16_t proc);
struct apr_reset_work {
	void *handle;
	struct work_struct work;
@@ -202,6 +203,20 @@ enum apr_subsys_state apr_cmpxchg_modem_state(enum apr_subsys_state prev,
	return atomic_cmpxchg(&q6.modem_state, prev, new);
}

static void apr_modem_down(unsigned long opcode)
{
	apr_set_modem_state(APR_SUBSYS_DOWN);
	dispatch_event(opcode, APR_DEST_MODEM);
}

static void apr_modem_up(void)
{
	if (apr_cmpxchg_modem_state(APR_SUBSYS_DOWN, APR_SUBSYS_UP) ==
							APR_SUBSYS_DOWN)
		wake_up(&modem_wait);
	is_modem_up = 1;
}

enum apr_subsys_state apr_get_q6_state(void)
{
	return atomic_read(&q6.q6_state);
@@ -224,6 +239,19 @@ enum apr_subsys_state apr_cmpxchg_q6_state(enum apr_subsys_state prev,
	return atomic_cmpxchg(&q6.q6_state, prev, new);
}

static void apr_adsp_down(unsigned long opcode)
{
	apr_set_q6_state(APR_SUBSYS_DOWN);
	dispatch_event(opcode, APR_DEST_QDSP6);
}

static void apr_adsp_up(void)
{
	if (apr_cmpxchg_q6_state(APR_SUBSYS_DOWN, APR_SUBSYS_LOADED) ==
							APR_SUBSYS_DOWN)
		wake_up(&dsp_wait);
}

int apr_wait_for_device_up(int dest_id)
{
	int rc = -1;
@@ -730,7 +758,7 @@ void apr_reset(void *handle)
}

/* Dispatch the Reset events to Modem and audio clients */
void dispatch_event(unsigned long code, uint16_t proc)
static void dispatch_event(unsigned long code, uint16_t proc)
{
	struct apr_client *apr_client;
	struct apr_client_data data;
@@ -783,128 +811,51 @@ void dispatch_event(unsigned long code, uint16_t proc)
	}
}

static int modem_notifier_cb(struct notifier_block *this, unsigned long code,
			     void *_cmd)
static int apr_notifier_service_cb(struct notifier_block *this,
				   unsigned long opcode, void *data)
{
	static int boot_count = 2;

	if (boot_count) {
		boot_count--;
		return NOTIFY_OK;
	}
	struct audio_notifier_cb_data *cb_data = data;

	switch (code) {
	case SUBSYS_BEFORE_SHUTDOWN:
		pr_debug("M-Notify: Shutdown started\n");
		apr_set_modem_state(APR_SUBSYS_DOWN);
		dispatch_event(code, APR_DEST_MODEM);
		break;
	case SUBSYS_AFTER_SHUTDOWN:
		pr_debug("M-Notify: Shutdown Completed\n");
		break;
	case SUBSYS_BEFORE_POWERUP:
		pr_debug("M-notify: Bootup started\n");
		break;
	case SUBSYS_AFTER_POWERUP:
		if (apr_cmpxchg_modem_state(APR_SUBSYS_DOWN, APR_SUBSYS_UP) ==
						APR_SUBSYS_DOWN)
			wake_up(&modem_wait);
		is_modem_up = 1;
		pr_debug("M-Notify: Bootup Completed\n");
		break;
	default:
		pr_err("M-Notify: General: %lu\n", code);
		break;
	}
	return NOTIFY_DONE;
	if (cb_data == NULL) {
		pr_err("%s: Callback data is NULL!\n", __func__);
		goto done;
	}

static struct notifier_block mnb = {
	.notifier_call = modem_notifier_cb,
};

static bool powered_on;

static int lpass_notifier_cb(struct notifier_block *this, unsigned long code,
			     void *_cmd)
{
	static int boot_count = 2;
	struct notif_data *data = (struct notif_data *)_cmd;
	struct scm_desc desc;

	if (boot_count) {
		boot_count--;
		return NOTIFY_OK;
	}
	pr_debug("%s: Service opcode 0x%lx, domain %d\n",
		__func__, opcode, cb_data->domain);

	switch (code) {
	case SUBSYS_BEFORE_SHUTDOWN:
		pr_debug("L-Notify: Shutdown started\n");
		apr_set_q6_state(APR_SUBSYS_DOWN);
		dispatch_event(code, APR_DEST_QDSP6);
		if (data && data->crashed) {
			/* Send NMI to QDSP6 via an SCM call. */
			if (!is_scm_armv8()) {
				scm_call_atomic1(SCM_SVC_UTIL,
						 SCM_Q6_NMI_CMD, 0x1);
			} else {
				desc.args[0] = 0x1;
				desc.arginfo = SCM_ARGS(1);
				scm_call2_atomic(SCM_SIP_FNID(SCM_SVC_UTIL,
						 SCM_Q6_NMI_CMD), &desc);
			}
			/* The write should go through before q6 is shutdown */
			mb();
			pr_debug("L-Notify: Q6 NMI was sent.\n");
		}
		break;
	case SUBSYS_AFTER_SHUTDOWN:
		powered_on = false;
		pr_debug("L-Notify: Shutdown Completed\n");
	switch (opcode) {
	case AUDIO_NOTIFIER_SERVICE_DOWN:
		/*
		 * Use flag to ignore down notifications during
		 * initial boot. There is no benefit from error
		 * recovery notifications during initial boot
		 * up since everything is expected to be down.
		 */
		if (is_initial_boot)
			break;
	case SUBSYS_BEFORE_POWERUP:
		pr_debug("L-notify: Bootup started\n");
		if (cb_data->domain == AUDIO_NOTIFIER_MODEM_DOMAIN)
			apr_modem_down(opcode);
		else
			apr_adsp_down(opcode);
		break;
	case SUBSYS_AFTER_POWERUP:
		if (apr_cmpxchg_q6_state(APR_SUBSYS_DOWN,
				APR_SUBSYS_LOADED) == APR_SUBSYS_DOWN)
			wake_up(&dsp_wait);
		powered_on = true;
		pr_debug("L-Notify: Bootup Completed\n");
	case AUDIO_NOTIFIER_SERVICE_UP:
		is_initial_boot = false;
		if (cb_data->domain == AUDIO_NOTIFIER_MODEM_DOMAIN)
			apr_modem_up();
		else
			apr_adsp_up();
		break;
	default:
		pr_err("L-Notify: Generel: %lu\n", code);
		break;
	}
	return NOTIFY_DONE;
done:
	return NOTIFY_OK;
}

static struct notifier_block lnb = {
static struct notifier_block service_nb = {
	.notifier_call  = apr_notifier_service_cb,
	.priority = 0,
	.notifier_call = lpass_notifier_cb,
};

static int panic_handler(struct notifier_block *this,
				unsigned long event, void *ptr)
{
	struct scm_desc desc;

	if (powered_on) {
		/* Send NMI to QDSP6 via an SCM call. */
		if (!is_scm_armv8()) {
			scm_call_atomic1(SCM_SVC_UTIL, SCM_Q6_NMI_CMD, 0x1);
		} else {
			desc.args[0] = 0x1;
			desc.arginfo = SCM_ARGS(1);
			scm_call2_atomic(SCM_SIP_FNID(SCM_SVC_UTIL,
					 SCM_Q6_NMI_CMD), &desc);
		}
	}
	return NOTIFY_DONE;
}

static struct notifier_block panic_nb = {
	.notifier_call  = panic_handler,
};

static int __init apr_init(void)
@@ -924,13 +875,18 @@ static int __init apr_init(void)
	apr_reset_workqueue = create_singlethread_workqueue("apr_driver");
	if (!apr_reset_workqueue)
		return -ENOMEM;
	atomic_notifier_chain_register(&panic_notifier_list, &panic_nb);

	apr_pkt_ctx = ipc_log_context_create(APR_PKT_IPC_LOG_PAGE_CNT,
						"apr", 0);
	if (!apr_pkt_ctx)
		pr_err("%s: Unable to create ipc log context\n", __func__);

	is_initial_boot = true;
	subsys_notif_register("apr_adsp", AUDIO_NOTIFIER_ADSP_DOMAIN,
			      &service_nb);
	subsys_notif_register("apr_modem", AUDIO_NOTIFIER_MODEM_DOMAIN,
			      &service_nb);

	return 0;
}
device_initcall(apr_init);
@@ -940,7 +896,7 @@ static int __init apr_late_init(void)
	int ret = 0;
	init_waitqueue_head(&dsp_wait);
	init_waitqueue_head(&modem_wait);
	subsys_notif_register(&mnb, &lnb);

	return ret;
}
late_initcall(apr_late_init);
+9 −11
Original line number Diff line number Diff line
@@ -18,8 +18,7 @@
#include <linux/qdsp6v2/apr.h>
#include <linux/qdsp6v2/apr_tal.h>
#include <linux/qdsp6v2/dsp_debug.h>

static const char *lpass_subsys_name = "adsp";
#include <linux/qdsp6v2/audio_notifier.h>

enum apr_subsys_state apr_get_subsys_state(void)
{
@@ -32,11 +31,6 @@ void apr_set_subsys_state(void)
	apr_set_modem_state(APR_SUBSYS_UP);
}

const char *apr_get_lpass_subsys_name(void)
{
	return lpass_subsys_name;
}

uint16_t apr_get_data_src(struct apr_hdr *hdr)
{
	if (hdr->src_domain == APR_DOMAIN_MODEM)
@@ -57,11 +51,15 @@ int apr_get_dest_id(char *dest)
		return APR_DEST_MODEM;
}

void subsys_notif_register(struct notifier_block *mod_notif,
				struct notifier_block *lp_notif)
void subsys_notif_register(char *client_name, int domain,
			   struct notifier_block *nb)
{
	subsys_notif_register_notifier("modem", mod_notif);
	subsys_notif_register_notifier(apr_get_lpass_subsys_name(), lp_notif);
	int ret;

	ret = audio_notifier_register(client_name, domain, nb);
	if (ret < 0)
		pr_err("%s: Audio notifier register failed for domain %d ret = %d\n",
			__func__, domain, ret);
}

uint16_t apr_get_reset_domain(uint16_t proc)
+15 −3
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@
#include <linux/qdsp6v2/apr.h>
#include <linux/qdsp6v2/apr_tal.h>
#include <linux/qdsp6v2/dsp_debug.h>
#include <linux/qdsp6v2/audio_notifier.h>

#define DEST_ID APR_DEST_MODEM

@@ -41,10 +42,21 @@ int apr_get_dest_id(char *dest)
	return DEST_ID;
}

void subsys_notif_register(struct notifier_block *mod_notif,
				struct notifier_block *lp_notif)
void subsys_notif_register(char *client_name, int domain,
			   struct notifier_block *nb)
{
	subsys_notif_register_notifier("modem", mod_notif);
	int ret;

	if (domain != AUDIO_NOTIFIER_MODEM_DOMAIN) {
		pr_debug("%s: Unused domain %d not registering with notifier\n",
			 __func__, domain);
		return;
	}

	ret = audio_notifier_register(client_name, domain, nb);
	if (ret < 0)
		pr_err("%s: Audio notifier register failed for domain %d ret = %d\n",
			__func__, domain, ret);
}

uint16_t apr_get_reset_domain(uint16_t proc)
+2 −2
Original line number Diff line number Diff line
@@ -172,8 +172,8 @@ inline int apr_fill_hdr(void *handle, uint32_t *buf, uint16_t src_port,

int apr_send_pkt(void *handle, uint32_t *buf);
int apr_deregister(void *handle);
void subsys_notif_register(struct notifier_block *mod_notif,
				struct notifier_block *lp_notif);
void subsys_notif_register(char *client_name, int domain,
			   struct notifier_block *nb);
int apr_get_dest_id(char *dest);
uint16_t apr_get_data_src(struct apr_hdr *hdr);
void change_q6_state(int state);
+3 −0
Original line number Diff line number Diff line
@@ -125,6 +125,9 @@ config SND_SOC_MSMCOBALT
	select SND_SOC_MSM_HOSTLESS_PCM
	select SND_DYNAMIC_MINORS
	select MSM_QDSP6_APRV2_GLINK
	select MSM_QDSP6_SSR
	select MSM_QDSP6_PDR
	select MSM_QDSP6_NOTIFIER
	select MSM_QDSP6V2_CODECS
	select SND_SOC_WCD9335
	select SND_SOC_WCD934X
Loading