audio: hal: Add AVD Drift Query support
- Add out set_param_data() and get_param_data() API.
- This API is needs to be used for client to set/get out stream
specific params.
- Currently it only supports get/set of afew out params. Going forward all
the new param needs to be supported by these APIs.
In future key,value pair based set/get param API will be deprecated.
- Use get_param_data() API to query avtimer vs device drift support.
Currently this API only supports drift query for HDMI device as for
other device DSP can directly do the drift correction.
Change-Id: Iaec94b7220cdaa243d4b616fb727aae7179539d2
diff --git a/hal/audio_extn/audio_defs.h b/hal/audio_extn/audio_defs.h
index ae90cb3..dc9e5bd 100644
--- a/hal/audio_extn/audio_defs.h
+++ b/hal/audio_extn/audio_defs.h
@@ -138,16 +138,42 @@
struct aptx_dec_bt_addr bt_addr;
};
+struct audio_avt_device_drift_param {
+ /* Flag to indicate if resync is required on the client side for
+ * drift correction. Flag is set to TRUE for the first get_param response
+ * after device interface starts. This flag value can be used by client
+ * to identify if device interface restart has happened and if any
+ * re-sync is required at their end for drift correction.
+ */
+ uint32_t resync_flag;
+ /* Accumulated drift value in microseconds. This value is updated
+ * every 100th ms.
+ * Positive drift value indicates AV timer is running faster than device.
+ * Negative drift value indicates AV timer is running slower than device.
+ */
+ int32_t avt_device_drift_value;
+ /* Lower 32 bits of the 64-bit absolute timestamp of reference
+ * timer in microseconds.
+ */
+ uint32_t ref_timer_abs_ts_lsw;
+ /* Upper 32 bits of the 64-bit absolute timestamp of reference
+ * timer in microseconds.
+ */
+ uint32_t ref_timer_abs_ts_msw;
+};
+
typedef union {
struct source_tracking_param st_params;
struct sound_focus_param sf_params;
struct aptx_dec_param aptx_params;
+ struct audio_avt_device_drift_param drift_params;
} audio_extn_param_payload;
typedef enum {
AUDIO_EXTN_PARAM_SOURCE_TRACK,
AUDIO_EXTN_PARAM_SOUND_FOCUS,
- AUDIO_EXTN_PARAM_APTX_DEC
+ AUDIO_EXTN_PARAM_APTX_DEC,
+ AUDIO_EXTN_PARAM_AVT_DEVICE_DRIFT
} audio_extn_param_id;
#endif /* AUDIO_DEFS_H */
diff --git a/hal/audio_extn/audio_extn.h b/hal/audio_extn/audio_extn.h
index c114d2d..bbdd129 100644
--- a/hal/audio_extn/audio_extn.h
+++ b/hal/audio_extn/audio_extn.h
@@ -820,4 +820,7 @@
int audio_extn_set_aptx_dec_params(struct aptx_dec_param *payload);
#endif
+int audio_extn_utils_get_avt_device_drift(
+ struct audio_usecase *usecase,
+ struct audio_avt_device_drift_param *drift_param);
#endif /* AUDIO_EXTN_H */
diff --git a/hal/audio_extn/utils.c b/hal/audio_extn/utils.c
index b12ab8e..91e83af 100644
--- a/hal/audio_extn/utils.c
+++ b/hal/audio_extn/utils.c
@@ -155,6 +155,17 @@
#endif
};
+/* payload structure avt_device drift query */
+struct audio_avt_device_drift_stats {
+ uint32_t minor_version;
+ /* Indicates the device interface direction as either
+ * source (Tx) or sink (Rx).
+ */
+ uint16_t device_direction;
+ /*params exposed to client */
+ struct audio_avt_device_drift_param drift_param;
+};
+
static char bTable[BASE_TABLE_SIZE] = {
'A','B','C','D','E','F','G','H','I','J','K','L',
'M','N','O','P','Q','R','S','T','U','V','W','X',
@@ -1548,3 +1559,75 @@
}
#endif
+
+int audio_extn_utils_get_avt_device_drift(
+ struct audio_usecase *usecase,
+ struct audio_avt_device_drift_param *drift_param)
+{
+ int ret = 0, count = 0;
+ char avt_device_drift_mixer_ctl_name[MIXER_PATH_MAX_LENGTH] = {0};
+ 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;
+ }
+ } else {
+ ALOGE("%s: Invalid usecase %d ",__func__, usecase->type);
+ ret = -EINVAL;
+ }
+
+ if(ret)
+ goto done;
+
+ 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",
+ __func__, avt_device_drift_mixer_ctl_name);
+
+ ret = -EINVAL;
+ goto done;
+ }
+
+ ALOGV("%s: Getting AV Timer vs Device Drift mixer ctrl name %s", __func__,
+ avt_device_drift_mixer_ctl_name);
+
+ mixer_ctl_update(ctl);
+ count = mixer_ctl_get_num_values(ctl);
+ if (count != sizeof(struct audio_avt_device_drift_stats)) {
+ ALOGE("%s: mixer_ctl_get_num_values() invalid drift_stats data size",
+ __func__);
+
+ ret = -EINVAL;
+ goto done;
+ }
+
+ ret = mixer_ctl_get_array(ctl, (void *)&drift_stats, count);
+ if (ret != 0) {
+ ALOGE("%s: mixer_ctl_get_array() failed to get drift_stats Params",
+ __func__);
+
+ ret = -EINVAL;
+ goto done;
+ }
+ memcpy(drift_param, &drift_stats.drift_param,
+ sizeof(struct audio_avt_device_drift_param));
+done:
+ return ret;
+}
diff --git a/hal/audio_hw_extn_api.c b/hal/audio_hw_extn_api.c
index f36d85d..25c4503 100644
--- a/hal/audio_hw_extn_api.c
+++ b/hal/audio_hw_extn_api.c
@@ -48,6 +48,61 @@
};
#endif
+static void lock_output_stream(struct stream_out *out)
+{
+ pthread_mutex_lock(&out->pre_lock);
+ pthread_mutex_lock(&out->lock);
+ pthread_mutex_unlock(&out->pre_lock);
+}
+
+/* API to send playback stream specific config parameters */
+int qahwi_out_set_param_data(struct audio_stream_out *stream __unused,
+ audio_extn_param_id param_id __unused,
+ audio_extn_param_payload *payload __unused) {
+ return -ENOSYS;
+}
+
+/* API to get playback stream specific config parameters */
+int qahwi_out_get_param_data(struct audio_stream_out *stream,
+ audio_extn_param_id param_id,
+ audio_extn_param_payload *payload)
+{
+ int ret = -EINVAL;
+ struct stream_out *out = (struct stream_out *)stream;
+ struct audio_usecase *uc_info;
+
+ if (!stream || !payload) {
+ ALOGE("%s:: Invalid Param",__func__);
+ return ret;
+ }
+
+ lock_output_stream(out);
+ ALOGD("%s: enter: stream (%p) usecase(%d: %s) param_id %d", __func__,
+ stream, out->usecase, use_case_table[out->usecase], param_id);
+
+ switch (param_id) {
+ case AUDIO_EXTN_PARAM_AVT_DEVICE_DRIFT:
+ uc_info = get_usecase_from_list(out->dev, out->usecase);
+ if (uc_info == NULL) {
+ ALOGE("%s: Could not find the usecase (%d) in the list",
+ __func__, out->usecase);
+ ret = -EINVAL;
+ } else {
+ ret = audio_extn_utils_get_avt_device_drift(uc_info,
+ (struct audio_avt_device_drift_param *)payload);
+ if(ret)
+ ALOGE("%s:: avdrift query failed error %d", __func__, ret);
+ }
+ break;
+ default:
+ ALOGE("%s:: unsupported param_id %d", __func__, param_id);
+ break;
+ }
+
+ pthread_mutex_unlock(&out->lock);
+ return ret;
+}
+
int qahwi_get_param_data(const struct audio_hw_device *adev,
audio_extn_param_id param_id,
audio_extn_param_payload *payload)