diff --git a/hal/audio_extn/audio_extn.c b/hal/audio_extn/audio_extn.c index 65f516c8..e46b7369 100644 --- a/hal/audio_extn/audio_extn.c +++ b/hal/audio_extn/audio_extn.c @@ -1142,3 +1142,52 @@ void audio_extn_perf_lock_release(int *handle) } } #endif /* KPI_OPTIMIZE_ENABLED */ + +static int audio_extn_set_multichannel_mask(struct audio_device *adev, + struct stream_in *in, + struct audio_config *config, + bool *channel_mask_updated) +{ + int ret = -EINVAL; + int channel_count = audio_channel_count_from_in_mask(in->channel_mask); + *channel_mask_updated = false; + + int max_mic_count = platform_get_max_mic_count(adev->platform); + /* validate input params*/ + if ((channel_count == 6) && + (in->format == AUDIO_FORMAT_PCM_16_BIT)) { + + switch (max_mic_count) { + case 4: + config->channel_mask = AUDIO_CHANNEL_INDEX_MASK_4; + break; + case 3: + config->channel_mask = AUDIO_CHANNEL_INDEX_MASK_3; + break; + case 2: + config->channel_mask = AUDIO_CHANNEL_IN_STEREO; + break; + default: + config->channel_mask = AUDIO_CHANNEL_IN_STEREO; + break; + } + ret = 0; + *channel_mask_updated = true; + } + return ret; +} + +int audio_extn_check_and_set_multichannel_usecase(struct audio_device *adev, + struct stream_in *in, + struct audio_config *config, + bool *update_params) +{ + bool ssr_supported = false; + ssr_supported = audio_extn_ssr_check_usecase(in); + if (ssr_supported) { + return audio_extn_ssr_set_usecase(in, config, update_params); + } else { + return audio_extn_set_multichannel_mask(adev, in, config, + update_params); + } +} diff --git a/hal/audio_extn/audio_extn.h b/hal/audio_extn/audio_extn.h index 069feda6..8ce06d91 100644 --- a/hal/audio_extn/audio_extn.h +++ b/hal/audio_extn/audio_extn.h @@ -189,17 +189,21 @@ void audio_extn_a2dp_set_handoff_mode(bool is_on); #endif #ifndef SSR_ENABLED -#define audio_extn_ssr_check_and_set_usecase(in) (-1) -#define audio_extn_ssr_init(in, num_out_chan) (0) -#define audio_extn_ssr_deinit() (0) -#define audio_extn_ssr_update_enabled() (0) -#define audio_extn_ssr_get_enabled() (0) -#define audio_extn_ssr_read(stream, buffer, bytes) (0) -#define audio_extn_ssr_set_parameters(adev, parms) (0) -#define audio_extn_ssr_get_parameters(adev, parms, reply) (0) -#define audio_extn_ssr_get_stream() (0) +#define audio_extn_ssr_check_usecase(in) (0) +#define audio_extn_ssr_set_usecase(in, config, channel_mask_updated) (0) +#define audio_extn_ssr_init(in, num_out_chan) (0) +#define audio_extn_ssr_deinit() (0) +#define audio_extn_ssr_update_enabled() (0) +#define audio_extn_ssr_get_enabled() (0) +#define audio_extn_ssr_read(stream, buffer, bytes) (0) +#define audio_extn_ssr_set_parameters(adev, parms) (0) +#define audio_extn_ssr_get_parameters(adev, parms, reply) (0) +#define audio_extn_ssr_get_stream() (0) #else -int audio_extn_ssr_check_and_set_usecase(struct stream_in *in); +bool audio_extn_ssr_check_usecase(struct stream_in *in); +int audio_extn_ssr_set_usecase(struct stream_in *in, + struct audio_config *config, + bool *channel_mask_updated); int32_t audio_extn_ssr_init(struct stream_in *in, int num_out_chan); int32_t audio_extn_ssr_deinit(); @@ -214,6 +218,10 @@ void audio_extn_ssr_get_parameters(const struct audio_device *adev, struct str_parms *reply); struct stream_in *audio_extn_ssr_get_stream(); #endif +int audio_extn_check_and_set_multichannel_usecase(struct audio_device *adev, + struct stream_in *in, + struct audio_config *config, + bool *update_params); #ifndef HW_VARIANTS_ENABLED #define hw_info_init(snd_card_name) (0) diff --git a/hal/audio_extn/ssr.c b/hal/audio_extn/ssr.c index f55f3ced..51a6a268 100644 --- a/hal/audio_extn/ssr.c +++ b/hal/audio_extn/ssr.c @@ -331,33 +331,55 @@ bool audio_extn_ssr_get_enabled() return false; } -int audio_extn_ssr_check_and_set_usecase(struct stream_in *in) -{ - int ret = -1; +bool audio_extn_ssr_check_usecase(struct stream_in *in) { + int ret = false; int channel_count = audio_channel_count_from_in_mask(in->channel_mask); audio_devices_t devices = in->device; audio_source_t source = in->source; - /* validate input params - * only stereo and 5:1 channel config is supported - * only AUDIO_DEVICE_IN_BUILTIN_MIC, AUDIO_DEVICE_IN_BACK_MIC supports 3 mics */ - if (audio_extn_ssr_get_enabled() && - ((channel_count == 2) || (channel_count == 6)) && - ((AUDIO_SOURCE_MIC == source) || (AUDIO_SOURCE_CAMCORDER == source)) && - ((AUDIO_DEVICE_IN_BUILTIN_MIC == devices) || (AUDIO_DEVICE_IN_BACK_MIC == devices)) && - (in->format == AUDIO_FORMAT_PCM_16_BIT)) { - - ALOGD("%s: Found SSR use case starting SSR lib with channel_count :%d", + if ((audio_extn_ssr_get_enabled()) && + ((channel_count == 2) || (channel_count == 6)) && + ((AUDIO_SOURCE_MIC == source) || (AUDIO_SOURCE_CAMCORDER == source)) && + ((AUDIO_DEVICE_IN_BUILTIN_MIC == devices) || (AUDIO_DEVICE_IN_BACK_MIC == devices)) && + (in->format == AUDIO_FORMAT_PCM_16_BIT)) { + ALOGD("%s: SSR enabled with channel_count :%d", __func__, channel_count); + ret = true; + } + return ret; +} - if (!audio_extn_ssr_init(in, channel_count)) { - ALOGD("%s: Created SSR session succesfully", __func__); +int audio_extn_ssr_set_usecase(struct stream_in *in, + struct audio_config *config, + bool *update_params) +{ + int ret = -EINVAL; + int channel_count = audio_channel_count_from_in_mask(in->channel_mask); + audio_channel_representation_t representation = + audio_channel_mask_get_representation(in->channel_mask); + *update_params = false; + + if (audio_extn_ssr_check_usecase(in)) { + + if (representation == AUDIO_CHANNEL_REPRESENTATION_INDEX) { + /* update params in case channel representation index. + * on returning error, flinger will retry with supported representation passed + */ + ALOGD("%s: SSR supports only channel representation position, channel_mask(%#x)" + ,__func__, config->channel_mask); + config->channel_mask = AUDIO_CHANNEL_IN_5POINT1; ret = 0; + *update_params = true; } else { - ALOGE("%s: Unable to start SSR record session", __func__); + if (!audio_extn_ssr_init(in, channel_count)) { + ALOGD("%s: Created SSR session succesfully", __func__); + ret = 0; + } else { + ALOGE("%s: Unable to start SSR record session", __func__); + } } - } - return ret; + } + return ret; } static void pcm_buffer_queue_push(struct pcm_buffer_queue **queue, diff --git a/hal/audio_hw.c b/hal/audio_hw.c index f6e11e81..569948a7 100644 --- a/hal/audio_hw.c +++ b/hal/audio_hw.c @@ -4348,6 +4348,7 @@ static int adev_open_input_stream(struct audio_hw_device *dev, int ret = 0, buffer_size, frame_size; int channel_count = audio_channel_count_from_in_mask(config->channel_mask); bool is_low_latency = false; + bool channel_mask_updated = false; *stream_in = NULL; if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0) { @@ -4442,7 +4443,14 @@ static int adev_open_input_stream(struct audio_hw_device *dev, in->config.channels = channel_count; in->config.rate = config->sample_rate; in->sample_rate = config->sample_rate; - } else if (!audio_extn_ssr_check_and_set_usecase(in)) { + } else if (!audio_extn_check_and_set_multichannel_usecase(adev, + in, config, &channel_mask_updated)) { + if (channel_mask_updated == true) { + ALOGD("%s: return error to retry with updated channel mask (%#x)", + __func__, config->channel_mask); + ret = -EINVAL; + goto err_open; + } ALOGD("%s: created surround sound session succesfully",__func__); } else if (audio_extn_compr_cap_enabled() && audio_extn_compr_cap_format_supported(config->format) && diff --git a/hal/msm8916/platform.c b/hal/msm8916/platform.c index 47f251fa..0296accc 100644 --- a/hal/msm8916/platform.c +++ b/hal/msm8916/platform.c @@ -5686,3 +5686,8 @@ int platform_retrieve_audio_cal(void* platform __unused, { return -ENOSYS; } + +int platform_get_max_mic_count(void *platform) { + struct platform_data *my_data = (struct platform_data *)platform; + return my_data->max_mic_count; +} diff --git a/hal/msm8974/platform.c b/hal/msm8974/platform.c index 48bb46cd..a52e2b16 100644 --- a/hal/msm8974/platform.c +++ b/hal/msm8974/platform.c @@ -5825,3 +5825,8 @@ int platform_retrieve_audio_cal(void* platform, int acdb_dev_id, ERROR_RETURN: return ret; } + +int platform_get_max_mic_count(void *platform) { + struct platform_data *my_data = (struct platform_data *)platform; + return my_data->max_mic_count; +} diff --git a/hal/platform_api.h b/hal/platform_api.h index 7bd6756f..c3b76b0d 100644 --- a/hal/platform_api.h +++ b/hal/platform_api.h @@ -178,4 +178,5 @@ int platform_retrieve_audio_cal(void* platform, int acdb_dev_id, int acdb_device void* data, int* length); unsigned char* platform_get_license(void* platform, int* size); +int platform_get_max_mic_count(void *platform); #endif // AUDIO_PLATFORM_API_H