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

Commit 9286b2f6 authored by Manish Dewangan's avatar Manish Dewangan Committed by Banajit Goswami
Browse files

ASoC: msm: qdsp6v2: Add support to set render mode



ASM driver changes to configure render mode.

Based on configured render mode DSP decides to whether to use
Audio Master Mode or STC Master mode for rendering.

CRs-Fixed: 1112258
Change-Id: I01c7a172b899fd7e950f216732d12a2cb2c737e9
Signed-off-by: default avatarManish Dewangan <manish@codeaurora.org>
parent c7120f83
Loading
Loading
Loading
Loading
+53 −2
Original line number Diff line number Diff line
@@ -10234,12 +10234,63 @@ struct asm_session_cmd_set_mtmx_strstr_params_v2 {
	 */
};

/* Parameter used by #ASM_SESSION_MTMX_STRTR_MODULE_ID_AVSYNC which allows the
 * audio client choose the rendering decision that the audio DSP should use.
 */
#define ASM_SESSION_MTMX_STRTR_PARAM_RENDER_MODE_CMD  0x00012F0D

/* Indicates that rendering decision will be based on default rate
 * (session clock based rendering, device driven).
 * 1. The default session clock based rendering is inherently driven
 *    by the timing of the device.
 * 2. After the initial decision is made (first buffer after a run
 *    command), subsequent data rendering decisions are made with
 *    respect to the rate at which the device is rendering, thus deriving
 *    its timing from the device.
 * 3. While this decision making is simple, it has some inherent limitations
 *    (mentioned in the next section).
 * 4. If this API is not set, the session clock based rendering will be assumed
 *    and this will ensure that the DSP is backward compatible.
 */
#define ASM_SESSION_MTMX_STRTR_PARAM_RENDER_DEFAULT 0

/* Indicates that rendering decision will be based on local clock rate.
 * 1. In the DSP loopback/client loopback use cases (frame based
 *    inputs), the incoming data into audio DSP is time-stamped at the
 *    local clock rate (STC).
 * 2. This TS rate may match the incoming data rate or maybe different
 *    from the incoming data rate.
 * 3. Regardless, the data will be time-stamped with local STC and
 *    therefore, the client is recommended to set this mode for these
 *    use cases. This method is inherently more robust to sequencing
 *    (AFE Start/Stop) and device switches, among other benefits.
 * 4. This API will inform the DSP to compare every incoming buffer TS
 *    against local STC.
 * 5. DSP will continue to honor render windows APIs, as before.
 */
#define ASM_SESSION_MTMX_STRTR_PARAM_RENDER_LOCAL_STC 1

/* Structure for rendering decision parameter */
struct asm_session_mtmx_strtr_param_render_mode_t {
	/* Specifies the type of rendering decision the audio DSP should use.
	 *
	 * @values
	 * - #ASM_SESSION_MTMX_STRTR_PARAM_RENDER_DEFAULT
	 * - #ASM_SESSION_MTMX_STRTR_PARAM_RENDER_LOCAL_STC
	 */
	u32                  flags;
} __packed;

union asm_session_mtmx_strtr_param_config {
	struct asm_session_mtmx_strtr_param_window_v2_t window_param;
	struct asm_session_mtmx_strtr_param_render_mode_t render_param;
} __packed;

struct asm_mtmx_strtr_params {
	struct apr_hdr  hdr;
	struct asm_session_cmd_set_mtmx_strstr_params_v2 param;
	struct asm_stream_param_data_v2 data;
	u32 window_lsw;
	u32 window_msw;
	union asm_session_mtmx_strtr_param_config config;
} __packed;

#define ASM_SESSION_CMD_GET_MTMX_STRTR_PARAMS_V2 0x00010DCF
+4 −0
Original line number Diff line number Diff line
@@ -641,6 +641,10 @@ int q6asm_send_mtmx_strtr_window(struct audio_client *ac,
		struct asm_session_mtmx_strtr_param_window_v2_t *window_param,
		uint32_t param_id);

/* Configure DSP render mode */
int q6asm_send_mtmx_strtr_render_mode(struct audio_client *ac,
		uint32_t render_mode);

/* Retrieve the current DSP path delay */
int q6asm_get_path_delay(struct audio_client *ac);

+94 −7
Original line number Diff line number Diff line
@@ -7917,16 +7917,18 @@ int q6asm_send_mtmx_strtr_window(struct audio_client *ac,
	matrix.param.data_payload_addr_lsw = 0;
	matrix.param.data_payload_addr_msw = 0;
	matrix.param.mem_map_handle = 0;
	matrix.param.data_payload_size = sizeof(matrix) -
			sizeof(matrix.hdr) - sizeof(matrix.param);
	matrix.param.data_payload_size =
		sizeof(struct asm_stream_param_data_v2) +
		sizeof(struct asm_session_mtmx_strtr_param_window_v2_t);
	matrix.param.direction = 0; /* RX */
	matrix.data.module_id = ASM_SESSION_MTMX_STRTR_MODULE_ID_AVSYNC;
	matrix.data.param_id = param_id;
	matrix.data.param_size = matrix.param.data_payload_size -
			sizeof(matrix.data);
	matrix.data.param_size =
		sizeof(struct asm_session_mtmx_strtr_param_window_v2_t);
	matrix.data.reserved = 0;
	matrix.window_lsw = window_param->window_lsw;
	matrix.window_msw = window_param->window_msw;
	memcpy(&(matrix.config.window_param),
	       window_param,
	       sizeof(struct asm_session_mtmx_strtr_param_window_v2_t));

	rc = apr_send_pkt(ac->apr, (uint32_t *) &matrix);
	if (rc < 0) {
@@ -7956,7 +7958,92 @@ int q6asm_send_mtmx_strtr_window(struct audio_client *ac,
	rc = 0;
fail_cmd:
	return rc;
};
}

int q6asm_send_mtmx_strtr_render_mode(struct audio_client *ac,
		uint32_t render_mode)
{
	struct asm_mtmx_strtr_params matrix;
	struct asm_session_mtmx_strtr_param_render_mode_t render_param;
	int sz = 0;
	int rc  = 0;

	pr_debug("%s: render mode is %d\n", __func__, render_mode);

	if (!ac) {
		pr_err("%s: audio client handle is NULL\n", __func__);
		rc = -EINVAL;
		goto exit;
	}

	if (ac->apr == NULL) {
		pr_err("%s: ac->apr is NULL\n", __func__);
		rc = -EINVAL;
		goto exit;
	}

	if ((render_mode != ASM_SESSION_MTMX_STRTR_PARAM_RENDER_DEFAULT) &&
	    (render_mode != ASM_SESSION_MTMX_STRTR_PARAM_RENDER_LOCAL_STC)) {
		pr_err("%s: Invalid render mode %d\n", __func__, render_mode);
		rc = -EINVAL;
		goto exit;
	}

	memset(&render_param, 0,
	       sizeof(struct asm_session_mtmx_strtr_param_render_mode_t));
	render_param.flags = render_mode;

	memset(&matrix, 0, sizeof(struct asm_mtmx_strtr_params));
	sz = sizeof(struct asm_mtmx_strtr_params);
	q6asm_add_hdr(ac, &matrix.hdr, sz, TRUE);
	atomic_set(&ac->cmd_state, -1);
	matrix.hdr.opcode = ASM_SESSION_CMD_SET_MTMX_STRTR_PARAMS_V2;

	matrix.param.data_payload_addr_lsw = 0;
	matrix.param.data_payload_addr_msw = 0;
	matrix.param.mem_map_handle = 0;
	matrix.param.data_payload_size =
		sizeof(struct asm_stream_param_data_v2) +
		sizeof(struct asm_session_mtmx_strtr_param_render_mode_t);
	matrix.param.direction = 0; /* RX */
	matrix.data.module_id = ASM_SESSION_MTMX_STRTR_MODULE_ID_AVSYNC;
	matrix.data.param_id = ASM_SESSION_MTMX_STRTR_PARAM_RENDER_MODE_CMD;
	matrix.data.param_size =
		sizeof(struct asm_session_mtmx_strtr_param_render_mode_t);
	matrix.data.reserved = 0;
	memcpy(&(matrix.config.render_param),
	       &render_param,
	       sizeof(struct asm_session_mtmx_strtr_param_render_mode_t));

	rc = apr_send_pkt(ac->apr, (uint32_t *) &matrix);
	if (rc < 0) {
		pr_err("%s: Render mode send failed paramid [0x%x]\n",
			__func__, matrix.data.param_id);
		rc = -EINVAL;
		goto exit;
	}

	rc = wait_event_timeout(ac->cmd_wait,
			(atomic_read(&ac->cmd_state) >= 0), 5*HZ);
	if (!rc) {
		pr_err("%s: timeout, Render mode send paramid [0x%x]\n",
			__func__, matrix.data.param_id);
		rc = -ETIMEDOUT;
		goto exit;
	}

	if (atomic_read(&ac->cmd_state) > 0) {
		pr_err("%s: DSP returned error[%s]\n",
				__func__, adsp_err_get_err_str(
				atomic_read(&ac->cmd_state)));
		rc = adsp_err_get_lnx_err_code(
				atomic_read(&ac->cmd_state));
		goto exit;
	}
	rc = 0;
exit:
	return rc;
}

static int __q6asm_cmd(struct audio_client *ac, int cmd, uint32_t stream_id)
{