hal: enable 24 bit capture
- capture 24_8 bit data from driver
- convert data to 8_24 bit and pass above
- allow 24 bit capture only when voice call is not active
Bug: git 27348418
Change-Id: I19138f008275ba2aa36f44c1b0aecbe6547bd399
diff --git a/hal/audio_hw.c b/hal/audio_hw.c
index b95ddf6..43a38aa 100644
--- a/hal/audio_hw.c
+++ b/hal/audio_hw.c
@@ -485,6 +485,8 @@
bool switch_device[AUDIO_USECASE_MAX];
int i, num_uc_to_switch = 0;
+ platform_check_and_set_capture_backend_cfg(adev, uc_info, snd_device);
+
/*
* This function is to make sure that all the active capture usecases
* are always routed to the same input sound device.
@@ -1292,7 +1294,7 @@
audio_format_t format,
int channel_count)
{
- if (format != AUDIO_FORMAT_PCM_16_BIT) {
+ if ((format != AUDIO_FORMAT_PCM_16_BIT) && (format != AUDIO_FORMAT_PCM_8_24_BIT)) {
ALOGE("%s: unsupported AUDIO FORMAT (%d) ", __func__, format);
return -EINVAL;
}
@@ -1335,9 +1337,8 @@
size = (sample_rate * AUDIO_CAPTURE_PERIOD_DURATION_MSEC) / 1000;
if (is_low_latency)
size = configured_low_latency_capture_period_size;
- /* ToDo: should use frame_size computed based on the format and
- channel_count here. */
- size *= sizeof(short) * channel_count;
+
+ size *= channel_count * audio_bytes_per_sample(format);
/* make sure the size is multiple of 32 bytes
* At 48 kHz mono 16-bit PCM:
@@ -1942,9 +1943,10 @@
return in->channel_mask;
}
-static audio_format_t in_get_format(const struct audio_stream *stream __unused)
+static audio_format_t in_get_format(const struct audio_stream *stream)
{
- return AUDIO_FORMAT_PCM_16_BIT;
+ struct stream_in *in = (struct stream_in *)stream;
+ return in->format;
}
static int in_set_format(struct audio_stream *stream __unused, audio_format_t format __unused)
@@ -2055,6 +2057,7 @@
struct stream_in *in = (struct stream_in *)stream;
struct audio_device *adev = in->dev;
int i, ret = -1;
+ int *int_buf_stream = NULL;
lock_input_stream(in);
@@ -2084,8 +2087,22 @@
if (in->pcm) {
if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
ret = pcm_mmap_read(in->pcm, buffer, bytes);
- } else
+ } else {
ret = pcm_read(in->pcm, buffer, bytes);
+ if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
+ if (bytes % 4 == 0) {
+ /* data from DSP comes in 24_8 format, convert it to 8_24 */
+ int_buf_stream = buffer;
+ for (size_t itt=0; itt < bytes/4 ; itt++) {
+ int_buf_stream[itt] >>= 8;
+ }
+ } else {
+ ALOGE("%s: !!! something wrong !!! ... data not 32 bit aligned ", __func__);
+ ret = -EINVAL;
+ goto exit;
+ }
+ }
+ }
}
if (adev->adm_abandon_focus)
@@ -2689,8 +2706,19 @@
in->channel_mask = config->channel_mask;
in->capture_handle = handle;
in->flags = flags;
+ in->format = config->format;
// in->frames_read = 0;
+ if (in->format == AUDIO_FORMAT_DEFAULT)
+ config->format = AUDIO_FORMAT_PCM_16_BIT;
+
+ if (config->format == AUDIO_FORMAT_PCM_FLOAT ||
+ config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) {
+ config->format = AUDIO_FORMAT_PCM_8_24_BIT;
+ ret = -EINVAL;
+ goto err_open;
+ }
+
/* Update config params with the requested sample rate and channels */
if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
if (config->sample_rate == 0)
@@ -2701,8 +2729,7 @@
ret = -EINVAL;
goto err_open;
}
- if (config->format == AUDIO_FORMAT_DEFAULT)
- config->format = AUDIO_FORMAT_PCM_16_BIT;
+
if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
config->format = AUDIO_FORMAT_PCM_16_BIT;
ret = -EINVAL;
@@ -2722,6 +2749,9 @@
}
in->config = pcm_config_audio_capture;
+ if (config->format == AUDIO_FORMAT_PCM_8_24_BIT)
+ in->config.format = PCM_FORMAT_S24_LE;
+
frame_size = audio_stream_in_frame_size(&in->stream);
buffer_size = get_input_buffer_size(config->sample_rate,
config->format,
diff --git a/hal/audio_hw.h b/hal/audio_hw.h
index 1a1e0ef..1d31489 100644
--- a/hal/audio_hw.h
+++ b/hal/audio_hw.h
@@ -203,6 +203,7 @@
bool is_st_session_active;
struct audio_device *dev;
+ audio_format_t format;
};
typedef enum {
diff --git a/hal/msm8960/platform.c b/hal/msm8960/platform.c
index b2d4e04..6a934c4 100644
--- a/hal/msm8960/platform.c
+++ b/hal/msm8960/platform.c
@@ -1096,3 +1096,9 @@
return 0;
}
+bool platform_check_and_set_capture_backend_cfg(struct audio_device* adev __unused,
+ struct audio_usecase *usecase __unused)
+{
+ return false;
+}
+
diff --git a/hal/msm8974/platform.c b/hal/msm8974/platform.c
index f4f2f73..e745b49 100644
--- a/hal/msm8974/platform.c
+++ b/hal/msm8974/platform.c
@@ -264,6 +264,9 @@
[SND_DEVICE_IN_VOICE_REC_HEADSET_MIC] = "headset-mic",
[SND_DEVICE_IN_UNPROCESSED_MIC] = "unprocessed-mic",
+ [SND_DEVICE_IN_UNPROCESSED_STEREO_MIC] = "voice-rec-dmic-ef",
+ [SND_DEVICE_IN_UNPROCESSED_THREE_MIC] = "three-mic",
+ [SND_DEVICE_IN_UNPROCESSED_QUAD_MIC] = "quad-mic",
[SND_DEVICE_IN_UNPROCESSED_HEADSET_MIC] = "headset-mic",
[SND_DEVICE_IN_VOICE_RX] = "voice-rx",
@@ -357,6 +360,9 @@
[SND_DEVICE_IN_UNPROCESSED_MIC] = ACDB_ID_VOICE_REC_MIC,
[SND_DEVICE_IN_UNPROCESSED_HEADSET_MIC] = ACDB_ID_HEADSET_MIC_AEC,
+ [SND_DEVICE_IN_UNPROCESSED_STEREO_MIC] = 35,
+ [SND_DEVICE_IN_UNPROCESSED_THREE_MIC] = 125,
+ [SND_DEVICE_IN_UNPROCESSED_QUAD_MIC] = 125,
[SND_DEVICE_IN_VOICE_RX] = 44,
@@ -456,6 +462,9 @@
{TO_NAME_INDEX(SND_DEVICE_IN_UNPROCESSED_MIC)},
{TO_NAME_INDEX(SND_DEVICE_IN_UNPROCESSED_HEADSET_MIC)},
+ {TO_NAME_INDEX(SND_DEVICE_IN_UNPROCESSED_STEREO_MIC)},
+ {TO_NAME_INDEX(SND_DEVICE_IN_UNPROCESSED_THREE_MIC)},
+ {TO_NAME_INDEX(SND_DEVICE_IN_UNPROCESSED_QUAD_MIC)},
{TO_NAME_INDEX(SND_DEVICE_IN_THREE_MIC)},
{TO_NAME_INDEX(SND_DEVICE_IN_QUAD_MIC)},
@@ -2104,7 +2113,19 @@
}
} else if (source == AUDIO_SOURCE_UNPROCESSED) {
if (in_device & AUDIO_DEVICE_IN_BUILTIN_MIC) {
- snd_device = SND_DEVICE_IN_UNPROCESSED_MIC;
+ if (((channel_mask == AUDIO_CHANNEL_IN_FRONT_BACK) ||
+ (channel_mask == AUDIO_CHANNEL_IN_STEREO)) &&
+ (my_data->source_mic_type & SOURCE_DUAL_MIC)) {
+ snd_device = SND_DEVICE_IN_UNPROCESSED_STEREO_MIC;
+ } else if (((int)channel_mask == AUDIO_CHANNEL_INDEX_MASK_3) &&
+ (my_data->source_mic_type & SOURCE_THREE_MIC)) {
+ snd_device = SND_DEVICE_IN_UNPROCESSED_THREE_MIC;
+ } else if (((int)channel_mask == AUDIO_CHANNEL_INDEX_MASK_4) &&
+ (my_data->source_mic_type & SOURCE_QUAD_MIC)) {
+ snd_device = SND_DEVICE_IN_UNPROCESSED_QUAD_MIC;
+ } else {
+ snd_device = SND_DEVICE_IN_UNPROCESSED_MIC;
+ }
} else if (in_device & AUDIO_DEVICE_IN_WIRED_HEADSET) {
snd_device = SND_DEVICE_IN_UNPROCESSED_HEADSET_MIC;
}
@@ -2529,6 +2550,26 @@
}
}
+bool platform_check_and_set_capture_backend_cfg(struct audio_device* adev,
+ struct audio_usecase *usecase, snd_device_t snd_device)
+{
+ enum pcm_format in_pcm_format = PCM_FORMAT_S16_LE;
+
+ if (adev && adev->active_input)
+ in_pcm_format = adev->active_input->config.format;
+
+ // allow 24 bit recording only if voice call is not active
+ if (!voice_is_in_call(adev) &&
+ adev->mode != AUDIO_MODE_IN_COMMUNICATION &&
+ in_pcm_format == PCM_FORMAT_S24_LE) {
+ audio_route_apply_and_update_path(adev->audio_route, "set-capture-format-24le");
+ } else {
+ audio_route_apply_and_update_path(adev->audio_route, "set-capture-format-default");
+ }
+
+ return true;
+}
+
int platform_set_snd_device_backend(snd_device_t device, const char *backend_tag,
const char * hw_interface)
{
diff --git a/hal/msm8974/platform.h b/hal/msm8974/platform.h
index 7a27359..0f81915 100644
--- a/hal/msm8974/platform.h
+++ b/hal/msm8974/platform.h
@@ -135,6 +135,9 @@
SND_DEVICE_IN_UNPROCESSED_MIC,
SND_DEVICE_IN_UNPROCESSED_HEADSET_MIC,
+ SND_DEVICE_IN_UNPROCESSED_STEREO_MIC,
+ SND_DEVICE_IN_UNPROCESSED_THREE_MIC,
+ SND_DEVICE_IN_UNPROCESSED_QUAD_MIC,
SND_DEVICE_IN_VOICE_RX,
diff --git a/hal/platform_api.h b/hal/platform_api.h
index 9bd55b1..5e54e03 100644
--- a/hal/platform_api.h
+++ b/hal/platform_api.h
@@ -86,4 +86,7 @@
int platform_set_parameters(void *platform, struct str_parms *parms);
+bool platform_check_and_set_capture_backend_cfg(struct audio_device* adev,
+ struct audio_usecase *usecase, snd_device_t snd_device);
+
#endif // AUDIO_PLATFORM_API_H