audio: hal: add DSP clock recovery support
-Changes to add DSP clock recovery support
Conflicts:
qahw_api/test/qahw_playback_test.c
hal/audio_extn/utils.c
CRs-Fixed: 2036937
Change-Id: I32e18e415c4a7dfdc7ae13d0e50c1ca76d739cc0
diff --git a/hal/audio_extn/audio_defs.h b/hal/audio_extn/audio_defs.h
index 06b4fb9..5fb5cdf 100644
--- a/hal/audio_extn/audio_defs.h
+++ b/hal/audio_extn/audio_defs.h
@@ -177,10 +177,23 @@
uint64_t start_delay; /* session start delay in microseconds*/
};
+struct audio_out_enable_drift_correction {
+ bool enable; /* enable drift correction*/
+};
+
+struct audio_out_correct_drift {
+ /*
+ * adjust time in microseconds, a positive value
+ * to advance the clock or a negative value to
+ * delay the clock.
+ */
+ int64_t adjust_time;
+};
+
/* type of asynchronous write callback events. Mutually exclusive
* event enums append those defined for stream_callback_event_t in audio.h */
typedef enum {
- AUDIO_EXTN_STREAM_CBK_EVENT_ADSP = 0x100 /* callback event from ADSP PP,
+ AUDIO_EXTN_STREAM_CBK_EVENT_ADSP = 0x100 /* callback event from ADSP PP,
* corresponding payload will be
* sent as is to the client
*/
@@ -203,6 +216,8 @@
struct audio_avt_device_drift_param drift_params;
struct audio_out_render_window_param render_window_param;
struct audio_out_start_delay_param start_delay;
+ struct audio_out_enable_drift_correction drift_enable_param;
+ struct audio_out_correct_drift drift_correction_param;
struct audio_adsp_event adsp_event_params;
} audio_extn_param_payload;
@@ -213,6 +228,10 @@
AUDIO_EXTN_PARAM_AVT_DEVICE_DRIFT,
AUDIO_EXTN_PARAM_OUT_RENDER_WINDOW, /* PARAM to set render window */
AUDIO_EXTN_PARAM_OUT_START_DELAY,
+ /* enable adsp drift correction this must be called before out_write */
+ AUDIO_EXTN_PARAM_OUT_ENABLE_DRIFT_CORRECTION,
+ /* param to set drift value to be adjusted by dsp */
+ AUDIO_EXTN_PARAM_OUT_CORRECT_DRIFT,
AUDIO_EXTN_PARAM_ADSP_STREAM_CMD
} audio_extn_param_id;
diff --git a/hal/audio_extn/audio_extn.c b/hal/audio_extn/audio_extn.c
index 3c9330c..05afda0 100644
--- a/hal/audio_extn/audio_extn.c
+++ b/hal/audio_extn/audio_extn.c
@@ -1367,12 +1367,20 @@
ret = audio_extn_utils_compress_set_start_delay(out,
(struct audio_out_start_delay_param *)(payload));
break;
+ case AUDIO_EXTN_PARAM_OUT_ENABLE_DRIFT_CORRECTION:
+ ret = audio_extn_utils_compress_enable_drift_correction(out,
+ (struct audio_out_enable_drift_correction *)(payload));
+ break;
+ case AUDIO_EXTN_PARAM_OUT_CORRECT_DRIFT:
+ ret = audio_extn_utils_compress_correct_drift(out,
+ (struct audio_out_correct_drift *)(payload));
+ break;
case AUDIO_EXTN_PARAM_ADSP_STREAM_CMD:
ret = audio_extn_adsp_hdlr_stream_set_param(out->adsp_hdlr_stream_handle,
ADSP_HDLR_STREAM_CMD_REGISTER_EVENT,
(void *)&payload->adsp_event_params);
break;
- default:
+ default:
ALOGE("%s:: unsupported param_id %d", __func__, param_id);
break;
}
diff --git a/hal/audio_extn/audio_extn.h b/hal/audio_extn/audio_extn.h
index e8210ac..c71037e 100644
--- a/hal/audio_extn/audio_extn.h
+++ b/hal/audio_extn/audio_extn.h
@@ -864,4 +864,10 @@
int audio_extn_utils_compress_set_start_delay(
struct stream_out *out,
struct audio_out_start_delay_param *start_delay_param);
+int audio_extn_utils_compress_enable_drift_correction(
+ struct stream_out *out,
+ struct audio_out_enable_drift_correction *drift_enable);
+int audio_extn_utils_compress_correct_drift(
+ struct stream_out *out,
+ struct audio_out_correct_drift *drift_correction_param);
#endif /* AUDIO_EXTN_H */
diff --git a/hal/audio_extn/utils.c b/hal/audio_extn/utils.c
index a2dff9f..0331fc4 100644
--- a/hal/audio_extn/utils.c
+++ b/hal/audio_extn/utils.c
@@ -1609,36 +1609,39 @@
{
int ret = 0, count = 0;
char avt_device_drift_mixer_ctl_name[MIXER_PATH_MAX_LENGTH] = {0};
+ const char *backend = NULL;
struct mixer_ctl *ctl = NULL;
struct audio_avt_device_drift_stats drift_stats;
struct audio_device *adev = NULL;
if (usecase != NULL && usecase->type == PCM_PLAYBACK) {
- adev = usecase->stream.out->dev;
- switch(usecase->out_snd_device) {
- case SND_DEVICE_OUT_HDMI:
- strlcpy(avt_device_drift_mixer_ctl_name,
- "HDMI RX Drift",
- MIXER_PATH_MAX_LENGTH);
- break;
- case SND_DEVICE_OUT_DISPLAY_PORT:
- strlcpy(avt_device_drift_mixer_ctl_name,
- "DISPLAY Port RX Drift",
- MIXER_PATH_MAX_LENGTH);
- break;
- default :
- ALOGE("%s: Unsupported device %d",__func__,
- usecase->stream.out->devices);
- ret = -EINVAL;
+ backend = platform_get_snd_device_backend_interface(usecase->out_snd_device);
+ if (!backend) {
+ ALOGE("%s: Unsupported device %d", __func__,
+ usecase->stream.out->devices);
+ ret = -EINVAL;
+ goto done;
+ }
+ strlcpy(avt_device_drift_mixer_ctl_name,
+ backend,
+ MIXER_PATH_MAX_LENGTH);
+
+ count = strlen(backend);
+ if (MIXER_PATH_MAX_LENGTH - count > 0) {
+ strlcat(&avt_device_drift_mixer_ctl_name[count],
+ " DRIFT",
+ MIXER_PATH_MAX_LENGTH - count);
+ } else {
+ ret = -EINVAL;
+ goto done;
}
} else {
ALOGE("%s: Invalid usecase",__func__);
ret = -EINVAL;
+ goto done;
}
- if(ret)
- goto done;
-
+ adev = usecase->stream.out->dev;
ctl = mixer_get_ctl_by_name(adev->mixer, avt_device_drift_mixer_ctl_name);
if (!ctl) {
ALOGE("%s: Could not get ctl for mixer cmd - %s",
@@ -1849,11 +1852,8 @@
goto exit;
}
- if ((out->render_mode == RENDER_MODE_AUDIO_MASTER) ||
- (out->render_mode == RENDER_MODE_AUDIO_STC_MASTER)) {
- memcpy(&out->render_window, render_window,
- sizeof(struct audio_out_render_window_param));
- } else {
+ if ((out->render_mode != RENDER_MODE_AUDIO_MASTER) &&
+ (out->render_mode != RENDER_MODE_AUDIO_STC_MASTER)) {
ALOGD("%s:: only supported in timestamp mode, current "
"render mode mode %d", __func__, out->render_mode);
goto exit;
@@ -1915,11 +1915,8 @@
goto exit;
}
- if ((out->render_mode == RENDER_MODE_AUDIO_MASTER) ||
- (out->render_mode == RENDER_MODE_AUDIO_STC_MASTER)) {
- /* store it to reconfigure in start_output_stream() */
- out->delay_param.start_delay = delay_param->start_delay;
- } else {
+ if ((out->render_mode != RENDER_MODE_AUDIO_MASTER) &&
+ (out->render_mode != RENDER_MODE_AUDIO_STC_MASTER)) {
ALOGD("%s:: only supported in timestamp mode, current "
"render mode mode %d", __func__, out->render_mode);
goto exit;
@@ -2016,3 +2013,104 @@
return snd_card_num;
}
+
+#ifdef SNDRV_COMPRESS_ENABLE_ADJUST_SESSION_CLOCK
+int audio_extn_utils_compress_enable_drift_correction(
+ struct stream_out *out,
+ struct audio_out_enable_drift_correction *drift)
+{
+ struct snd_compr_metadata metadata;
+ int ret = -EINVAL;
+
+ if(drift == NULL) {
+ ALOGE("%s:: Invalid param", __func__);
+ goto exit;
+ }
+
+ ALOGD("%s:: drift enable %d", __func__,drift->enable);
+
+ if (!is_offload_usecase(out->usecase)) {
+ ALOGE("%s:: not supported for non offload session", __func__);
+ goto exit;
+ }
+
+ if (!out->compr) {
+ ALOGW("%s:: offload session not yet opened,"
+ "start delay will be configure later", __func__);
+ goto exit;
+ }
+
+ metadata.key = SNDRV_COMPRESS_ENABLE_ADJUST_SESSION_CLOCK;
+ metadata.value[0] = drift->enable;
+ out->drift_correction_enabled = drift->enable;
+
+ ret = compress_set_metadata(out->compr, &metadata);
+ if(ret) {
+ ALOGE("%s::error %s", __func__, compress_get_error(out->compr));
+ out->drift_correction_enabled = false;
+ }
+
+exit:
+ return ret;
+}
+#else
+int audio_extn_utils_compress_enable_drift_correction(
+ struct stream_out *out __unused,
+ struct audio_out_enable_drift_correction *drift __unused)
+{
+ ALOGD("%s:: configuring drift enablement not supported", __func__);
+ return 0;
+}
+#endif
+
+#ifdef SNDRV_COMPRESS_ADJUST_SESSION_CLOCK
+int audio_extn_utils_compress_correct_drift(
+ struct stream_out *out,
+ struct audio_out_correct_drift *drift_param)
+{
+ struct snd_compr_metadata metadata;
+ int ret = -EINVAL;
+
+ if (drift_param == NULL) {
+ ALOGE("%s:: Invalid drift_param", __func__);
+ goto exit;
+ }
+
+ ALOGD("%s:: adjust time 0x%"PRIx64" ", __func__,
+ drift_param->adjust_time);
+
+ if (!is_offload_usecase(out->usecase)) {
+ ALOGE("%s:: not supported for non offload session", __func__);
+ goto exit;
+ }
+
+ if (!out->compr) {
+ ALOGW("%s:: offload session not yet opened", __func__);
+ goto exit;
+ }
+
+ if (!out->drift_correction_enabled) {
+ ALOGE("%s:: drift correction not enabled", __func__);
+ goto exit;
+ }
+
+ metadata.key = SNDRV_COMPRESS_ADJUST_SESSION_CLOCK;
+ metadata.value[0] = 0xFFFFFFFF & drift_param->adjust_time; /* lsb */
+ metadata.value[1] = \
+ (0xFFFFFFFF00000000 & drift_param->adjust_time) >> 32; /* msb*/
+
+ ret = compress_set_metadata(out->compr, &metadata);
+ if(ret)
+ ALOGE("%s::error %s", __func__, compress_get_error(out->compr));
+exit:
+ return ret;
+}
+#else
+int audio_extn_utils_compress_correct_drift(
+ struct stream_out *out __unused,
+ struct audio_out_correct_drift *drift_param __unused)
+{
+ ALOGD("%s:: setting adjust clock not supported", __func__);
+ return 0;
+}
+#endif