Loading hal/Android.mk +3 −0 Original line number Diff line number Diff line Loading @@ -126,6 +126,9 @@ ifeq ($(strip $(AUDIO_FEATURE_DISABLED_DS1_DOLBY_DDP)),true) endif endif ifeq ($(strip $(AUDIO_FEATURE_ENABLED_MULTIPLE_TUNNEL)), true) LOCAL_CFLAGS += -DMULTIPLE_OFFLOAD_ENABLED endif LOCAL_SHARED_LIBRARIES := \ liblog \ Loading hal/audio_extn/audio_extn.c +27 −0 Original line number Diff line number Diff line Loading @@ -52,6 +52,8 @@ static struct audio_extn_module aextnmod = { #define AUDIO_PARAMETER_KEY_WFD "wfd_channel_cap" #define AUDIO_PARAMETER_CAN_OPEN_PROXY "can_open_proxy" #define AUDIO_PARAMETER_CUSTOM_STEREO "stereo_as_dual_mono" /* Query offload playback instances count */ #define AUDIO_PARAMETER_OFFLOAD_NUM_ACTIVE "offload_num_active" #ifndef FM_ENABLED #define audio_extn_fm_set_parameters(adev, parms) (0) Loading Loading @@ -424,6 +426,30 @@ int32_t audio_extn_get_afe_proxy_channel_count() #endif /* AFE_PROXY_ENABLED */ static int get_active_offload_usecases(const struct audio_device *adev, struct str_parms *query, struct str_parms *reply) { int ret, count = 0; char value[32]={0}; struct listnode *node; struct audio_usecase *usecase; ALOGV("%s", __func__); ret = str_parms_get_str(query, AUDIO_PARAMETER_OFFLOAD_NUM_ACTIVE, value, sizeof(value)); if (ret >= 0) { list_for_each(node, &adev->usecase_list) { usecase = node_to_item(node, struct audio_usecase, list); if (is_offload_usecase(usecase->id)) count++; } ALOGV("%s, number of active offload usecases: %d", __func__, count); str_parms_add_int(reply, AUDIO_PARAMETER_OFFLOAD_NUM_ACTIVE, count); } return ret; } void audio_extn_set_parameters(struct audio_device *adev, struct str_parms *parms) { Loading @@ -444,6 +470,7 @@ void audio_extn_get_parameters(const struct audio_device *adev, char *kv_pairs = NULL; audio_extn_get_afe_proxy_parameters(query, reply); audio_extn_get_fluence_parameters(adev, query, reply); get_active_offload_usecases(adev, query, reply); kv_pairs = str_parms_to_str(reply); ALOGD_IF(kv_pairs != NULL, "%s: returns %s", __func__, kv_pairs); Loading hal/audio_hw.c +88 −20 Original line number Diff line number Diff line Loading @@ -107,6 +107,16 @@ const char * const use_case_table[AUDIO_USECASE_MAX] = { [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = "low-latency-playback", [USECASE_AUDIO_PLAYBACK_MULTI_CH] = "multi-channel-playback", [USECASE_AUDIO_PLAYBACK_OFFLOAD] = "compress-offload-playback", #ifdef MULTIPLE_OFFLOAD_ENABLED [USECASE_AUDIO_PLAYBACK_OFFLOAD2] = "compress-offload-playback2", [USECASE_AUDIO_PLAYBACK_OFFLOAD3] = "compress-offload-playback3", [USECASE_AUDIO_PLAYBACK_OFFLOAD4] = "compress-offload-playback4", [USECASE_AUDIO_PLAYBACK_OFFLOAD5] = "compress-offload-playback5", [USECASE_AUDIO_PLAYBACK_OFFLOAD6] = "compress-offload-playback6", [USECASE_AUDIO_PLAYBACK_OFFLOAD7] = "compress-offload-playback7", [USECASE_AUDIO_PLAYBACK_OFFLOAD8] = "compress-offload-playback8", [USECASE_AUDIO_PLAYBACK_OFFLOAD9] = "compress-offload-playback9", #endif [USECASE_AUDIO_RECORD] = "audio-record", [USECASE_AUDIO_RECORD_COMPRESS] = "audio-record-compress", [USECASE_AUDIO_RECORD_LOW_LATENCY] = "low-latency-record", Loading Loading @@ -134,6 +144,19 @@ const char * const use_case_table[AUDIO_USECASE_MAX] = { [USECASE_AUDIO_SPKR_CALIB_TX] = "spkr-vi-record", }; static const audio_usecase_t offload_usecases[] = { USECASE_AUDIO_PLAYBACK_OFFLOAD, #ifdef MULTIPLE_OFFLOAD_ENABLED USECASE_AUDIO_PLAYBACK_OFFLOAD2, USECASE_AUDIO_PLAYBACK_OFFLOAD3, USECASE_AUDIO_PLAYBACK_OFFLOAD4, USECASE_AUDIO_PLAYBACK_OFFLOAD5, USECASE_AUDIO_PLAYBACK_OFFLOAD6, USECASE_AUDIO_PLAYBACK_OFFLOAD7, USECASE_AUDIO_PLAYBACK_OFFLOAD8, USECASE_AUDIO_PLAYBACK_OFFLOAD9, #endif }; #define STRING_TO_ENUM(string) { #string, string } Loading Loading @@ -877,6 +900,51 @@ static void stop_compressed_output_l(struct stream_out *out) } } bool is_offload_usecase(audio_usecase_t uc_id) { unsigned int i; for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) { if (uc_id == offload_usecases[i]) return true; } return false; } static audio_usecase_t get_offload_usecase(struct audio_device *adev) { audio_usecase_t ret = USECASE_AUDIO_PLAYBACK_OFFLOAD; unsigned int i, num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]); char value[PROPERTY_VALUE_MAX] = {0}; property_get("audio.offload.multiple.enabled", value, NULL); if (!(atoi(value) || !strncmp("true", value, 4))) num_usecase = 1; /* If prop is not set, limit the num of offload usecases to 1 */ ALOGV("%s: num_usecase: %d", __func__, num_usecase); for (i = 0; i < num_usecase; i++) { if (!(adev->offload_usecases_state & (0x1<<i))) { adev->offload_usecases_state |= 0x1 << i; ret = offload_usecases[i]; break; } } ALOGV("%s: offload usecase is %d", __func__, ret); return ret; } static void free_offload_usecase(struct audio_device *adev, audio_usecase_t uc_id) { unsigned int i; for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) { if (offload_usecases[i] == uc_id) { adev->offload_usecases_state &= ~(0x1<<i); break; } } ALOGV("%s: free offload usecase %d", __func__, uc_id); } static void *offload_thread_loop(void *context) { struct stream_out *out = (struct stream_out *) context; Loading Loading @@ -1024,7 +1092,7 @@ static bool allow_hdmi_channel_config(struct audio_device *adev) "no change in HDMI channels", __func__); ret = false; break; } else if (usecase->id == USECASE_AUDIO_PLAYBACK_OFFLOAD && } else if (is_offload_usecase(usecase->id) && popcount(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); Loading Loading @@ -1097,7 +1165,7 @@ static int stop_output_stream(struct stream_out *out) return -EINVAL; } if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) { if (is_offload_usecase(out->usecase)) { if (adev->visualizer_stop_output != NULL) adev->visualizer_stop_output(out->handle, out->pcm_device_id); if (adev->offload_effects_stop_output != NULL) Loading Loading @@ -1147,7 +1215,7 @@ int start_output_stream(struct stream_out *out) /* This must be called before adding this usecase to the list */ if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) { if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) if (is_offload_usecase(out->usecase)) check_and_set_hdmi_channels(adev, out->compr_config.codec->ch_in); else check_and_set_hdmi_channels(adev, out->config.channels); Loading @@ -1159,7 +1227,7 @@ int start_output_stream(struct stream_out *out) ALOGV("%s: Opening PCM device card_id(%d) device_id(%d)", __func__, 0, out->pcm_device_id); if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) { if (!is_offload_usecase(out->usecase)) { out->pcm = pcm_open(adev->snd_card, out->pcm_device_id, PCM_OUT | PCM_MONOTONIC, &out->config); Loading Loading @@ -1277,7 +1345,7 @@ static size_t out_get_buffer_size(const struct audio_stream *stream) { struct stream_out *out = (struct stream_out *)stream; if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) if (is_offload_usecase(out->usecase)) return out->compr_config.fragment_size; else if(out->usecase == USECASE_COMPRESS_VOIP_CALL) return voice_extn_compress_voip_out_get_buffer_size(out); Loading Loading @@ -1323,7 +1391,7 @@ static int out_standby(struct audio_stream *stream) if (!out->standby) { pthread_mutex_lock(&adev->lock); out->standby = true; if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) { if (!is_offload_usecase(out->usecase)) { if (out->pcm) { pcm_close(out->pcm); out->pcm = NULL; Loading Loading @@ -1490,7 +1558,7 @@ static int out_set_parameters(struct audio_stream *stream, const char *kvpairs) audio_extn_set_parameters(adev, parms); pthread_mutex_unlock(&adev->lock); } if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) { if (is_offload_usecase(out->usecase)) { pthread_mutex_lock(&out->lock); parse_compress_metadata(out, parms); pthread_mutex_unlock(&out->lock); Loading Loading @@ -1549,7 +1617,7 @@ static uint32_t out_get_latency(const struct audio_stream_out *stream) { struct stream_out *out = (struct stream_out *)stream; if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) if (is_offload_usecase(out->usecase)) return COMPRESS_OFFLOAD_PLAYBACK_LATENCY; return (out->config.period_count * out->config.period_size * 1000) / Loading @@ -1566,7 +1634,7 @@ static int out_set_volume(struct audio_stream_out *stream, float left, /* only take left channel into account: the API is for stereo anyway */ out->muted = (left == 0.0f); return 0; } else if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) { } else if (is_offload_usecase(out->usecase)) { char mixer_ctl_name[128]; struct audio_device *adev = out->dev; struct mixer_ctl *ctl; Loading Loading @@ -1613,7 +1681,7 @@ static ssize_t out_write(struct audio_stream_out *stream, const void *buffer, } } if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) { if (is_offload_usecase(out->usecase)) { ALOGD("copl(%x): writing buffer (%d bytes) to compress device", (unsigned int)out, bytes); if (out->send_new_metadata) { ALOGD("copl(%x):send new gapless metadata", (unsigned int)out); Loading Loading @@ -1663,7 +1731,7 @@ static int out_get_render_position(const struct audio_stream_out *stream, { struct stream_out *out = (struct stream_out *)stream; *dsp_frames = 0; if ((out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) && (dsp_frames != NULL)) { if (is_offload_usecase(out->usecase) && (dsp_frames != NULL)) { pthread_mutex_lock(&out->lock); if (out->compr != NULL) { compress_get_tstamp(out->compr, (unsigned long *)dsp_frames, Loading Loading @@ -1702,7 +1770,7 @@ static int out_get_presentation_position(const struct audio_stream_out *stream, pthread_mutex_lock(&out->lock); if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) { if (is_offload_usecase(out->usecase)) { if (out->compr != NULL) { compress_get_tstamp(out->compr, &dsp_frames, &out->sample_rate); Loading Loading @@ -1756,7 +1824,7 @@ static int out_pause(struct audio_stream_out* stream) struct stream_out *out = (struct stream_out *)stream; int status = -ENOSYS; ALOGV("%s", __func__); if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) { if (is_offload_usecase(out->usecase)) { ALOGD("copl(%x):pause compress driver", (unsigned int)out); pthread_mutex_lock(&out->lock); if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) { Loading @@ -1773,7 +1841,7 @@ static int out_resume(struct audio_stream_out* stream) struct stream_out *out = (struct stream_out *)stream; int status = -ENOSYS; ALOGV("%s", __func__); if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) { if (is_offload_usecase(out->usecase)) { ALOGD("copl(%x):resume compress driver", (unsigned int)out); status = 0; pthread_mutex_lock(&out->lock); Loading @@ -1791,7 +1859,7 @@ static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type ) struct stream_out *out = (struct stream_out *)stream; int status = -ENOSYS; ALOGV("%s", __func__); if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) { if (is_offload_usecase(out->usecase)) { pthread_mutex_lock(&out->lock); if (type == AUDIO_DRAIN_EARLY_NOTIFY) status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN); Loading @@ -1806,7 +1874,7 @@ static int out_flush(struct audio_stream_out* stream) { struct stream_out *out = (struct stream_out *)stream; ALOGV("%s", __func__); if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) { if (is_offload_usecase(out->usecase)) { ALOGD("copl(%x):calling compress flush", (unsigned int)out); pthread_mutex_lock(&out->lock); stop_compressed_output_l(out); Loading Loading @@ -2169,7 +2237,7 @@ static int adev_open_output_stream(struct audio_hw_device *dev, out->compr_config.codec = (struct snd_codec *) calloc(1, sizeof(struct snd_codec)); out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD; out->usecase = get_offload_usecase(adev); if (config->offload_info.channel_mask) out->channel_mask = config->offload_info.channel_mask; else if (config->channel_mask) { Loading Loading @@ -2324,9 +2392,9 @@ static void adev_close_output_stream(struct audio_hw_device *dev, else out_standby(&stream->common); if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) { if (is_offload_usecase(out->usecase)) { destroy_offload_callback_thread(out); free_offload_usecase(adev, out->usecase); if (out->compr_config.codec != NULL) free(out->compr_config.codec); } Loading Loading @@ -2702,7 +2770,7 @@ static int adev_open(const hw_module_t *module, const char *name, voice_init(adev); list_init(&adev->usecase_list); adev->cur_wfd_channels = 2; adev->offload_usecases_state = 0; /* Loads platform specific libraries dynamically */ adev->platform = platform_init(adev); if (!adev->platform) { Loading hal/audio_hw.h +14 −2 Original line number Diff line number Diff line Loading @@ -65,6 +65,16 @@ typedef enum { USECASE_AUDIO_PLAYBACK_LOW_LATENCY, USECASE_AUDIO_PLAYBACK_MULTI_CH, USECASE_AUDIO_PLAYBACK_OFFLOAD, #ifdef MULTIPLE_OFFLOAD_ENABLED USECASE_AUDIO_PLAYBACK_OFFLOAD2, USECASE_AUDIO_PLAYBACK_OFFLOAD3, USECASE_AUDIO_PLAYBACK_OFFLOAD4, USECASE_AUDIO_PLAYBACK_OFFLOAD5, USECASE_AUDIO_PLAYBACK_OFFLOAD6, USECASE_AUDIO_PLAYBACK_OFFLOAD7, USECASE_AUDIO_PLAYBACK_OFFLOAD8, USECASE_AUDIO_PLAYBACK_OFFLOAD9, #endif /* FM usecase */ USECASE_AUDIO_PLAYBACK_FM, Loading Loading @@ -234,7 +244,7 @@ struct audio_device { int snd_card; void *platform; unsigned int offload_usecases_state; void *visualizer_lib; int (*visualizer_start_output)(audio_io_handle_t, int); int (*visualizer_stop_output)(audio_io_handle_t, int); Loading @@ -260,6 +270,8 @@ int enable_audio_route(struct audio_device *adev, struct audio_usecase *get_usecase_from_list(struct audio_device *adev, audio_usecase_t uc_id); bool is_offload_usecase(audio_usecase_t uc_id); #define LITERAL_TO_STRING(x) #x #define CHECK(condition) LOG_ALWAYS_FATAL_IF(!(condition), "%s",\ __FILE__ ":" LITERAL_TO_STRING(__LINE__)\ Loading hal/msm8974/platform.c +18 −0 Original line number Diff line number Diff line Loading @@ -139,6 +139,24 @@ static const int pcm_device_table[AUDIO_USECASE_MAX][2] = { MULTIMEDIA2_PCM_DEVICE}, [USECASE_AUDIO_PLAYBACK_OFFLOAD] = {PLAYBACK_OFFLOAD_DEVICE, PLAYBACK_OFFLOAD_DEVICE}, #ifdef MULTIPLE_OFFLOAD_ENABLED [USECASE_AUDIO_PLAYBACK_OFFLOAD2] = {PLAYBACK_OFFLOAD_DEVICE2, PLAYBACK_OFFLOAD_DEVICE2}, [USECASE_AUDIO_PLAYBACK_OFFLOAD3] = {PLAYBACK_OFFLOAD_DEVICE3, PLAYBACK_OFFLOAD_DEVICE3}, [USECASE_AUDIO_PLAYBACK_OFFLOAD4] = {PLAYBACK_OFFLOAD_DEVICE4, PLAYBACK_OFFLOAD_DEVICE4}, [USECASE_AUDIO_PLAYBACK_OFFLOAD5] = {PLAYBACK_OFFLOAD_DEVICE5, PLAYBACK_OFFLOAD_DEVICE5}, [USECASE_AUDIO_PLAYBACK_OFFLOAD6] = {PLAYBACK_OFFLOAD_DEVICE6, PLAYBACK_OFFLOAD_DEVICE6}, [USECASE_AUDIO_PLAYBACK_OFFLOAD7] = {PLAYBACK_OFFLOAD_DEVICE7, PLAYBACK_OFFLOAD_DEVICE7}, [USECASE_AUDIO_PLAYBACK_OFFLOAD8] = {PLAYBACK_OFFLOAD_DEVICE8, PLAYBACK_OFFLOAD_DEVICE8}, [USECASE_AUDIO_PLAYBACK_OFFLOAD9] = {PLAYBACK_OFFLOAD_DEVICE9, PLAYBACK_OFFLOAD_DEVICE9}, #endif [USECASE_AUDIO_RECORD] = {AUDIO_RECORD_PCM_DEVICE, AUDIO_RECORD_PCM_DEVICE}, [USECASE_AUDIO_RECORD_COMPRESS] = {COMPRESS_CAPTURE_DEVICE, COMPRESS_CAPTURE_DEVICE}, [USECASE_AUDIO_RECORD_LOW_LATENCY] = {LOWLATENCY_PCM_DEVICE, Loading Loading
hal/Android.mk +3 −0 Original line number Diff line number Diff line Loading @@ -126,6 +126,9 @@ ifeq ($(strip $(AUDIO_FEATURE_DISABLED_DS1_DOLBY_DDP)),true) endif endif ifeq ($(strip $(AUDIO_FEATURE_ENABLED_MULTIPLE_TUNNEL)), true) LOCAL_CFLAGS += -DMULTIPLE_OFFLOAD_ENABLED endif LOCAL_SHARED_LIBRARIES := \ liblog \ Loading
hal/audio_extn/audio_extn.c +27 −0 Original line number Diff line number Diff line Loading @@ -52,6 +52,8 @@ static struct audio_extn_module aextnmod = { #define AUDIO_PARAMETER_KEY_WFD "wfd_channel_cap" #define AUDIO_PARAMETER_CAN_OPEN_PROXY "can_open_proxy" #define AUDIO_PARAMETER_CUSTOM_STEREO "stereo_as_dual_mono" /* Query offload playback instances count */ #define AUDIO_PARAMETER_OFFLOAD_NUM_ACTIVE "offload_num_active" #ifndef FM_ENABLED #define audio_extn_fm_set_parameters(adev, parms) (0) Loading Loading @@ -424,6 +426,30 @@ int32_t audio_extn_get_afe_proxy_channel_count() #endif /* AFE_PROXY_ENABLED */ static int get_active_offload_usecases(const struct audio_device *adev, struct str_parms *query, struct str_parms *reply) { int ret, count = 0; char value[32]={0}; struct listnode *node; struct audio_usecase *usecase; ALOGV("%s", __func__); ret = str_parms_get_str(query, AUDIO_PARAMETER_OFFLOAD_NUM_ACTIVE, value, sizeof(value)); if (ret >= 0) { list_for_each(node, &adev->usecase_list) { usecase = node_to_item(node, struct audio_usecase, list); if (is_offload_usecase(usecase->id)) count++; } ALOGV("%s, number of active offload usecases: %d", __func__, count); str_parms_add_int(reply, AUDIO_PARAMETER_OFFLOAD_NUM_ACTIVE, count); } return ret; } void audio_extn_set_parameters(struct audio_device *adev, struct str_parms *parms) { Loading @@ -444,6 +470,7 @@ void audio_extn_get_parameters(const struct audio_device *adev, char *kv_pairs = NULL; audio_extn_get_afe_proxy_parameters(query, reply); audio_extn_get_fluence_parameters(adev, query, reply); get_active_offload_usecases(adev, query, reply); kv_pairs = str_parms_to_str(reply); ALOGD_IF(kv_pairs != NULL, "%s: returns %s", __func__, kv_pairs); Loading
hal/audio_hw.c +88 −20 Original line number Diff line number Diff line Loading @@ -107,6 +107,16 @@ const char * const use_case_table[AUDIO_USECASE_MAX] = { [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = "low-latency-playback", [USECASE_AUDIO_PLAYBACK_MULTI_CH] = "multi-channel-playback", [USECASE_AUDIO_PLAYBACK_OFFLOAD] = "compress-offload-playback", #ifdef MULTIPLE_OFFLOAD_ENABLED [USECASE_AUDIO_PLAYBACK_OFFLOAD2] = "compress-offload-playback2", [USECASE_AUDIO_PLAYBACK_OFFLOAD3] = "compress-offload-playback3", [USECASE_AUDIO_PLAYBACK_OFFLOAD4] = "compress-offload-playback4", [USECASE_AUDIO_PLAYBACK_OFFLOAD5] = "compress-offload-playback5", [USECASE_AUDIO_PLAYBACK_OFFLOAD6] = "compress-offload-playback6", [USECASE_AUDIO_PLAYBACK_OFFLOAD7] = "compress-offload-playback7", [USECASE_AUDIO_PLAYBACK_OFFLOAD8] = "compress-offload-playback8", [USECASE_AUDIO_PLAYBACK_OFFLOAD9] = "compress-offload-playback9", #endif [USECASE_AUDIO_RECORD] = "audio-record", [USECASE_AUDIO_RECORD_COMPRESS] = "audio-record-compress", [USECASE_AUDIO_RECORD_LOW_LATENCY] = "low-latency-record", Loading Loading @@ -134,6 +144,19 @@ const char * const use_case_table[AUDIO_USECASE_MAX] = { [USECASE_AUDIO_SPKR_CALIB_TX] = "spkr-vi-record", }; static const audio_usecase_t offload_usecases[] = { USECASE_AUDIO_PLAYBACK_OFFLOAD, #ifdef MULTIPLE_OFFLOAD_ENABLED USECASE_AUDIO_PLAYBACK_OFFLOAD2, USECASE_AUDIO_PLAYBACK_OFFLOAD3, USECASE_AUDIO_PLAYBACK_OFFLOAD4, USECASE_AUDIO_PLAYBACK_OFFLOAD5, USECASE_AUDIO_PLAYBACK_OFFLOAD6, USECASE_AUDIO_PLAYBACK_OFFLOAD7, USECASE_AUDIO_PLAYBACK_OFFLOAD8, USECASE_AUDIO_PLAYBACK_OFFLOAD9, #endif }; #define STRING_TO_ENUM(string) { #string, string } Loading Loading @@ -877,6 +900,51 @@ static void stop_compressed_output_l(struct stream_out *out) } } bool is_offload_usecase(audio_usecase_t uc_id) { unsigned int i; for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) { if (uc_id == offload_usecases[i]) return true; } return false; } static audio_usecase_t get_offload_usecase(struct audio_device *adev) { audio_usecase_t ret = USECASE_AUDIO_PLAYBACK_OFFLOAD; unsigned int i, num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]); char value[PROPERTY_VALUE_MAX] = {0}; property_get("audio.offload.multiple.enabled", value, NULL); if (!(atoi(value) || !strncmp("true", value, 4))) num_usecase = 1; /* If prop is not set, limit the num of offload usecases to 1 */ ALOGV("%s: num_usecase: %d", __func__, num_usecase); for (i = 0; i < num_usecase; i++) { if (!(adev->offload_usecases_state & (0x1<<i))) { adev->offload_usecases_state |= 0x1 << i; ret = offload_usecases[i]; break; } } ALOGV("%s: offload usecase is %d", __func__, ret); return ret; } static void free_offload_usecase(struct audio_device *adev, audio_usecase_t uc_id) { unsigned int i; for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) { if (offload_usecases[i] == uc_id) { adev->offload_usecases_state &= ~(0x1<<i); break; } } ALOGV("%s: free offload usecase %d", __func__, uc_id); } static void *offload_thread_loop(void *context) { struct stream_out *out = (struct stream_out *) context; Loading Loading @@ -1024,7 +1092,7 @@ static bool allow_hdmi_channel_config(struct audio_device *adev) "no change in HDMI channels", __func__); ret = false; break; } else if (usecase->id == USECASE_AUDIO_PLAYBACK_OFFLOAD && } else if (is_offload_usecase(usecase->id) && popcount(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); Loading Loading @@ -1097,7 +1165,7 @@ static int stop_output_stream(struct stream_out *out) return -EINVAL; } if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) { if (is_offload_usecase(out->usecase)) { if (adev->visualizer_stop_output != NULL) adev->visualizer_stop_output(out->handle, out->pcm_device_id); if (adev->offload_effects_stop_output != NULL) Loading Loading @@ -1147,7 +1215,7 @@ int start_output_stream(struct stream_out *out) /* This must be called before adding this usecase to the list */ if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) { if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) if (is_offload_usecase(out->usecase)) check_and_set_hdmi_channels(adev, out->compr_config.codec->ch_in); else check_and_set_hdmi_channels(adev, out->config.channels); Loading @@ -1159,7 +1227,7 @@ int start_output_stream(struct stream_out *out) ALOGV("%s: Opening PCM device card_id(%d) device_id(%d)", __func__, 0, out->pcm_device_id); if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) { if (!is_offload_usecase(out->usecase)) { out->pcm = pcm_open(adev->snd_card, out->pcm_device_id, PCM_OUT | PCM_MONOTONIC, &out->config); Loading Loading @@ -1277,7 +1345,7 @@ static size_t out_get_buffer_size(const struct audio_stream *stream) { struct stream_out *out = (struct stream_out *)stream; if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) if (is_offload_usecase(out->usecase)) return out->compr_config.fragment_size; else if(out->usecase == USECASE_COMPRESS_VOIP_CALL) return voice_extn_compress_voip_out_get_buffer_size(out); Loading Loading @@ -1323,7 +1391,7 @@ static int out_standby(struct audio_stream *stream) if (!out->standby) { pthread_mutex_lock(&adev->lock); out->standby = true; if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) { if (!is_offload_usecase(out->usecase)) { if (out->pcm) { pcm_close(out->pcm); out->pcm = NULL; Loading Loading @@ -1490,7 +1558,7 @@ static int out_set_parameters(struct audio_stream *stream, const char *kvpairs) audio_extn_set_parameters(adev, parms); pthread_mutex_unlock(&adev->lock); } if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) { if (is_offload_usecase(out->usecase)) { pthread_mutex_lock(&out->lock); parse_compress_metadata(out, parms); pthread_mutex_unlock(&out->lock); Loading Loading @@ -1549,7 +1617,7 @@ static uint32_t out_get_latency(const struct audio_stream_out *stream) { struct stream_out *out = (struct stream_out *)stream; if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) if (is_offload_usecase(out->usecase)) return COMPRESS_OFFLOAD_PLAYBACK_LATENCY; return (out->config.period_count * out->config.period_size * 1000) / Loading @@ -1566,7 +1634,7 @@ static int out_set_volume(struct audio_stream_out *stream, float left, /* only take left channel into account: the API is for stereo anyway */ out->muted = (left == 0.0f); return 0; } else if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) { } else if (is_offload_usecase(out->usecase)) { char mixer_ctl_name[128]; struct audio_device *adev = out->dev; struct mixer_ctl *ctl; Loading Loading @@ -1613,7 +1681,7 @@ static ssize_t out_write(struct audio_stream_out *stream, const void *buffer, } } if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) { if (is_offload_usecase(out->usecase)) { ALOGD("copl(%x): writing buffer (%d bytes) to compress device", (unsigned int)out, bytes); if (out->send_new_metadata) { ALOGD("copl(%x):send new gapless metadata", (unsigned int)out); Loading Loading @@ -1663,7 +1731,7 @@ static int out_get_render_position(const struct audio_stream_out *stream, { struct stream_out *out = (struct stream_out *)stream; *dsp_frames = 0; if ((out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) && (dsp_frames != NULL)) { if (is_offload_usecase(out->usecase) && (dsp_frames != NULL)) { pthread_mutex_lock(&out->lock); if (out->compr != NULL) { compress_get_tstamp(out->compr, (unsigned long *)dsp_frames, Loading Loading @@ -1702,7 +1770,7 @@ static int out_get_presentation_position(const struct audio_stream_out *stream, pthread_mutex_lock(&out->lock); if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) { if (is_offload_usecase(out->usecase)) { if (out->compr != NULL) { compress_get_tstamp(out->compr, &dsp_frames, &out->sample_rate); Loading Loading @@ -1756,7 +1824,7 @@ static int out_pause(struct audio_stream_out* stream) struct stream_out *out = (struct stream_out *)stream; int status = -ENOSYS; ALOGV("%s", __func__); if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) { if (is_offload_usecase(out->usecase)) { ALOGD("copl(%x):pause compress driver", (unsigned int)out); pthread_mutex_lock(&out->lock); if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) { Loading @@ -1773,7 +1841,7 @@ static int out_resume(struct audio_stream_out* stream) struct stream_out *out = (struct stream_out *)stream; int status = -ENOSYS; ALOGV("%s", __func__); if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) { if (is_offload_usecase(out->usecase)) { ALOGD("copl(%x):resume compress driver", (unsigned int)out); status = 0; pthread_mutex_lock(&out->lock); Loading @@ -1791,7 +1859,7 @@ static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type ) struct stream_out *out = (struct stream_out *)stream; int status = -ENOSYS; ALOGV("%s", __func__); if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) { if (is_offload_usecase(out->usecase)) { pthread_mutex_lock(&out->lock); if (type == AUDIO_DRAIN_EARLY_NOTIFY) status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN); Loading @@ -1806,7 +1874,7 @@ static int out_flush(struct audio_stream_out* stream) { struct stream_out *out = (struct stream_out *)stream; ALOGV("%s", __func__); if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) { if (is_offload_usecase(out->usecase)) { ALOGD("copl(%x):calling compress flush", (unsigned int)out); pthread_mutex_lock(&out->lock); stop_compressed_output_l(out); Loading Loading @@ -2169,7 +2237,7 @@ static int adev_open_output_stream(struct audio_hw_device *dev, out->compr_config.codec = (struct snd_codec *) calloc(1, sizeof(struct snd_codec)); out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD; out->usecase = get_offload_usecase(adev); if (config->offload_info.channel_mask) out->channel_mask = config->offload_info.channel_mask; else if (config->channel_mask) { Loading Loading @@ -2324,9 +2392,9 @@ static void adev_close_output_stream(struct audio_hw_device *dev, else out_standby(&stream->common); if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) { if (is_offload_usecase(out->usecase)) { destroy_offload_callback_thread(out); free_offload_usecase(adev, out->usecase); if (out->compr_config.codec != NULL) free(out->compr_config.codec); } Loading Loading @@ -2702,7 +2770,7 @@ static int adev_open(const hw_module_t *module, const char *name, voice_init(adev); list_init(&adev->usecase_list); adev->cur_wfd_channels = 2; adev->offload_usecases_state = 0; /* Loads platform specific libraries dynamically */ adev->platform = platform_init(adev); if (!adev->platform) { Loading
hal/audio_hw.h +14 −2 Original line number Diff line number Diff line Loading @@ -65,6 +65,16 @@ typedef enum { USECASE_AUDIO_PLAYBACK_LOW_LATENCY, USECASE_AUDIO_PLAYBACK_MULTI_CH, USECASE_AUDIO_PLAYBACK_OFFLOAD, #ifdef MULTIPLE_OFFLOAD_ENABLED USECASE_AUDIO_PLAYBACK_OFFLOAD2, USECASE_AUDIO_PLAYBACK_OFFLOAD3, USECASE_AUDIO_PLAYBACK_OFFLOAD4, USECASE_AUDIO_PLAYBACK_OFFLOAD5, USECASE_AUDIO_PLAYBACK_OFFLOAD6, USECASE_AUDIO_PLAYBACK_OFFLOAD7, USECASE_AUDIO_PLAYBACK_OFFLOAD8, USECASE_AUDIO_PLAYBACK_OFFLOAD9, #endif /* FM usecase */ USECASE_AUDIO_PLAYBACK_FM, Loading Loading @@ -234,7 +244,7 @@ struct audio_device { int snd_card; void *platform; unsigned int offload_usecases_state; void *visualizer_lib; int (*visualizer_start_output)(audio_io_handle_t, int); int (*visualizer_stop_output)(audio_io_handle_t, int); Loading @@ -260,6 +270,8 @@ int enable_audio_route(struct audio_device *adev, struct audio_usecase *get_usecase_from_list(struct audio_device *adev, audio_usecase_t uc_id); bool is_offload_usecase(audio_usecase_t uc_id); #define LITERAL_TO_STRING(x) #x #define CHECK(condition) LOG_ALWAYS_FATAL_IF(!(condition), "%s",\ __FILE__ ":" LITERAL_TO_STRING(__LINE__)\ Loading
hal/msm8974/platform.c +18 −0 Original line number Diff line number Diff line Loading @@ -139,6 +139,24 @@ static const int pcm_device_table[AUDIO_USECASE_MAX][2] = { MULTIMEDIA2_PCM_DEVICE}, [USECASE_AUDIO_PLAYBACK_OFFLOAD] = {PLAYBACK_OFFLOAD_DEVICE, PLAYBACK_OFFLOAD_DEVICE}, #ifdef MULTIPLE_OFFLOAD_ENABLED [USECASE_AUDIO_PLAYBACK_OFFLOAD2] = {PLAYBACK_OFFLOAD_DEVICE2, PLAYBACK_OFFLOAD_DEVICE2}, [USECASE_AUDIO_PLAYBACK_OFFLOAD3] = {PLAYBACK_OFFLOAD_DEVICE3, PLAYBACK_OFFLOAD_DEVICE3}, [USECASE_AUDIO_PLAYBACK_OFFLOAD4] = {PLAYBACK_OFFLOAD_DEVICE4, PLAYBACK_OFFLOAD_DEVICE4}, [USECASE_AUDIO_PLAYBACK_OFFLOAD5] = {PLAYBACK_OFFLOAD_DEVICE5, PLAYBACK_OFFLOAD_DEVICE5}, [USECASE_AUDIO_PLAYBACK_OFFLOAD6] = {PLAYBACK_OFFLOAD_DEVICE6, PLAYBACK_OFFLOAD_DEVICE6}, [USECASE_AUDIO_PLAYBACK_OFFLOAD7] = {PLAYBACK_OFFLOAD_DEVICE7, PLAYBACK_OFFLOAD_DEVICE7}, [USECASE_AUDIO_PLAYBACK_OFFLOAD8] = {PLAYBACK_OFFLOAD_DEVICE8, PLAYBACK_OFFLOAD_DEVICE8}, [USECASE_AUDIO_PLAYBACK_OFFLOAD9] = {PLAYBACK_OFFLOAD_DEVICE9, PLAYBACK_OFFLOAD_DEVICE9}, #endif [USECASE_AUDIO_RECORD] = {AUDIO_RECORD_PCM_DEVICE, AUDIO_RECORD_PCM_DEVICE}, [USECASE_AUDIO_RECORD_COMPRESS] = {COMPRESS_CAPTURE_DEVICE, COMPRESS_CAPTURE_DEVICE}, [USECASE_AUDIO_RECORD_LOW_LATENCY] = {LOWLATENCY_PCM_DEVICE, Loading