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

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

ASoC: msm: qdsp6v2: Support to configure clock recovery mode



ASM driver changes to configure clock recovery mode.
Based on the configure mode, DSP decides whether to enable
clock recovery or not.

CRs-Fixed: 1112258
Change-Id: Ia6a6c33ce7b478af8d2397c20fcc6281d96ec3ce
Signed-off-by: default avatarManish Dewangan <manish@codeaurora.org>
parent b65183cb
Loading
Loading
Loading
Loading
+45 −0
Original line number Diff line number Diff line
@@ -10281,9 +10281,54 @@ struct asm_session_mtmx_strtr_param_render_mode_t {
	u32                  flags;
} __packed;

/* Parameter used by #ASM_SESSION_MTMX_STRTR_MODULE_ID_AVSYNC which allows the
 * audio client to specify the clock recovery mechanism that the audio DSP
 * should use.
 */

#define ASM_SESSION_MTMX_STRTR_PARAM_CLK_REC_CMD 0x00012F0E

/* Indicates that default clock recovery will be used (no clock recovery).
 * If the client wishes that no clock recovery be done, the client can
 * choose this. This means that no attempt will made by the DSP to try and
 * match the rates of the input and output audio.
 */
#define ASM_SESSION_MTMX_STRTR_PARAM_CLK_REC_NONE 0

/* Indicates that independent clock recovery needs to be used.
 * 1. In the DSP loopback/client loopback use cases (frame based inputs),
 *    the client should choose the independent clock recovery option.
 * 2. This basically de-couples the audio and video from knowing each others
 *    clock sources and lets the audio DSP independently rate match the input
 *    and output rates.
 * 3. After drift detection, the drift correction is achieved by either pulling
 *    the PLLs (if applicable) or by stream to device rate matching
 *    (for PCM use cases) by comparing drift with respect to STC.
 * 4. For passthrough use cases, since the PLL pulling is the only option,
 *    a best effort will be made.
 *    If PLL pulling is not possible / available, the rendering will be
 *    done without rate matching.
 */
#define ASM_SESSION_MTMX_STRTR_PARAM_CLK_REC_AUTO 1

/* Payload of the #ASM_SESSION_MTMX_STRTR_PARAM_CLK_REC parameter.
 */
struct asm_session_mtmx_strtr_param_clk_rec_t {
	/* Specifies the type of clock recovery that the audio DSP should
	 * use for rate matching.
	 */

	/* @values
	 * #ASM_SESSION_MTMX_STRTR_PARAM_CLK_REC_DEFAULT
	 * #ASM_SESSION_MTMX_STRTR_PARAM_CLK_REC_INDEPENDENT
	 */
	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;
	struct asm_session_mtmx_strtr_param_clk_rec_t clk_rec_param;
} __packed;

struct asm_mtmx_strtr_params {
+4 −0
Original line number Diff line number Diff line
@@ -645,6 +645,10 @@ int q6asm_send_mtmx_strtr_window(struct audio_client *ac,
int q6asm_send_mtmx_strtr_render_mode(struct audio_client *ac,
		uint32_t render_mode);

/* Configure DSP clock recovery mode */
int q6asm_send_mtmx_strtr_clk_rec_mode(struct audio_client *ac,
		uint32_t clk_rec_mode);

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

+85 −0
Original line number Diff line number Diff line
@@ -8045,6 +8045,91 @@ int q6asm_send_mtmx_strtr_render_mode(struct audio_client *ac,
	return rc;
}

int q6asm_send_mtmx_strtr_clk_rec_mode(struct audio_client *ac,
		uint32_t clk_rec_mode)
{
	struct asm_mtmx_strtr_params matrix;
	struct asm_session_mtmx_strtr_param_clk_rec_t clk_rec_param;
	int sz = 0;
	int rc  = 0;

	pr_debug("%s: clk rec mode is %d\n", __func__, clk_rec_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 ((clk_rec_mode != ASM_SESSION_MTMX_STRTR_PARAM_CLK_REC_NONE) &&
	    (clk_rec_mode != ASM_SESSION_MTMX_STRTR_PARAM_CLK_REC_AUTO)) {
		pr_err("%s: Invalid clk rec mode %d\n", __func__, clk_rec_mode);
		rc = -EINVAL;
		goto exit;
	}

	memset(&clk_rec_param, 0,
	       sizeof(struct asm_session_mtmx_strtr_param_clk_rec_t));
	clk_rec_param.flags = clk_rec_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_clk_rec_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_CLK_REC_CMD;
	matrix.data.param_size =
		sizeof(struct asm_session_mtmx_strtr_param_clk_rec_t);
	matrix.data.reserved = 0;
	memcpy(&(matrix.config.clk_rec_param),
	       &clk_rec_param,
	       sizeof(struct asm_session_mtmx_strtr_param_clk_rec_t));

	rc = apr_send_pkt(ac->apr, (uint32_t *) &matrix);
	if (rc < 0) {
		pr_err("%s: clk rec 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, clk rec 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)
{
	struct apr_hdr hdr;