hal: changes to support 24 bit record
-Changes to support 24 bit record if input format request is
AUDIO_FORMAT_PCM_8_24_BIT or AUDIO_FORMAT_PCM_24_BIT_PACKED
Change-Id: I68076524ccccbf9f0be3c88bb01180ae7e4fd8b1
diff --git a/configs/msm8996/audio_policy.conf b/configs/msm8996/audio_policy.conf
index eaf896f..453aca4 100644
--- a/configs/msm8996/audio_policy.conf
+++ b/configs/msm8996/audio_policy.conf
@@ -99,6 +99,12 @@
formats AUDIO_FORMAT_PCM_16_BIT|AUDIO_FORMAT_AMR_NB|AUDIO_FORMAT_AMR_WB|AUDIO_FORMAT_QCELP|AUDIO_FORMAT_EVRC|AUDIO_FORMAT_EVRCB|AUDIO_FORMAT_EVRCWB|AUDIO_FORMAT_EVRCNW
devices AUDIO_DEVICE_IN_WIRED_HEADSET|AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET|AUDIO_DEVICE_IN_FM_TUNER|AUDIO_DEVICE_IN_VOICE_CALL
}
+ float {
+ sampling_rates 8000|11025|12000|16000|22050|24000|32000|44100|48000|96000|192000
+ channel_masks AUDIO_CHANNEL_IN_MONO|AUDIO_CHANNEL_IN_STEREO|AUDIO_CHANNEL_IN_FRONT_BACK
+ formats AUDIO_FORMAT_PCM_24_BIT_PACKED
+ devices AUDIO_DEVICE_IN_BUILTIN_MIC|AUDIO_DEVICE_IN_BACK_MIC|AUDIO_DEVICE_IN_WIRED_HEADSET
+ }
surround_sound {
sampling_rates 8000|11025|12000|16000|22050|24000|32000|44100|48000
channel_masks AUDIO_CHANNEL_IN_5POINT1|AUDIO_CHANNEL_IN_MONO|AUDIO_CHANNEL_IN_STEREO|AUDIO_CHANNEL_IN_FRONT_BACK
diff --git a/hal/audio_extn/ssr.c b/hal/audio_extn/ssr.c
index 6534385..f55f3ce 100644
--- a/hal/audio_extn/ssr.c
+++ b/hal/audio_extn/ssr.c
@@ -344,7 +344,8 @@
if (audio_extn_ssr_get_enabled() &&
((channel_count == 2) || (channel_count == 6)) &&
((AUDIO_SOURCE_MIC == source) || (AUDIO_SOURCE_CAMCORDER == source)) &&
- ((AUDIO_DEVICE_IN_BUILTIN_MIC == devices) || (AUDIO_DEVICE_IN_BACK_MIC == devices))) {
+ ((AUDIO_DEVICE_IN_BUILTIN_MIC == devices) || (AUDIO_DEVICE_IN_BACK_MIC == devices)) &&
+ (in->format == AUDIO_FORMAT_PCM_16_BIT)) {
ALOGD("%s: Found SSR use case starting SSR lib with channel_count :%d",
__func__, channel_count);
diff --git a/hal/audio_hw.c b/hal/audio_hw.c
index aa1bc05..8486e18 100644
--- a/hal/audio_hw.c
+++ b/hal/audio_hw.c
@@ -751,7 +751,7 @@
}
}
-static void check_and_route_capture_usecases(struct audio_device *adev,
+static void check_usecases_capture_codec_backend(struct audio_device *adev,
struct audio_usecase *uc_info,
snd_device_t snd_device)
{
@@ -760,6 +760,9 @@
bool switch_device[AUDIO_USECASE_MAX];
int i, num_uc_to_switch = 0;
+ bool force_routing = platform_check_and_set_capture_codec_backend_cfg(adev, uc_info,
+ snd_device);
+ ALOGD("%s:becf: force routing %d", __func__, force_routing);
/*
* This function is to make sure that all the active capture usecases
* are always routed to the same input sound device.
@@ -777,7 +780,7 @@
usecase = node_to_item(node, struct audio_usecase, list);
if (usecase->type != PCM_PLAYBACK &&
usecase != uc_info &&
- usecase->in_snd_device != snd_device &&
+ (usecase->in_snd_device != snd_device || force_routing) &&
((uc_info->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
(((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND) ||
(usecase->type == VOICE_CALL))) &&
@@ -1149,7 +1152,7 @@
}
if (in_snd_device != SND_DEVICE_NONE) {
- check_and_route_capture_usecases(adev, usecase, in_snd_device);
+ check_usecases_capture_codec_backend(adev, usecase, in_snd_device);
enable_snd_device(adev, in_snd_device);
}
@@ -1291,8 +1294,8 @@
adev->perf_lock_opts_size);
select_devices(adev, in->usecase);
- ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
- __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
+ ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d format %d",
+ __func__, adev->snd_card, in->pcm_device_id, in->config.channels, in->config.format);
unsigned int flags = PCM_IN;
unsigned int pcm_open_retry_count = 0;
@@ -1996,9 +1999,11 @@
{
int ret = 0;
- if ((format != AUDIO_FORMAT_PCM_16_BIT) &&
+ if (((format != AUDIO_FORMAT_PCM_16_BIT) && (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
+ (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) && (format != AUDIO_FORMAT_PCM_32_BIT) &&
+ (format != AUDIO_FORMAT_PCM_FLOAT)) &&
!voice_extn_compress_voip_is_format_supported(format) &&
- !audio_extn_compr_cap_format_supported(format)) ret = -EINVAL;
+ !audio_extn_compr_cap_format_supported(format)) ret = -EINVAL;
switch (channel_count) {
case 1:
@@ -2019,6 +2024,8 @@
case 32000:
case 44100:
case 48000:
+ case 96000:
+ case 192000:
break;
default:
ret = -EINVAL;
@@ -2040,9 +2047,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 *= audio_bytes_per_sample(format) * channel_count;
/* make sure the size is multiple of 32 bytes
* At 48 kHz mono 16-bit PCM:
@@ -3033,6 +3039,7 @@
struct audio_device *adev = in->dev;
int ret = -1;
int snd_scard_state = get_snd_card_state(adev);
+ int *int_buf_stream = NULL;
lock_input_stream(in);
@@ -3069,16 +3076,30 @@
adev->adm_request_focus(adev->adm_data, in->capture_handle);
if (in->pcm) {
- if (audio_extn_ssr_get_stream() == in)
+ if (audio_extn_ssr_get_stream() == in) {
ret = audio_extn_ssr_read(stream, buffer, bytes);
- else if (audio_extn_compr_cap_usecase_supported(in->usecase))
+ } else if (audio_extn_compr_cap_usecase_supported(in->usecase)) {
ret = audio_extn_compr_cap_read(in, buffer, bytes);
- else if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY)
+ } else 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 < 0)
- ret = -errno;
+ 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 (ret < 0) {
+ ret = -errno;
+ }
+ }
}
if (adev->adm_abandon_focus)
@@ -3921,9 +3942,8 @@
}
ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
- stream_handle(%p) io_handle(%d) source(%d)",__func__, config->sample_rate, config->channel_mask,
- devices, &in->stream, handle, source);
-
+ stream_handle(%p) io_handle(%d) source(%d) format %x",__func__, config->sample_rate,
+ config->channel_mask, devices, &in->stream, handle, source, config->format);
pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
@@ -3963,6 +3983,8 @@
in->config = pcm_config_audio_capture;
in->config.rate = config->sample_rate;
in->format = config->format;
+ in->bit_width = 16;
+ in->sample_rate = config->sample_rate;
if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
if (adev->mode != AUDIO_MODE_IN_CALL) {
@@ -3989,6 +4011,7 @@
in->config = pcm_config_afe_proxy_record;
in->config.channels = channel_count;
in->config.rate = config->sample_rate;
+ in->sample_rate = config->sample_rate;
} else if (!audio_extn_ssr_check_and_set_usecase(in)) {
ALOGD("%s: created surround sound session succesfully",__func__);
} else if (audio_extn_compr_cap_enabled() &&
@@ -3996,6 +4019,48 @@
(in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
audio_extn_compr_cap_init(in);
} else {
+ /* restrict 24 bit capture for unprocessed source only
+ * for other sources if 24 bit requested reject 24 and set 16 bit capture only
+ */
+ if (config->format == AUDIO_FORMAT_DEFAULT) {
+ config->format = AUDIO_FORMAT_PCM_16_BIT;
+ } else if ((config->format == AUDIO_FORMAT_PCM_FLOAT) ||
+ (config->format == AUDIO_FORMAT_PCM_32_BIT) ||
+ (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) ||
+ (config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
+ bool ret_error = false;
+ in->bit_width = 24;
+ /* 24 bit is restricted to UNPROCESSED source only,also format supported
+ from HAL is 24_packed and 8_24
+ *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
+ 24_packed return error indicating supported format is 24_packed
+ *> In case of any other source requesting 24 bit or float return error
+ indicating format supported is 16 bit only.
+
+ on error flinger will retry with supported format passed
+ */
+ if ((source != AUDIO_SOURCE_UNPROCESSED) &&
+ (source != AUDIO_SOURCE_CAMCORDER)) {
+ config->format = AUDIO_FORMAT_PCM_16_BIT;
+ if( config->sample_rate > 48000)
+ config->sample_rate = 48000;
+ ret_error = true;
+ } else if (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) {
+ in->config.format = PCM_FORMAT_S24_3LE;
+ } else if (config->format == AUDIO_FORMAT_PCM_8_24_BIT) {
+ in->config.format = PCM_FORMAT_S24_LE;
+ } else {
+ config->format = AUDIO_FORMAT_PCM_24_BIT_PACKED;
+ ret_error = true;
+ }
+
+ if (ret_error) {
+ ret = -EINVAL;
+ goto err_open;
+ }
+ }
+
+ in->format = config->format;
in->config.channels = channel_count;
frame_size = audio_stream_in_frame_size(&in->stream);
buffer_size = get_input_buffer_size(config->sample_rate,
diff --git a/hal/audio_hw.h b/hal/audio_hw.h
index a1d69a6..31184d5 100644
--- a/hal/audio_hw.h
+++ b/hal/audio_hw.h
@@ -247,7 +247,8 @@
audio_input_flags_t flags;
bool is_st_session;
bool is_st_session_active;
-
+ int sample_rate;
+ int bit_width;
struct audio_device *dev;
};
diff --git a/hal/msm8916/platform.c b/hal/msm8916/platform.c
index 8f27e80..857d9e1 100644
--- a/hal/msm8916/platform.c
+++ b/hal/msm8916/platform.c
@@ -252,6 +252,7 @@
void *edid_info;
bool edid_valid;
codec_backend_cfg_t current_backend_cfg[MAX_CODEC_BACKENDS];
+ codec_backend_cfg_t current_tx_backend_cfg[MAX_CODEC_TX_BACKENDS];
char ec_ref_mixer_path[64];
char codec_version[CODEC_VERSION_MAX_LENGTH];
int hw_dep_fd;
@@ -1809,6 +1810,11 @@
my_data->current_backend_cfg[idx].bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
}
+ my_data->current_tx_backend_cfg[DEFAULT_CODEC_BACKEND].sample_rate =
+ CODEC_BACKEND_DEFAULT_SAMPLE_RATE;
+ my_data->current_tx_backend_cfg[DEFAULT_CODEC_BACKEND].bit_width =
+ CODEC_BACKEND_DEFAULT_BIT_WIDTH;
+
if (is_external_codec) {
my_data->current_backend_cfg[DEFAULT_CODEC_BACKEND].bitwidth_mixer_ctl =
strdup("SLIM_0_RX Format");
@@ -1824,11 +1830,21 @@
strdup("SLIM_6_RX Format");
my_data->current_backend_cfg[HEADPHONE_BACKEND].samplerate_mixer_ctl =
strdup("SLIM_6_RX SampleRate");
+
+ my_data->current_tx_backend_cfg[DEFAULT_CODEC_BACKEND].bitwidth_mixer_ctl =
+ strdup("SLIM_0_TX Format");
+ my_data->current_tx_backend_cfg[DEFAULT_CODEC_BACKEND].samplerate_mixer_ctl =
+ strdup("SLIM_0_TX SampleRate");
} else {
my_data->current_backend_cfg[DEFAULT_CODEC_BACKEND].bitwidth_mixer_ctl =
strdup("MI2S_RX Format");
my_data->current_backend_cfg[DEFAULT_CODEC_BACKEND].samplerate_mixer_ctl =
strdup("MI2S_RX SampleRate");
+
+ my_data->current_tx_backend_cfg[DEFAULT_CODEC_BACKEND].bitwidth_mixer_ctl =
+ strdup("MI2S_TX Format");
+ my_data->current_tx_backend_cfg[DEFAULT_CODEC_BACKEND].samplerate_mixer_ctl =
+ strdup("MI2S_TX SampleRate");
}
ret = audio_extn_utils_get_codec_version(snd_card_name,
@@ -4163,6 +4179,205 @@
return ret;
}
+/*
+ * configures afe with bit width and Sample Rate
+ */
+
+int platform_set_capture_codec_backend_cfg(struct audio_device* adev,
+ snd_device_t snd_device,
+ unsigned int bit_width, unsigned int sample_rate,
+ audio_format_t format)
+{
+ int ret = 0;
+ int backend_idx = DEFAULT_CODEC_BACKEND;
+ struct platform_data *my_data = (struct platform_data *)adev->platform;
+
+ ALOGI("%s:txbecf: afe: bitwidth %d, samplerate %d, backend_idx %d device (%s)",
+ __func__, bit_width, sample_rate, backend_idx,
+ platform_get_snd_device_name(snd_device));
+
+ if (bit_width !=
+ my_data->current_tx_backend_cfg[backend_idx].bit_width) {
+
+ struct mixer_ctl *ctl = NULL;
+ ctl = mixer_get_ctl_by_name(adev->mixer,
+ my_data->current_tx_backend_cfg[backend_idx].bitwidth_mixer_ctl);
+ if (!ctl) {
+ ALOGE("%s:txbecf: afe: Could not get ctl for mixer command - %s",
+ __func__,
+ my_data->current_tx_backend_cfg[backend_idx].bitwidth_mixer_ctl);
+ return -EINVAL;
+ }
+
+ if (bit_width == 24) {
+ if (format == AUDIO_FORMAT_PCM_24_BIT_PACKED)
+ ret = mixer_ctl_set_enum_by_string(ctl, "S24_3LE");
+ else
+ ret = mixer_ctl_set_enum_by_string(ctl, "S24_LE");
+ } else {
+ ret = mixer_ctl_set_enum_by_string(ctl, "S16_LE");
+ }
+
+ if (ret < 0) {
+ ALOGE("%s:txbecf: afe: Could not set ctl for mixer command - %s",
+ __func__,
+ my_data->current_tx_backend_cfg[backend_idx].bitwidth_mixer_ctl);
+ return -EINVAL;
+ }
+
+ my_data->current_tx_backend_cfg[backend_idx].bit_width = bit_width;
+ ALOGD("%s:txbecf: afe: %s mixer set to %d bit", __func__,
+ my_data->current_tx_backend_cfg[backend_idx].bitwidth_mixer_ctl, bit_width);
+ }
+
+ /*
+ * Backend sample rate configuration follows:
+ * 16 bit record - 48khz for streams at any valid sample rate
+ * 24 bit record - 48khz for stream sample rate less than 48khz
+ * 24 bit record - 96khz for sample rate range of 48khz to 96khz
+ * 24 bit record - 192khz for sample rate range of 96khz to 192 khz
+ * Upper limit is inclusive in the sample rate range.
+ */
+ // TODO: This has to be more dynamic based on policy file
+
+ if (sample_rate != my_data->current_tx_backend_cfg[(int)backend_idx].sample_rate) {
+ /*
+ * sample rate update is needed only for hifi audio enabled platforms
+ */
+ char *rate_str = NULL;
+ struct mixer_ctl *ctl = NULL;
+
+ switch (sample_rate) {
+ case 8000:
+ case 11025:
+ case 16000:
+ case 22050:
+ case 32000:
+ case 44100:
+ case 48000:
+ rate_str = "KHZ_48";
+ break;
+ case 64000:
+ case 88200:
+ case 96000:
+ rate_str = "KHZ_96";
+ break;
+ case 176400:
+ case 192000:
+ rate_str = "KHZ_192";
+ break;
+ default:
+ rate_str = "KHZ_48";
+ break;
+ }
+
+ ctl = mixer_get_ctl_by_name(adev->mixer,
+ my_data->current_tx_backend_cfg[backend_idx].samplerate_mixer_ctl);
+
+ if (ctl < 0) {
+ ALOGE("%s:txbecf: afe: Could not get ctl to set the Sample Rate for mixer command - %s",
+ __func__,
+ my_data->current_tx_backend_cfg[backend_idx].samplerate_mixer_ctl);
+ return -EINVAL;
+ }
+
+ ALOGD("%s:txbecf: afe: %s set to %s", __func__,
+ my_data->current_tx_backend_cfg[backend_idx].samplerate_mixer_ctl,
+ rate_str);
+ ret = mixer_ctl_set_enum_by_string(ctl, rate_str);
+ if (ret < 0) {
+ ALOGE("%s:txbecf: afe: Could not set ctl for mixer command - %s",
+ __func__,
+ my_data->current_tx_backend_cfg[backend_idx].samplerate_mixer_ctl);
+ return -EINVAL;
+ }
+
+ my_data->current_tx_backend_cfg[backend_idx].sample_rate = sample_rate;
+ }
+
+ return ret;
+}
+
+/*
+ * goes through all the current usecases and picks the highest
+ * bitwidth & samplerate
+ */
+bool platform_check_capture_codec_backend_cfg(struct audio_device* adev,
+ unsigned int* new_bit_width,
+ unsigned int* new_sample_rate)
+{
+ bool backend_change = false;
+ unsigned int bit_width;
+ unsigned int sample_rate;
+ int backend_idx = DEFAULT_CODEC_BACKEND;
+ struct platform_data *my_data = (struct platform_data *)adev->platform;
+
+ bit_width = *new_bit_width;
+ sample_rate = *new_sample_rate;
+
+ ALOGI("%s:txbecf: afe: Codec selected backend: %d current bit width: %d and "
+ "sample rate: %d",__func__,backend_idx, bit_width, sample_rate);
+
+ // For voice calls use default configuration i.e. 16b/48K, only applicable to
+ // default backend
+ // force routing is not required here, caller will do it anyway
+ if ((voice_is_in_call(adev) || adev->mode == AUDIO_MODE_IN_COMMUNICATION) ||
+ (!is_external_codec)) {
+ ALOGW("%s:txbecf: afe:Use default bw and sr for voice/voip calls",
+ __func__);
+ bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
+ sample_rate = CODEC_BACKEND_DEFAULT_SAMPLE_RATE;
+ }
+
+ ALOGI("%s:txbecf: afe: Codec selected backend: %d updated bit width: %d and "
+ "sample rate: %d", __func__, backend_idx, bit_width, sample_rate);
+ // Force routing if the expected bitwdith or samplerate
+ // is not same as current backend comfiguration
+ if ((bit_width != my_data->current_tx_backend_cfg[backend_idx].bit_width) ||
+ (sample_rate != my_data->current_tx_backend_cfg[backend_idx].sample_rate)) {
+ *new_bit_width = bit_width;
+ *new_sample_rate = sample_rate;
+ backend_change = true;
+ ALOGI("%s:txbecf: afe: Codec backend needs to be updated. new bit width: %d "
+ "new sample rate: %d", __func__, *new_bit_width, *new_sample_rate);
+ }
+
+ return backend_change;
+}
+
+bool platform_check_and_set_capture_codec_backend_cfg(struct audio_device* adev,
+ struct audio_usecase *usecase, snd_device_t snd_device)
+{
+ unsigned int new_bit_width;
+ unsigned int new_sample_rate;
+ audio_format_t format = AUDIO_FORMAT_PCM_16_BIT;
+ int backend_idx = DEFAULT_CODEC_BACKEND;
+ int ret = 0;
+
+ if(usecase->type == PCM_CAPTURE) {
+ new_sample_rate = usecase->stream.in->sample_rate;
+ new_bit_width = usecase->stream.in->bit_width;
+ format = usecase->stream.in->format;
+ } else {
+ new_bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
+ new_sample_rate = CODEC_BACKEND_DEFAULT_SAMPLE_RATE;
+ }
+
+ ALOGI("%s:txbecf: afe: bitwidth %d, samplerate %d"
+ ", backend_idx %d usecase = %d device (%s)", __func__, new_bit_width,
+ new_sample_rate, backend_idx, usecase->id,
+ platform_get_snd_device_name(snd_device));
+ if (platform_check_capture_codec_backend_cfg(adev, &new_bit_width,
+ &new_sample_rate)) {
+ ret = platform_set_capture_codec_backend_cfg(adev, snd_device,
+ new_bit_width, new_sample_rate, format);
+ if(!ret)
+ return true;
+ }
+
+ return false;
+}
+
int platform_set_snd_device_backend(snd_device_t device, const char *backend_tag,
const char * hw_interface)
{
diff --git a/hal/msm8916/platform.h b/hal/msm8916/platform.h
index 23435ea..9380561 100644
--- a/hal/msm8916/platform.h
+++ b/hal/msm8916/platform.h
@@ -189,6 +189,7 @@
#define MAX_PORT 6
#define ALL_CODEC_BACKEND_PORT 0
#define HEADPHONE_44_1_BACKEND_PORT 5
+#define MAX_CODEC_TX_BACKENDS 1
enum {
DEFAULT_CODEC_BACKEND,
SLIMBUS_0_RX = DEFAULT_CODEC_BACKEND,
@@ -239,10 +240,6 @@
#define AUDIO_CAPTURE_PERIOD_DURATION_MSEC 20
#define AUDIO_CAPTURE_PERIOD_COUNT 2
-#define LOW_LATENCY_CAPTURE_SAMPLE_RATE 48000
-#define LOW_LATENCY_CAPTURE_PERIOD_SIZE 240
-#define LOW_LATENCY_CAPTURE_USE_CASE 1
-
#define DEVICE_NAME_MAX_SIZE 128
#define HW_INFO_ARRAY_MAX_SIZE 32
diff --git a/hal/msm8960/platform.c b/hal/msm8960/platform.c
index 43de781..5a41b07 100644
--- a/hal/msm8960/platform.c
+++ b/hal/msm8960/platform.c
@@ -1069,6 +1069,12 @@
return false;
}
+bool platform_check_and_set_capture_codec_backend_cfg(struct audio_device* adev __unused,
+ struct audio_usecase *usecase __unused)
+{
+ return false;
+}
+
int platform_get_usecase_index(const char * usecase __unused)
{
return -ENOSYS;
diff --git a/hal/msm8974/platform.c b/hal/msm8974/platform.c
index 4b20544..385d20b 100644
--- a/hal/msm8974/platform.c
+++ b/hal/msm8974/platform.c
@@ -243,6 +243,7 @@
bool edid_valid;
char ec_ref_mixer_path[64];
codec_backend_cfg_t current_backend_cfg[MAX_CODEC_BACKENDS];
+ codec_backend_cfg_t current_tx_backend_cfg[MAX_CODEC_TX_BACKENDS];
char codec_version[CODEC_VERSION_MAX_LENGTH];
int hw_dep_fd;
};
@@ -1630,6 +1631,11 @@
my_data->current_backend_cfg[HEADPHONE_44_1_BACKEND].samplerate_mixer_ctl =
strdup("SLIM_5_RX SampleRate");
+ my_data->current_tx_backend_cfg[DEFAULT_CODEC_BACKEND].bitwidth_mixer_ctl =
+ strdup("SLIM_0_TX Format");
+ my_data->current_tx_backend_cfg[DEFAULT_CODEC_BACKEND].samplerate_mixer_ctl =
+ strdup("SLIM_0_TX SampleRate");
+
ret = audio_extn_utils_get_codec_version(snd_card_name,
my_data->adev->snd_card,
my_data->codec_version);
@@ -4075,6 +4081,202 @@
return ret;
}
+/*
+ * configures afe with bit width and Sample Rate
+ */
+
+int platform_set_capture_codec_backend_cfg(struct audio_device* adev,
+ snd_device_t snd_device,
+ unsigned int bit_width, unsigned int sample_rate,
+ audio_format_t format)
+{
+ int ret = 0;
+ int backend_idx = DEFAULT_CODEC_BACKEND;
+ struct platform_data *my_data = (struct platform_data *)adev->platform;
+
+ ALOGI("%s:txbecf: afe: bitwidth %d, samplerate %d, backend_idx %d device (%s)",
+ __func__, bit_width, sample_rate, backend_idx,
+ platform_get_snd_device_name(snd_device));
+
+ if (bit_width !=
+ my_data->current_tx_backend_cfg[backend_idx].bit_width) {
+
+ struct mixer_ctl *ctl = NULL;
+ ctl = mixer_get_ctl_by_name(adev->mixer,
+ my_data->current_tx_backend_cfg[backend_idx].bitwidth_mixer_ctl);
+ if (!ctl) {
+ ALOGE("%s:txbecf: afe: Could not get ctl for mixer command - %s",
+ __func__,
+ my_data->current_tx_backend_cfg[backend_idx].bitwidth_mixer_ctl);
+ return -EINVAL;
+ }
+ if (bit_width == 24) {
+ if (format == AUDIO_FORMAT_PCM_24_BIT_PACKED)
+ ret = mixer_ctl_set_enum_by_string(ctl, "S24_3LE");
+ else
+ ret = mixer_ctl_set_enum_by_string(ctl, "S24_LE");
+ } else {
+ ret = mixer_ctl_set_enum_by_string(ctl, "S16_LE");
+ }
+
+ if (ret < 0) {
+ ALOGE("%s:txbecf: afe: Could not set ctl for mixer command - %s",
+ __func__,
+ my_data->current_tx_backend_cfg[backend_idx].bitwidth_mixer_ctl);
+ return -EINVAL;
+ }
+
+ my_data->current_tx_backend_cfg[backend_idx].bit_width = bit_width;
+ ALOGD("%s:txbecf: afe: %s mixer set to %d bit", __func__,
+ my_data->current_tx_backend_cfg[backend_idx].bitwidth_mixer_ctl, bit_width);
+ }
+
+ /*
+ * Backend sample rate configuration follows:
+ * 16 bit record - 48khz for streams at any valid sample rate
+ * 24 bit record - 48khz for stream sample rate less than 48khz
+ * 24 bit record - 96khz for sample rate range of 48khz to 96khz
+ * 24 bit record - 192khz for sample rate range of 96khz to 192 khz
+ * Upper limit is inclusive in the sample rate range.
+ */
+ // TODO: This has to be more dynamic based on policy file
+
+ if (sample_rate != my_data->current_tx_backend_cfg[(int)backend_idx].sample_rate) {
+ /*
+ * sample rate update is needed only for hifi audio enabled platforms
+ */
+ char *rate_str = NULL;
+ struct mixer_ctl *ctl = NULL;
+
+ switch (sample_rate) {
+ case 8000:
+ case 11025:
+ case 16000:
+ case 22050:
+ case 32000:
+ case 44100:
+ case 48000:
+ rate_str = "KHZ_48";
+ break;
+ case 64000:
+ case 88200:
+ case 96000:
+ rate_str = "KHZ_96";
+ break;
+ case 176400:
+ case 192000:
+ rate_str = "KHZ_192";
+ break;
+ default:
+ rate_str = "KHZ_48";
+ break;
+ }
+
+ ctl = mixer_get_ctl_by_name(adev->mixer,
+ my_data->current_tx_backend_cfg[backend_idx].samplerate_mixer_ctl);
+
+ if (!ctl) {
+ ALOGE("%s:txbecf: afe: Could not get ctl to set the Sample Rate for mixer command - %s",
+ __func__,
+ my_data->current_tx_backend_cfg[backend_idx].samplerate_mixer_ctl);
+ return -EINVAL;
+ }
+
+ ALOGD("%s:txbecf: afe: %s set to %s", __func__,
+ my_data->current_tx_backend_cfg[backend_idx].samplerate_mixer_ctl,
+ rate_str);
+ ret = mixer_ctl_set_enum_by_string(ctl, rate_str);
+ if (ret < 0) {
+ ALOGE("%s:txbecf: afe: Could not set ctl for mixer command - %s",
+ __func__,
+ my_data->current_tx_backend_cfg[backend_idx].samplerate_mixer_ctl);
+ return -EINVAL;
+ }
+
+ my_data->current_tx_backend_cfg[backend_idx].sample_rate = sample_rate;
+ }
+
+ return ret;
+}
+
+/*
+ * goes through all the current usecases and picks the highest
+ * bitwidth & samplerate
+ */
+bool platform_check_capture_codec_backend_cfg(struct audio_device* adev,
+ unsigned int* new_bit_width,
+ unsigned int* new_sample_rate)
+{
+ bool backend_change = false;
+ unsigned int bit_width;
+ unsigned int sample_rate;
+ int backend_idx = DEFAULT_CODEC_BACKEND;
+ struct platform_data *my_data = (struct platform_data *)adev->platform;
+
+ bit_width = *new_bit_width;
+ sample_rate = *new_sample_rate;
+
+ ALOGI("%s:txbecf: afe: Codec selected backend: %d current bit width: %d and "
+ "sample rate: %d",__func__,backend_idx, bit_width, sample_rate);
+
+ // For voice calls use default configuration i.e. 16b/48K, only applicable to
+ // default backend
+ // force routing is not required here, caller will do it anyway
+ if (voice_is_in_call(adev) || adev->mode == AUDIO_MODE_IN_COMMUNICATION) {
+ ALOGW("%s:txbecf: afe:Use default bw and sr for voice/voip calls and "
+ "for unprocessed/camera source", __func__);
+ bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
+ sample_rate = CODEC_BACKEND_DEFAULT_SAMPLE_RATE;
+ }
+
+ ALOGI("%s:txbecf: afe: Codec selected backend: %d updated bit width: %d and "
+ "sample rate: %d", __func__, backend_idx, bit_width, sample_rate);
+ // Force routing if the expected bitwdith or samplerate
+ // is not same as current backend comfiguration
+ if ((bit_width != my_data->current_tx_backend_cfg[backend_idx].bit_width) ||
+ (sample_rate != my_data->current_tx_backend_cfg[backend_idx].sample_rate)) {
+ *new_bit_width = bit_width;
+ *new_sample_rate = sample_rate;
+ backend_change = true;
+ ALOGI("%s:txbecf: afe: Codec backend needs to be updated. new bit width: %d "
+ "new sample rate: %d", __func__, *new_bit_width, *new_sample_rate);
+ }
+
+ return backend_change;
+}
+
+bool platform_check_and_set_capture_codec_backend_cfg(struct audio_device* adev,
+ struct audio_usecase *usecase, snd_device_t snd_device)
+{
+ unsigned int new_bit_width;
+ unsigned int new_sample_rate;
+ audio_format_t format = AUDIO_FORMAT_PCM_16_BIT;
+ int backend_idx = DEFAULT_CODEC_BACKEND;
+ int ret = 0;
+ if(usecase->type == PCM_CAPTURE) {
+ new_sample_rate = usecase->stream.in->sample_rate;
+ new_bit_width = usecase->stream.in->bit_width;
+ format = usecase->stream.in->format;
+ } else {
+ new_bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
+ new_sample_rate = CODEC_BACKEND_DEFAULT_SAMPLE_RATE;
+ }
+
+ ALOGI("%s:txbecf: afe: bitwidth %d, samplerate %d"
+ ", backend_idx %d usecase = %d device (%s)", __func__, new_bit_width,
+ new_sample_rate, backend_idx, usecase->id,
+ platform_get_snd_device_name(snd_device));
+ if (platform_check_capture_codec_backend_cfg(adev, &new_bit_width,
+ &new_sample_rate)) {
+ ret = platform_set_capture_codec_backend_cfg(adev, snd_device,
+ new_bit_width, new_sample_rate, format);
+ if(!ret)
+ return true;
+ }
+
+ return false;
+}
+
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 caa40d1..7fe7271 100644
--- a/hal/msm8974/platform.h
+++ b/hal/msm8974/platform.h
@@ -179,7 +179,7 @@
#define DEFAULT_OUTPUT_SAMPLING_RATE 48000
#define OUTPUT_SAMPLING_RATE_44100 44100
-
+#define MAX_CODEC_TX_BACKENDS 1
enum {
DEFAULT_CODEC_BACKEND,
SLIMBUS_0_RX = DEFAULT_CODEC_BACKEND,
diff --git a/hal/platform_api.h b/hal/platform_api.h
index 04ed8f5..df80a0c 100644
--- a/hal/platform_api.h
+++ b/hal/platform_api.h
@@ -114,6 +114,8 @@
bool platform_check_and_set_codec_backend_cfg(struct audio_device* adev,
struct audio_usecase *usecase, snd_device_t snd_device);
+bool platform_check_and_set_capture_codec_backend_cfg(struct audio_device* adev,
+ struct audio_usecase *usecase, snd_device_t snd_device);
int platform_get_usecase_index(const char * usecase);
int platform_set_usecase_pcm_id(audio_usecase_t usecase, int32_t type, int32_t pcm_id);
void platform_set_echo_reference(struct audio_device *adev, bool enable, audio_devices_t out_device);