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

Commit 70c29ec0 authored by Mangesh Kunchamwar's avatar Mangesh Kunchamwar
Browse files

dsp: update q6core driver to vote for LPASS island NPA resource



Add interface functions to vote for LPASS island NPA resource
from clients.

Change-Id: I532dd697f986aca48c3125b1bab3435b890d4039
Signed-off-by: default avatarMangesh Kunchamwar <mangeshk@codeaurora.org>
parent 3e19f3c0
Loading
Loading
Loading
Loading
+218 −1
Original line number Diff line number Diff line
@@ -32,7 +32,7 @@

#define TIMEOUT_MS 1000
/*
 * AVS bring up in the modem is optimitized for the new
 * AVS bring up in the modem is optimized for the new
 * Sub System Restart design and 100 milliseconds timeout
 * is sufficient to make sure the Q6 will be ready.
 */
@@ -67,6 +67,8 @@ struct q6core_str {
	wait_queue_head_t mdf_map_resp_wait;
	wait_queue_head_t cmd_req_wait;
	wait_queue_head_t avcs_fwk_ver_req_wait;
	wait_queue_head_t lpass_npa_rsc_wait;
	u32 lpass_npa_rsc_rsp_rcvd;
	u32 bus_bw_resp_received;
	u32 mdf_map_resp_received;
	enum cmd_flags {
@@ -84,6 +86,7 @@ struct q6core_str {
	struct cal_type_data *cal_data[CORE_MAX_CAL];
	uint32_t mem_map_cal_handle;
	uint32_t mdf_mem_map_cal_handle;
	uint32_t npa_client_handle;
	int32_t adsp_status;
	int32_t avs_state;
	struct q6core_avcs_ver_info q6core_avcs_ver_info;
@@ -321,6 +324,15 @@ static int32_t aprv2_core_fn_q(struct apr_client_data *data, void *priv)
				"AVCS_CMD_UNLOAD_TOPO_MODULES",
				adsp_err_get_err_str(payload1[1]));
			break;
		case AVCS_CMD_DESTROY_LPASS_NPA_CLIENT:
		case AVCS_CMD_REQUEST_LPASS_NPA_RESOURCES:
			pr_debug("%s: Cmd = AVCS_CMD_CREATE_LPASS_NPA_CLIENT/AVCS_CMD_DESTROY_LPASS_NPA_CLIENT status[%s]\n",
				__func__, adsp_err_get_err_str(payload1[1]));
			/* ADSP status to match Linux error standard */
			q6core_lcl.adsp_status = -payload1[1];
			q6core_lcl.lpass_npa_rsc_rsp_rcvd = 1;
			wake_up(&q6core_lcl.lpass_npa_rsc_wait);
			break;
		default:
			pr_err("%s: Invalid cmd rsp[0x%x][0x%x] opcode %d\n",
					__func__,
@@ -355,6 +367,15 @@ static int32_t aprv2_core_fn_q(struct apr_client_data *data, void *priv)
			wake_up(&q6core_lcl.bus_bw_req_wait);
		}
		break;
	case AVCS_CMDRSP_CREATE_LPASS_NPA_CLIENT:
		payload1 = data->payload;
		pr_debug("%s: AVCS_CMDRSP_CREATE_LPASS_NPA_CLIENT handle %d\n",
			__func__, payload1[1]);
		q6core_lcl.adsp_status = payload1[0];
		q6core_lcl.npa_client_handle = payload1[1];
		q6core_lcl.lpass_npa_rsc_rsp_rcvd = 1;
		wake_up(&q6core_lcl.lpass_npa_rsc_wait);
		break;
	case AVCS_CMDRSP_ADSP_EVENT_GET_STATE:
		payload1 = data->payload;
		q6core_lcl.param = payload1[0];
@@ -933,6 +954,201 @@ bool q6core_is_adsp_ready(void)
}
EXPORT_SYMBOL(q6core_is_adsp_ready);

int q6core_create_lpass_npa_client(uint32_t node_id, char *client_name,
				   uint32_t *client_handle)
{
	struct avcs_cmd_create_lpass_npa_client_t create_lpass_npa_client;
	struct avcs_cmd_create_lpass_npa_client_t *cmd_ptr =
						&create_lpass_npa_client;
	int ret = 0;

	if (!client_name) {
		pr_err("%s: Invalid params\n", __func__);
		return -EINVAL;
	}

	mutex_lock(&(q6core_lcl.cmd_lock));

	memset(cmd_ptr, 0, sizeof(create_lpass_npa_client));

	cmd_ptr->hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
				APR_HDR_LEN(APR_HDR_SIZE),
				APR_PKT_VER);
	cmd_ptr->hdr.pkt_size = sizeof(create_lpass_npa_client);
	cmd_ptr->hdr.src_port = 0;
	cmd_ptr->hdr.dest_port = 0;
	cmd_ptr->hdr.token = 0;
	cmd_ptr->hdr.opcode = AVCS_CMD_CREATE_LPASS_NPA_CLIENT;
	cmd_ptr->node_id = AVCS_SLEEP_ISLAND_CORE_DRIVER_NODE_ID;
	strlcpy(cmd_ptr->client_name, client_name,
			sizeof(cmd_ptr->client_name));

	pr_debug("%s: create lpass npa client opcode[0x%x] node id[0x%x]\n",
		__func__, cmd_ptr->hdr.opcode, cmd_ptr->node_id);

	*client_handle = 0;
	q6core_lcl.adsp_status = 0;
	q6core_lcl.lpass_npa_rsc_rsp_rcvd = 0;
	ret = apr_send_pkt(q6core_lcl.core_handle_q, (uint32_t *) cmd_ptr);
	if (ret < 0) {
		pr_err("%s: create lpass npa client failed %d\n",
			__func__, ret);
		ret = -EINVAL;
		goto done;
	}

	ret = wait_event_timeout(q6core_lcl.lpass_npa_rsc_wait,
				(q6core_lcl.lpass_npa_rsc_rsp_rcvd == 1),
				msecs_to_jiffies(TIMEOUT_MS));
	if (!ret) {
		pr_err("%s: timeout. waited for create lpass npa rsc client\n",
			__func__);
		ret = -ETIMEDOUT;
		goto done;
	} else {
		/* set ret to 0 as no timeout happened */
		ret = 0;
	}

	if (q6core_lcl.adsp_status < 0) {
		pr_err("%s: DSP returned error %d\n",
			__func__, q6core_lcl.adsp_status);
		ret = q6core_lcl.adsp_status;
		goto done;
	}

	*client_handle = q6core_lcl.npa_client_handle;
	pr_debug("%s: q6core_lcl.npa_client_handle %d\n", __func__,
		q6core_lcl.npa_client_handle);
done:
	mutex_unlock(&q6core_lcl.cmd_lock);
	return ret;
}
EXPORT_SYMBOL(q6core_create_lpass_npa_client);

int q6core_destroy_lpass_npa_client(uint32_t client_handle)
{
	struct avcs_cmd_destroy_lpass_npa_client_t destroy_lpass_npa_client;
	struct avcs_cmd_destroy_lpass_npa_client_t *cmd_ptr =
						&destroy_lpass_npa_client;
	int ret = 0;

	mutex_lock(&(q6core_lcl.cmd_lock));

	memset(cmd_ptr, 0, sizeof(destroy_lpass_npa_client));

	cmd_ptr->hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
				APR_HDR_LEN(APR_HDR_SIZE),
				APR_PKT_VER);
	cmd_ptr->hdr.pkt_size = sizeof(destroy_lpass_npa_client);
	cmd_ptr->hdr.src_port = 0;
	cmd_ptr->hdr.dest_port = 0;
	cmd_ptr->hdr.token = 0;
	cmd_ptr->hdr.opcode = AVCS_CMD_DESTROY_LPASS_NPA_CLIENT;
	cmd_ptr->client_handle = client_handle;

	pr_debug("%s: dstry lpass npa client opcode[0x%x] client hdl[0x%x]\n",
		__func__, cmd_ptr->hdr.opcode, cmd_ptr->client_handle);

	q6core_lcl.adsp_status = 0;
	q6core_lcl.lpass_npa_rsc_rsp_rcvd = 0;
	ret = apr_send_pkt(q6core_lcl.core_handle_q, (uint32_t *) cmd_ptr);
	if (ret < 0) {
		pr_err("%s: destroy lpass npa client failed %d\n",
			__func__, ret);
		ret = -EINVAL;
		goto done;
	}

	ret = wait_event_timeout(q6core_lcl.lpass_npa_rsc_wait,
				(q6core_lcl.lpass_npa_rsc_rsp_rcvd == 1),
				msecs_to_jiffies(TIMEOUT_MS));
	if (!ret) {
		pr_err("%s: timeout. waited for destroy lpass npa rsc client\n",
			__func__);
		ret = -ETIMEDOUT;
		goto done;
	} else {
		/* set ret to 0 as no timeout happened */
		ret = 0;
	}

	if (q6core_lcl.adsp_status < 0) {
		pr_err("%s: DSP returned error %d\n",
			__func__, q6core_lcl.adsp_status);
		ret = q6core_lcl.adsp_status;
	}
done:
	mutex_unlock(&q6core_lcl.cmd_lock);
	return ret;
}
EXPORT_SYMBOL(q6core_destroy_lpass_npa_client);

int q6core_request_island_transition(uint32_t client_handle,
				     uint32_t island_allow_mode)
{
	struct avcs_sleep_node_island_transition_config_t island_tsn_cfg;
	struct avcs_sleep_node_island_transition_config_t *cmd_ptr =
						&island_tsn_cfg;
	int ret = 0;

	mutex_lock(&(q6core_lcl.cmd_lock));

	memset(cmd_ptr, 0, sizeof(island_tsn_cfg));

	cmd_ptr->req_lpass_npa_rsc.hdr.hdr_field =
				APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
				APR_HDR_LEN(APR_HDR_SIZE),
				APR_PKT_VER);
	cmd_ptr->req_lpass_npa_rsc.hdr.pkt_size = sizeof(island_tsn_cfg);
	cmd_ptr->req_lpass_npa_rsc.hdr.src_port = 0;
	cmd_ptr->req_lpass_npa_rsc.hdr.dest_port = 0;
	cmd_ptr->req_lpass_npa_rsc.hdr.token = 0;
	cmd_ptr->req_lpass_npa_rsc.hdr.opcode =
					AVCS_CMD_REQUEST_LPASS_NPA_RESOURCES;
	cmd_ptr->req_lpass_npa_rsc.client_handle = client_handle;
	cmd_ptr->req_lpass_npa_rsc.resource_id =
				AVCS_SLEEP_NODE_ISLAND_TRANSITION_RESOURCE_ID;
	cmd_ptr->island_allow_mode = island_allow_mode;

	pr_debug("%s: req islnd tnsn opcode[0x%x] island_allow_mode[0x%x]\n",
		__func__, cmd_ptr->req_lpass_npa_rsc.hdr.opcode,
		cmd_ptr->island_allow_mode);

	q6core_lcl.adsp_status = 0;
	q6core_lcl.lpass_npa_rsc_rsp_rcvd = 0;
	ret = apr_send_pkt(q6core_lcl.core_handle_q, (uint32_t *) cmd_ptr);
	if (ret < 0) {
		pr_err("%s: island tnsn cmd send failed %d\n",
			__func__, ret);
		ret = -EINVAL;
		goto done;
	}

	ret = wait_event_timeout(q6core_lcl.lpass_npa_rsc_wait,
				(q6core_lcl.lpass_npa_rsc_rsp_rcvd == 1),
				msecs_to_jiffies(TIMEOUT_MS));
	if (!ret) {
		pr_err("%s: timeout. waited for island lpass npa rsc req\n",
			__func__);
		ret = -ETIMEDOUT;
		goto done;
	} else {
		/* set ret to 0 as no timeout happened */
		ret = 0;
	}

	if (q6core_lcl.adsp_status < 0) {
		pr_err("%s: DSP returned error %d\n",
			__func__, q6core_lcl.adsp_status);
		ret = q6core_lcl.adsp_status;
	}
done:
	mutex_unlock(&q6core_lcl.cmd_lock);
	return ret;
}
EXPORT_SYMBOL(q6core_request_island_transition);

int q6core_map_memory_regions(phys_addr_t *buf_add, uint32_t mempool_id,
			uint32_t *bufsz, uint32_t bufcnt, uint32_t *map_handle)
{
@@ -1671,6 +1887,7 @@ int __init core_init(void)
	init_waitqueue_head(&q6core_lcl.cmd_req_wait);
	init_waitqueue_head(&q6core_lcl.avcs_fwk_ver_req_wait);
	init_waitqueue_head(&q6core_lcl.mdf_map_resp_wait);
	init_waitqueue_head(&q6core_lcl.lpass_npa_rsc_wait);
	q6core_lcl.cmd_resp_received_flag = FLAG_NONE;
	mutex_init(&q6core_lcl.cmd_lock);
	mutex_init(&q6core_lcl.ver_lock);
+102 −1
Original line number Diff line number Diff line
@@ -19,6 +19,8 @@

#define AVCS_CMD_ADSP_EVENT_GET_STATE		0x0001290C
#define AVCS_CMDRSP_ADSP_EVENT_GET_STATE	0x0001290D
#define AVCS_API_VERSION_V4		4
#define APRV2_IDS_SERVICE_ID_ADSP_CORE_V (0x3)

bool q6core_is_adsp_ready(void);

@@ -195,6 +197,99 @@ struct avcs_cmd_load_unload_topo_modules {
	uint32_t topology_id;
} __packed;

/* This command allows a remote client(HLOS) creates a client to LPASS NPA
 * resource node. Currently, this command supports only the NPA Sleep resource
 * "/island/core/drivers" node ID.
 */
#define AVCS_CMD_CREATE_LPASS_NPA_CLIENT    0x00012985

#define AVCS_SLEEP_ISLAND_CORE_DRIVER_NODE_ID    0x00000001

struct avcs_cmd_create_lpass_npa_client_t {
	struct apr_hdr hdr;
	uint32_t  node_id;
	/* Unique ID of the NPA node.
	 * @values
	 *   - #AVCS_SLEEP_ISLAND_CORE_DRIVER_NODE_ID
	 */

	char client_name[16];
	/* Client name, up to a maximum of sixteen characters.*/
};

/* In response to the #AVCS_CMD_CREATE_LPASS_NPA_CLIENT command, the AVCS
 * returns the handle to remote HLOS client.
 */
#define AVCS_CMDRSP_CREATE_LPASS_NPA_CLIENT    0x00012986

struct avcs_cmdrsp_create_lpass_npa_client_t {
	uint32_t status;
	/* Status message (error code).
	 * @values
	 *   - ADSP_EOK -- Create was successful
	 *   - ADSP_EFAILED -- Create failed
	 */

	uint32_t  client_handle;
	/* Handle of the client.*/
};

/* The remote HLOS client use this command to issue the request to the npa
 * resource. Remote client(HLOS) must send the valid npa client handle and
 * resource id info.
 */
#define AVCS_CMD_REQUEST_LPASS_NPA_RESOURCES    0x00012987

#define AVCS_SLEEP_NODE_ISLAND_TRANSITION_RESOURCE_ID    0x00000001

#define SLEEP_RESTRICT_ISLAND                0x0
#define SLEEP_ALLOW_ISLAND                   0x1

/* Immediately following this structure is the resource request configuration
 * data payload. Payload varies depend on the resource_id requested.
 * Currently supported only island transition payload.
 */
struct avcs_cmd_request_lpass_npa_resources_t {
	struct apr_hdr hdr;
	uint32_t  client_handle;
	/* Handle of the client.
	 * @values
	 * - Valid uint32 number
	 */

	uint32_t  resource_id;
	/* Unique ID of the NPA resource ID.
	 * @values
	 * - #AVCS_SLEEP_NODE_ISLAND_TRANSITION_RESOURCE_ID
	 */
};

/* This structure contains the sleep node resource payload data.
 */
struct avcs_sleep_node_island_transition_config_t {
	struct avcs_cmd_request_lpass_npa_resources_t req_lpass_npa_rsc;
	uint32_t  island_allow_mode;
	/* Specifies the island state.
	 * @values
	 * - #SLEEP_RESTRICT_ISLAND
	 * - #SLEEP_ALLOW_ISLAND
	 */
};

/* This command allows remote client(HLOS) to destroy the npa node client
 * handle, which is created using the #AVCS_CMD_CREATE_LPASS_NPA_CLIENT command.
 * Remote client(HLOS) must send the valid npa client handle.
 */
#define AVCS_CMD_DESTROY_LPASS_NPA_CLIENT    0x00012988

struct avcs_cmd_destroy_lpass_npa_client_t {
	struct apr_hdr hdr;
	uint32_t  client_handle;
	/* Handle of the client.
	 * @values
	 * - Valid uint32 number
	 */
};

int q6core_map_memory_regions(phys_addr_t *buf_add, uint32_t mempool_id,
			uint32_t *bufsz, uint32_t bufcnt, uint32_t *map_handle);
@@ -212,6 +307,12 @@ int32_t core_get_license_status(uint32_t module_id);
int32_t q6core_load_unload_topo_modules(uint32_t topology_id,
			bool preload_type);

int q6core_create_lpass_npa_client(uint32_t node_id, char *client_name,
				   uint32_t *client_handle);
int q6core_destroy_lpass_npa_client(uint32_t client_handle);
int q6core_request_island_transition(uint32_t client_handle,
				     uint32_t island_allow_mode);

#if IS_ENABLED(CONFIG_USE_Q6_32CH_SUPPORT)
static inline bool q6core_use_Q6_32ch_support(void)
{