audio: Apply app type gain at start of stream
App type for a usecase is derived at start of stream.
Therefore, any volume gain based on app type cannot be
applied before start. Cache any gain value
sent from AF before start of stream and send after
stream has started
Bug: 62393776
Test: hangout call
Change-Id: Ia772d5ee1b2cc7293d69b31f06f1c160a5d7284e
Signed-off-by: David Lin <dtwlin@google.com>
diff --git a/hal/audio_extn/audio_extn.h b/hal/audio_extn/audio_extn.h
index 600c179..36a8ba5 100644
--- a/hal/audio_extn/audio_extn.h
+++ b/hal/audio_extn/audio_extn.h
@@ -145,6 +145,9 @@
struct audio_usecase *usecase);
void audio_extn_utils_send_audio_calibration(struct audio_device *adev,
struct audio_usecase *usecase);
+int audio_extn_utils_send_app_type_gain(struct audio_device *adev,
+ int app_type,
+ int *gain);
#ifndef HWDEP_CAL_ENABLED
#define audio_extn_hwdep_cal_send(snd_card, acdb_handle) (0)
#else
diff --git a/hal/audio_extn/utils.c b/hal/audio_extn/utils.c
index 2fc424c..c9d2397 100644
--- a/hal/audio_extn/utils.c
+++ b/hal/audio_extn/utils.c
@@ -218,7 +218,7 @@
struct stream_app_type_cfg *app_type_cfg = &in->app_type_cfg;
*sample_rate = DEFAULT_INPUT_SAMPLING_RATE;
- if (in->device & AUDIO_DEVICE_IN_USB_DEVICE) {
+ if (audio_is_usb_in_device(in->device)) {
platform_check_and_update_copp_sample_rate(adev->platform,
usecase->in_snd_device,
in->sample_rate,
@@ -271,7 +271,7 @@
// add speaker prot changes if needed
// and use that to check for device
- if (out->devices & AUDIO_DEVICE_OUT_USB_DEVICE) {
+ if (audio_is_usb_out_device(out->devices)) {
platform_check_and_update_copp_sample_rate(adev->platform,
usecase->out_snd_device,
out->sample_rate,
@@ -385,6 +385,28 @@
return 0;
}
+int audio_extn_utils_send_app_type_gain(struct audio_device *adev,
+ int app_type,
+ int *gain)
+{
+ int gain_cfg[4];
+ const char *mixer_ctl_name = "App Type Gain";
+ struct mixer_ctl *ctl;
+ ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
+ if (!ctl) {
+ ALOGE("%s: Could not get volume ctl mixer %s", __func__,
+ mixer_ctl_name);
+ return -EINVAL;
+ }
+ gain_cfg[0] = 0;
+ gain_cfg[1] = app_type;
+ gain_cfg[2] = gain[0];
+ gain_cfg[3] = gain[1];
+ ALOGV("%s app_type %d l(%d) r(%d)", __func__, app_type, gain[0], gain[1]);
+ return mixer_ctl_set_array(ctl, gain_cfg,
+ sizeof(gain_cfg)/sizeof(gain_cfg[0]));
+}
+
// this assumes correct app_type and sample_rate fields
// have been set for the stream using audio_extn_utils_send_app_type_cfg
void audio_extn_utils_send_audio_calibration(struct audio_device *adev,
diff --git a/hal/audio_hw.c b/hal/audio_hw.c
index 44a0216..3ad965e 100644
--- a/hal/audio_hw.c
+++ b/hal/audio_hw.c
@@ -66,7 +66,11 @@
#define COMPRESS_OFFLOAD_NUM_FRAGMENTS 3
/* ToDo: Check and update a proper value in msec */
#define COMPRESS_OFFLOAD_PLAYBACK_LATENCY 96
+/* treat as unsigned Q1.13 */
+#define APP_TYPE_GAIN_DEFAULT 0x2000
#define COMPRESS_PLAYBACK_VOLUME_MAX 0x2000
+
+/* treat as unsigned Q1.13 */
#define VOIP_PLAYBACK_VOLUME_MAX 0x2000
#define PROXY_OPEN_RETRY_COUNT 100
@@ -536,6 +540,11 @@
return ret;
}
+static void stream_app_type_cfg_init(struct stream_app_type_cfg *cfg)
+{
+ cfg->gain[0] = cfg->gain[1] = APP_TYPE_GAIN_DEFAULT;
+}
+
int enable_audio_route(struct audio_device *adev,
struct audio_usecase *usecase)
{
@@ -1859,7 +1868,9 @@
register_out_stream(out);
audio_extn_perf_lock_release();
audio_extn_tfa_98xx_enable_speaker();
-
+ audio_extn_utils_send_app_type_gain(out->dev,
+ out->app_type_cfg.app_type,
+ &out->app_type_cfg.gain[0]);
ALOGV("%s: exit", __func__);
return 0;
error_open:
@@ -2378,21 +2389,14 @@
mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
return 0;
} else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
- int gain_cfg[4];
- const char *mixer_ctl_name = "App Type Gain";
- struct audio_device *adev = out->dev;
- struct mixer_ctl *ctl;
- ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
- if (!ctl) {
- ALOGE("%s: Could not get volume ctl mixer %s", __func__,
- mixer_ctl_name);
- return -EINVAL;
+ out->app_type_cfg.gain[0] = (int)(left * VOIP_PLAYBACK_VOLUME_MAX);
+ out->app_type_cfg.gain[1] = (int)(right * VOIP_PLAYBACK_VOLUME_MAX);
+ if (!out->standby) {
+ // if in standby, cached volume will be sent after stream is opened
+ audio_extn_utils_send_app_type_gain(out->dev,
+ out->app_type_cfg.app_type,
+ &out->app_type_cfg.gain[0]);
}
- gain_cfg[0] = 0;
- gain_cfg[1] = out->app_type_cfg.app_type;
- gain_cfg[2] = (int)(left * VOIP_PLAYBACK_VOLUME_MAX);
- gain_cfg[3] = (int)(right * VOIP_PLAYBACK_VOLUME_MAX);
- mixer_ctl_set_array(ctl, gain_cfg, sizeof(gain_cfg)/sizeof(gain_cfg[0]));
return 0;
}
@@ -3765,6 +3769,8 @@
pthread_mutex_unlock(&adev->lock);
pthread_mutex_unlock(&out->lock);
+ stream_app_type_cfg_init(&out->app_type_cfg);
+
*stream_out = &out->stream;
ALOGV("%s: exit", __func__);
@@ -4258,6 +4264,7 @@
ALOGV("%s: USECASE_AUDIO_RECORD_MMAP", __func__);
} else if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION &&
in->dev->mode == AUDIO_MODE_IN_COMMUNICATION &&
+ in->flags & AUDIO_INPUT_FLAG_VOIP_TX &&
(config->sample_rate == 8000 ||
config->sample_rate == 16000 ||
config->sample_rate == 32000 ||
@@ -4274,7 +4281,6 @@
in->config.period_count = VOIP_CAPTURE_PERIOD_COUNT;
in->config.rate = config->sample_rate;
in->af_period_multiplier = 1;
- in->flags |= AUDIO_INPUT_FLAG_VOIP_TX;
} else {
in->config = pcm_config_audio_capture;
frame_size = audio_stream_in_frame_size(&in->stream);
@@ -4305,6 +4311,8 @@
pthread_mutex_unlock(&adev->lock);
pthread_mutex_unlock(&in->lock);
+ stream_app_type_cfg_init(&in->app_type_cfg);
+
*stream_in = &in->stream;
ALOGV("%s: exit", __func__);
return 0;
diff --git a/hal/audio_hw.h b/hal/audio_hw.h
index 28bf19b..46384a2 100644
--- a/hal/audio_hw.h
+++ b/hal/audio_hw.h
@@ -177,6 +177,7 @@
uint32_t bit_width; // unused
const char *mode;
int app_type;
+ int gain[2];
};
struct stream_out {