summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSteve Kondik <steve@cyngn.com>2014-07-11 10:39:59 -0700
committerSteve Kondik <steve@cyngn.com>2016-01-19 12:21:19 -0800
commitb56a2b2fc76d9d7e69012efb1c4d7321726a5707 (patch)
tree8871edc188c329aabd075fde8f378b6ee582a8ef
parent9f78676f577ac731943299c9860d1c899aa018be (diff)
downloadhardware_qcom_audio-b56a2b2fc76d9d7e69012efb1c4d7321726a5707.tar.gz
hardware_qcom_audio-b56a2b2fc76d9d7e69012efb1c4d7321726a5707.tar.bz2
hardware_qcom_audio-b56a2b2fc76d9d7e69012efb1c4d7321726a5707.zip
hal: Squashed support for new offload features
hal: add extended audio definitions in hal - Add audio_defs.h in hal for extended audio definitions. hal: Add support for PCM in offload path - Translate PCM Offload format to pcm codec id - Set 16/24 sub format id in compress params format - Calculate offload fragment size for pcm - Move offload calculation functions to platform file - Update audio policy manager isOffloadSupported for pcm offload profile. Use audio.offload.pcm.enable hal: set gapless metadata for compress offload playback -If any of the metadata parameters are set from the framework. set the gapless metadata to one. CRs-Fixed: 588353 hal: Support for FLAC 24 bit format in offload path - Add flac in supported codecs list - Set FLAC codec specific parameters - Set fragment size based on bit width and sampling rate for flac - Configure backend to 24/16 bit based on the current usecases running hal: Fix backend configuration for 24 bit offload playback Backend sample rate configuration follows: 16 bit playback - 48khz for streams at any valid sample rate 24 bit playback - 48khz for stream sample rate upto 48khz 24 bit playback - 96khz for sample rate range of 48khz to 96khz 24 bit playback - 192khz for sample rate range of 96khz to 192 khz For invalid or out of range sample rate, default rate is 48K Upper limit is inclusive in the sample rate range audio: Update error number in HAL - Error number is not propagated from pcm/compress driver on pcm/compress error - Read error number in HAL from errno define hal: Fix backend configuration during stream switch -Currently, input stream sample rate and/or bit width is compared with current backend sample rate and/or bit width. Backend is re-configured only if input stream's rate/width is higher. This causes incorrect sampling rate during stream switch of varying sample rates. -The backend is configured at highest bit width and/or sample rate amongst all active playback usecases. -By setting the backend re-configuration flag only when the selected sample rate and/or bit width differ with current backend sample rate and/or bit width, re-routing is enabled and backend is re-configured. -Exception: 16 bit playbacks is allowed through 16/48 backend only. -Enable logs for app type, acdb id and sample rate. hal: fix 24bit compilation error with extended flag disabled - use PCM_OUTPUT_BIT_WIDTH instead of out->bit_width to fix compilation errors while it is not defined in audio.h hal: Fix backend for 24 bit playback on speaker Configure backend at 48khz for 24 bit playback on speakers. Currently, ADM can be configured only at the begining of stream playback. During device switch, in the middle of a playback, the backend remains at the previous configuration. By allowing ADM and backend re-configuration during playback, 24-bit playback is enforced on appropriate backend. hal: Fix combo device configuration for 24 bit playback on speaker -Fix combo device configuration for 24 bit playback on speaker -Move exception hadndling code to audio_extn hal: Remove checks for 24 bit platform support Check for 24 bit in HAL is not needed as the check for 24 bit platform support is achieved through flags in frameworks. hal: fix voice call mute issue The backend is always configured with default bit width and sample rate for voice calls. The backend reconfiguration should not be done when a new stream starts during voice call. CRs-fixed: 747001 hal: bug fixes for PCM offload When pcm offload is done, override the buffer size that was calculated and use the value from the system property Make write call blocking if small buffers are used in offload Update latency value for pcm offload with small buffer hint based on period size and period count. hal: send additional param for gapless flac Currently, metadata such as min/max block size is sent only for first stream in FLAC gapless playback. This causes incorrect configuration and, subsequently, framedrops in decoding of second stream and onwards Sending additional parameters CRs-Fixed: 781837 hal: align fragment size to 24 instead of 1024 for PCM offload Aligning PCM buffer size to 1024 bytes is not required in case of PCM offloading. It actually creates problem when playing 6 ch, 96KHz, 16-bit stream PCM in offload mode, due to aligning PCM data becomes unequal for the six channels. Align the buffer to LCM of 2, 4, 6, 8 i.e. 24. CRs-fixed: 780001 hal: Fix bit width for 24 bit PCM offload playback PCM offload bit width is selected as 16 bit even for 24 bit pcm offload playback streams if QTI_FLAC_DECODER flag is not defined. Fix this issue by defining appropriate flag PCM_OFFLOAD_ENABLED_24. hal: Reduce offload latency and log spam Offload latency is set to 96. Change it to 50 to reflect the rendering latency more correctly Modify pcm offload latency to return offload latency rather than the latency based on buffering since volume is applied immediately for offload use cases. Also reduce log spam in offload use cases CRs-Fixed: 787448 hal: Fix alignement of of buffer sent to DSP Currently, ALIGN macro can align properly only if the buffer size is a power of 2. To have same PCM samples for all channels, the buffer size requires to be multiple of (number of channels * bytes per sample). For writes to succeed, the buffer must be written at address which is multiple of 32. Alignment of 96 satsfies both of the above requirements. CRs-Fixed: 795936 hal : Avoid use of small buf flag and bit width info. -small buf flag and bit width info are not member of offload into structure. -avoid use of small buf flag and bit width info, use PCM offload format. audio: hal: Add support to send codec specific data in gapless Codec specific metadata is sent only for first stream in gapless playback. This causes incorrect configuration to be set for second stream and distortions are observed due to framedrops in adsp. Add support to send codec specific format data of second stream during gapless playback. Use vorbis bitstream format info from metadata instead of hardcoding. This avoids sending gapless metadata each time set parameters is called during vorbis playback. Set flag to send new metadata at start of session for first track and for the next stream in gapless after return from partial drain. hal: set output bitwidth to 24 bit for 32 bit data. - parser gives 32 bit data for 24 bit AIFF playback and same is sent down to HAL. - So update bit width to 24 bit if offload info bit width is 32 bit to configure back end to 24 bit for 24 bit e2e playback. hal: check offload_callback not NULL before calling - in case when offload o/p stream is created in blocking mode flinger do not sets the callback pointer. So check for offload callback pointer before calling. hal: Increase PCM offload buffering Increase PCM offload buffering to 40ms Change-Id: I13fbab3518a1e7e4314ce112d673469f0a30d457 CRs-Fixed: 924443
-rw-r--r--hal/Android.mk13
-rw-r--r--hal/audio_extn/audio_defs.h78
-rw-r--r--hal/audio_extn/audio_extn.c43
-rw-r--r--hal/audio_extn/audio_extn.h22
-rw-r--r--hal/audio_hw.c195
-rw-r--r--hal/audio_hw.h7
-rw-r--r--hal/msm8960/platform.c8
-rw-r--r--hal/msm8974/platform.c255
-rw-r--r--hal/platform_api.h10
9 files changed, 592 insertions, 39 deletions
diff --git a/hal/Android.mk b/hal/Android.mk
index 1e157412..413fb15b 100644
--- a/hal/Android.mk
+++ b/hal/Android.mk
@@ -108,6 +108,19 @@ ifneq ($(filter msm8992 msm8994,$(TARGET_BOARD_PLATFORM)),)
LOCAL_SRC_FILES += audio_extn/hwdep_cal.c
endif
+ifeq ($(strip $(AUDIO_FEATURE_ENABLED_PCM_OFFLOAD)),true)
+ LOCAL_CFLAGS += -DPCM_OFFLOAD_ENABLED
+endif
+
+ifeq ($(strip $(AUDIO_FEATURE_ENABLED_FLAC_OFFLOAD)),true)
+ LOCAL_CFLAGS += -DFLAC_OFFLOAD_ENABLED
+ LOCAL_CFLAGS += -DPCM_OFFLOAD_ENABLED
+ LOCAL_CFLAGS += -DCOMPRESS_METADATA_NEEDED
+endif
+
+LOCAL_COPY_HEADERS_TO := mm-audio
+LOCAL_COPY_HEADERS := audio_extn/audio_defs.h
+
LOCAL_MODULE := audio.primary.$(TARGET_BOARD_PLATFORM)
LOCAL_MODULE_RELATIVE_PATH := hw
diff --git a/hal/audio_extn/audio_defs.h b/hal/audio_extn/audio_defs.h
new file mode 100644
index 00000000..335a6295
--- /dev/null
+++ b/hal/audio_extn/audio_defs.h
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2014, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef AUDIO_DEFS_H
+#define AUDIO_DEFS_H
+
+
+/**
+ * extended audio codec parameters
+ */
+
+#define AUDIO_OFFLOAD_CODEC_WMA_FORMAT_TAG "music_offload_wma_format_tag"
+#define AUDIO_OFFLOAD_CODEC_WMA_BLOCK_ALIGN "music_offload_wma_block_align"
+#define AUDIO_OFFLOAD_CODEC_WMA_BIT_PER_SAMPLE "music_offload_wma_bit_per_sample"
+#define AUDIO_OFFLOAD_CODEC_WMA_CHANNEL_MASK "music_offload_wma_channel_mask"
+#define AUDIO_OFFLOAD_CODEC_WMA_ENCODE_OPTION "music_offload_wma_encode_option"
+#define AUDIO_OFFLOAD_CODEC_WMA_ENCODE_OPTION1 "music_offload_wma_encode_option1"
+#define AUDIO_OFFLOAD_CODEC_WMA_ENCODE_OPTION2 "music_offload_wma_encode_option2"
+#define AUDIO_OFFLOAD_CODEC_FORMAT "music_offload_codec_format"
+#define AUDIO_OFFLOAD_CODEC_FLAC_MIN_BLK_SIZE "music_offload_flac_min_blk_size"
+#define AUDIO_OFFLOAD_CODEC_FLAC_MAX_BLK_SIZE "music_offload_flac_max_blk_size"
+#define AUDIO_OFFLOAD_CODEC_FLAC_MIN_FRAME_SIZE "music_offload_flac_min_frame_size"
+#define AUDIO_OFFLOAD_CODEC_FLAC_MAX_FRAME_SIZE "music_offload_flac_max_frame_size"
+
+/* Query handle fm parameter*/
+#define AUDIO_PARAMETER_KEY_HANDLE_FM "handle_fm"
+
+/* Query fm volume */
+#define AUDIO_PARAMETER_KEY_FM_VOLUME "fm_volume"
+
+/* Query Fluence type */
+#define AUDIO_PARAMETER_KEY_FLUENCE "fluence"
+#define AUDIO_PARAMETER_VALUE_QUADMIC "quadmic"
+#define AUDIO_PARAMETER_VALUE_DUALMIC "dualmic"
+#define AUDIO_PARAMETER_KEY_NO_FLUENCE "none"
+
+/* Query if surround sound recording is supported */
+#define AUDIO_PARAMETER_KEY_SSR "ssr"
+
+/* Query if a2dp is supported */
+#define AUDIO_PARAMETER_KEY_HANDLE_A2DP_DEVICE "isA2dpDeviceSupported"
+
+/* Query ADSP Status */
+#define AUDIO_PARAMETER_KEY_ADSP_STATUS "ADSP_STATUS"
+
+/* Query Sound Card Status */
+#define AUDIO_PARAMETER_KEY_SND_CARD_STATUS "SND_CARD_STATUS"
+
+/* Query if Proxy can be Opend */
+#define AUDIO_PARAMETER_KEY_CAN_OPEN_PROXY "can_open_proxy"
+
+#endif /* AUDIO_DEFS_H */
diff --git a/hal/audio_extn/audio_extn.c b/hal/audio_extn/audio_extn.c
index 7583f835..c9d805bf 100644
--- a/hal/audio_extn/audio_extn.c
+++ b/hal/audio_extn/audio_extn.c
@@ -29,7 +29,50 @@
#include "platform.h"
#include "platform_api.h"
+#include "sound/compress_params.h"
+#ifndef COMPRESS_METADATA_NEEDED
+#define audio_extn_parse_compress_metadata(out, parms) (0)
+#else
+int audio_extn_parse_compress_metadata(struct stream_out *out,
+ struct str_parms *parms)
+{
+ int ret = 0;
+ char value[32];
+
+#ifdef FLAC_OFFLOAD_ENABLED
+ if (out->format == AUDIO_FORMAT_FLAC) {
+ ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_FLAC_MIN_BLK_SIZE, value, sizeof(value));
+ if (ret >= 0) {
+ out->compr_config.codec->options.flac_dec.min_blk_size = atoi(value);
+ out->is_compr_metadata_avail = true;
+ }
+ ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_FLAC_MAX_BLK_SIZE, value, sizeof(value));
+ if (ret >= 0) {
+ out->compr_config.codec->options.flac_dec.max_blk_size = atoi(value);
+ out->is_compr_metadata_avail = true;
+ }
+ ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_FLAC_MIN_FRAME_SIZE, value, sizeof(value));
+ if (ret >= 0) {
+ out->compr_config.codec->options.flac_dec.min_frame_size = atoi(value);
+ out->is_compr_metadata_avail = true;
+ }
+ ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_FLAC_MAX_FRAME_SIZE, value, sizeof(value));
+ if (ret >= 0) {
+ out->compr_config.codec->options.flac_dec.max_frame_size = atoi(value);
+ out->is_compr_metadata_avail = true;
+ }
+ ALOGV("FLAC metadata: min_blk_size %d, max_blk_size %d min_frame_size %d max_frame_size %d",
+ out->compr_config.codec->options.flac_dec.min_blk_size,
+ out->compr_config.codec->options.flac_dec.max_blk_size,
+ out->compr_config.codec->options.flac_dec.min_frame_size,
+ out->compr_config.codec->options.flac_dec.max_frame_size);
+ }
+#endif
+
+ return ret;
+}
+#endif
#ifdef KPI_OPTIMIZE_ENABLED
typedef int (*perf_lock_acquire_t)(int, int, int*, int);
diff --git a/hal/audio_extn/audio_extn.h b/hal/audio_extn/audio_extn.h
index c518faa7..3d3db003 100644
--- a/hal/audio_extn/audio_extn.h
+++ b/hal/audio_extn/audio_extn.h
@@ -25,6 +25,28 @@ void audio_extn_extspk_update(void* extn);
void audio_extn_extspk_set_mode(void* extn, audio_mode_t mode);
void audio_extn_extspk_set_voice_vol(void* extn, float vol);
+#ifndef PCM_OFFLOAD_ENABLED
+#define AUDIO_FORMAT_PCM_OFFLOAD 0x1A000000UL
+#define AUDIO_FORMAT_PCM_16_BIT_OFFLOAD (AUDIO_FORMAT_PCM_OFFLOAD | AUDIO_FORMAT_PCM_SUB_16_BIT)
+#define AUDIO_FORMAT_PCM_24_BIT_OFFLOAD (AUDIO_FORMAT_PCM_OFFLOAD | AUDIO_FORMAT_PCM_SUB_8_24_BIT)
+#define AUDIO_OFFLOAD_CODEC_FORMAT "music_offload_codec_format"
+#define audio_is_offload_pcm(format) (0)
+#endif
+
+#ifndef FLAC_OFFLOAD_ENABLED
+#define AUDIO_FORMAT_FLAC 0x1B000000UL
+#endif
+
+#ifndef COMPRESS_METADATA_NEEDED
+#define audio_extn_parse_compress_metadata(out, parms) (0)
+#else
+int audio_extn_parse_compress_metadata(struct stream_out *out,
+ struct str_parms *parms);
+#endif
+
+#define AUDIO_OUTPUT_BIT_WIDTH ((config->offload_info.bit_width == 32) ? 24\
+ :config->offload_info.bit_width)
+
#ifndef SPKR_PROT_ENABLED
#define audio_extn_spkr_prot_init(adev) (0)
#define audio_extn_spkr_prot_start_processing(snd_device) (-EINVAL)
diff --git a/hal/audio_hw.c b/hal/audio_hw.c
index 2e954d67..e0203905 100644
--- a/hal/audio_hw.c
+++ b/hal/audio_hw.c
@@ -1,5 +1,8 @@
/*
- * Copyright (C) 2013-2014 The Android Open Source Project
+ * Copyright (c) 2013-2015, The Linux Foundation. All rights reserved.
+ * Not a Contribution.
+ *
+ * Copyright (C) 2013 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -51,12 +54,13 @@
#include "voice_extn.h"
#include "sound/compress_params.h"
+#include "sound/asound.h"
#define COMPRESS_OFFLOAD_FRAGMENT_SIZE (256 * 1024)
// 2 buffers causes problems with high bitrate files
#define COMPRESS_OFFLOAD_NUM_FRAGMENTS 3
/* ToDo: Check and update a proper value in msec */
-#define COMPRESS_OFFLOAD_PLAYBACK_LATENCY 96
+#define COMPRESS_OFFLOAD_PLAYBACK_LATENCY 50
#define COMPRESS_PLAYBACK_VOLUME_MAX 0x2000
#define PROXY_OPEN_RETRY_COUNT 100
@@ -222,15 +226,24 @@ bool audio_hw_send_gain_dep_calibration(int level) {
static bool is_supported_format(audio_format_t format)
{
- switch (format) {
- case AUDIO_FORMAT_MP3:
- case AUDIO_FORMAT_AAC_LC:
- case AUDIO_FORMAT_AAC_HE_V1:
- case AUDIO_FORMAT_AAC_HE_V2:
- return true;
- default:
- break;
- }
+ if (format == AUDIO_FORMAT_MP3 ||
+ format == AUDIO_FORMAT_AAC ||
+ format == AUDIO_FORMAT_AAC_LC ||
+ format == AUDIO_FORMAT_AAC_HE_V1 ||
+ format == AUDIO_FORMAT_AAC_HE_V2)
+ return true;
+
+#ifdef PCM_OFFLOAD_ENABLED
+ if (format == AUDIO_FORMAT_PCM_16_BIT_OFFLOAD ||
+ format == AUDIO_FORMAT_PCM_24_BIT_OFFLOAD)
+ return true;
+#endif
+
+#ifdef FLAC_OFFLOAD_ENABLED
+ if (format == AUDIO_FORMAT_FLAC)
+ return true;
+#endif
+
return false;
}
@@ -245,8 +258,19 @@ static int get_snd_codec_id(audio_format_t format)
case AUDIO_FORMAT_AAC:
id = SND_AUDIOCODEC_AAC;
break;
+#ifdef PCM_OFFLOAD_ENABLED
+ case AUDIO_FORMAT_PCM_16_BIT_OFFLOAD:
+ case AUDIO_FORMAT_PCM_24_BIT_OFFLOAD:
+ id = SND_AUDIOCODEC_PCM;
+ break;
+#endif
+#ifdef FLAC_OFFLOAD_ENABLED
+ case AUDIO_FORMAT_FLAC:
+ id = SND_AUDIOCODEC_FLAC;
+ break;
+#endif
default:
- ALOGE("%s: Unsupported audio format", __func__);
+ ALOGE("%s: Unsupported audio format %x", __func__, format);
}
return id;
@@ -415,6 +439,15 @@ static void check_and_route_playback_usecases(struct audio_device *adev,
* because of the limitation that both the devices cannot be enabled
* at the same time as they share the same backend.
*/
+ /*
+ * This call is to check if we need to force routing for a particular stream
+ * If there is a backend configuration change for the device when a
+ * new stream starts, then ADM needs to be closed and re-opened with the new
+ * configuraion. This call check if we need to re-route all the streams
+ * associated with the backend. Touch tone + 24 bit playback.
+ */
+ bool force_routing = platform_check_and_set_codec_backend_cfg(adev, uc_info);
+
/* Disable all the usecases on the shared backend other than the
specified usecase */
for (i = 0; i < AUDIO_USECASE_MAX; i++)
@@ -424,7 +457,7 @@ static void check_and_route_playback_usecases(struct audio_device *adev,
usecase = node_to_item(node, struct audio_usecase, list);
if (usecase->type != PCM_CAPTURE &&
usecase != uc_info &&
- usecase->out_snd_device != snd_device &&
+ (usecase->out_snd_device != snd_device || force_routing) &&
usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND &&
platform_check_backends_match(snd_device, usecase->out_snd_device)) {
ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
@@ -909,6 +942,7 @@ static void *offload_thread_loop(void *context)
{
struct stream_out *out = (struct stream_out *) context;
struct listnode *item;
+ int ret = 0;
out->offload_state = OFFLOAD_STATE_IDLE;
out->playback_started = 0;
@@ -961,12 +995,24 @@ static void *offload_thread_loop(void *context)
event = STREAM_CBK_EVENT_WRITE_READY;
break;
case OFFLOAD_CMD_PARTIAL_DRAIN:
- compress_next_track(out->compr);
- compress_partial_drain(out->compr);
+ ret = compress_next_track(out->compr);
+ if(ret == 0) {
+ ALOGD("copl(%p):calling compress_partial_drain", out);
+ compress_partial_drain(out->compr);
+ ALOGD("copl(%p):out of compress_partial_drain", out);
+ }
+ else if(ret == -ETIMEDOUT)
+ compress_drain(out->compr);
+ else
+ ALOGE("%s: Next track returned error %d",__func__, ret);
+
send_callback = true;
event = STREAM_CBK_EVENT_DRAIN_READY;
+ pthread_mutex_lock(&out->lock);
/* Resend the metadata for next iteration */
out->send_new_metadata = 1;
+ out->send_next_track_params = true;
+ pthread_mutex_unlock(&out->lock);
break;
case OFFLOAD_CMD_DRAIN:
compress_drain(out->compr);
@@ -980,7 +1026,7 @@ static void *offload_thread_loop(void *context)
lock_output_stream(out);
out->offload_thread_blocked = false;
pthread_cond_signal(&out->cond);
- if (send_callback) {
+ if (send_callback && out->offload_callback) {
ALOGVV("%s: sending offload_callback event %d", __func__, event);
out->offload_callback(event, NULL, out->offload_cookie);
}
@@ -1218,6 +1264,9 @@ int start_output_stream(struct stream_out *out)
ret = -EIO;
goto error_open;
}
+ /* compress_open sends params of the track, so reset the flag here */
+ out->is_compr_metadata_avail = false;
+
if (out->offload_callback)
compress_nonblock(out->compr, out->non_blocking);
@@ -1362,6 +1411,8 @@ static int out_standby(struct audio_stream *stream)
}
} else {
stop_compressed_output_l(out);
+ out->send_next_track_params = false;
+ out->is_compr_metadata_avail = false;
out->gapless_mdata.encoder_delay = 0;
out->gapless_mdata.encoder_padding = 0;
if (out->compr != NULL) {
@@ -1386,28 +1437,23 @@ static int parse_compress_metadata(struct stream_out *out, struct str_parms *par
{
int ret = 0;
char value[32];
- struct compr_gapless_mdata tmp_mdata;
if (!out || !parms) {
+ ALOGE("%s: return invalid ",__func__);
return -EINVAL;
}
+ ret = audio_extn_parse_compress_metadata(out, parms);
+
ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
if (ret >= 0) {
- tmp_mdata.encoder_delay = atoi(value); //whats a good limit check?
- } else {
- return -EINVAL;
+ out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
}
-
ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
if (ret >= 0) {
- tmp_mdata.encoder_padding = atoi(value);
- } else {
- return -EINVAL;
+ out->gapless_mdata.encoder_padding = atoi(value);
}
- out->gapless_mdata = tmp_mdata;
- out->send_new_metadata = 1;
ALOGV("%s new encoder delay %u and padding %u", __func__,
out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
@@ -1497,7 +1543,9 @@ static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
}
if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
+ pthread_mutex_lock(&out->lock);
parse_compress_metadata(out, parms);
+ pthread_mutex_unlock(&out->lock);
}
str_parms_destroy(parms);
@@ -1547,12 +1595,17 @@ static char* out_get_parameters(const struct audio_stream *stream, const char *k
static uint32_t out_get_latency(const struct audio_stream_out *stream)
{
struct stream_out *out = (struct stream_out *)stream;
+ uint32_t latency = 0;
- if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD)
- return COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
-
- return (out->config.period_count * out->config.period_size * 1000) /
+ if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
+ latency = COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
+ } else {
+ latency = (out->config.period_count * out->config.period_size * 1000) /
(out->config.rate);
+ }
+
+ ALOGV("%s: Latency %d", __func__, latency);
+ return latency;
}
static int out_set_volume(struct audio_stream_out *stream, float left,
@@ -1632,14 +1685,22 @@ static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
}
if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
- ALOGVV("%s: writing buffer (%d bytes) to compress device", __func__, bytes);
+ ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
if (out->send_new_metadata) {
ALOGVV("send new gapless metadata");
compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
out->send_new_metadata = 0;
+ if (out->send_next_track_params && out->is_compr_metadata_avail) {
+ ALOGD("copl(%p):send next track params in gapless", out);
+ compress_set_next_track_param(out->compr, &(out->compr_config.codec->options));
+ out->send_next_track_params = false;
+ out->is_compr_metadata_avail = false;
+ }
}
ret = compress_write(out->compr, buffer, bytes);
+ if (ret < 0)
+ ret = -errno;
ALOGVV("%s: writing buffer (%d bytes) to compress device returned %d", __func__, bytes, ret);
if (ret >= 0 && ret < (ssize_t)bytes) {
send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
@@ -1666,7 +1727,9 @@ static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
else
ret = pcm_write(out->pcm, (void *)buffer, bytes);
- if (ret == 0)
+ if (ret < 0)
+ ret = -errno;
+ else if (ret == 0)
out->written += bytes / (out->config.channels * sizeof(short));
if (adev->adm_abandon_focus)
@@ -1691,19 +1754,22 @@ static int out_get_render_position(const struct audio_stream_out *stream,
uint32_t *dsp_frames)
{
struct stream_out *out = (struct stream_out *)stream;
+ ssize_t ret = 0;
*dsp_frames = 0;
if ((out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) && (dsp_frames != NULL)) {
lock_output_stream(out);
if (out->compr != NULL) {
- compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
+ ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
&out->sample_rate);
+ if (ret < 0)
+ ret = -errno;
ALOGVV("%s rendered frames %d sample_rate %d",
__func__, *dsp_frames, out->sample_rate);
}
pthread_mutex_unlock(&out->lock);
return 0;
- } else
- return -EINVAL;
+ }
+ return ret;
}
static int out_add_audio_effect(const struct audio_stream *stream __unused,
@@ -2016,6 +2082,8 @@ static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
ret = pcm_mmap_read(in->pcm, buffer, bytes);
} else
ret = pcm_read(in->pcm, buffer, bytes);
+ if (ret < 0)
+ ret = -errno;
}
if (adev->adm_abandon_focus)
@@ -2117,7 +2185,8 @@ static int adev_open_output_stream(struct audio_hw_device *dev,
{
struct audio_device *adev = (struct audio_device *)dev;
struct stream_out *out;
- int i, ret;
+ int i, ret = 0;
+ int32_t sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
ALOGV("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)",
__func__, config->sample_rate, config->channel_mask, devices, flags);
@@ -2135,6 +2204,9 @@ static int adev_open_output_stream(struct audio_hw_device *dev,
out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
out->handle = handle;
+ out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
+ out->non_blocking = 0;
+ out->use_small_bufs = false;
/* Init use case and pcm_config */
if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT &&
@@ -2177,8 +2249,10 @@ static int adev_open_output_stream(struct audio_hw_device *dev,
out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
if (config->offload_info.channel_mask)
out->channel_mask = config->offload_info.channel_mask;
- else if (config->channel_mask)
+ else if (config->channel_mask) {
out->channel_mask = config->channel_mask;
+ config->offload_info.channel_mask = config->channel_mask;
+ }
out->format = config->offload_info.format;
out->sample_rate = config->offload_info.sample_rate;
@@ -2187,10 +2261,18 @@ static int adev_open_output_stream(struct audio_hw_device *dev,
out->stream.resume = out_resume;
out->stream.drain = out_drain;
out->stream.flush = out_flush;
+ out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
out->compr_config.codec->id =
get_snd_codec_id(config->offload_info.format);
- out->compr_config.fragment_size = COMPRESS_OFFLOAD_FRAGMENT_SIZE;
+#ifdef PCM_OFFLOAD_ENABLED
+ if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_PCM_OFFLOAD)
+ out->compr_config.fragment_size =
+ platform_get_pcm_offload_buffer_size(&config->offload_info);
+ else
+#endif
+ out->compr_config.fragment_size =
+ platform_get_compress_offload_buffer_size(&config->offload_info);
out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
out->compr_config.codec->sample_rate = config->offload_info.sample_rate;
out->compr_config.codec->bit_rate =
@@ -2198,11 +2280,35 @@ static int adev_open_output_stream(struct audio_hw_device *dev,
out->compr_config.codec->ch_in =
audio_channel_count_from_out_mask(config->channel_mask);
out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
+ out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
+
+ if (config->offload_info.format == AUDIO_FORMAT_AAC)
+ out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
+
+#ifdef PCM_OFFLOAD_ENABLED
+ if (config->offload_info.format == AUDIO_FORMAT_PCM_16_BIT_OFFLOAD)
+ out->compr_config.codec->format = SNDRV_PCM_FORMAT_S16_LE;
+ if(config->offload_info.format == AUDIO_FORMAT_PCM_24_BIT_OFFLOAD)
+ out->compr_config.codec->format = SNDRV_PCM_FORMAT_S24_LE;
+ if (out->bit_width == 24) {
+ out->compr_config.codec->format = SNDRV_PCM_FORMAT_S24_LE;
+ }
+#endif
+
+#ifdef FLAC_OFFLOAD_ENABLED
+ if (config->offload_info.format == AUDIO_FORMAT_FLAC)
+ out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
+#endif
if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
out->non_blocking = 1;
out->send_new_metadata = 1;
+ out->send_next_track_params = false;
+ out->is_compr_metadata_avail = false;
+ out->offload_state = OFFLOAD_STATE_IDLE;
+ out->playback_started = 0;
+
create_offload_callback_thread(out);
ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
__func__, config->offload_info.version,
@@ -2263,8 +2369,17 @@ static int adev_open_output_stream(struct audio_hw_device *dev,
ALOGV("%s: Usecase(%s) config->format %#x out->config.format %#x\n",
__func__, use_case_table[out->usecase], config->format, out->config.format);
+ if ((24 == out->bit_width) &&
+ (devices == AUDIO_DEVICE_OUT_SPEAKER)) {
+ sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
+ ALOGI("%s 24-bit playback on Speaker is allowed ONLY at 48khz. Hence changing sample rate to: %d",
+ __func__, sample_rate);
+ } else {
+ sample_rate = out->sample_rate;
+ }
+
if (flags & AUDIO_OUTPUT_FLAG_PRIMARY) {
- if (adev->primary_output == NULL)
+ if(adev->primary_output == NULL)
adev->primary_output = out;
else {
ALOGE("%s: Primary output is already opened", __func__);
@@ -2891,6 +3006,8 @@ static int adev_open(const hw_module_t *module, const char *name,
adev->bluetooth_nrec = true;
adev->acdb_settings = TTY_MODE_OFF;
/* adev->cur_hdmi_channels = 0; by calloc() */
+ adev->cur_codec_backend_samplerate = CODEC_BACKEND_DEFAULT_SAMPLE_RATE;
+ adev->cur_codec_backend_bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
voice_init(adev);
list_init(&adev->usecase_list);
diff --git a/hal/audio_hw.h b/hal/audio_hw.h
index b82ee8b1..147c7f1b 100644
--- a/hal/audio_hw.h
+++ b/hal/audio_hw.h
@@ -25,6 +25,7 @@
#include <tinycompress/tinycompress.h>
#include <audio_route/audio_route.h>
+#include "audio_defs.h"
#include "voice.h"
#define VISUALIZER_LIBRARY_PATH "/system/lib/soundfx/libqcomvisualizer.so"
@@ -146,6 +147,7 @@ struct stream_out {
audio_io_handle_t handle;
int non_blocking;
+ bool use_small_bufs;
int playback_started;
int offload_state;
pthread_cond_t offload_cond;
@@ -157,6 +159,9 @@ struct stream_out {
void *offload_cookie;
struct compr_gapless_mdata gapless_mdata;
int send_new_metadata;
+ bool send_next_track_params;
+ bool is_compr_metadata_avail;
+ unsigned int bit_width;
struct audio_device *dev;
};
@@ -236,6 +241,8 @@ struct audio_device {
bool enable_voicerx;
int snd_card;
+ unsigned int cur_codec_backend_samplerate;
+ unsigned int cur_codec_backend_bit_width;
void *platform;
void *extspk;
diff --git a/hal/msm8960/platform.c b/hal/msm8960/platform.c
index 0ffe8a98..4988dbe5 100644
--- a/hal/msm8960/platform.c
+++ b/hal/msm8960/platform.c
@@ -1087,3 +1087,11 @@ bool platform_check_backends_match(snd_device_t snd_device1 __unused,
{
return true;
}
+
+bool platform_check_and_set_codec_backend_cfg(struct audio_device* adev, struct audio_usecase *usecase) {
+ return false;
+}
+
+uint32_t platform_get_compress_offload_buffer_size(audio_offload_info_t* info) {
+ return 0;
+}
diff --git a/hal/msm8974/platform.c b/hal/msm8974/platform.c
index c856bb0a..4a4d3b3e 100644
--- a/hal/msm8974/platform.c
+++ b/hal/msm8974/platform.c
@@ -27,6 +27,7 @@
#include "platform.h"
#include "audio_extn.h"
#include <linux/msm_audio.h>
+#include "sound/compress_params.h"
#define MIXER_XML_PATH "/system/etc/mixer_paths.xml"
#define LIB_ACDB_LOADER "libacdbloader.so"
@@ -34,6 +35,23 @@
#define CVD_VERSION_MIXER_CTL "CVD Version"
+#define MAX_COMPRESS_OFFLOAD_FRAGMENT_SIZE (256 * 1024)
+#define MIN_COMPRESS_OFFLOAD_FRAGMENT_SIZE (2 * 1024)
+#define COMPRESS_OFFLOAD_FRAGMENT_SIZE_FOR_AV_STREAMING (2 * 1024)
+#define COMPRESS_OFFLOAD_FRAGMENT_SIZE (32 * 1024)
+
+/* Used in calculating fragment size for pcm offload */
+#define PCM_OFFLOAD_BUFFER_DURATION 40 /* 40 millisecs */
+
+/* MAX PCM fragment size cannot be increased further due
+ * to flinger's cblk size of 1mb,and it has to be a multiple of
+ * 24 - lcm of channels supported by DSP
+ */
+#define MAX_PCM_OFFLOAD_FRAGMENT_SIZE (240 * 1024)
+#define MIN_PCM_OFFLOAD_FRAGMENT_SIZE (32 * 1024)
+
+#define DIV_ROUND_UP(x, y) (((x) + (y) - 1)/(y))
+#define ALIGN(x, y) ((y) * DIV_ROUND_UP((x), (y)))
/*
* This file will have a maximum of 38 bytes:
*
@@ -2513,3 +2531,240 @@ int platform_swap_lr_channels(struct audio_device *adev, bool swap_channels)
}
return 0;
}
+
+/* Read offload buffer size from a property.
+ * If value is not power of 2 round it to
+ * power of 2.
+ */
+uint32_t platform_get_compress_offload_buffer_size(audio_offload_info_t* info)
+{
+ char value[PROPERTY_VALUE_MAX] = {0};
+ uint32_t fragment_size = COMPRESS_OFFLOAD_FRAGMENT_SIZE;
+ if((property_get("audio.offload.buffer.size.kb", value, "")) &&
+ atoi(value)) {
+ fragment_size = atoi(value) * 1024;
+ }
+
+#ifdef FLAC_OFFLOAD_ENABLED
+ // For FLAC use max size since it is loss less, and has sampling rates
+ // upto 192kHZ
+ if (info != NULL && !info->has_video &&
+ info->format == AUDIO_FORMAT_FLAC) {
+ fragment_size = MAX_COMPRESS_OFFLOAD_FRAGMENT_SIZE;
+ ALOGV("FLAC fragment size %d", fragment_size);
+ }
+#endif
+
+ if (info != NULL && info->has_video && info->is_streaming) {
+ fragment_size = COMPRESS_OFFLOAD_FRAGMENT_SIZE_FOR_AV_STREAMING;
+ ALOGV("%s: offload fragment size reduced for AV streaming to %d",
+ __func__, fragment_size);
+ }
+
+ fragment_size = ALIGN( fragment_size, 1024);
+
+ if(fragment_size < MIN_COMPRESS_OFFLOAD_FRAGMENT_SIZE)
+ fragment_size = MIN_COMPRESS_OFFLOAD_FRAGMENT_SIZE;
+ else if(fragment_size > MAX_COMPRESS_OFFLOAD_FRAGMENT_SIZE)
+ fragment_size = MAX_COMPRESS_OFFLOAD_FRAGMENT_SIZE;
+ ALOGV("%s: fragment_size %d", __func__, fragment_size);
+ return fragment_size;
+}
+
+#ifdef PCM_OFFLOAD_ENABLED
+uint32_t platform_get_pcm_offload_buffer_size(audio_offload_info_t* info)
+{
+ uint32_t fragment_size = 0;
+ uint32_t bits_per_sample = 16;
+ uint32_t pcm_offload_time = PCM_OFFLOAD_BUFFER_DURATION;
+
+ if (info->format == AUDIO_FORMAT_PCM_24_BIT_OFFLOAD) {
+ bits_per_sample = 32;
+ }
+
+ //duration is set to 40 ms worth of stereo data at 48Khz
+ //with 16 bit per sample, modify this when the channel
+ //configuration is different
+ fragment_size = (pcm_offload_time
+ * info->sample_rate
+ * (bits_per_sample >> 3)
+ * popcount(info->channel_mask))/1000;
+ // To have same PCM samples for all channels, the buffer size requires to
+ // be multiple of (number of channels * bytes per sample)
+ // For writes to succeed, the buffer must be written at address which is multiple of 32
+ // Alignment of 96 satsfies both of the above requirements
+ fragment_size = ALIGN(fragment_size, 96);
+ if(fragment_size < MIN_PCM_OFFLOAD_FRAGMENT_SIZE)
+ fragment_size = MIN_PCM_OFFLOAD_FRAGMENT_SIZE;
+ else if(fragment_size > MAX_PCM_OFFLOAD_FRAGMENT_SIZE)
+ fragment_size = MAX_PCM_OFFLOAD_FRAGMENT_SIZE;
+
+ ALOGI("PCM offload Fragment size to %d bytes", fragment_size);
+ return fragment_size;
+}
+#endif
+
+int platform_set_codec_backend_cfg(struct audio_device* adev,
+ unsigned int bit_width, unsigned int sample_rate)
+{
+ ALOGV("%s bit width: %d, sample rate: %d", __func__, bit_width, sample_rate);
+
+ int ret = 0;
+ if (bit_width != adev->cur_codec_backend_bit_width) {
+ const char * mixer_ctl_name = "SLIM_0_RX Format";
+ struct mixer_ctl *ctl;
+ ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
+ if (!ctl) {
+ ALOGE("%s: Could not get ctl for mixer command - %s",
+ __func__, mixer_ctl_name);
+ return -EINVAL;
+ }
+
+ if (bit_width == 24) {
+ mixer_ctl_set_enum_by_string(ctl, "S24_LE");
+ } else {
+ mixer_ctl_set_enum_by_string(ctl, "S16_LE");
+ sample_rate = CODEC_BACKEND_DEFAULT_SAMPLE_RATE;
+ }
+ adev->cur_codec_backend_bit_width = bit_width;
+ ALOGE("Backend bit width is set to %d ", bit_width);
+ }
+
+ /*
+ * Backend sample rate configuration follows:
+ * 16 bit playback - 48khz for streams at any valid sample rate
+ * 24 bit playback - 48khz for stream sample rate less than 48khz
+ * 24 bit playback - 96khz for sample rate range of 48khz to 96khz
+ * 24 bit playback - 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 != adev->cur_codec_backend_samplerate) {
+ char *rate_str = NULL;
+ const char * mixer_ctl_name = "SLIM_0_RX SampleRate";
+ struct mixer_ctl *ctl;
+
+ 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, mixer_ctl_name);
+ if(!ctl) {
+ ALOGE("%s: Could not get ctl for mixer command - %s",
+ __func__, mixer_ctl_name);
+ return -EINVAL;
+ }
+
+ ALOGV("Set sample rate as rate_str = %s", rate_str);
+ mixer_ctl_set_enum_by_string(ctl, rate_str);
+ adev->cur_codec_backend_samplerate = sample_rate;
+ }
+
+ return ret;
+}
+
+bool platform_check_codec_backend_cfg(struct audio_device* adev,
+ struct audio_usecase* usecase,
+ unsigned int* new_bit_width,
+ unsigned int* new_sample_rate)
+{
+ bool backend_change = false;
+ struct listnode *node;
+ struct stream_out *out = NULL;
+ unsigned int bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
+ unsigned int sample_rate = CODEC_BACKEND_DEFAULT_SAMPLE_RATE;
+
+ // For voice calls use default configuration
+ // 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:Use default bw and sr for voice/voip calls ",__func__);
+ bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
+ sample_rate = CODEC_BACKEND_DEFAULT_SAMPLE_RATE;
+ } else {
+ /*
+ * The backend should be configured at highest bit width and/or
+ * sample rate amongst all playback usecases.
+ * If the selected sample rate and/or bit width differ with
+ * current backend sample rate and/or bit width, then, we set the
+ * backend re-configuration flag.
+ *
+ * Exception: 16 bit playbacks is allowed through 16 bit/48 khz backend only
+ */
+ list_for_each(node, &adev->usecase_list) {
+ struct audio_usecase *curr_usecase;
+ curr_usecase = node_to_item(node, struct audio_usecase, list);
+ if (curr_usecase->type == PCM_PLAYBACK) {
+ struct stream_out *out =
+ (struct stream_out*) curr_usecase->stream.out;
+ if (out != NULL ) {
+ ALOGV("Offload playback running bw %d sr %d",
+ out->bit_width, out->sample_rate);
+ if (bit_width < out->bit_width)
+ bit_width = out->bit_width;
+ if (sample_rate < out->sample_rate)
+ sample_rate = out->sample_rate;
+ }
+ }
+ }
+ }
+
+ // 24 bit playback on speakers and all 16 bit playbacks is allowed through
+ // 16 bit/48 khz backend only
+ if ((16 == bit_width) ||
+ ((24 == bit_width) &&
+ (usecase->stream.out->devices & AUDIO_DEVICE_OUT_SPEAKER))) {
+ sample_rate = CODEC_BACKEND_DEFAULT_SAMPLE_RATE;
+ }
+ // Force routing if the expected bitwdith or samplerate
+ // is not same as current backend comfiguration
+ if ((bit_width != adev->cur_codec_backend_bit_width) ||
+ (sample_rate != adev->cur_codec_backend_samplerate)) {
+ *new_bit_width = bit_width;
+ *new_sample_rate = sample_rate;
+ backend_change = true;
+ ALOGI("%s 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_codec_backend_cfg(struct audio_device* adev, struct audio_usecase *usecase)
+{
+ ALOGV("platform_check_and_set_codec_backend_cfg usecase = %d",usecase->id );
+
+ unsigned int new_bit_width, old_bit_width;
+ unsigned int new_sample_rate, old_sample_rate;
+
+ new_bit_width = old_bit_width = adev->cur_codec_backend_bit_width;
+ new_sample_rate = old_sample_rate = adev->cur_codec_backend_samplerate;
+
+ ALOGW("Codec backend bitwidth %d, samplerate %d", old_bit_width, old_sample_rate);
+ if (platform_check_codec_backend_cfg(adev, usecase,
+ &new_bit_width, &new_sample_rate)) {
+ platform_set_codec_backend_cfg(adev, new_bit_width, new_sample_rate);
+ return true;
+ }
+
+ return false;
+}
diff --git a/hal/platform_api.h b/hal/platform_api.h
index 1e413587..c707db18 100644
--- a/hal/platform_api.h
+++ b/hal/platform_api.h
@@ -17,6 +17,9 @@
#ifndef AUDIO_PLATFORM_API_H
#define AUDIO_PLATFORM_API_H
+#define CODEC_BACKEND_DEFAULT_BIT_WIDTH 16
+#define CODEC_BACKEND_DEFAULT_SAMPLE_RATE 48000
+
void *platform_init(struct audio_device *adev);
void platform_deinit(void *platform);
const char *platform_get_snd_device_name(snd_device_t snd_device);
@@ -84,4 +87,11 @@ bool platform_check_backends_match(snd_device_t snd_device1, snd_device_t snd_de
int platform_set_parameters(void *platform, struct str_parms *parms);
+struct audio_offload_info_t;
+uint32_t platform_get_compress_offload_buffer_size(audio_offload_info_t* info);
+#ifdef PCM_OFFLOAD_ENABLED
+uint32_t platform_get_pcm_offload_buffer_size(audio_offload_info_t* info);
+#endif
+
+bool platform_check_and_set_codec_backend_cfg(struct audio_device* adev, struct audio_usecase *usecase);
#endif // AUDIO_PLATFORM_API_H