ASoC: msm: qdsp6v2: Add support for DSP clock recovery
ASM driver changes to apply DSP clock recovery. Clients can issue clock recovery command with a positive value to advance the clock or a negative value to delay the clock. CRs-Fixed: 2036899 Change-Id: If2f10368afafe203ebdea219edcc2227cd381801 Signed-off-by: Manish Dewangan <manish@codeaurora.org>
This commit is contained in:
parent
c01ba1a5f9
commit
761f20e31b
3 changed files with 173 additions and 0 deletions
|
@ -10320,10 +10320,33 @@ struct asm_session_mtmx_strtr_param_clk_rec_t {
|
|||
u32 flags;
|
||||
} __packed;
|
||||
|
||||
|
||||
/* Parameter used by #ASM_SESSION_MTMX_STRTR_MODULE_ID_AVSYNC to
|
||||
* realize smoother adjustment of audio session clock for a specified session.
|
||||
* The desired audio session clock adjustment(in micro seconds) is specified
|
||||
* using the command #ASM_SESSION_CMD_ADJUST_SESSION_CLOCK_V2.
|
||||
* Delaying/Advancing the session clock would be implemented by inserting
|
||||
* interpolated/dropping audio samples in the playback path respectively.
|
||||
* Also, this parameter has to be configured before the Audio Session is put
|
||||
* to RUN state to avoid cold start latency/glitches in the playback.
|
||||
*/
|
||||
|
||||
#define ASM_SESSION_MTMX_PARAM_ADJUST_SESSION_TIME_CTL 0x00013217
|
||||
|
||||
struct asm_session_mtmx_param_adjust_session_time_ctl_t {
|
||||
/* Specifies whether the module is enabled or not
|
||||
* @values
|
||||
* 0 -- disabled
|
||||
* 1 -- enabled
|
||||
*/
|
||||
u32 enable;
|
||||
};
|
||||
|
||||
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;
|
||||
struct asm_session_mtmx_param_adjust_session_time_ctl_t adj_time_param;
|
||||
} __packed;
|
||||
|
||||
struct asm_mtmx_strtr_params {
|
||||
|
|
|
@ -655,6 +655,10 @@ int q6asm_send_mtmx_strtr_render_mode(struct audio_client *ac,
|
|||
int q6asm_send_mtmx_strtr_clk_rec_mode(struct audio_client *ac,
|
||||
uint32_t clk_rec_mode);
|
||||
|
||||
/* Enable adjust session clock in DSP */
|
||||
int q6asm_send_mtmx_strtr_enable_adjust_session_clock(struct audio_client *ac,
|
||||
bool enable);
|
||||
|
||||
/* Retrieve the current DSP path delay */
|
||||
int q6asm_get_path_delay(struct audio_client *ac);
|
||||
|
||||
|
@ -662,4 +666,8 @@ int q6asm_get_path_delay(struct audio_client *ac);
|
|||
uint8_t q6asm_get_buf_index_from_token(uint32_t token);
|
||||
uint8_t q6asm_get_stream_id_from_token(uint32_t token);
|
||||
|
||||
/* Adjust session clock in DSP */
|
||||
int q6asm_adjust_session_clock(struct audio_client *ac,
|
||||
uint32_t adjust_time_lsw,
|
||||
uint32_t adjust_time_msw);
|
||||
#endif /* __Q6_ASM_H__ */
|
||||
|
|
|
@ -2059,6 +2059,12 @@ static int32_t q6asm_callback(struct apr_client_data *data, void *priv)
|
|||
(void *)pp_event_package, ac->priv);
|
||||
kfree(pp_event_package);
|
||||
return 0;
|
||||
case ASM_SESSION_CMDRSP_ADJUST_SESSION_CLOCK_V2:
|
||||
pr_debug("%s: ASM_SESSION_CMDRSP_ADJUST_SESSION_CLOCK_V2 sesion %d status 0x%x msw %u lsw %u\n",
|
||||
__func__, ac->session, payload[0], payload[2],
|
||||
payload[1]);
|
||||
wake_up(&ac->cmd_wait);
|
||||
break;
|
||||
case ASM_SESSION_CMDRSP_GET_PATH_DELAY_V2:
|
||||
pr_debug("%s: ASM_SESSION_CMDRSP_GET_PATH_DELAY_V2 session %d status 0x%x msw %u lsw %u\n",
|
||||
__func__, ac->session, payload[0], payload[2],
|
||||
|
@ -8277,6 +8283,80 @@ exit:
|
|||
return rc;
|
||||
}
|
||||
|
||||
int q6asm_send_mtmx_strtr_enable_adjust_session_clock(struct audio_client *ac,
|
||||
bool enable)
|
||||
{
|
||||
struct asm_mtmx_strtr_params matrix;
|
||||
struct asm_session_mtmx_param_adjust_session_time_ctl_t adjust_time;
|
||||
int sz = 0;
|
||||
int rc = 0;
|
||||
|
||||
pr_debug("%s: adjust session enable %d\n", __func__, enable);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
adjust_time.enable = enable;
|
||||
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_param_adjust_session_time_ctl_t);
|
||||
matrix.param.direction = 0; /* RX */
|
||||
matrix.data.module_id = ASM_SESSION_MTMX_STRTR_MODULE_ID_AVSYNC;
|
||||
matrix.data.param_id = ASM_SESSION_MTMX_PARAM_ADJUST_SESSION_TIME_CTL;
|
||||
matrix.data.param_size =
|
||||
sizeof(struct asm_session_mtmx_param_adjust_session_time_ctl_t);
|
||||
matrix.data.reserved = 0;
|
||||
matrix.config.adj_time_param.enable = adjust_time.enable;
|
||||
|
||||
rc = apr_send_pkt(ac->apr, (uint32_t *) &matrix);
|
||||
if (rc < 0) {
|
||||
pr_err("%s: enable adjust session failed 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: enable adjust session failed failed 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;
|
||||
|
@ -8666,6 +8746,68 @@ fail_cmd:
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
int q6asm_adjust_session_clock(struct audio_client *ac,
|
||||
uint32_t adjust_time_lsw,
|
||||
uint32_t adjust_time_msw)
|
||||
{
|
||||
int rc = 0;
|
||||
int sz = 0;
|
||||
struct asm_session_cmd_adjust_session_clock_v2 adjust_clock;
|
||||
|
||||
pr_debug("%s: adjust_time_lsw is %x, adjust_time_msw is %x\n", __func__,
|
||||
adjust_time_lsw, adjust_time_msw);
|
||||
|
||||
if (!ac) {
|
||||
pr_err("%s: audio client handle is NULL\n", __func__);
|
||||
rc = -EINVAL;
|
||||
goto fail_cmd;
|
||||
}
|
||||
|
||||
if (ac->apr == NULL) {
|
||||
pr_err("%s: ac->apr is NULL", __func__);
|
||||
rc = -EINVAL;
|
||||
goto fail_cmd;
|
||||
}
|
||||
|
||||
sz = sizeof(struct asm_session_cmd_adjust_session_clock_v2);
|
||||
q6asm_add_hdr(ac, &adjust_clock.hdr, sz, TRUE);
|
||||
atomic_set(&ac->cmd_state, -1);
|
||||
adjust_clock.hdr.opcode = ASM_SESSION_CMD_ADJUST_SESSION_CLOCK_V2;
|
||||
|
||||
adjust_clock.adjustime_lsw = adjust_time_lsw;
|
||||
adjust_clock.adjustime_msw = adjust_time_msw;
|
||||
|
||||
|
||||
rc = apr_send_pkt(ac->apr, (uint32_t *) &adjust_clock);
|
||||
if (rc < 0) {
|
||||
pr_err("%s: adjust_clock send failed paramid [0x%x]\n",
|
||||
__func__, adjust_clock.hdr.opcode);
|
||||
rc = -EINVAL;
|
||||
goto fail_cmd;
|
||||
}
|
||||
|
||||
rc = wait_event_timeout(ac->cmd_wait,
|
||||
(atomic_read(&ac->cmd_state) >= 0), 5*HZ);
|
||||
if (!rc) {
|
||||
pr_err("%s: timeout, adjust_clock paramid[0x%x]\n",
|
||||
__func__, adjust_clock.hdr.opcode);
|
||||
rc = -ETIMEDOUT;
|
||||
goto fail_cmd;
|
||||
}
|
||||
|
||||
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 fail_cmd;
|
||||
}
|
||||
rc = 0;
|
||||
fail_cmd:
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
* q6asm_get_path_delay() - get the path delay for an audio session
|
||||
* @ac: audio client handle
|
||||
|
|
Loading…
Add table
Reference in a new issue