audio: hal: enable dynamic DSP bitwidth configuration
DSP Bitwidth can be dynamically configured. ASM bitwidth
is configured via mixer ctl, while ADM and AFE are set
by HAL interface.
CRs-Fixed: 2080987
Change-Id: I6f35ac8036e3e4ddc3714c7a2c03272d9da5d584
diff --git a/hal/audio_extn/audio_extn.h b/hal/audio_extn/audio_extn.h
index 67a8e26..19f08c6 100644
--- a/hal/audio_extn/audio_extn.h
+++ b/hal/audio_extn/audio_extn.h
@@ -594,6 +594,7 @@
struct audio_device *adev,
struct audio_usecase *usecase);
int audio_extn_utils_get_snd_card_num();
+bool audio_extn_is_dsp_bit_width_enforce_mode_supported(audio_output_flags_t flags);
#ifdef DS2_DOLBY_DAP_ENABLED
#define LIB_DS2_DAP_HAL "vendor/lib/libhwdaphal.so"
diff --git a/hal/audio_extn/utils.c b/hal/audio_extn/utils.c
index 9b0df8e..303cb63 100644
--- a/hal/audio_extn/utils.c
+++ b/hal/audio_extn/utils.c
@@ -385,6 +385,7 @@
struct mixer_ctl *ctl = NULL;
const char *mixer_ctl_name = "App Type Config";
struct streams_io_cfg *s_info = NULL;
+ uint32_t target_bit_width = 0;
if (!mixer) {
ALOGE("%s: mixer is null",__func__);
@@ -410,6 +411,9 @@
num_app_types += 1;
}
+ /* get target bit width for ADM enforce mode */
+ target_bit_width = adev_get_dsp_bit_width_enforce_mode();
+
list_for_each(node, streams_output_cfg_list) {
s_info = node_to_item(node, struct streams_io_cfg, list);
update = true;
@@ -421,6 +425,11 @@
app_type_cfg[i+2] = s_info->app_type_cfg.sample_rate;
if (app_type_cfg[i+3] < (size_t)s_info->app_type_cfg.bit_width)
app_type_cfg[i+3] = s_info->app_type_cfg.bit_width;
+ /* ADM bit width = max(enforce_bit_width, bit_width from s_info */
+ if (audio_extn_is_dsp_bit_width_enforce_mode_supported(s_info->flags.out_flags) &&
+ (target_bit_width > app_type_cfg[i+3]))
+ app_type_cfg[i+3] = target_bit_width;
+
update = false;
break;
}
@@ -429,7 +438,12 @@
num_app_types += 1;
app_type_cfg[length++] = s_info->app_type_cfg.app_type;
app_type_cfg[length++] = s_info->app_type_cfg.sample_rate;
- app_type_cfg[length++] = s_info->app_type_cfg.bit_width;
+ app_type_cfg[length] = s_info->app_type_cfg.bit_width;
+ if (audio_extn_is_dsp_bit_width_enforce_mode_supported(s_info->flags.out_flags) &&
+ (target_bit_width > app_type_cfg[length]))
+ app_type_cfg[length] = target_bit_width;
+
+ length++;
}
}
list_for_each(node, streams_input_cfg_list) {
@@ -759,6 +773,28 @@
return native_usecase;
}
+bool audio_extn_is_dsp_bit_width_enforce_mode_supported(audio_output_flags_t flags)
+{
+ /* DSP bitwidth enforce mode for ADM and AFE:
+ * includes:
+ * deep buffer, low latency, direct pcm and offload.
+ * excludes:
+ * ull(raw+fast), VOIP.
+ */
+ if ((flags & AUDIO_OUTPUT_FLAG_VOIP_RX) ||
+ ((flags & AUDIO_OUTPUT_FLAG_RAW) &&
+ (flags & AUDIO_OUTPUT_FLAG_FAST)))
+ return false;
+
+
+ if ((flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
+ (flags & AUDIO_OUTPUT_FLAG_DIRECT) ||
+ (flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) ||
+ (flags & AUDIO_OUTPUT_FLAG_PRIMARY))
+ return true;
+ else
+ return false;
+}
static inline bool audio_is_vr_mode_on(struct audio_device *(__attribute__((unused)) adev))
{
diff --git a/hal/audio_hw.c b/hal/audio_hw.c
index f5129c5..f2820a7 100644
--- a/hal/audio_hw.c
+++ b/hal/audio_hw.c
@@ -1439,6 +1439,84 @@
return active;
}
+uint32_t adev_get_dsp_bit_width_enforce_mode()
+{
+ if (adev == NULL) {
+ ALOGE("%s: adev is null. Disable DSP bit width enforce mode.\n", __func__);
+ return 0;
+ }
+ return adev->dsp_bit_width_enforce_mode;
+}
+
+static uint32_t adev_init_dsp_bit_width_enforce_mode(struct mixer *mixer)
+{
+ char value[PROPERTY_VALUE_MAX];
+ int trial;
+ uint32_t dsp_bit_width_enforce_mode = 0;
+
+ if (!mixer) {
+ ALOGE("%s: adev mixer is null. cannot update DSP bitwidth.\n",
+ __func__);
+ return 0;
+ }
+
+ if (property_get("persist.vendor.audio_hal.dsp_bit_width_enforce_mode",
+ value, NULL) > 0) {
+ trial = atoi(value);
+ switch (trial) {
+ case 16:
+ dsp_bit_width_enforce_mode = 16;
+ break;
+ case 24:
+ dsp_bit_width_enforce_mode = 24;
+ break;
+ case 32:
+ dsp_bit_width_enforce_mode = 32;
+ break;
+ default:
+ dsp_bit_width_enforce_mode = 0;
+ ALOGD("%s Dynamic DSP bitwidth config is disabled.", __func__);
+ break;
+ }
+ }
+
+ return dsp_bit_width_enforce_mode;
+}
+
+static void audio_enable_asm_bit_width_enforce_mode(struct mixer *mixer,
+ uint32_t enforce_mode,
+ bool enable)
+{
+ struct mixer_ctl *ctl = NULL;
+ const char *mixer_ctl_name = "ASM Bit Width";
+ uint32_t asm_bit_width_mode = 0;
+
+ if (enforce_mode == 0) {
+ ALOGD("%s: DSP bitwidth feature is disabled.", __func__);
+ return;
+ }
+
+ ctl = mixer_get_ctl_by_name(mixer, mixer_ctl_name);
+ if (!ctl) {
+ ALOGE("%s: Could not get ctl for mixer cmd - %s",
+ __func__, mixer_ctl_name);
+ return;
+ }
+
+ if (enable)
+ asm_bit_width_mode = enforce_mode;
+ else
+ asm_bit_width_mode = 0;
+
+ ALOGV("%s DSP bit width feature status is %d width=%d",
+ __func__, enable, asm_bit_width_mode);
+ if (mixer_ctl_set_value(ctl, 0, asm_bit_width_mode) < 0)
+ ALOGE("%s: Could not set ASM biwidth %d", __func__,
+ asm_bit_width_mode);
+
+ return;
+}
+
/*
* if native DSD playback active
*/
@@ -2297,6 +2375,12 @@
/* 2. Disable the rx device */
disable_snd_device(adev, uc_info->out_snd_device);
+ if (is_offload_usecase(out->usecase)) {
+ audio_enable_asm_bit_width_enforce_mode(adev->mixer,
+ adev->dsp_bit_width_enforce_mode,
+ false);
+ }
+
list_remove(&uc_info->list);
free(uc_info);
out->started = 0;
@@ -2483,6 +2567,9 @@
} else {
platform_set_stream_channel_map(adev->platform, out->channel_mask,
out->pcm_device_id, &out->channel_map_param.channel_map[0]);
+ audio_enable_asm_bit_width_enforce_mode(adev->mixer,
+ adev->dsp_bit_width_enforce_mode,
+ true);
out->pcm = NULL;
out->compr = compress_open(adev->snd_card,
out->pcm_device_id,
@@ -5591,6 +5678,7 @@
adev->perf_lock_opts[0] = 0x101;
adev->perf_lock_opts[1] = 0x20E;
adev->perf_lock_opts_size = 2;
+ adev->dsp_bit_width_enforce_mode = 0;
/* Loads platform specific libraries dynamically */
adev->platform = platform_init(adev);
@@ -5703,6 +5791,8 @@
audio_extn_ds2_enable(adev);
*device = &adev->device.common;
+ adev->dsp_bit_width_enforce_mode =
+ adev_init_dsp_bit_width_enforce_mode(adev->mixer);
audio_extn_utils_update_streams_cfg_lists(adev->platform, adev->mixer,
&adev->streams_output_cfg_list,
diff --git a/hal/audio_hw.h b/hal/audio_hw.h
index 80b11b8..1aa5385 100644
--- a/hal/audio_hw.h
+++ b/hal/audio_hw.h
@@ -466,6 +466,7 @@
bool asrc_mode_enabled;
qahwi_device_t qahwi_dev;
bool vr_audio_mode_enabled;
+ uint32_t dsp_bit_width_enforce_mode;
bool bt_sco_on;
};
@@ -492,6 +493,8 @@
bool audio_is_dsd_native_stream_active(struct audio_device *adev);
+uint32_t adev_get_dsp_bit_width_enforce_mode();
+
int pcm_ioctl(struct pcm *pcm, int request, ...);
audio_usecase_t get_usecase_id_from_usecase_type(const struct audio_device *adev,
diff --git a/hal/msm8916/platform.c b/hal/msm8916/platform.c
index 3fc1ef2..257d3bc 100644
--- a/hal/msm8916/platform.c
+++ b/hal/msm8916/platform.c
@@ -5748,6 +5748,10 @@
backend_cfg.format = usecase->stream.out->format;
backend_cfg.channels = audio_channel_count_from_out_mask(usecase->stream.out->channel_mask);
}
+ /* enforce AFE bitwidth mode via backend_cfg */
+ if (audio_extn_is_dsp_bit_width_enforce_mode_supported(usecase->stream.out->flags) &&
+ (adev->dsp_bit_width_enforce_mode > backend_cfg.bit_width))
+ backend_cfg.bit_width = adev->dsp_bit_width_enforce_mode;
/*this is populated by check_codec_backend_cfg hence set default value to false*/
backend_cfg.passthrough_enabled = false;
diff --git a/hal/msm8974/platform.c b/hal/msm8974/platform.c
old mode 100755
new mode 100644
index 9c23f16..d7a36a6
--- a/hal/msm8974/platform.c
+++ b/hal/msm8974/platform.c
@@ -5598,6 +5598,9 @@
backend_cfg.format = usecase->stream.out->format;
backend_cfg.channels = audio_channel_count_from_out_mask(usecase->stream.out->channel_mask);
}
+ if (audio_extn_is_dsp_bit_width_enforce_mode_supported(usecase->stream.out->flags) &&
+ (adev->dsp_bit_width_enforce_mode > backend_cfg.bit_width))
+ backend_cfg.bit_width = adev->dsp_bit_width_enforce_mode;
/*this is populated by check_codec_backend_cfg hence set default value to false*/
backend_cfg.passthrough_enabled = false;