Loading hal/Android.mk +4 −0 Original line number Diff line number Diff line Loading @@ -167,6 +167,10 @@ ifneq ($(strip $(DOLBY_DDP)),true) endif endif ifeq ($(strip $(AUDIO_FEATURE_ENABLED_HDMI_PASSTHROUGH)),true) LOCAL_CFLAGS += -DHDMI_PASSTHROUGH_ENABLED endif LOCAL_SHARED_LIBRARIES := \ liblog \ libcutils \ Loading hal/audio_extn/audio_extn.h +28 −1 Original line number Diff line number Diff line Loading @@ -270,7 +270,6 @@ void audio_extn_dolby_set_license(struct audio_device *adev); void audio_extn_dolby_set_endpoint(struct audio_device *adev); #endif #if defined(DS1_DOLBY_DDP_ENABLED) || defined(DS2_DOLBY_DAP_ENABLED) bool audio_extn_is_dolby_format(audio_format_t format); int audio_extn_dolby_get_snd_codec_id(struct audio_device *adev, Loading @@ -288,6 +287,34 @@ int audio_extn_dolby_get_snd_codec_id(struct audio_device *adev, void audio_extn_ddp_set_parameters(struct audio_device *adev, struct str_parms *parms); void audio_extn_dolby_send_ddp_endp_params(struct audio_device *adev); #endif #ifndef HDMI_PASSTHROUGH_ENABLED #define audio_extn_dolby_update_passt_formats(adev, out) (0) #define audio_extn_dolby_update_passt_stream_configuration(adev, out) (0) #define audio_extn_dolby_is_passt_convert_supported(adev, out) (0) #define audio_extn_dolby_is_passt_supported(adev, out) (0) #define audio_extn_dolby_is_passthrough_stream(flags) (0) #define audio_extn_dolby_set_hdmi_config(adev, out) (0) #define audio_extn_dolby_get_passt_buffer_size(info) (0) #define audio_extn_dolby_set_passt_volume(out, mute) (0) #define audio_extn_dolby_set_passt_latency(out, latency) (0) #else int audio_extn_dolby_update_passt_formats(struct audio_device *adev, struct stream_out *out); bool audio_extn_dolby_is_passt_convert_supported(struct audio_device *adev, struct stream_out *out); bool audio_extn_dolby_is_passt_supported(struct audio_device *adev, struct stream_out *out); void audio_extn_dolby_update_passt_stream_configuration(struct audio_device *adev, struct stream_out *out); bool audio_extn_dolby_is_passthrough_stream(int flags); int audio_extn_dolby_set_hdmi_config(struct audio_device *adev, struct stream_out *out); int audio_extn_dolby_get_passt_buffer_size(audio_offload_info_t* info); int audio_extn_dolby_set_passt_volume(struct stream_out *out, int mute); int audio_extn_dolby_set_passt_latency(struct stream_out *out, int latency); #endif #ifndef HFP_ENABLED Loading hal/audio_extn/dolby.c +112 −0 Original line number Diff line number Diff line Loading @@ -408,6 +408,118 @@ bool audio_extn_is_dolby_format(audio_format_t format) } #endif /* DS1_DOLBY_DDP_ENABLED || DS2_DOLBY_DAP_ENABLED */ #ifdef HDMI_PASSTHROUGH_ENABLED int audio_extn_dolby_update_passt_formats(struct audio_device *adev, struct stream_out *out) { int32_t i = 0, ret = -ENOSYS; if (platform_is_edid_supported_format(adev->platform, AUDIO_FORMAT_AC3) || platform_is_edid_supported_format(adev->platform, AUDIO_FORMAT_E_AC3)) { out->supported_formats[i++] = AUDIO_FORMAT_AC3; out->supported_formats[i++] = AUDIO_FORMAT_E_AC3; /* Reciever must support JOC and advertise, otherwise JOC is treated as DDP */ out->supported_formats[i++] = AUDIO_FORMAT_E_AC3_JOC; ret = 0; } ALOGV("%s: ret = %d", __func__, ret); return ret; } bool audio_extn_dolby_is_passt_convert_supported(struct audio_device *adev, struct stream_out *out) { bool convert = false; switch (out->format) { case AUDIO_FORMAT_E_AC3: case AUDIO_FORMAT_E_AC3_JOC: if (!platform_is_edid_supported_format(adev->platform, AUDIO_FORMAT_E_AC3)) { ALOGV("%s:PASSTHROUGH_CONVERT supported", __func__); convert = true; } break; default: ALOGE("%s: PASSTHROUGH_CONVERT not supported for format 0x%x", __func__, out->format); break; } ALOGE("%s: convert %d", __func__, convert); return convert; } bool audio_extn_dolby_is_passt_supported(struct audio_device *adev, struct stream_out *out) { bool passt = false; switch (out->format) { case AUDIO_FORMAT_E_AC3: if (platform_is_edid_supported_format(adev->platform, out->format)) { ALOGV("%s:PASSTHROUGH supported for format %x", __func__, out->format); passt = true; } break; case AUDIO_FORMAT_AC3: if (platform_is_edid_supported_format(adev->platform, AUDIO_FORMAT_AC3) || platform_is_edid_supported_format(adev->platform, AUDIO_FORMAT_E_AC3)) { ALOGV("%s:PASSTHROUGH supported for format %x", __func__, out->format); passt = true; } break; case AUDIO_FORMAT_E_AC3_JOC: /* Check for DDP capability in edid for JOC contents.*/ if (platform_is_edid_supported_format(adev->platform, AUDIO_FORMAT_E_AC3)) { ALOGV("%s:PASSTHROUGH supported for format %x", __func__, out->format); passt = true; } default: ALOGV("%s:Passthrough not supported", __func__); } return passt; } void audio_extn_dolby_update_passt_stream_configuration( struct audio_device *adev, struct stream_out *out) { if (audio_extn_dolby_is_passt_supported(adev, out)) { ALOGV("%s:PASSTHROUGH", __func__); out->compr_config.codec->compr_passthr = PASSTHROUGH; } else if (audio_extn_dolby_is_passt_convert_supported(adev, out)){ ALOGV("%s:PASSTHROUGH CONVERT", __func__); out->compr_config.codec->compr_passthr = PASSTHROUGH_CONVERT; } else { ALOGV("%s:NO PASSTHROUGH", __func__); out->compr_config.codec->compr_passthr = LEGACY_PCM; } } bool audio_extn_dolby_is_passthrough_stream(int flags) { if (flags & AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH) return true; return false; } int audio_extn_dolby_set_hdmi_config(struct audio_device *adev, struct stream_out *out) { return platform_set_hdmi_config(out); } int audio_extn_dolby_get_passt_buffer_size(audio_offload_info_t* info) { return platform_get_compress_passthrough_buffer_size(info); } int audio_extn_dolby_set_passt_volume(struct stream_out *out, int mute) { return platform_set_device_params(out, DEVICE_PARAM_MUTE_ID, mute); } int audio_extn_dolby_set_passt_latency(struct stream_out *out, int latency) { return platform_set_device_params(out, DEVICE_PARAM_LATENCY_ID, latency); } #endif /* HDMI_PASSTHROUGH_ENABLED */ #ifdef DS1_DOLBY_DAP_ENABLED void audio_extn_dolby_set_endpoint(struct audio_device *adev) { Loading hal/audio_extn/utils.c +11 −3 Original line number Diff line number Diff line Loading @@ -64,12 +64,14 @@ const struct string_to_enum s_flag_name_to_enum_table[] = { STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_DEEP_BUFFER), STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD), STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_NON_BLOCKING), STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_HW_AV_SYNC), #ifdef INCALL_MUSIC_ENABLED STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_INCALL_MUSIC), #endif #ifdef COMPRESS_VOIP_ENABLED STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_VOIP_RX), #endif STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH), }; const struct string_to_enum s_format_name_to_enum_table[] = { Loading Loading @@ -98,6 +100,7 @@ const struct string_to_enum s_format_name_to_enum_table[] = { STRING_TO_ENUM(AUDIO_FORMAT_PCM_16_BIT_OFFLOAD), STRING_TO_ENUM(AUDIO_FORMAT_PCM_24_BIT_OFFLOAD), STRING_TO_ENUM(AUDIO_FORMAT_FLAC), STRING_TO_ENUM(AUDIO_FORMAT_E_AC3_JOC), #endif }; Loading Loading @@ -404,6 +407,7 @@ static bool set_output_cfg(struct streams_output_cfg *so_info, ss_info = node_to_item(node_i, struct stream_sample_rate, list); if ((sample_rate <= ss_info->sample_rate) && (bit_width == so_info->app_type_cfg.bit_width)) { app_type_cfg->app_type = so_info->app_type_cfg.app_type; app_type_cfg->sample_rate = ss_info->sample_rate; app_type_cfg->bit_width = so_info->app_type_cfg.bit_width; Loading Loading @@ -509,7 +513,7 @@ int audio_extn_utils_send_app_type_cfg(struct audio_usecase *usecase) (usecase->id != USECASE_AUDIO_PLAYBACK_LOW_LATENCY) && (usecase->id != USECASE_AUDIO_PLAYBACK_MULTI_CH) && (!is_offload_usecase(usecase->id))) { ALOGV("%s: a playback path where app type cfg is not required", __func__); ALOGV("%s: a playback path where app type cfg is not required %d", __func__, usecase->id); rc = 0; goto exit_send_app_type_cfg; } Loading Loading @@ -548,8 +552,12 @@ int audio_extn_utils_send_app_type_cfg(struct audio_usecase *usecase) app_type_cfg[len++] = out->app_type_cfg.app_type; app_type_cfg[len++] = acdb_dev_id; if (((out->format == AUDIO_FORMAT_E_AC3) || (out->format == AUDIO_FORMAT_E_AC3_JOC)) && (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH)) app_type_cfg[len++] = sample_rate * 4; else app_type_cfg[len++] = sample_rate; mixer_ctl_set_array(ctl, app_type_cfg, len); ALOGI("%s app_type %d, acdb_dev_id %d, sample_rate %d", __func__, out->app_type_cfg.app_type, acdb_dev_id, sample_rate); Loading hal/audio_hw.c +107 −31 Original line number Diff line number Diff line Loading @@ -1277,8 +1277,9 @@ static bool allow_hdmi_channel_config(struct audio_device *adev) break; } else if (is_offload_usecase(usecase->id) && audio_channel_count_from_out_mask(usecase->stream.out->channel_mask) > 2) { ALOGD("%s: multi-channel(%x) compress offload playback is active, " "no change in HDMI channels", __func__, usecase->stream.out->channel_mask); ALOGD("%s:multi-channel(%x) compress offload playback is active" ", no change in HDMI channels", __func__, usecase->stream.out->channel_mask); ret = false; break; } Loading Loading @@ -1309,6 +1310,7 @@ static int check_and_set_hdmi_channels(struct audio_device *adev, return 0; } /*TODO: CHECK for passthrough don't set channel map for passthrough*/ platform_set_hdmi_channels(adev->platform, channels); platform_set_edid_channels_configuration(adev->platform, channels); adev->cur_hdmi_channels = channels; Loading Loading @@ -1356,7 +1358,8 @@ static int stop_output_stream(struct stream_out *out) return -EINVAL; } if (is_offload_usecase(out->usecase)) { if (is_offload_usecase(out->usecase) && !(audio_extn_dolby_is_passthrough_stream(out->flags))) { if (adev->visualizer_stop_output != NULL) adev->visualizer_stop_output(out->handle, out->pcm_device_id); if (adev->offload_effects_stop_output != NULL) Loading @@ -1372,6 +1375,15 @@ static int stop_output_stream(struct stream_out *out) list_remove(&uc_info->list); free(uc_info); if (is_offload_usecase(out->usecase) && (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) && (audio_extn_dolby_is_passthrough_stream(out->flags))) { ALOGV("Disable passthrough , reset mixer to pcm"); /* NO_PASSTHROUGH */ out->compr_config.codec->compr_passthr = 0; audio_extn_dolby_set_hdmi_config(adev, out); audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON); } /* Must be called after removing the usecase from list */ if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) check_and_set_hdmi_channels(adev, DEFAULT_HDMI_OUT_CHANNELS); Loading Loading @@ -1409,7 +1421,7 @@ int start_output_stream(struct stream_out *out) ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)", __func__, out->pcm_device_id, out->usecase); ret = -EINVAL; goto error_config; goto error_open; } uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase)); Loading @@ -1425,9 +1437,17 @@ int start_output_stream(struct stream_out *out) uc_info->devices = out->devices; uc_info->in_snd_device = SND_DEVICE_NONE; uc_info->out_snd_device = SND_DEVICE_NONE; /* This must be called before adding this usecase to the list */ if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) { if (is_offload_usecase(out->usecase)) { if (audio_extn_dolby_is_passthrough_stream(out->flags)) { ret = audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_BYPASS); if(ret != 0) { goto error_open; } audio_extn_dolby_update_passt_stream_configuration(adev, out); } } property_get("audio.use.hdmi.sink.cap", prop_value, NULL); if (!strncmp("true", prop_value, 4)) { sink_channels = platform_edid_get_max_channels(out->dev->platform); Loading @@ -1435,13 +1455,17 @@ int start_output_stream(struct stream_out *out) __func__, sink_channels); check_and_set_hdmi_channels(adev, sink_channels); } else { if (is_offload_usecase(out->usecase)) check_and_set_hdmi_channels(adev, out->compr_config.codec->ch_in); else if (is_offload_usecase(out->usecase)) { unsigned int ch_count = out->compr_config.codec->ch_in; if (audio_extn_dolby_is_passthrough_stream(out->flags)) /* backend channel config for passthrough stream is stereo */ ch_count = 2; check_and_set_hdmi_channels(adev, ch_count); } else check_and_set_hdmi_channels(adev, out->config.channels); } audio_extn_dolby_set_hdmi_config(adev, out); } list_add_tail(&adev->usecase_list, &uc_info->list); select_devices(adev, out->usecase); Loading Loading @@ -1498,12 +1522,13 @@ int start_output_stream(struct stream_out *out) if (audio_extn_is_dolby_format(out->format)) audio_extn_dolby_send_ddp_endp_params(adev); #endif if (!(audio_extn_dolby_is_passthrough_stream(out->flags))) { if (adev->visualizer_start_output != NULL) adev->visualizer_start_output(out->handle, out->pcm_device_id); if (adev->offload_effects_start_output != NULL) adev->offload_effects_start_output(out->handle, out->pcm_device_id); } } ALOGV("%s: exit", __func__); return 0; error_open: Loading Loading @@ -1891,6 +1916,28 @@ static char* out_get_parameters(const struct audio_stream *stream, const char *k str = strdup(keys); } } ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value)); if (ret >= 0) { value[0] = '\0'; i = 0; first = true; while (out->supported_formats[i] != 0) { for (j = 0; j < ARRAY_SIZE(out_formats_name_to_enum_table); j++) { if (out_formats_name_to_enum_table[j].value == out->supported_formats[i]) { if (!first) { strcat(value, "|"); } strlcat(value, out_formats_name_to_enum_table[j].name, sizeof(value)); first = false; break; } } i++; } str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value); str = str_parms_to_str(reply); } str_parms_destroy(query); str_parms_destroy(reply); ALOGV("%s: exit: returns - %s", __func__, str); Loading Loading @@ -1919,6 +1966,14 @@ static int out_set_volume(struct audio_stream_out *stream, float left, out->muted = (left == 0.0f); return 0; } else if (is_offload_usecase(out->usecase)) { if (audio_extn_dolby_is_passthrough_stream(out->flags)) { /* * Set mute or umute on HDMI passthrough stream. * Only take left channel into account. * Mute is 0 and unmute 1 */ audio_extn_dolby_set_passt_volume(out, (left == 0.0f)); } else { char mixer_ctl_name[128]; struct audio_device *adev = out->dev; struct mixer_ctl *ctl; Loading @@ -1938,6 +1993,7 @@ static int out_set_volume(struct audio_stream_out *stream, float left, mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0])); return 0; } } return -ENOSYS; } Loading Loading @@ -2633,6 +2689,18 @@ static int adev_open_output_stream(struct audio_hw_device *dev, ret = -EINVAL; goto error_open; } if ((out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) && ((audio_extn_dolby_is_passthrough_stream(out->flags)))) { ALOGV("read and update_pass through formats"); ret = audio_extn_dolby_update_passt_formats(adev, out); if(ret != 0) { goto error_open; } if(config->offload_info.format == 0) config->offload_info.format = out->supported_formats[0]; } if (!is_supported_format(config->offload_info.format) && !audio_extn_is_dolby_format(config->offload_info.format)) { ALOGE("%s: Unsupported audio format", __func__); Loading Loading @@ -2675,6 +2743,9 @@ static int adev_open_output_stream(struct audio_hw_device *dev, if (audio_is_offload_pcm(config->offload_info.format)) { out->compr_config.fragment_size = platform_get_pcm_offload_buffer_size(&config->offload_info); } else if (audio_extn_dolby_is_passthrough_stream(out->flags)) { out->compr_config.fragment_size = audio_extn_dolby_get_passt_buffer_size(&config->offload_info); } else { out->compr_config.fragment_size = platform_get_compress_offload_buffer_size(&config->offload_info); Loading @@ -2688,6 +2759,8 @@ static int adev_open_output_stream(struct audio_hw_device *dev, audio_channel_count_from_out_mask(config->channel_mask); out->compr_config.codec->ch_out = out->compr_config.codec->ch_in; out->bit_width = PCM_OUTPUT_BIT_WIDTH; /*TODO: Do we need to change it for passthrough */ out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW; if (config->offload_info.format == AUDIO_FORMAT_AAC) out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW; Loading Loading @@ -2761,6 +2834,9 @@ static int adev_open_output_stream(struct audio_hw_device *dev, ALOGV("%s devices %d,flags %x, format %x, out->sample_rate %d, out->bit_width %d", __func__, devices, flags, format, out->sample_rate, out->bit_width); /* TODO remove this hardcoding and check why width is zero*/ if (out->bit_width == 0) out->bit_width = 16; audio_extn_utils_update_stream_app_type_cfg(adev->platform, &adev->streams_output_cfg_list, devices, flags, format, out->sample_rate, Loading Loading
hal/Android.mk +4 −0 Original line number Diff line number Diff line Loading @@ -167,6 +167,10 @@ ifneq ($(strip $(DOLBY_DDP)),true) endif endif ifeq ($(strip $(AUDIO_FEATURE_ENABLED_HDMI_PASSTHROUGH)),true) LOCAL_CFLAGS += -DHDMI_PASSTHROUGH_ENABLED endif LOCAL_SHARED_LIBRARIES := \ liblog \ libcutils \ Loading
hal/audio_extn/audio_extn.h +28 −1 Original line number Diff line number Diff line Loading @@ -270,7 +270,6 @@ void audio_extn_dolby_set_license(struct audio_device *adev); void audio_extn_dolby_set_endpoint(struct audio_device *adev); #endif #if defined(DS1_DOLBY_DDP_ENABLED) || defined(DS2_DOLBY_DAP_ENABLED) bool audio_extn_is_dolby_format(audio_format_t format); int audio_extn_dolby_get_snd_codec_id(struct audio_device *adev, Loading @@ -288,6 +287,34 @@ int audio_extn_dolby_get_snd_codec_id(struct audio_device *adev, void audio_extn_ddp_set_parameters(struct audio_device *adev, struct str_parms *parms); void audio_extn_dolby_send_ddp_endp_params(struct audio_device *adev); #endif #ifndef HDMI_PASSTHROUGH_ENABLED #define audio_extn_dolby_update_passt_formats(adev, out) (0) #define audio_extn_dolby_update_passt_stream_configuration(adev, out) (0) #define audio_extn_dolby_is_passt_convert_supported(adev, out) (0) #define audio_extn_dolby_is_passt_supported(adev, out) (0) #define audio_extn_dolby_is_passthrough_stream(flags) (0) #define audio_extn_dolby_set_hdmi_config(adev, out) (0) #define audio_extn_dolby_get_passt_buffer_size(info) (0) #define audio_extn_dolby_set_passt_volume(out, mute) (0) #define audio_extn_dolby_set_passt_latency(out, latency) (0) #else int audio_extn_dolby_update_passt_formats(struct audio_device *adev, struct stream_out *out); bool audio_extn_dolby_is_passt_convert_supported(struct audio_device *adev, struct stream_out *out); bool audio_extn_dolby_is_passt_supported(struct audio_device *adev, struct stream_out *out); void audio_extn_dolby_update_passt_stream_configuration(struct audio_device *adev, struct stream_out *out); bool audio_extn_dolby_is_passthrough_stream(int flags); int audio_extn_dolby_set_hdmi_config(struct audio_device *adev, struct stream_out *out); int audio_extn_dolby_get_passt_buffer_size(audio_offload_info_t* info); int audio_extn_dolby_set_passt_volume(struct stream_out *out, int mute); int audio_extn_dolby_set_passt_latency(struct stream_out *out, int latency); #endif #ifndef HFP_ENABLED Loading
hal/audio_extn/dolby.c +112 −0 Original line number Diff line number Diff line Loading @@ -408,6 +408,118 @@ bool audio_extn_is_dolby_format(audio_format_t format) } #endif /* DS1_DOLBY_DDP_ENABLED || DS2_DOLBY_DAP_ENABLED */ #ifdef HDMI_PASSTHROUGH_ENABLED int audio_extn_dolby_update_passt_formats(struct audio_device *adev, struct stream_out *out) { int32_t i = 0, ret = -ENOSYS; if (platform_is_edid_supported_format(adev->platform, AUDIO_FORMAT_AC3) || platform_is_edid_supported_format(adev->platform, AUDIO_FORMAT_E_AC3)) { out->supported_formats[i++] = AUDIO_FORMAT_AC3; out->supported_formats[i++] = AUDIO_FORMAT_E_AC3; /* Reciever must support JOC and advertise, otherwise JOC is treated as DDP */ out->supported_formats[i++] = AUDIO_FORMAT_E_AC3_JOC; ret = 0; } ALOGV("%s: ret = %d", __func__, ret); return ret; } bool audio_extn_dolby_is_passt_convert_supported(struct audio_device *adev, struct stream_out *out) { bool convert = false; switch (out->format) { case AUDIO_FORMAT_E_AC3: case AUDIO_FORMAT_E_AC3_JOC: if (!platform_is_edid_supported_format(adev->platform, AUDIO_FORMAT_E_AC3)) { ALOGV("%s:PASSTHROUGH_CONVERT supported", __func__); convert = true; } break; default: ALOGE("%s: PASSTHROUGH_CONVERT not supported for format 0x%x", __func__, out->format); break; } ALOGE("%s: convert %d", __func__, convert); return convert; } bool audio_extn_dolby_is_passt_supported(struct audio_device *adev, struct stream_out *out) { bool passt = false; switch (out->format) { case AUDIO_FORMAT_E_AC3: if (platform_is_edid_supported_format(adev->platform, out->format)) { ALOGV("%s:PASSTHROUGH supported for format %x", __func__, out->format); passt = true; } break; case AUDIO_FORMAT_AC3: if (platform_is_edid_supported_format(adev->platform, AUDIO_FORMAT_AC3) || platform_is_edid_supported_format(adev->platform, AUDIO_FORMAT_E_AC3)) { ALOGV("%s:PASSTHROUGH supported for format %x", __func__, out->format); passt = true; } break; case AUDIO_FORMAT_E_AC3_JOC: /* Check for DDP capability in edid for JOC contents.*/ if (platform_is_edid_supported_format(adev->platform, AUDIO_FORMAT_E_AC3)) { ALOGV("%s:PASSTHROUGH supported for format %x", __func__, out->format); passt = true; } default: ALOGV("%s:Passthrough not supported", __func__); } return passt; } void audio_extn_dolby_update_passt_stream_configuration( struct audio_device *adev, struct stream_out *out) { if (audio_extn_dolby_is_passt_supported(adev, out)) { ALOGV("%s:PASSTHROUGH", __func__); out->compr_config.codec->compr_passthr = PASSTHROUGH; } else if (audio_extn_dolby_is_passt_convert_supported(adev, out)){ ALOGV("%s:PASSTHROUGH CONVERT", __func__); out->compr_config.codec->compr_passthr = PASSTHROUGH_CONVERT; } else { ALOGV("%s:NO PASSTHROUGH", __func__); out->compr_config.codec->compr_passthr = LEGACY_PCM; } } bool audio_extn_dolby_is_passthrough_stream(int flags) { if (flags & AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH) return true; return false; } int audio_extn_dolby_set_hdmi_config(struct audio_device *adev, struct stream_out *out) { return platform_set_hdmi_config(out); } int audio_extn_dolby_get_passt_buffer_size(audio_offload_info_t* info) { return platform_get_compress_passthrough_buffer_size(info); } int audio_extn_dolby_set_passt_volume(struct stream_out *out, int mute) { return platform_set_device_params(out, DEVICE_PARAM_MUTE_ID, mute); } int audio_extn_dolby_set_passt_latency(struct stream_out *out, int latency) { return platform_set_device_params(out, DEVICE_PARAM_LATENCY_ID, latency); } #endif /* HDMI_PASSTHROUGH_ENABLED */ #ifdef DS1_DOLBY_DAP_ENABLED void audio_extn_dolby_set_endpoint(struct audio_device *adev) { Loading
hal/audio_extn/utils.c +11 −3 Original line number Diff line number Diff line Loading @@ -64,12 +64,14 @@ const struct string_to_enum s_flag_name_to_enum_table[] = { STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_DEEP_BUFFER), STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD), STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_NON_BLOCKING), STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_HW_AV_SYNC), #ifdef INCALL_MUSIC_ENABLED STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_INCALL_MUSIC), #endif #ifdef COMPRESS_VOIP_ENABLED STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_VOIP_RX), #endif STRING_TO_ENUM(AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH), }; const struct string_to_enum s_format_name_to_enum_table[] = { Loading Loading @@ -98,6 +100,7 @@ const struct string_to_enum s_format_name_to_enum_table[] = { STRING_TO_ENUM(AUDIO_FORMAT_PCM_16_BIT_OFFLOAD), STRING_TO_ENUM(AUDIO_FORMAT_PCM_24_BIT_OFFLOAD), STRING_TO_ENUM(AUDIO_FORMAT_FLAC), STRING_TO_ENUM(AUDIO_FORMAT_E_AC3_JOC), #endif }; Loading Loading @@ -404,6 +407,7 @@ static bool set_output_cfg(struct streams_output_cfg *so_info, ss_info = node_to_item(node_i, struct stream_sample_rate, list); if ((sample_rate <= ss_info->sample_rate) && (bit_width == so_info->app_type_cfg.bit_width)) { app_type_cfg->app_type = so_info->app_type_cfg.app_type; app_type_cfg->sample_rate = ss_info->sample_rate; app_type_cfg->bit_width = so_info->app_type_cfg.bit_width; Loading Loading @@ -509,7 +513,7 @@ int audio_extn_utils_send_app_type_cfg(struct audio_usecase *usecase) (usecase->id != USECASE_AUDIO_PLAYBACK_LOW_LATENCY) && (usecase->id != USECASE_AUDIO_PLAYBACK_MULTI_CH) && (!is_offload_usecase(usecase->id))) { ALOGV("%s: a playback path where app type cfg is not required", __func__); ALOGV("%s: a playback path where app type cfg is not required %d", __func__, usecase->id); rc = 0; goto exit_send_app_type_cfg; } Loading Loading @@ -548,8 +552,12 @@ int audio_extn_utils_send_app_type_cfg(struct audio_usecase *usecase) app_type_cfg[len++] = out->app_type_cfg.app_type; app_type_cfg[len++] = acdb_dev_id; if (((out->format == AUDIO_FORMAT_E_AC3) || (out->format == AUDIO_FORMAT_E_AC3_JOC)) && (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH)) app_type_cfg[len++] = sample_rate * 4; else app_type_cfg[len++] = sample_rate; mixer_ctl_set_array(ctl, app_type_cfg, len); ALOGI("%s app_type %d, acdb_dev_id %d, sample_rate %d", __func__, out->app_type_cfg.app_type, acdb_dev_id, sample_rate); Loading
hal/audio_hw.c +107 −31 Original line number Diff line number Diff line Loading @@ -1277,8 +1277,9 @@ static bool allow_hdmi_channel_config(struct audio_device *adev) break; } else if (is_offload_usecase(usecase->id) && audio_channel_count_from_out_mask(usecase->stream.out->channel_mask) > 2) { ALOGD("%s: multi-channel(%x) compress offload playback is active, " "no change in HDMI channels", __func__, usecase->stream.out->channel_mask); ALOGD("%s:multi-channel(%x) compress offload playback is active" ", no change in HDMI channels", __func__, usecase->stream.out->channel_mask); ret = false; break; } Loading Loading @@ -1309,6 +1310,7 @@ static int check_and_set_hdmi_channels(struct audio_device *adev, return 0; } /*TODO: CHECK for passthrough don't set channel map for passthrough*/ platform_set_hdmi_channels(adev->platform, channels); platform_set_edid_channels_configuration(adev->platform, channels); adev->cur_hdmi_channels = channels; Loading Loading @@ -1356,7 +1358,8 @@ static int stop_output_stream(struct stream_out *out) return -EINVAL; } if (is_offload_usecase(out->usecase)) { if (is_offload_usecase(out->usecase) && !(audio_extn_dolby_is_passthrough_stream(out->flags))) { if (adev->visualizer_stop_output != NULL) adev->visualizer_stop_output(out->handle, out->pcm_device_id); if (adev->offload_effects_stop_output != NULL) Loading @@ -1372,6 +1375,15 @@ static int stop_output_stream(struct stream_out *out) list_remove(&uc_info->list); free(uc_info); if (is_offload_usecase(out->usecase) && (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) && (audio_extn_dolby_is_passthrough_stream(out->flags))) { ALOGV("Disable passthrough , reset mixer to pcm"); /* NO_PASSTHROUGH */ out->compr_config.codec->compr_passthr = 0; audio_extn_dolby_set_hdmi_config(adev, out); audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON); } /* Must be called after removing the usecase from list */ if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) check_and_set_hdmi_channels(adev, DEFAULT_HDMI_OUT_CHANNELS); Loading Loading @@ -1409,7 +1421,7 @@ int start_output_stream(struct stream_out *out) ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)", __func__, out->pcm_device_id, out->usecase); ret = -EINVAL; goto error_config; goto error_open; } uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase)); Loading @@ -1425,9 +1437,17 @@ int start_output_stream(struct stream_out *out) uc_info->devices = out->devices; uc_info->in_snd_device = SND_DEVICE_NONE; uc_info->out_snd_device = SND_DEVICE_NONE; /* This must be called before adding this usecase to the list */ if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) { if (is_offload_usecase(out->usecase)) { if (audio_extn_dolby_is_passthrough_stream(out->flags)) { ret = audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_BYPASS); if(ret != 0) { goto error_open; } audio_extn_dolby_update_passt_stream_configuration(adev, out); } } property_get("audio.use.hdmi.sink.cap", prop_value, NULL); if (!strncmp("true", prop_value, 4)) { sink_channels = platform_edid_get_max_channels(out->dev->platform); Loading @@ -1435,13 +1455,17 @@ int start_output_stream(struct stream_out *out) __func__, sink_channels); check_and_set_hdmi_channels(adev, sink_channels); } else { if (is_offload_usecase(out->usecase)) check_and_set_hdmi_channels(adev, out->compr_config.codec->ch_in); else if (is_offload_usecase(out->usecase)) { unsigned int ch_count = out->compr_config.codec->ch_in; if (audio_extn_dolby_is_passthrough_stream(out->flags)) /* backend channel config for passthrough stream is stereo */ ch_count = 2; check_and_set_hdmi_channels(adev, ch_count); } else check_and_set_hdmi_channels(adev, out->config.channels); } audio_extn_dolby_set_hdmi_config(adev, out); } list_add_tail(&adev->usecase_list, &uc_info->list); select_devices(adev, out->usecase); Loading Loading @@ -1498,12 +1522,13 @@ int start_output_stream(struct stream_out *out) if (audio_extn_is_dolby_format(out->format)) audio_extn_dolby_send_ddp_endp_params(adev); #endif if (!(audio_extn_dolby_is_passthrough_stream(out->flags))) { if (adev->visualizer_start_output != NULL) adev->visualizer_start_output(out->handle, out->pcm_device_id); if (adev->offload_effects_start_output != NULL) adev->offload_effects_start_output(out->handle, out->pcm_device_id); } } ALOGV("%s: exit", __func__); return 0; error_open: Loading Loading @@ -1891,6 +1916,28 @@ static char* out_get_parameters(const struct audio_stream *stream, const char *k str = strdup(keys); } } ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value)); if (ret >= 0) { value[0] = '\0'; i = 0; first = true; while (out->supported_formats[i] != 0) { for (j = 0; j < ARRAY_SIZE(out_formats_name_to_enum_table); j++) { if (out_formats_name_to_enum_table[j].value == out->supported_formats[i]) { if (!first) { strcat(value, "|"); } strlcat(value, out_formats_name_to_enum_table[j].name, sizeof(value)); first = false; break; } } i++; } str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value); str = str_parms_to_str(reply); } str_parms_destroy(query); str_parms_destroy(reply); ALOGV("%s: exit: returns - %s", __func__, str); Loading Loading @@ -1919,6 +1966,14 @@ static int out_set_volume(struct audio_stream_out *stream, float left, out->muted = (left == 0.0f); return 0; } else if (is_offload_usecase(out->usecase)) { if (audio_extn_dolby_is_passthrough_stream(out->flags)) { /* * Set mute or umute on HDMI passthrough stream. * Only take left channel into account. * Mute is 0 and unmute 1 */ audio_extn_dolby_set_passt_volume(out, (left == 0.0f)); } else { char mixer_ctl_name[128]; struct audio_device *adev = out->dev; struct mixer_ctl *ctl; Loading @@ -1938,6 +1993,7 @@ static int out_set_volume(struct audio_stream_out *stream, float left, mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0])); return 0; } } return -ENOSYS; } Loading Loading @@ -2633,6 +2689,18 @@ static int adev_open_output_stream(struct audio_hw_device *dev, ret = -EINVAL; goto error_open; } if ((out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) && ((audio_extn_dolby_is_passthrough_stream(out->flags)))) { ALOGV("read and update_pass through formats"); ret = audio_extn_dolby_update_passt_formats(adev, out); if(ret != 0) { goto error_open; } if(config->offload_info.format == 0) config->offload_info.format = out->supported_formats[0]; } if (!is_supported_format(config->offload_info.format) && !audio_extn_is_dolby_format(config->offload_info.format)) { ALOGE("%s: Unsupported audio format", __func__); Loading Loading @@ -2675,6 +2743,9 @@ static int adev_open_output_stream(struct audio_hw_device *dev, if (audio_is_offload_pcm(config->offload_info.format)) { out->compr_config.fragment_size = platform_get_pcm_offload_buffer_size(&config->offload_info); } else if (audio_extn_dolby_is_passthrough_stream(out->flags)) { out->compr_config.fragment_size = audio_extn_dolby_get_passt_buffer_size(&config->offload_info); } else { out->compr_config.fragment_size = platform_get_compress_offload_buffer_size(&config->offload_info); Loading @@ -2688,6 +2759,8 @@ static int adev_open_output_stream(struct audio_hw_device *dev, audio_channel_count_from_out_mask(config->channel_mask); out->compr_config.codec->ch_out = out->compr_config.codec->ch_in; out->bit_width = PCM_OUTPUT_BIT_WIDTH; /*TODO: Do we need to change it for passthrough */ out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW; if (config->offload_info.format == AUDIO_FORMAT_AAC) out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW; Loading Loading @@ -2761,6 +2834,9 @@ static int adev_open_output_stream(struct audio_hw_device *dev, ALOGV("%s devices %d,flags %x, format %x, out->sample_rate %d, out->bit_width %d", __func__, devices, flags, format, out->sample_rate, out->bit_width); /* TODO remove this hardcoding and check why width is zero*/ if (out->bit_width == 0) out->bit_width = 16; audio_extn_utils_update_stream_app_type_cfg(adev->platform, &adev->streams_output_cfg_list, devices, flags, format, out->sample_rate, Loading