Loading hal/audio_extn/audio_extn.c +16 −0 Original line number Diff line number Diff line Loading @@ -5485,6 +5485,11 @@ typedef void (*maxxaudio_set_parameters_t)(struct audio_device *, struct str_parms *); static maxxaudio_set_parameters_t maxxaudio_set_parameters; typedef void (*maxxaudio_get_parameters_t)(struct audio_device *, struct str_parms *, struct str_parms *); static maxxaudio_get_parameters_t maxxaudio_get_parameters; typedef bool (*maxxaudio_supported_usb_t)(); static maxxaudio_supported_usb_t maxxaudio_supported_usb; Loading Loading @@ -5512,6 +5517,8 @@ int maxx_audio_feature_init(bool is_feature_enabled) (maxxaudio_set_device_t)dlsym(maxxaudio_lib_handle, "ma_set_device")) || !(maxxaudio_set_parameters = (maxxaudio_set_parameters_t)dlsym(maxxaudio_lib_handle, "ma_set_parameters")) || !(maxxaudio_get_parameters = (maxxaudio_get_parameters_t)dlsym(maxxaudio_lib_handle, "ma_get_parameters")) || !(maxxaudio_supported_usb = (maxxaudio_supported_usb_t)dlsym( maxxaudio_lib_handle, "ma_supported_usb"))) { Loading @@ -5533,6 +5540,7 @@ feature_disabled: maxxaudio_set_state = NULL; maxxaudio_set_device = NULL; maxxaudio_set_parameters = NULL; maxxaudio_get_parameters = NULL; maxxaudio_supported_usb = NULL; ALOGW(":: %s: ---- Feature MAXX_AUDIO is disabled ----", __func__); return -ENOSYS; Loading Loading @@ -5580,6 +5588,14 @@ void audio_extn_ma_set_parameters(struct audio_device *adev, maxxaudio_set_parameters(adev, parms); } void audio_extn_ma_get_parameters(struct audio_device *adev, struct str_parms *query, struct str_parms *reply) { if (maxxaudio_get_parameters) maxxaudio_get_parameters(adev, query, reply); } bool audio_extn_ma_supported_usb() { return (maxxaudio_supported_usb ? maxxaudio_supported_usb(): false); Loading hal/audio_extn/audio_extn.h +3 −0 Original line number Diff line number Diff line Loading @@ -361,6 +361,9 @@ bool audio_extn_ma_set_state(struct audio_device *adev, int stream_type, void audio_extn_ma_set_device(struct audio_usecase *usecase); void audio_extn_ma_set_parameters(struct audio_device *adev, struct str_parms *parms); void audio_extn_ma_get_parameters(struct audio_device *adev, struct str_parms *query, struct str_parms *reply); bool audio_extn_ma_supported_usb(); bool audio_extn_is_maxx_audio_enabled(); // --- Function pointers from audio_extn needed by MAXX_AUDIO Loading hal/audio_extn/maxxaudio.c +176 −57 Original line number Diff line number Diff line Loading @@ -50,10 +50,14 @@ #define MA_QDSP_SET_VOL "maxxaudio_qdsp_set_volume" #define MA_QDSP_SET_VOLT "maxxaudio_qdsp_set_volume_table" #define MA_QDSP_SET_PARAM "maxxaudio_qdsp_set_parameter" #define MA_QDSP_SET_COMMAND "maxxaudio_qdsp_set_command" #define MA_QDSP_GET_COMMAND "maxxaudio_qdsp_get_command" #define SUPPORT_DEV "18d1:5033" // Blackbird usbid #define SUPPORTED_USB 0x01 #define WAVES_COMMAND_SIZE 10240 typedef unsigned int effective_scope_flag_t; const effective_scope_flag_t EFFECTIVE_SCOPE_RTC = 1 << 0; /* RTC */ const effective_scope_flag_t EFFECTIVE_SCOPE_ACDB = 1 << 1; /* ACDB */ Loading Loading @@ -145,6 +149,16 @@ typedef bool (*ma_set_param_t)(ma_audio_cal_handle_t, const struct ma_audio_cal_settings *, unsigned int, double); typedef bool (*ma_set_cmd_t)(ma_audio_cal_handle_t handle, const struct ma_audio_cal_settings *, const char*); typedef bool (*ma_get_cmd_t)(ma_audio_cal_handle_t handle, const struct ma_audio_cal_settings *, const char *, char *, uint32_t); struct ma_platform_data { void *waves_handle; void *platform; Loading @@ -158,6 +172,8 @@ struct ma_platform_data { ma_set_volume_t ma_set_volume; ma_set_volume_table_t ma_set_volume_table; ma_set_param_t ma_set_param; ma_set_cmd_t ma_set_cmd; ma_get_cmd_t ma_get_cmd; bool speaker_lr_swap; bool orientation_used; int dispaly_orientation; Loading @@ -167,6 +183,9 @@ ma_audio_cal_handle_t g_ma_audio_cal_handle = NULL; static uint16_t g_supported_dev = 0; static struct ma_state ma_cur_state_table[STREAM_MAX_TYPES]; static struct ma_platform_data *my_data = NULL; static char ma_command_data[WAVES_COMMAND_SIZE]; static char ma_reply_data[WAVES_COMMAND_SIZE]; // --- external function dependency --- fp_platform_set_parameters_t fp_platform_set_parameters; fp_audio_extn_get_snd_card_split_t fp_audio_extn_get_snd_card_split; Loading Loading @@ -276,7 +295,6 @@ static void ma_cal_init(struct ma_audio_cal_settings *ma_cal) static bool check_and_send_all_audio_cal(struct audio_device *adev, ma_cmd_t cmd) { int i = 0; bool ret = false; struct listnode *node; struct audio_usecase *usecase; Loading Loading @@ -481,15 +499,14 @@ void ma_init(void *platform, maxx_audio_init_config_t init_config) } else { ALOGV("%s: DLOPEN successful for %s", __func__, LIB_MA_PARAM); my_data->ma_param_init = (ma_param_init_t)dlsym(my_data->waves_handle, MA_QDSP_PARAM_INIT); my_data->ma_param_init = (ma_param_init_t)dlsym(my_data->waves_handle, MA_QDSP_PARAM_INIT); if (!my_data->ma_param_init) { ALOGE("%s: dlsym error %s for ma_param_init", __func__, dlerror()); goto error; } my_data->ma_param_deinit = (ma_param_deinit_t)dlsym( my_data->waves_handle, MA_QDSP_PARAM_DEINIT); my_data->ma_param_deinit = (ma_param_deinit_t)dlsym(my_data->waves_handle, MA_QDSP_PARAM_DEINIT); if (!my_data->ma_param_deinit) { ALOGE("%s: dlsym error %s for ma_param_deinit", __func__, dlerror()); goto error; Loading @@ -514,33 +531,41 @@ void ma_init(void *platform, maxx_audio_init_config_t init_config) goto error; } my_data->ma_set_sound_mode = (ma_set_sound_mode_t)dlsym( my_data->waves_handle, MA_QDSP_SET_MODE); my_data->ma_set_sound_mode = (ma_set_sound_mode_t)dlsym(my_data->waves_handle, MA_QDSP_SET_MODE); if (!my_data->ma_set_sound_mode) { ALOGE("%s: dlsym error %s for ma_set_sound_mode", __func__, dlerror()); goto error; } my_data->ma_set_volume = (ma_set_volume_t)dlsym(my_data->waves_handle, MA_QDSP_SET_VOL); my_data->ma_set_volume = (ma_set_volume_t)dlsym(my_data->waves_handle, MA_QDSP_SET_VOL); if (!my_data->ma_set_volume) { ALOGE("%s: dlsym error %s for ma_set_volume", __func__, dlerror()); goto error; } my_data->ma_set_volume_table = (ma_set_volume_table_t)dlsym( my_data->waves_handle, MA_QDSP_SET_VOLT); my_data->ma_set_volume_table = (ma_set_volume_table_t)dlsym(my_data->waves_handle, MA_QDSP_SET_VOLT); if (!my_data->ma_set_volume_table) { ALOGE("%s: dlsym error %s for ma_set_volume_table", __func__, dlerror()); goto error; } my_data->ma_set_param = (ma_set_param_t)dlsym( my_data->waves_handle, MA_QDSP_SET_PARAM); my_data->ma_set_param = (ma_set_param_t)dlsym(my_data->waves_handle, MA_QDSP_SET_PARAM); if (!my_data->ma_set_param) { ALOGE("%s: dlsym error %s for ma_set_param", __func__, dlerror()); goto error; } my_data->ma_set_cmd = (ma_set_cmd_t)dlsym(my_data->waves_handle, MA_QDSP_SET_COMMAND); if (!my_data->ma_set_cmd) { ALOGE("%s: dlsym error %s for ma_set_cmd", __func__, dlerror()); } my_data->ma_get_cmd = (ma_get_cmd_t)dlsym(my_data->waves_handle, MA_QDSP_GET_COMMAND); if (!my_data->ma_get_cmd) { ALOGE("%s: dlsym error %s for ma_get_cmd", __func__, dlerror()); } } /* get preset table */ Loading Loading @@ -679,7 +704,6 @@ bool ma_set_state(struct audio_device *adev, int stream_type, void ma_set_device(struct audio_usecase *usecase) { int i = 0; struct ma_audio_cal_settings ma_cal; if (!my_data) { Loading Loading @@ -731,8 +755,101 @@ void ma_set_device(struct audio_usecase *usecase) pthread_mutex_unlock(&my_data->lock); } void ma_set_parameters(struct audio_device *adev, struct str_parms *parms) static bool ma_set_command(struct ma_audio_cal_settings *audio_cal_settings, char *cmd_data) { if (my_data->ma_set_cmd) return my_data->ma_set_cmd(g_ma_audio_cal_handle, audio_cal_settings, cmd_data); return false; } static bool ma_get_command(struct ma_audio_cal_settings *audio_cal_settings, char *cmd_data, char *reply_data, uint32_t reply_size) { if (my_data->ma_get_cmd) return my_data->ma_get_cmd(g_ma_audio_cal_handle, audio_cal_settings, cmd_data, reply_data, reply_size); return false; } static bool ma_fill_apptype_and_device_from_params(struct str_parms *parms, uint32_t *app_type, struct listnode *devices) { int ret; char value[128]; ret = str_parms_get_str(parms, "cal_apptype", value, sizeof(value)); if (ret >= 0) { *app_type = (uint32_t)atoi(value); ret = str_parms_get_str(parms, "cal_devid", value, sizeof(value)); if (ret >= 0) { update_device_list(devices, (uint32_t)atoi(value), "", true); return true; } } return false; } static bool ma_add_apptype_and_device_to_params(struct str_parms *parms, uint32_t app_type, struct listnode *devices) { if (0 <= str_parms_add_int(parms, "cal_apptype", app_type)) { if (0 <= str_parms_add_int(parms, "cal_devid", get_device_types(devices))) { return true; } } return false; } static bool ma_get_command_parameters(struct str_parms *query, struct str_parms *reply) { struct ma_audio_cal_settings ma_cal; int ret; ret = str_parms_get_str(query, "waves_data", ma_command_data, sizeof(ma_command_data)); if (ret >= 0) { ma_cal_init(&ma_cal); if (ma_fill_apptype_and_device_from_params(query, &ma_cal.common.app_type, &ma_cal.common.devices)) { ma_add_apptype_and_device_to_params(reply, ma_cal.common.app_type, &ma_cal.common.devices); ALOGV("%s: before - command=%s", __func__, (char *)ma_command_data); if (ma_get_command(&ma_cal, ma_command_data, ma_reply_data, sizeof(ma_reply_data))) { str_parms_add_str(reply, "waves_data", ma_reply_data); ALOGV("%s: after - command=%s", __func__, (char *)ma_reply_data); return true; } else { str_parms_add_str(reply, "waves_data", ""); } } } return false; } static bool ma_set_command_parameters(struct str_parms *parms) { struct ma_audio_cal_settings ma_cal; int ret; ret = str_parms_get_str(parms, "waves_data", ma_command_data, sizeof(ma_command_data)); if (ret >= 0) { ma_cal_init(&ma_cal); if (ma_fill_apptype_and_device_from_params(parms, &ma_cal.common.app_type, &ma_cal.common.devices)) { return ma_set_command(&ma_cal, ma_command_data); } } return false; } void ma_get_parameters(struct audio_device *adev, struct str_parms *query, struct str_parms *reply) { (void)adev; ma_get_command_parameters(query, reply); } void ma_set_parameters(struct audio_device *adev, struct str_parms *parms) { int ret; int val; Loading Loading @@ -791,6 +908,8 @@ void ma_set_parameters(struct audio_device *adev, } } } ma_set_command_parameters(parms); } bool ma_supported_usb() Loading hal/audio_hw.c +80 −5 Original line number Diff line number Diff line Loading @@ -65,6 +65,7 @@ #include <hardware/audio_alsaops.h> #include <system/thread_defs.h> #include <tinyalsa/asoundlib.h> #include <utils/Timers.h> // systemTime #include <audio_effects/effect_aec.h> #include <audio_effects/effect_ns.h> #include <audio_utils/format.h> Loading Loading @@ -2642,7 +2643,11 @@ int select_devices(struct audio_device *adev, audio_usecase_t uc_id) is_single_device_type_equal(&vc_usecase->device_list, AUDIO_DEVICE_OUT_HEARING_AID) || is_single_device_type_equal(&usecase->device_list, AUDIO_DEVICE_IN_VOICE_CALL))) { AUDIO_DEVICE_IN_VOICE_CALL) || (is_single_device_type_equal(&usecase->device_list, AUDIO_DEVICE_IN_USB_HEADSET) && is_single_device_type_equal(&vc_usecase->device_list, AUDIO_DEVICE_OUT_USB_HEADSET)))) { in_snd_device = vc_usecase->in_snd_device; out_snd_device = vc_usecase->out_snd_device; } Loading Loading @@ -4549,6 +4554,17 @@ static int out_dump(const struct audio_stream *stream, int fd) dprintf(fd, " Standby: %s\n", out->standby ? "yes" : "no"); dprintf(fd, " Frames written: %lld\n", (long long)out->written); char buffer[256]; // for statistics formatting if (!is_offload_usecase(out->usecase)) { simple_stats_to_string(&out->fifo_underruns, buffer, sizeof(buffer)); dprintf(fd, " Fifo frame underruns: %s\n", buffer); } if (out->start_latency_ms.n > 0) { simple_stats_to_string(&out->start_latency_ms, buffer, sizeof(buffer)); dprintf(fd, " Start latency ms: %s\n", buffer); } if (locked) { pthread_mutex_unlock(&out->lock); } Loading Loading @@ -5705,6 +5721,8 @@ static ssize_t out_write(struct audio_stream_out *stream, const void *buffer, if (out->standby) { out->standby = false; const int64_t startNs = systemTime(SYSTEM_TIME_MONOTONIC); pthread_mutex_lock(&adev->lock); if (out->usecase == USECASE_COMPRESS_VOIP_CALL) ret = voice_extn_compress_voip_start_output_stream(out); Loading @@ -5717,6 +5735,7 @@ static ssize_t out_write(struct audio_stream_out *stream, const void *buffer, goto exit; } out->started = 1; out->last_fifo_valid = false; // we're coming out of standby, last_fifo isn't valid. if (last_known_cal_step != -1) { ALOGD("%s: retry previous failed cal level set", __func__); audio_hw_send_gain_dep_calibration(last_known_cal_step); Loading @@ -5731,6 +5750,10 @@ static ssize_t out_write(struct audio_stream_out *stream, const void *buffer, } if (out->set_dual_mono) audio_extn_send_dual_mono_mixing_coefficients(out); // log startup time in ms. simple_stats_log( &out->start_latency_ms, (systemTime(SYSTEM_TIME_MONOTONIC) - startNs) * 1e-6); } if (adev->is_channel_status_set == false && Loading Loading @@ -5885,6 +5908,30 @@ static ssize_t out_write(struct audio_stream_out *stream, const void *buffer, bytes_to_write /= 2; } } // Note: since out_get_presentation_position() is called alternating with out_write() // by AudioFlinger, we can check underruns using the prior timestamp read. // (Alternately we could check if the buffer is empty using pcm_get_htimestamp(). if (out->last_fifo_valid) { // compute drain to see if there is an underrun. const int64_t current_ns = systemTime(SYSTEM_TIME_MONOTONIC); // sys call const int64_t frames_by_time = (current_ns - out->last_fifo_time_ns) * out->config.rate / NANOS_PER_SECOND; const int64_t underrun = frames_by_time - out->last_fifo_frames_remaining; if (underrun > 0) { simple_stats_log(&out->fifo_underruns, underrun); ALOGW("%s: underrun(%lld) " "frames_by_time(%lld) > out->last_fifo_frames_remaining(%lld)", __func__, (long long)out->fifo_underruns.n, (long long)frames_by_time, (long long)out->last_fifo_frames_remaining); } out->last_fifo_valid = false; // we're writing below, mark fifo info as stale. } ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes); long ns = 0; Loading Loading @@ -6114,15 +6161,26 @@ static int out_get_presentation_position(const struct audio_stream_out *stream, if (out->pcm) { unsigned int avail; if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) { size_t kernel_buffer_size = out->config.period_size * out->config.period_count; uint64_t signed_frames = 0; uint64_t frames_temp = 0; frames_temp = (kernel_buffer_size > avail) ? (kernel_buffer_size - avail) : 0; if (out->kernel_buffer_size > avail) { frames_temp = out->last_fifo_frames_remaining = out->kernel_buffer_size - avail; } else { ALOGW("%s: avail:%u > kernel_buffer_size:%zu clamping!", __func__, avail, out->kernel_buffer_size); avail = out->kernel_buffer_size; frames_temp = out->last_fifo_frames_remaining = 0; } out->last_fifo_valid = true; out->last_fifo_time_ns = audio_utils_ns_from_timespec(timestamp); if (out->written >= frames_temp) signed_frames = out->written - frames_temp; ALOGVV("%s: frames:%lld avail:%u kernel_buffer_size:%zu", __func__, (long long)signed_frames, avail, out->kernel_buffer_size); // This adjustment accounts for buffering after app processor. // It is based on estimated DSP latency per use case, rather than exact. frames_temp = platform_render_latency(out->usecase) * out->sample_rate / 1000000LL; Loading @@ -6141,7 +6199,9 @@ static int out_get_presentation_position(const struct audio_stream_out *stream, *frames = signed_frames; ret = 0; } } else if (out->card_status == CARD_STATUS_OFFLINE) { } else if (out->card_status == CARD_STATUS_OFFLINE || // audioflinger still needs position updates when A2DP is suspended (is_a2dp_out_device_type(&out->device_list) && audio_extn_a2dp_source_is_suspended())) { *frames = out->written; clock_gettime(CLOCK_MONOTONIC, timestamp); if (is_offload_usecase(out->usecase)) Loading Loading @@ -6609,6 +6669,12 @@ static int in_dump(const struct audio_stream *stream, dprintf(fd, " Frames read: %lld\n", (long long)in->frames_read); dprintf(fd, " Frames muted: %lld\n", (long long)in->frames_muted); char buffer[256]; // for statistics formatting if (in->start_latency_ms.n > 0) { simple_stats_to_string(&in->start_latency_ms, buffer, sizeof(buffer)); dprintf(fd, " Start latency ms: %s\n", buffer); } if (locked) { pthread_mutex_unlock(&in->lock); } Loading Loading @@ -6870,6 +6936,8 @@ static ssize_t in_read(struct audio_stream_in *stream, void *buffer, } if (in->standby) { const int64_t startNs = systemTime(SYSTEM_TIME_MONOTONIC); pthread_mutex_lock(&adev->lock); if (in->usecase == USECASE_COMPRESS_VOIP_CALL) ret = voice_extn_compress_voip_start_input_stream(in); Loading @@ -6884,6 +6952,10 @@ static ssize_t in_read(struct audio_stream_in *stream, void *buffer, goto exit; } in->standby = 0; // log startup time in ms. simple_stats_log( &in->start_latency_ms, (systemTime(SYSTEM_TIME_MONOTONIC) - startNs) * 1e-6); } /* Avoid read if capture_stopped is set */ Loading Loading @@ -8256,6 +8328,8 @@ int adev_open_output_stream(struct audio_hw_device *dev, else out->af_period_multiplier = 1; out->kernel_buffer_size = out->config.period_size * out->config.period_count; out->standby = 1; /* out->muted = false; by calloc() */ /* out->written = 0; by calloc() */ Loading Loading @@ -8772,6 +8846,7 @@ static char* adev_get_parameters(const struct audio_hw_device *dev, voice_get_parameters(adev, query, reply); audio_extn_a2dp_get_parameters(query, reply); platform_get_parameters(adev->platform, query, reply); audio_extn_ma_get_parameters(adev, query, reply); pthread_mutex_unlock(&adev->lock); exit: Loading hal/audio_hw.h +14 −0 Original line number Diff line number Diff line Loading @@ -48,6 +48,8 @@ #include <audio_route/audio_route.h> #include <audio_utils/ErrorLog.h> #include <audio_utils/Statistics.h> #include <audio_utils/clock.h> #include "audio_defs.h" #include "voice.h" #include "audio_hw_extn_api.h" Loading Loading @@ -454,6 +456,16 @@ struct stream_out { int stream; } cs; } extconn; size_t kernel_buffer_size; // cached value of the alsa buffer size, const after open(). // last out_get_presentation_position() cached info. bool last_fifo_valid; unsigned int last_fifo_frames_remaining; int64_t last_fifo_time_ns; simple_stats_t fifo_underruns; // TODO: keep a list of the last N fifo underrun times. simple_stats_t start_latency_ms; }; struct stream_in { Loading Loading @@ -507,6 +519,8 @@ struct stream_in { int64_t frames_muted; /* total frames muted, not cleared when entering standby */ error_log_t *error_log; simple_stats_t start_latency_ms; }; typedef enum { Loading Loading
hal/audio_extn/audio_extn.c +16 −0 Original line number Diff line number Diff line Loading @@ -5485,6 +5485,11 @@ typedef void (*maxxaudio_set_parameters_t)(struct audio_device *, struct str_parms *); static maxxaudio_set_parameters_t maxxaudio_set_parameters; typedef void (*maxxaudio_get_parameters_t)(struct audio_device *, struct str_parms *, struct str_parms *); static maxxaudio_get_parameters_t maxxaudio_get_parameters; typedef bool (*maxxaudio_supported_usb_t)(); static maxxaudio_supported_usb_t maxxaudio_supported_usb; Loading Loading @@ -5512,6 +5517,8 @@ int maxx_audio_feature_init(bool is_feature_enabled) (maxxaudio_set_device_t)dlsym(maxxaudio_lib_handle, "ma_set_device")) || !(maxxaudio_set_parameters = (maxxaudio_set_parameters_t)dlsym(maxxaudio_lib_handle, "ma_set_parameters")) || !(maxxaudio_get_parameters = (maxxaudio_get_parameters_t)dlsym(maxxaudio_lib_handle, "ma_get_parameters")) || !(maxxaudio_supported_usb = (maxxaudio_supported_usb_t)dlsym( maxxaudio_lib_handle, "ma_supported_usb"))) { Loading @@ -5533,6 +5540,7 @@ feature_disabled: maxxaudio_set_state = NULL; maxxaudio_set_device = NULL; maxxaudio_set_parameters = NULL; maxxaudio_get_parameters = NULL; maxxaudio_supported_usb = NULL; ALOGW(":: %s: ---- Feature MAXX_AUDIO is disabled ----", __func__); return -ENOSYS; Loading Loading @@ -5580,6 +5588,14 @@ void audio_extn_ma_set_parameters(struct audio_device *adev, maxxaudio_set_parameters(adev, parms); } void audio_extn_ma_get_parameters(struct audio_device *adev, struct str_parms *query, struct str_parms *reply) { if (maxxaudio_get_parameters) maxxaudio_get_parameters(adev, query, reply); } bool audio_extn_ma_supported_usb() { return (maxxaudio_supported_usb ? maxxaudio_supported_usb(): false); Loading
hal/audio_extn/audio_extn.h +3 −0 Original line number Diff line number Diff line Loading @@ -361,6 +361,9 @@ bool audio_extn_ma_set_state(struct audio_device *adev, int stream_type, void audio_extn_ma_set_device(struct audio_usecase *usecase); void audio_extn_ma_set_parameters(struct audio_device *adev, struct str_parms *parms); void audio_extn_ma_get_parameters(struct audio_device *adev, struct str_parms *query, struct str_parms *reply); bool audio_extn_ma_supported_usb(); bool audio_extn_is_maxx_audio_enabled(); // --- Function pointers from audio_extn needed by MAXX_AUDIO Loading
hal/audio_extn/maxxaudio.c +176 −57 Original line number Diff line number Diff line Loading @@ -50,10 +50,14 @@ #define MA_QDSP_SET_VOL "maxxaudio_qdsp_set_volume" #define MA_QDSP_SET_VOLT "maxxaudio_qdsp_set_volume_table" #define MA_QDSP_SET_PARAM "maxxaudio_qdsp_set_parameter" #define MA_QDSP_SET_COMMAND "maxxaudio_qdsp_set_command" #define MA_QDSP_GET_COMMAND "maxxaudio_qdsp_get_command" #define SUPPORT_DEV "18d1:5033" // Blackbird usbid #define SUPPORTED_USB 0x01 #define WAVES_COMMAND_SIZE 10240 typedef unsigned int effective_scope_flag_t; const effective_scope_flag_t EFFECTIVE_SCOPE_RTC = 1 << 0; /* RTC */ const effective_scope_flag_t EFFECTIVE_SCOPE_ACDB = 1 << 1; /* ACDB */ Loading Loading @@ -145,6 +149,16 @@ typedef bool (*ma_set_param_t)(ma_audio_cal_handle_t, const struct ma_audio_cal_settings *, unsigned int, double); typedef bool (*ma_set_cmd_t)(ma_audio_cal_handle_t handle, const struct ma_audio_cal_settings *, const char*); typedef bool (*ma_get_cmd_t)(ma_audio_cal_handle_t handle, const struct ma_audio_cal_settings *, const char *, char *, uint32_t); struct ma_platform_data { void *waves_handle; void *platform; Loading @@ -158,6 +172,8 @@ struct ma_platform_data { ma_set_volume_t ma_set_volume; ma_set_volume_table_t ma_set_volume_table; ma_set_param_t ma_set_param; ma_set_cmd_t ma_set_cmd; ma_get_cmd_t ma_get_cmd; bool speaker_lr_swap; bool orientation_used; int dispaly_orientation; Loading @@ -167,6 +183,9 @@ ma_audio_cal_handle_t g_ma_audio_cal_handle = NULL; static uint16_t g_supported_dev = 0; static struct ma_state ma_cur_state_table[STREAM_MAX_TYPES]; static struct ma_platform_data *my_data = NULL; static char ma_command_data[WAVES_COMMAND_SIZE]; static char ma_reply_data[WAVES_COMMAND_SIZE]; // --- external function dependency --- fp_platform_set_parameters_t fp_platform_set_parameters; fp_audio_extn_get_snd_card_split_t fp_audio_extn_get_snd_card_split; Loading Loading @@ -276,7 +295,6 @@ static void ma_cal_init(struct ma_audio_cal_settings *ma_cal) static bool check_and_send_all_audio_cal(struct audio_device *adev, ma_cmd_t cmd) { int i = 0; bool ret = false; struct listnode *node; struct audio_usecase *usecase; Loading Loading @@ -481,15 +499,14 @@ void ma_init(void *platform, maxx_audio_init_config_t init_config) } else { ALOGV("%s: DLOPEN successful for %s", __func__, LIB_MA_PARAM); my_data->ma_param_init = (ma_param_init_t)dlsym(my_data->waves_handle, MA_QDSP_PARAM_INIT); my_data->ma_param_init = (ma_param_init_t)dlsym(my_data->waves_handle, MA_QDSP_PARAM_INIT); if (!my_data->ma_param_init) { ALOGE("%s: dlsym error %s for ma_param_init", __func__, dlerror()); goto error; } my_data->ma_param_deinit = (ma_param_deinit_t)dlsym( my_data->waves_handle, MA_QDSP_PARAM_DEINIT); my_data->ma_param_deinit = (ma_param_deinit_t)dlsym(my_data->waves_handle, MA_QDSP_PARAM_DEINIT); if (!my_data->ma_param_deinit) { ALOGE("%s: dlsym error %s for ma_param_deinit", __func__, dlerror()); goto error; Loading @@ -514,33 +531,41 @@ void ma_init(void *platform, maxx_audio_init_config_t init_config) goto error; } my_data->ma_set_sound_mode = (ma_set_sound_mode_t)dlsym( my_data->waves_handle, MA_QDSP_SET_MODE); my_data->ma_set_sound_mode = (ma_set_sound_mode_t)dlsym(my_data->waves_handle, MA_QDSP_SET_MODE); if (!my_data->ma_set_sound_mode) { ALOGE("%s: dlsym error %s for ma_set_sound_mode", __func__, dlerror()); goto error; } my_data->ma_set_volume = (ma_set_volume_t)dlsym(my_data->waves_handle, MA_QDSP_SET_VOL); my_data->ma_set_volume = (ma_set_volume_t)dlsym(my_data->waves_handle, MA_QDSP_SET_VOL); if (!my_data->ma_set_volume) { ALOGE("%s: dlsym error %s for ma_set_volume", __func__, dlerror()); goto error; } my_data->ma_set_volume_table = (ma_set_volume_table_t)dlsym( my_data->waves_handle, MA_QDSP_SET_VOLT); my_data->ma_set_volume_table = (ma_set_volume_table_t)dlsym(my_data->waves_handle, MA_QDSP_SET_VOLT); if (!my_data->ma_set_volume_table) { ALOGE("%s: dlsym error %s for ma_set_volume_table", __func__, dlerror()); goto error; } my_data->ma_set_param = (ma_set_param_t)dlsym( my_data->waves_handle, MA_QDSP_SET_PARAM); my_data->ma_set_param = (ma_set_param_t)dlsym(my_data->waves_handle, MA_QDSP_SET_PARAM); if (!my_data->ma_set_param) { ALOGE("%s: dlsym error %s for ma_set_param", __func__, dlerror()); goto error; } my_data->ma_set_cmd = (ma_set_cmd_t)dlsym(my_data->waves_handle, MA_QDSP_SET_COMMAND); if (!my_data->ma_set_cmd) { ALOGE("%s: dlsym error %s for ma_set_cmd", __func__, dlerror()); } my_data->ma_get_cmd = (ma_get_cmd_t)dlsym(my_data->waves_handle, MA_QDSP_GET_COMMAND); if (!my_data->ma_get_cmd) { ALOGE("%s: dlsym error %s for ma_get_cmd", __func__, dlerror()); } } /* get preset table */ Loading Loading @@ -679,7 +704,6 @@ bool ma_set_state(struct audio_device *adev, int stream_type, void ma_set_device(struct audio_usecase *usecase) { int i = 0; struct ma_audio_cal_settings ma_cal; if (!my_data) { Loading Loading @@ -731,8 +755,101 @@ void ma_set_device(struct audio_usecase *usecase) pthread_mutex_unlock(&my_data->lock); } void ma_set_parameters(struct audio_device *adev, struct str_parms *parms) static bool ma_set_command(struct ma_audio_cal_settings *audio_cal_settings, char *cmd_data) { if (my_data->ma_set_cmd) return my_data->ma_set_cmd(g_ma_audio_cal_handle, audio_cal_settings, cmd_data); return false; } static bool ma_get_command(struct ma_audio_cal_settings *audio_cal_settings, char *cmd_data, char *reply_data, uint32_t reply_size) { if (my_data->ma_get_cmd) return my_data->ma_get_cmd(g_ma_audio_cal_handle, audio_cal_settings, cmd_data, reply_data, reply_size); return false; } static bool ma_fill_apptype_and_device_from_params(struct str_parms *parms, uint32_t *app_type, struct listnode *devices) { int ret; char value[128]; ret = str_parms_get_str(parms, "cal_apptype", value, sizeof(value)); if (ret >= 0) { *app_type = (uint32_t)atoi(value); ret = str_parms_get_str(parms, "cal_devid", value, sizeof(value)); if (ret >= 0) { update_device_list(devices, (uint32_t)atoi(value), "", true); return true; } } return false; } static bool ma_add_apptype_and_device_to_params(struct str_parms *parms, uint32_t app_type, struct listnode *devices) { if (0 <= str_parms_add_int(parms, "cal_apptype", app_type)) { if (0 <= str_parms_add_int(parms, "cal_devid", get_device_types(devices))) { return true; } } return false; } static bool ma_get_command_parameters(struct str_parms *query, struct str_parms *reply) { struct ma_audio_cal_settings ma_cal; int ret; ret = str_parms_get_str(query, "waves_data", ma_command_data, sizeof(ma_command_data)); if (ret >= 0) { ma_cal_init(&ma_cal); if (ma_fill_apptype_and_device_from_params(query, &ma_cal.common.app_type, &ma_cal.common.devices)) { ma_add_apptype_and_device_to_params(reply, ma_cal.common.app_type, &ma_cal.common.devices); ALOGV("%s: before - command=%s", __func__, (char *)ma_command_data); if (ma_get_command(&ma_cal, ma_command_data, ma_reply_data, sizeof(ma_reply_data))) { str_parms_add_str(reply, "waves_data", ma_reply_data); ALOGV("%s: after - command=%s", __func__, (char *)ma_reply_data); return true; } else { str_parms_add_str(reply, "waves_data", ""); } } } return false; } static bool ma_set_command_parameters(struct str_parms *parms) { struct ma_audio_cal_settings ma_cal; int ret; ret = str_parms_get_str(parms, "waves_data", ma_command_data, sizeof(ma_command_data)); if (ret >= 0) { ma_cal_init(&ma_cal); if (ma_fill_apptype_and_device_from_params(parms, &ma_cal.common.app_type, &ma_cal.common.devices)) { return ma_set_command(&ma_cal, ma_command_data); } } return false; } void ma_get_parameters(struct audio_device *adev, struct str_parms *query, struct str_parms *reply) { (void)adev; ma_get_command_parameters(query, reply); } void ma_set_parameters(struct audio_device *adev, struct str_parms *parms) { int ret; int val; Loading Loading @@ -791,6 +908,8 @@ void ma_set_parameters(struct audio_device *adev, } } } ma_set_command_parameters(parms); } bool ma_supported_usb() Loading
hal/audio_hw.c +80 −5 Original line number Diff line number Diff line Loading @@ -65,6 +65,7 @@ #include <hardware/audio_alsaops.h> #include <system/thread_defs.h> #include <tinyalsa/asoundlib.h> #include <utils/Timers.h> // systemTime #include <audio_effects/effect_aec.h> #include <audio_effects/effect_ns.h> #include <audio_utils/format.h> Loading Loading @@ -2642,7 +2643,11 @@ int select_devices(struct audio_device *adev, audio_usecase_t uc_id) is_single_device_type_equal(&vc_usecase->device_list, AUDIO_DEVICE_OUT_HEARING_AID) || is_single_device_type_equal(&usecase->device_list, AUDIO_DEVICE_IN_VOICE_CALL))) { AUDIO_DEVICE_IN_VOICE_CALL) || (is_single_device_type_equal(&usecase->device_list, AUDIO_DEVICE_IN_USB_HEADSET) && is_single_device_type_equal(&vc_usecase->device_list, AUDIO_DEVICE_OUT_USB_HEADSET)))) { in_snd_device = vc_usecase->in_snd_device; out_snd_device = vc_usecase->out_snd_device; } Loading Loading @@ -4549,6 +4554,17 @@ static int out_dump(const struct audio_stream *stream, int fd) dprintf(fd, " Standby: %s\n", out->standby ? "yes" : "no"); dprintf(fd, " Frames written: %lld\n", (long long)out->written); char buffer[256]; // for statistics formatting if (!is_offload_usecase(out->usecase)) { simple_stats_to_string(&out->fifo_underruns, buffer, sizeof(buffer)); dprintf(fd, " Fifo frame underruns: %s\n", buffer); } if (out->start_latency_ms.n > 0) { simple_stats_to_string(&out->start_latency_ms, buffer, sizeof(buffer)); dprintf(fd, " Start latency ms: %s\n", buffer); } if (locked) { pthread_mutex_unlock(&out->lock); } Loading Loading @@ -5705,6 +5721,8 @@ static ssize_t out_write(struct audio_stream_out *stream, const void *buffer, if (out->standby) { out->standby = false; const int64_t startNs = systemTime(SYSTEM_TIME_MONOTONIC); pthread_mutex_lock(&adev->lock); if (out->usecase == USECASE_COMPRESS_VOIP_CALL) ret = voice_extn_compress_voip_start_output_stream(out); Loading @@ -5717,6 +5735,7 @@ static ssize_t out_write(struct audio_stream_out *stream, const void *buffer, goto exit; } out->started = 1; out->last_fifo_valid = false; // we're coming out of standby, last_fifo isn't valid. if (last_known_cal_step != -1) { ALOGD("%s: retry previous failed cal level set", __func__); audio_hw_send_gain_dep_calibration(last_known_cal_step); Loading @@ -5731,6 +5750,10 @@ static ssize_t out_write(struct audio_stream_out *stream, const void *buffer, } if (out->set_dual_mono) audio_extn_send_dual_mono_mixing_coefficients(out); // log startup time in ms. simple_stats_log( &out->start_latency_ms, (systemTime(SYSTEM_TIME_MONOTONIC) - startNs) * 1e-6); } if (adev->is_channel_status_set == false && Loading Loading @@ -5885,6 +5908,30 @@ static ssize_t out_write(struct audio_stream_out *stream, const void *buffer, bytes_to_write /= 2; } } // Note: since out_get_presentation_position() is called alternating with out_write() // by AudioFlinger, we can check underruns using the prior timestamp read. // (Alternately we could check if the buffer is empty using pcm_get_htimestamp(). if (out->last_fifo_valid) { // compute drain to see if there is an underrun. const int64_t current_ns = systemTime(SYSTEM_TIME_MONOTONIC); // sys call const int64_t frames_by_time = (current_ns - out->last_fifo_time_ns) * out->config.rate / NANOS_PER_SECOND; const int64_t underrun = frames_by_time - out->last_fifo_frames_remaining; if (underrun > 0) { simple_stats_log(&out->fifo_underruns, underrun); ALOGW("%s: underrun(%lld) " "frames_by_time(%lld) > out->last_fifo_frames_remaining(%lld)", __func__, (long long)out->fifo_underruns.n, (long long)frames_by_time, (long long)out->last_fifo_frames_remaining); } out->last_fifo_valid = false; // we're writing below, mark fifo info as stale. } ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes); long ns = 0; Loading Loading @@ -6114,15 +6161,26 @@ static int out_get_presentation_position(const struct audio_stream_out *stream, if (out->pcm) { unsigned int avail; if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) { size_t kernel_buffer_size = out->config.period_size * out->config.period_count; uint64_t signed_frames = 0; uint64_t frames_temp = 0; frames_temp = (kernel_buffer_size > avail) ? (kernel_buffer_size - avail) : 0; if (out->kernel_buffer_size > avail) { frames_temp = out->last_fifo_frames_remaining = out->kernel_buffer_size - avail; } else { ALOGW("%s: avail:%u > kernel_buffer_size:%zu clamping!", __func__, avail, out->kernel_buffer_size); avail = out->kernel_buffer_size; frames_temp = out->last_fifo_frames_remaining = 0; } out->last_fifo_valid = true; out->last_fifo_time_ns = audio_utils_ns_from_timespec(timestamp); if (out->written >= frames_temp) signed_frames = out->written - frames_temp; ALOGVV("%s: frames:%lld avail:%u kernel_buffer_size:%zu", __func__, (long long)signed_frames, avail, out->kernel_buffer_size); // This adjustment accounts for buffering after app processor. // It is based on estimated DSP latency per use case, rather than exact. frames_temp = platform_render_latency(out->usecase) * out->sample_rate / 1000000LL; Loading @@ -6141,7 +6199,9 @@ static int out_get_presentation_position(const struct audio_stream_out *stream, *frames = signed_frames; ret = 0; } } else if (out->card_status == CARD_STATUS_OFFLINE) { } else if (out->card_status == CARD_STATUS_OFFLINE || // audioflinger still needs position updates when A2DP is suspended (is_a2dp_out_device_type(&out->device_list) && audio_extn_a2dp_source_is_suspended())) { *frames = out->written; clock_gettime(CLOCK_MONOTONIC, timestamp); if (is_offload_usecase(out->usecase)) Loading Loading @@ -6609,6 +6669,12 @@ static int in_dump(const struct audio_stream *stream, dprintf(fd, " Frames read: %lld\n", (long long)in->frames_read); dprintf(fd, " Frames muted: %lld\n", (long long)in->frames_muted); char buffer[256]; // for statistics formatting if (in->start_latency_ms.n > 0) { simple_stats_to_string(&in->start_latency_ms, buffer, sizeof(buffer)); dprintf(fd, " Start latency ms: %s\n", buffer); } if (locked) { pthread_mutex_unlock(&in->lock); } Loading Loading @@ -6870,6 +6936,8 @@ static ssize_t in_read(struct audio_stream_in *stream, void *buffer, } if (in->standby) { const int64_t startNs = systemTime(SYSTEM_TIME_MONOTONIC); pthread_mutex_lock(&adev->lock); if (in->usecase == USECASE_COMPRESS_VOIP_CALL) ret = voice_extn_compress_voip_start_input_stream(in); Loading @@ -6884,6 +6952,10 @@ static ssize_t in_read(struct audio_stream_in *stream, void *buffer, goto exit; } in->standby = 0; // log startup time in ms. simple_stats_log( &in->start_latency_ms, (systemTime(SYSTEM_TIME_MONOTONIC) - startNs) * 1e-6); } /* Avoid read if capture_stopped is set */ Loading Loading @@ -8256,6 +8328,8 @@ int adev_open_output_stream(struct audio_hw_device *dev, else out->af_period_multiplier = 1; out->kernel_buffer_size = out->config.period_size * out->config.period_count; out->standby = 1; /* out->muted = false; by calloc() */ /* out->written = 0; by calloc() */ Loading Loading @@ -8772,6 +8846,7 @@ static char* adev_get_parameters(const struct audio_hw_device *dev, voice_get_parameters(adev, query, reply); audio_extn_a2dp_get_parameters(query, reply); platform_get_parameters(adev->platform, query, reply); audio_extn_ma_get_parameters(adev, query, reply); pthread_mutex_unlock(&adev->lock); exit: Loading
hal/audio_hw.h +14 −0 Original line number Diff line number Diff line Loading @@ -48,6 +48,8 @@ #include <audio_route/audio_route.h> #include <audio_utils/ErrorLog.h> #include <audio_utils/Statistics.h> #include <audio_utils/clock.h> #include "audio_defs.h" #include "voice.h" #include "audio_hw_extn_api.h" Loading Loading @@ -454,6 +456,16 @@ struct stream_out { int stream; } cs; } extconn; size_t kernel_buffer_size; // cached value of the alsa buffer size, const after open(). // last out_get_presentation_position() cached info. bool last_fifo_valid; unsigned int last_fifo_frames_remaining; int64_t last_fifo_time_ns; simple_stats_t fifo_underruns; // TODO: keep a list of the last N fifo underrun times. simple_stats_t start_latency_ms; }; struct stream_in { Loading Loading @@ -507,6 +519,8 @@ struct stream_in { int64_t frames_muted; /* total frames muted, not cleared when entering standby */ error_log_t *error_log; simple_stats_t start_latency_ms; }; typedef enum { Loading