hal: Adding Pan-Scale, downmix mixer control support.
Add support in HAL to send mix matrix params using downmix,
Pan-Scale mixer controls. Add new interactive usecases and
also add support to open and teardown for interactive streams.
Add support in test app for supporting up to 9 concurrent
streams. Add support for mixer matrix params handling.
Change-Id: I0dc5b908ee779b2b2c526a67609c057f591f26e7
diff --git a/hal/audio_extn/audio_defs.h b/hal/audio_extn/audio_defs.h
index dfe8c61..4e5f4d8 100644
--- a/hal/audio_extn/audio_defs.h
+++ b/hal/audio_extn/audio_defs.h
@@ -236,6 +236,17 @@
struct audio_device_cfg_param dev_cfg_params;
};
+typedef struct mix_matrix_params {
+ uint16_t num_output_channels;
+ uint16_t num_input_channels;
+ uint8_t has_output_channel_map;
+ uint32_t output_channel_map[AUDIO_CHANNEL_COUNT_MAX];
+ uint8_t has_input_channel_map;
+ uint32_t input_channel_map[AUDIO_CHANNEL_COUNT_MAX];
+ uint8_t has_mixer_coeffs;
+ float mixer_coeffs[AUDIO_CHANNEL_COUNT_MAX][AUDIO_CHANNEL_COUNT_MAX];
+} mix_matrix_params_t;
+
typedef union {
struct source_tracking_param st_params;
struct sound_focus_param sf_params;
@@ -248,6 +259,7 @@
struct audio_adsp_event adsp_event_params;
struct audio_out_channel_map_param channel_map_param;
struct audio_device_cfg_param device_cfg;
+ struct mix_matrix_params mm_params;
} audio_extn_param_payload;
typedef enum {
@@ -264,7 +276,11 @@
AUDIO_EXTN_PARAM_ADSP_STREAM_CMD,
/* param to set input channel map for playback stream */
AUDIO_EXTN_PARAM_OUT_CHANNEL_MAP,
- AUDIO_EXTN_PARAM_DEVICE_CONFIG
+ AUDIO_EXTN_PARAM_DEVICE_CONFIG,
+ /* Pan/scale params to be set on ASM */
+ AUDIO_EXTN_PARAM_OUT_MIX_MATRIX_PARAMS,
+ /* Downmix params to be set on ADM */
+ AUDIO_EXTN_PARAM_CH_MIX_MATRIX_PARAMS
} audio_extn_param_id;
#endif /* AUDIO_DEFS_H */
diff --git a/hal/audio_extn/audio_extn.c b/hal/audio_extn/audio_extn.c
index 072444e..84de66f 100644
--- a/hal/audio_extn/audio_extn.c
+++ b/hal/audio_extn/audio_extn.c
@@ -1379,6 +1379,14 @@
ret = audio_extn_utils_set_channel_map(out,
(struct audio_out_channel_map_param *)(payload));
break;
+ case AUDIO_EXTN_PARAM_OUT_MIX_MATRIX_PARAMS:
+ ret = audio_extn_utils_set_pan_scale_params(out,
+ (struct mix_matrix_params *)(payload));
+ break;
+ case AUDIO_EXTN_PARAM_CH_MIX_MATRIX_PARAMS:
+ ret = audio_extn_utils_set_downmix_params(out,
+ (struct mix_matrix_params *)(payload));
+ break;
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 c2a5484..8360703 100644
--- a/hal/audio_extn/audio_extn.h
+++ b/hal/audio_extn/audio_extn.h
@@ -103,6 +103,10 @@
#define AUDIO_OUTPUT_FLAG_TIMESTAMP 0x10000
#endif
+#ifndef AUDIO_OUTPUT_FLAG_INTERACTIVE
+#define AUDIO_OUTPUT_FLAG_INTERACTIVE 0x40000
+#endif
+
#ifndef COMPRESS_METADATA_NEEDED
#define audio_extn_parse_compress_metadata(out, parms) (0)
#else
@@ -892,6 +896,12 @@
int audio_extn_utils_set_channel_map(
struct stream_out *out,
struct audio_out_channel_map_param *channel_map_param);
+int audio_extn_utils_set_pan_scale_params(
+ struct stream_out *out,
+ struct mix_matrix_params *mm_params);
+int audio_extn_utils_set_downmix_params(
+ struct stream_out *out,
+ struct mix_matrix_params *mm_params);
#ifdef AUDIO_HW_LOOPBACK_ENABLED
/* API to create audio patch */
int audio_extn_hw_loopback_create_audio_patch(struct audio_hw_device *dev,
diff --git a/hal/audio_extn/utils.c b/hal/audio_extn/utils.c
index 9f78a0c..fb1362c 100644
--- a/hal/audio_extn/utils.c
+++ b/hal/audio_extn/utils.c
@@ -102,6 +102,10 @@
/* ToDo: Check and update a proper value in msec */
#define COMPRESS_OFFLOAD_PLAYBACK_LATENCY 50
+#ifndef MAX_CHANNELS_SUPPORTED
+#define MAX_CHANNELS_SUPPORTED 8
+#endif
+
struct string_to_enum {
const char *name;
uint32_t value;
@@ -122,6 +126,7 @@
STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH),
STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_TIMESTAMP),
STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_VOIP_RX),
+ STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_INTERACTIVE),
STRING_TO_ENUM(AUDIO_INPUT_FLAG_NONE),
STRING_TO_ENUM(AUDIO_INPUT_FLAG_FAST),
STRING_TO_ENUM(AUDIO_INPUT_FLAG_HW_HOTWORD),
@@ -821,6 +826,9 @@
int snd_device = split_snd_device, snd_device_be_idx = -1;
int32_t sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
char value[PROPERTY_VALUE_MAX] = {0};
+ struct streams_io_cfg *s_info = NULL;
+ struct listnode *node = NULL;
+ int direct_app_type = 0;
ALOGV("%s: usecase->out_snd_device %s, usecase->in_snd_device %s, split_snd_device %s",
__func__, platform_get_snd_device_name(usecase->out_snd_device),
@@ -837,6 +845,7 @@
(usecase->id != USECASE_AUDIO_PLAYBACK_MULTI_CH) &&
(usecase->id != USECASE_AUDIO_PLAYBACK_ULL) &&
(usecase->id != USECASE_AUDIO_PLAYBACK_VOIP) &&
+ (!is_interactive_usecase(usecase->id)) &&
(!is_offload_usecase(usecase->id)) &&
(usecase->type != PCM_CAPTURE)) {
ALOGV("%s: a rx/tx/loopback path where app type cfg is not required %d", __func__, usecase->id);
@@ -917,7 +926,18 @@
}
sample_rate = usecase->stream.out->app_type_cfg.sample_rate;
- app_type = usecase->stream.out->app_type_cfg.app_type;
+ /* Interactive streams are supported with only direct app type id.
+ * Get Direct profile app type and use it for interactive streams
+ */
+ list_for_each(node, &adev->streams_output_cfg_list) {
+ s_info = node_to_item(node, struct streams_io_cfg, list);
+ if (s_info->flags.out_flags == AUDIO_OUTPUT_FLAG_DIRECT)
+ direct_app_type = s_info->app_type_cfg.app_type;
+ }
+ if (usecase->stream.out->flags == AUDIO_OUTPUT_FLAG_INTERACTIVE)
+ app_type = direct_app_type;
+ else
+ app_type = usecase->stream.out->app_type_cfg.app_type;
app_type_cfg[len++] = app_type;
app_type_cfg[len++] = acdb_dev_id;
if (((usecase->stream.out->format == AUDIO_FORMAT_E_AC3) ||
@@ -2160,3 +2180,100 @@
exit:
return ret;
}
+
+int audio_extn_utils_set_pan_scale_params(
+ struct stream_out *out,
+ struct mix_matrix_params *mm_params)
+{
+ int ret = -EINVAL, i = 0, j = 0;
+
+ if (mm_params == NULL && out != NULL) {
+ ALOGE("%s:: Invalid mix matrix params", __func__);
+ goto exit;
+ }
+
+ if (mm_params->num_output_channels > MAX_CHANNELS_SUPPORTED ||
+ mm_params->num_output_channels <= 0 ||
+ mm_params->num_input_channels > MAX_CHANNELS_SUPPORTED ||
+ mm_params->num_input_channels <= 0)
+ goto exit;
+
+ out->pan_scale_params.num_output_channels = mm_params->num_output_channels;
+ out->pan_scale_params.num_input_channels = mm_params->num_input_channels;
+ out->pan_scale_params.has_output_channel_map =
+ mm_params->has_output_channel_map;
+ for (i = 0; i < mm_params->num_output_channels; i++)
+ out->pan_scale_params.output_channel_map[i] =
+ mm_params->output_channel_map[i];
+
+ out->pan_scale_params.has_input_channel_map =
+ mm_params->has_input_channel_map;
+ for (i = 0; i < mm_params->num_input_channels; i++)
+ out->pan_scale_params.input_channel_map[i] =
+ mm_params->input_channel_map[i];
+
+ out->pan_scale_params.has_mixer_coeffs = mm_params->has_mixer_coeffs;
+ for (i = 0; i < mm_params->num_output_channels; i++)
+ for (j = 0; j < mm_params->num_input_channels; j++) {
+ //Convert the channel coefficient gains in Q14 format
+ out->pan_scale_params.mixer_coeffs[i][j] =
+ mm_params->mixer_coeffs[i][j] * (2 << 13);
+ }
+
+ ret = platform_set_stream_pan_scale_params(out->dev->platform,
+ out->pcm_device_id,
+ out->pan_scale_params);
+
+exit:
+ return ret;
+}
+
+int audio_extn_utils_set_downmix_params(
+ struct stream_out *out,
+ struct mix_matrix_params *mm_params)
+{
+ int ret = -EINVAL, i = 0, j = 0;
+ struct audio_usecase *usecase = NULL;
+
+ if (mm_params == NULL && out != NULL) {
+ ALOGE("%s:: Invalid mix matrix params", __func__);
+ goto exit;
+ }
+
+ if (mm_params->num_output_channels > MAX_CHANNELS_SUPPORTED ||
+ mm_params->num_output_channels <= 0 ||
+ mm_params->num_input_channels > MAX_CHANNELS_SUPPORTED ||
+ mm_params->num_input_channels <= 0)
+ goto exit;
+
+ usecase = get_usecase_from_list(out->dev, out->usecase);
+ out->downmix_params.num_output_channels = mm_params->num_output_channels;
+ out->downmix_params.num_input_channels = mm_params->num_input_channels;
+
+ out->downmix_params.has_output_channel_map =
+ mm_params->has_output_channel_map;
+ for (i = 0; i < mm_params->num_output_channels; i++) {
+ out->downmix_params.output_channel_map[i] =
+ mm_params->output_channel_map[i];
+ }
+
+ out->downmix_params.has_input_channel_map =
+ mm_params->has_input_channel_map;
+ for (i = 0; i < mm_params->num_input_channels; i++)
+ out->downmix_params.input_channel_map[i] =
+ mm_params->input_channel_map[i];
+
+ out->downmix_params.has_mixer_coeffs = mm_params->has_mixer_coeffs;
+ for (i = 0; i < mm_params->num_output_channels; i++)
+ for (j = 0; j < mm_params->num_input_channels; j++)
+ out->downmix_params.mixer_coeffs[i][j] =
+ mm_params->mixer_coeffs[i][j];
+
+ ret = platform_set_stream_downmix_params(out->dev->platform,
+ out->pcm_device_id,
+ usecase->out_snd_device,
+ out->downmix_params);
+
+exit:
+ return ret;
+}