audio: Enable 24 bit packed direct pcm support.
-Add support for 24 bit packed audio in audio hal. -Disable gapless for AV playback and direct pcm usecase, this ensures that the buffering in DSP is not more. -Simulate rendered time stamp for direct pcm usecase based on the number of frames written to the compress driver, bufferring in the driver and DSP latency. -Pass mixer instance to offload effects library to avoid an unnecessary mixer_open call, this optimizes audio start delay in compress playback. Change-Id: I422a53af5632eaf6cc362a6c44f62ff8412965f7
This commit is contained in:
parent
5f8ebf1f09
commit
5106d36bb0
|
@ -40,17 +40,6 @@
|
|||
|
||||
#include <cutils/str_parms.h>
|
||||
|
||||
#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)
|
||||
#define OFFLOAD_USE_SMALL_BUFFER false
|
||||
#else
|
||||
#define OFFLOAD_USE_SMALL_BUFFER ((info->format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_PCM_OFFLOAD)
|
||||
#endif
|
||||
|
||||
#ifndef AFE_PROXY_ENABLED
|
||||
#define AUDIO_DEVICE_OUT_PROXY 0x40000
|
||||
#endif
|
||||
|
|
|
@ -97,6 +97,8 @@ const struct string_to_enum s_flag_name_to_enum_table[] = {
|
|||
|
||||
const struct string_to_enum s_format_name_to_enum_table[] = {
|
||||
STRING_TO_ENUM(AUDIO_FORMAT_PCM_16_BIT),
|
||||
STRING_TO_ENUM(AUDIO_FORMAT_PCM_24_BIT_PACKED),
|
||||
STRING_TO_ENUM(AUDIO_FORMAT_PCM_8_24_BIT),
|
||||
STRING_TO_ENUM(AUDIO_FORMAT_PCM_8_BIT),
|
||||
STRING_TO_ENUM(AUDIO_FORMAT_MP3),
|
||||
STRING_TO_ENUM(AUDIO_FORMAT_AAC),
|
||||
|
@ -117,8 +119,6 @@ const struct string_to_enum s_format_name_to_enum_table[] = {
|
|||
STRING_TO_ENUM(AUDIO_FORMAT_QCELP),
|
||||
STRING_TO_ENUM(AUDIO_FORMAT_MP2),
|
||||
STRING_TO_ENUM(AUDIO_FORMAT_EVRCNW),
|
||||
STRING_TO_ENUM(AUDIO_FORMAT_PCM_16_BIT_OFFLOAD),
|
||||
STRING_TO_ENUM(AUDIO_FORMAT_PCM_24_BIT_OFFLOAD),
|
||||
STRING_TO_ENUM(AUDIO_FORMAT_FLAC),
|
||||
STRING_TO_ENUM(AUDIO_FORMAT_ALAC),
|
||||
STRING_TO_ENUM(AUDIO_FORMAT_APE),
|
||||
|
|
168
hal/audio_hw.c
168
hal/audio_hw.c
|
@ -74,6 +74,8 @@
|
|||
#include "sound/asound.h"
|
||||
|
||||
#define COMPRESS_OFFLOAD_NUM_FRAGMENTS 4
|
||||
/*DIRECT PCM has same buffer sizes as DEEP Buffer*/
|
||||
#define DIRECT_PCM_NUM_FRAGMENTS 2
|
||||
/* ToDo: Check and update a proper value in msec */
|
||||
#define COMPRESS_OFFLOAD_PLAYBACK_LATENCY 50
|
||||
#define COMPRESS_PLAYBACK_VOLUME_MAX 0x2000
|
||||
|
@ -287,17 +289,17 @@ bool audio_hw_send_gain_dep_calibration(int level) {
|
|||
return ret_val;
|
||||
}
|
||||
|
||||
static int check_and_set_gapless_mode(struct audio_device *adev) {
|
||||
|
||||
|
||||
char value[PROPERTY_VALUE_MAX] = {0};
|
||||
static int check_and_set_gapless_mode(struct audio_device *adev, bool enable_gapless)
|
||||
{
|
||||
bool gapless_enabled = false;
|
||||
const char *mixer_ctl_name = "Compress Gapless Playback";
|
||||
struct mixer_ctl *ctl;
|
||||
|
||||
ALOGV("%s:", __func__);
|
||||
property_get("audio.offload.gapless.enabled", value, NULL);
|
||||
gapless_enabled = atoi(value) || !strncmp("true", value, 4);
|
||||
gapless_enabled = property_get_bool("audio.offload.gapless.enabled", false);
|
||||
|
||||
/*Disable gapless if its AV playback*/
|
||||
gapless_enabled = gapless_enabled && enable_gapless;
|
||||
|
||||
ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
|
||||
if (!ctl) {
|
||||
|
@ -323,8 +325,8 @@ static bool is_supported_format(audio_format_t format)
|
|||
format == AUDIO_FORMAT_AAC_ADTS_LC ||
|
||||
format == AUDIO_FORMAT_AAC_ADTS_HE_V1 ||
|
||||
format == AUDIO_FORMAT_AAC_ADTS_HE_V2 ||
|
||||
format == AUDIO_FORMAT_PCM_16_BIT_OFFLOAD ||
|
||||
format == AUDIO_FORMAT_PCM_24_BIT_OFFLOAD ||
|
||||
format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
|
||||
format == AUDIO_FORMAT_PCM_8_24_BIT ||
|
||||
format == AUDIO_FORMAT_PCM_16_BIT ||
|
||||
format == AUDIO_FORMAT_FLAC ||
|
||||
format == AUDIO_FORMAT_ALAC ||
|
||||
|
@ -351,7 +353,6 @@ static int get_snd_codec_id(audio_format_t format)
|
|||
case AUDIO_FORMAT_AAC_ADTS:
|
||||
id = SND_AUDIOCODEC_AAC;
|
||||
break;
|
||||
case AUDIO_FORMAT_PCM_OFFLOAD:
|
||||
case AUDIO_FORMAT_PCM:
|
||||
id = SND_AUDIOCODEC_PCM;
|
||||
break;
|
||||
|
@ -1956,7 +1957,7 @@ int start_output_stream(struct stream_out *out)
|
|||
for the default max poll time (20s) in the event of an SSR.
|
||||
Reduce the poll time to observe and deal with SSR faster.
|
||||
*/
|
||||
if (out->use_small_bufs) {
|
||||
if (!out->non_blocking) {
|
||||
compress_set_max_poll_wait(out->compr, 1000);
|
||||
}
|
||||
|
||||
|
@ -1973,7 +1974,7 @@ int start_output_stream(struct stream_out *out)
|
|||
if (adev->visualizer_start_output != NULL)
|
||||
adev->visualizer_start_output(out->handle, out->pcm_device_id);
|
||||
if (adev->offload_effects_start_output != NULL)
|
||||
adev->offload_effects_start_output(out->handle, out->pcm_device_id);
|
||||
adev->offload_effects_start_output(out->handle, out->pcm_device_id, adev->mixer);
|
||||
audio_extn_check_and_set_dts_hpx_state(adev);
|
||||
}
|
||||
}
|
||||
|
@ -2061,6 +2062,37 @@ static size_t get_input_buffer_size(uint32_t sample_rate,
|
|||
return size;
|
||||
}
|
||||
|
||||
static uint64_t get_actual_pcm_frames_rendered(struct stream_out *out)
|
||||
{
|
||||
uint64_t actual_frames_rendered = 0;
|
||||
size_t kernel_buffer_size = out->compr_config.fragment_size * out->compr_config.fragments;
|
||||
|
||||
/* This adjustment accounts for buffering after app processor.
|
||||
* It is based on estimated DSP latency per use case, rather than exact.
|
||||
*/
|
||||
int64_t platform_latency = platform_render_latency(out->usecase) *
|
||||
out->sample_rate / 1000000LL;
|
||||
|
||||
/* not querying actual state of buffering in kernel as it would involve an ioctl call
|
||||
* which then needs protection, this causes delay in TS query for pcm_offload usecase
|
||||
* hence only estimate.
|
||||
*/
|
||||
int64_t signed_frames = out->written - kernel_buffer_size;
|
||||
|
||||
signed_frames = signed_frames / (audio_bytes_per_sample(out->format) * popcount(out->channel_mask)) - platform_latency;
|
||||
|
||||
if (signed_frames > 0)
|
||||
actual_frames_rendered = signed_frames;
|
||||
|
||||
ALOGVV("%s signed frames %lld out_written %lld kernel_buffer_size %d"
|
||||
"bytes/sample %zu channel count %d", __func__,(long long int)signed_frames,
|
||||
(long long int)out->written, (int)kernel_buffer_size,
|
||||
audio_bytes_per_sample(out->compr_config.codec->format),
|
||||
popcount(out->channel_mask));
|
||||
|
||||
return actual_frames_rendered;
|
||||
}
|
||||
|
||||
static uint32_t out_get_sample_rate(const struct audio_stream *stream)
|
||||
{
|
||||
struct stream_out *out = (struct stream_out *)stream;
|
||||
|
@ -2553,6 +2585,9 @@ static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
|
|||
out_standby(&out->stream.common);
|
||||
return ret;
|
||||
}
|
||||
if ( ret == (ssize_t)bytes && !out->non_blocking)
|
||||
out->written += bytes;
|
||||
|
||||
if (!out->playback_started && ret >= 0) {
|
||||
compress_start(out->compr);
|
||||
audio_extn_dts_eagle_fade(adev, true, out);
|
||||
|
@ -2627,14 +2662,24 @@ static int out_get_render_position(const struct audio_stream_out *stream,
|
|||
*dsp_frames = 0;
|
||||
if (is_offload_usecase(out->usecase)) {
|
||||
ssize_t ret = 0;
|
||||
|
||||
/* Below piece of code is not guarded against any lock beacuse audioFliner serializes
|
||||
* this operation and adev_close_output_stream(where out gets reset).
|
||||
*/
|
||||
if (!out->non_blocking && (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) {
|
||||
*dsp_frames = get_actual_pcm_frames_rendered(out);
|
||||
ALOGVV("dsp_frames %d sampleRate %d",(int)*dsp_frames,out->sample_rate);
|
||||
return 0;
|
||||
}
|
||||
|
||||
lock_output_stream(out);
|
||||
if (out->compr != NULL) {
|
||||
if (out->compr != NULL && out->non_blocking) {
|
||||
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);
|
||||
__func__, *dsp_frames, out->sample_rate);
|
||||
}
|
||||
pthread_mutex_unlock(&out->lock);
|
||||
if (-ENETRESET == ret) {
|
||||
|
@ -2686,27 +2731,37 @@ static int out_get_presentation_position(const struct audio_stream_out *stream,
|
|||
int ret = -1;
|
||||
unsigned long dsp_frames;
|
||||
|
||||
/* below piece of code is not guarded against any lock because audioFliner serializes
|
||||
* this operation and adev_close_output_stream( where out gets reset).
|
||||
*/
|
||||
if (is_offload_usecase(out->usecase) && !out->non_blocking &&
|
||||
(out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) {
|
||||
*frames = get_actual_pcm_frames_rendered(out);
|
||||
/* this is the best we can do */
|
||||
clock_gettime(CLOCK_MONOTONIC, timestamp);
|
||||
ALOGVV("frames %lld playedat %lld",(long long int)*frames,
|
||||
timestamp->tv_sec * 1000000LL + timestamp->tv_nsec / 1000);
|
||||
return 0;
|
||||
}
|
||||
|
||||
lock_output_stream(out);
|
||||
|
||||
if (is_offload_usecase(out->usecase)) {
|
||||
if (out->compr != NULL) {
|
||||
ret = compress_get_tstamp(out->compr, &dsp_frames,
|
||||
&out->sample_rate);
|
||||
ALOGVV("%s rendered frames %ld sample_rate %d",
|
||||
__func__, dsp_frames, out->sample_rate);
|
||||
*frames = dsp_frames;
|
||||
if (ret < 0)
|
||||
ret = -errno;
|
||||
if (-ENETRESET == ret) {
|
||||
ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
|
||||
set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
|
||||
ret = -EINVAL;
|
||||
} else
|
||||
ret = 0;
|
||||
|
||||
/* this is the best we can do */
|
||||
clock_gettime(CLOCK_MONOTONIC, timestamp);
|
||||
}
|
||||
if (is_offload_usecase(out->usecase) && out->compr != NULL && out->non_blocking) {
|
||||
ret = compress_get_tstamp(out->compr, &dsp_frames,
|
||||
&out->sample_rate);
|
||||
ALOGVV("%s rendered frames %ld sample_rate %d",
|
||||
__func__, dsp_frames, out->sample_rate);
|
||||
*frames = dsp_frames;
|
||||
if (ret < 0)
|
||||
ret = -errno;
|
||||
if (-ENETRESET == ret) {
|
||||
ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
|
||||
set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
|
||||
ret = -EINVAL;
|
||||
} else
|
||||
ret = 0;
|
||||
/* this is the best we can do */
|
||||
clock_gettime(CLOCK_MONOTONIC, timestamp);
|
||||
} else {
|
||||
if (out->pcm) {
|
||||
unsigned int avail;
|
||||
|
@ -2837,6 +2892,7 @@ static int out_flush(struct audio_stream_out* stream)
|
|||
ALOGD("copl(%p):calling compress flush", out);
|
||||
lock_output_stream(out);
|
||||
stop_compressed_output_l(out);
|
||||
out->written = 0;
|
||||
pthread_mutex_unlock(&out->lock);
|
||||
ALOGD("copl(%p):out of compress flush", out);
|
||||
return 0;
|
||||
|
@ -3238,7 +3294,6 @@ static int adev_open_output_stream(struct audio_hw_device *dev,
|
|||
out->handle = handle;
|
||||
out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
|
||||
out->non_blocking = 0;
|
||||
out->use_small_bufs = false;
|
||||
|
||||
if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL &&
|
||||
(flags & AUDIO_OUTPUT_FLAG_DIRECT)) {
|
||||
|
@ -3337,6 +3392,9 @@ static int adev_open_output_stream(struct audio_hw_device *dev,
|
|||
}
|
||||
|
||||
if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) {
|
||||
out->stream.pause = out_pause;
|
||||
out->stream.flush = out_flush;
|
||||
out->stream.resume = out_resume;
|
||||
out->usecase = get_offload_usecase(adev, true);
|
||||
ALOGV("DIRECT_PCM usecase ... usecase selected %d ", out->usecase);
|
||||
} else {
|
||||
|
@ -3381,18 +3439,19 @@ static int adev_open_output_stream(struct audio_hw_device *dev,
|
|||
out->compr_config.codec->id =
|
||||
get_snd_codec_id(config->offload_info.format);
|
||||
|
||||
if (((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_PCM_OFFLOAD)||
|
||||
((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_PCM)) {
|
||||
if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_PCM) {
|
||||
out->compr_config.fragment_size =
|
||||
platform_get_pcm_offload_buffer_size(&config->offload_info);
|
||||
out->compr_config.fragments = DIRECT_PCM_NUM_FRAGMENTS;
|
||||
} else if (audio_extn_dolby_is_passthrough_stream(out)) {
|
||||
out->compr_config.fragment_size =
|
||||
audio_extn_dolby_get_passt_buffer_size(&config->offload_info);
|
||||
out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
|
||||
} else {
|
||||
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.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
|
||||
out->compr_config.codec->sample_rate =
|
||||
config->offload_info.sample_rate;
|
||||
out->compr_config.codec->bit_rate =
|
||||
|
@ -3408,16 +3467,12 @@ static int adev_open_output_stream(struct audio_hw_device *dev,
|
|||
out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
|
||||
if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS)
|
||||
out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
|
||||
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 (config->offload_info.format == AUDIO_FORMAT_PCM_16_BIT)
|
||||
out->compr_config.codec->format = SNDRV_PCM_FORMAT_S16_LE;
|
||||
|
||||
if (out->bit_width == 24) {
|
||||
if (config->offload_info.format == AUDIO_FORMAT_PCM_24_BIT_PACKED)
|
||||
out->compr_config.codec->format = SNDRV_PCM_FORMAT_S24_3LE;
|
||||
if (config->offload_info.format == AUDIO_FORMAT_PCM_8_24_BIT)
|
||||
out->compr_config.codec->format = SNDRV_PCM_FORMAT_S24_LE;
|
||||
}
|
||||
|
||||
if (config->offload_info.format == AUDIO_FORMAT_FLAC)
|
||||
out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
|
||||
|
@ -3425,14 +3480,6 @@ static int adev_open_output_stream(struct audio_hw_device *dev,
|
|||
if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
|
||||
out->non_blocking = 1;
|
||||
|
||||
if (platform_use_small_buffer(&config->offload_info)) {
|
||||
//this flag is set from framework only if its for PCM formats
|
||||
//no need to check for PCM format again
|
||||
out->non_blocking = 0;
|
||||
out->use_small_bufs = true;
|
||||
ALOGI("Keep write blocking for small buff: non_blockling %d",
|
||||
out->non_blocking);
|
||||
}
|
||||
|
||||
out->send_new_metadata = 1;
|
||||
out->send_next_track_params = false;
|
||||
|
@ -3446,11 +3493,18 @@ static int adev_open_output_stream(struct audio_hw_device *dev,
|
|||
ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
|
||||
__func__, config->offload_info.version,
|
||||
config->offload_info.bit_rate);
|
||||
//Decide if we need to use gapless mode by default
|
||||
if (!audio_extn_dolby_is_passthrough_stream(out)) {
|
||||
ALOGV("%s: don't enable gapless for passthrough", __func__);
|
||||
check_and_set_gapless_mode(adev);
|
||||
}
|
||||
|
||||
/* Disable gapless if any of the following is true
|
||||
* passthrough playback
|
||||
* AV playback
|
||||
* Direct PCM playback
|
||||
*/
|
||||
if (audio_extn_dolby_is_passthrough_stream(out) ||
|
||||
config->offload_info.has_video ||
|
||||
out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) {
|
||||
check_and_set_gapless_mode(adev, false);
|
||||
} else
|
||||
check_and_set_gapless_mode(adev, true);
|
||||
|
||||
if (audio_extn_dolby_is_passthrough_stream(out)) {
|
||||
out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
|
||||
|
@ -4288,7 +4342,7 @@ static int adev_open(const hw_module_t *module, const char *name,
|
|||
ALOGV("%s: DLOPEN successful for %s", __func__,
|
||||
OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
|
||||
adev->offload_effects_start_output =
|
||||
(int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
|
||||
(int (*)(audio_io_handle_t, int, struct mixer *))dlsym(adev->offload_effects_lib,
|
||||
"offload_effects_bundle_hal_start_output");
|
||||
adev->offload_effects_stop_output =
|
||||
(int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
|
||||
|
|
|
@ -209,7 +209,6 @@ struct stream_out {
|
|||
struct stream_app_type_cfg app_type_cfg;
|
||||
|
||||
int non_blocking;
|
||||
bool use_small_bufs;
|
||||
int playback_started;
|
||||
int offload_state;
|
||||
pthread_cond_t offload_cond;
|
||||
|
@ -343,7 +342,7 @@ struct audio_device {
|
|||
int (*visualizer_start_output)(audio_io_handle_t, int);
|
||||
int (*visualizer_stop_output)(audio_io_handle_t, int);
|
||||
void *offload_effects_lib;
|
||||
int (*offload_effects_start_output)(audio_io_handle_t, int);
|
||||
int (*offload_effects_start_output)(audio_io_handle_t, int, struct mixer *);
|
||||
int (*offload_effects_stop_output)(audio_io_handle_t, int);
|
||||
|
||||
struct sound_card_status snd_card_status;
|
||||
|
|
|
@ -760,6 +760,7 @@ static int msm_device_to_be_id_external_codec [][NO_COLS] = {
|
|||
|
||||
|
||||
#define DEEP_BUFFER_PLATFORM_DELAY (29*1000LL)
|
||||
#define PCM_OFFLOAD_PLATFORM_DELAY (30*1000LL)
|
||||
#define LOW_LATENCY_PLATFORM_DELAY (13*1000LL)
|
||||
|
||||
static bool is_misc_usecase(audio_usecase_t usecase) {
|
||||
|
@ -3651,7 +3652,7 @@ void platform_get_parameters(void *platform,
|
|||
free(kv_pairs);
|
||||
}
|
||||
|
||||
/* Delay in Us */
|
||||
/* Delay in Us, only to be used for PCM formats */
|
||||
int64_t platform_render_latency(audio_usecase_t usecase)
|
||||
{
|
||||
switch (usecase) {
|
||||
|
@ -3659,6 +3660,9 @@ int64_t platform_render_latency(audio_usecase_t usecase)
|
|||
return DEEP_BUFFER_PLATFORM_DELAY;
|
||||
case USECASE_AUDIO_PLAYBACK_LOW_LATENCY:
|
||||
return LOW_LATENCY_PLATFORM_DELAY;
|
||||
case USECASE_AUDIO_PLAYBACK_OFFLOAD:
|
||||
case USECASE_AUDIO_PLAYBACK_OFFLOAD2:
|
||||
return PCM_OFFLOAD_PLATFORM_DELAY;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
@ -3846,19 +3850,17 @@ uint32_t platform_get_compress_offload_buffer_size(audio_offload_info_t* info)
|
|||
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 bytes_per_sample;
|
||||
uint32_t pcm_offload_time = PCM_OFFLOAD_BUFFER_DURATION;
|
||||
|
||||
if (info->format == AUDIO_FORMAT_PCM_24_BIT_OFFLOAD) {
|
||||
bits_per_sample = 32;
|
||||
}
|
||||
bytes_per_sample = audio_bytes_per_sample(info->format);
|
||||
|
||||
//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)
|
||||
* bytes_per_sample
|
||||
* popcount(info->channel_mask))/1000;
|
||||
if(fragment_size < MIN_PCM_OFFLOAD_FRAGMENT_SIZE)
|
||||
fragment_size = MIN_PCM_OFFLOAD_FRAGMENT_SIZE;
|
||||
|
@ -3867,23 +3869,18 @@ uint32_t platform_get_pcm_offload_buffer_size(audio_offload_info_t* info)
|
|||
// 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
|
||||
fragment_size = ALIGN(fragment_size, ((bits_per_sample >> 3)* popcount(info->channel_mask) * 32));
|
||||
fragment_size = ALIGN(fragment_size, (bytes_per_sample * popcount(info->channel_mask) * 32));
|
||||
|
||||
ALOGI("PCM offload Fragment size to %d bytes", fragment_size);
|
||||
return fragment_size;
|
||||
}
|
||||
|
||||
bool platform_use_small_buffer(audio_offload_info_t* info)
|
||||
{
|
||||
return OFFLOAD_USE_SMALL_BUFFER;
|
||||
}
|
||||
|
||||
/*
|
||||
* configures afe with bit width and Sample Rate
|
||||
*/
|
||||
static int platform_set_codec_backend_cfg(struct audio_device* adev,
|
||||
snd_device_t snd_device,
|
||||
unsigned int bit_width, unsigned int sample_rate)
|
||||
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;
|
||||
|
@ -3908,13 +3905,17 @@ static int platform_set_codec_backend_cfg(struct audio_device* adev,
|
|||
}
|
||||
|
||||
if (bit_width == 24) {
|
||||
if (format == AUDIO_FORMAT_PCM_24_BIT_PACKED)
|
||||
mixer_ctl_set_enum_by_string(ctl, "S24_3LE");
|
||||
else
|
||||
mixer_ctl_set_enum_by_string(ctl, "S24_LE");
|
||||
} else {
|
||||
mixer_ctl_set_enum_by_string(ctl, "S16_LE");
|
||||
}
|
||||
my_data->current_backend_cfg[backend_idx].bit_width = bit_width;
|
||||
ALOGD("%s:becf: afe: %s mixer set to %d bit", __func__,
|
||||
my_data->current_backend_cfg[backend_idx].bitwidth_mixer_ctl, bit_width);
|
||||
ALOGD("%s:becf: afe: %s mixer set to %d bit for %x format", __func__,
|
||||
my_data->current_backend_cfg[backend_idx].bitwidth_mixer_ctl,
|
||||
bit_width, format);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -4150,11 +4151,13 @@ bool platform_check_and_set_codec_backend_cfg(struct audio_device* adev,
|
|||
int new_snd_devices[SND_DEVICE_OUT_END];
|
||||
int i, num_devices = 1;
|
||||
bool ret = false;
|
||||
audio_format_t format;
|
||||
|
||||
backend_idx = platform_get_backend_index(snd_device);
|
||||
|
||||
new_bit_width = usecase->stream.out->bit_width;
|
||||
new_sample_rate = usecase->stream.out->sample_rate;
|
||||
format = usecase->stream.out->format;
|
||||
|
||||
ALOGI("%s:becf: afe: bitwidth %d, samplerate %d"
|
||||
", backend_idx %d usecase = %d device (%s)", __func__, new_bit_width,
|
||||
|
@ -4171,7 +4174,7 @@ bool platform_check_and_set_codec_backend_cfg(struct audio_device* adev,
|
|||
if (platform_check_codec_backend_cfg(adev, usecase, new_snd_devices[i],
|
||||
&new_bit_width, &new_sample_rate)) {
|
||||
platform_set_codec_backend_cfg(adev, new_snd_devices[i],
|
||||
new_bit_width, new_sample_rate);
|
||||
new_bit_width, new_sample_rate, format);
|
||||
ret = true;
|
||||
}
|
||||
}
|
||||
|
@ -4691,8 +4694,8 @@ unsigned char platform_map_to_edid_format(int audio_format)
|
|||
format = DTS_HD;
|
||||
break;
|
||||
case AUDIO_FORMAT_PCM_16_BIT:
|
||||
case AUDIO_FORMAT_PCM_16_BIT_OFFLOAD:
|
||||
case AUDIO_FORMAT_PCM_24_BIT_OFFLOAD:
|
||||
case AUDIO_FORMAT_PCM_24_BIT_PACKED:
|
||||
case AUDIO_FORMAT_PCM_8_24_BIT:
|
||||
ALOGV("%s:PCM", __func__);
|
||||
format = LPCM;
|
||||
break;
|
||||
|
|
|
@ -1119,11 +1119,6 @@ uint32_t platform_get_pcm_offload_buffer_size(audio_offload_info_t* info __unuse
|
|||
return 0;
|
||||
}
|
||||
|
||||
bool platform_use_small_buffer(audio_offload_info_t* info)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
int platform_get_edid_info(void *platform __unused)
|
||||
{
|
||||
return -ENOSYS;
|
||||
|
|
|
@ -757,6 +757,7 @@ static int msm_be_id_array_len =
|
|||
|
||||
|
||||
#define DEEP_BUFFER_PLATFORM_DELAY (29*1000LL)
|
||||
#define PCM_OFFLOAD_PLATFORM_DELAY (30*1000LL)
|
||||
#define LOW_LATENCY_PLATFORM_DELAY (13*1000LL)
|
||||
|
||||
bool platform_send_gain_dep_cal(void *platform, int level) {
|
||||
|
@ -3677,7 +3678,7 @@ void platform_get_parameters(void *platform,
|
|||
free(kv_pairs);
|
||||
}
|
||||
|
||||
/* Delay in Us */
|
||||
/* Delay in Us, only to be used for PCM formats */
|
||||
int64_t platform_render_latency(audio_usecase_t usecase)
|
||||
{
|
||||
switch (usecase) {
|
||||
|
@ -3685,6 +3686,9 @@ int64_t platform_render_latency(audio_usecase_t usecase)
|
|||
return DEEP_BUFFER_PLATFORM_DELAY;
|
||||
case USECASE_AUDIO_PLAYBACK_LOW_LATENCY:
|
||||
return LOW_LATENCY_PLATFORM_DELAY;
|
||||
case USECASE_AUDIO_PLAYBACK_OFFLOAD:
|
||||
case USECASE_AUDIO_PLAYBACK_OFFLOAD2:
|
||||
return PCM_OFFLOAD_PLATFORM_DELAY;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
@ -3782,44 +3786,38 @@ uint32_t platform_get_compress_offload_buffer_size(audio_offload_info_t* info)
|
|||
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 bytes_per_sample;
|
||||
uint32_t pcm_offload_time = PCM_OFFLOAD_BUFFER_DURATION;
|
||||
|
||||
if (info->format == AUDIO_FORMAT_PCM_24_BIT_OFFLOAD) {
|
||||
bits_per_sample = 32;
|
||||
}
|
||||
bytes_per_sample = audio_bytes_per_sample(info->format);
|
||||
|
||||
//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)
|
||||
* bytes_per_sample
|
||||
* popcount(info->channel_mask))/1000;
|
||||
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;
|
||||
|
||||
// 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
|
||||
fragment_size = ALIGN(fragment_size, ((bits_per_sample >> 3)* popcount(info->channel_mask) * 32));
|
||||
fragment_size = ALIGN(fragment_size, ((bytes_per_sample) * popcount(info->channel_mask) * 32));
|
||||
|
||||
ALOGI("PCM offload Fragment size to %d bytes", fragment_size);
|
||||
return fragment_size;
|
||||
}
|
||||
|
||||
bool platform_use_small_buffer(audio_offload_info_t* info)
|
||||
{
|
||||
return OFFLOAD_USE_SMALL_BUFFER;
|
||||
}
|
||||
|
||||
/*
|
||||
* configures afe with bit width and Sample Rate
|
||||
*/
|
||||
static int platform_set_codec_backend_cfg(struct audio_device* adev,
|
||||
snd_device_t snd_device,
|
||||
unsigned int bit_width, unsigned int sample_rate)
|
||||
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;
|
||||
|
@ -3845,13 +3843,16 @@ static int platform_set_codec_backend_cfg(struct audio_device* adev,
|
|||
}
|
||||
|
||||
if (bit_width == 24) {
|
||||
mixer_ctl_set_enum_by_string(ctl, "S24_LE");
|
||||
if (format == AUDIO_FORMAT_PCM_24_BIT_PACKED)
|
||||
mixer_ctl_set_enum_by_string(ctl, "S24_3LE");
|
||||
else
|
||||
mixer_ctl_set_enum_by_string(ctl, "S24_LE");
|
||||
} else {
|
||||
mixer_ctl_set_enum_by_string(ctl, "S16_LE");
|
||||
}
|
||||
my_data->current_backend_cfg[backend_idx].bit_width = bit_width;
|
||||
ALOGD("%s:becf: afe: %s mixer set to %d bit", __func__,
|
||||
my_data->current_backend_cfg[backend_idx].bitwidth_mixer_ctl, bit_width);
|
||||
ALOGD("%s:becf: afe: %s mixer set to %d bit for %x format", __func__,
|
||||
my_data->current_backend_cfg[backend_idx].bitwidth_mixer_ctl, bit_width, format);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -4053,11 +4054,13 @@ bool platform_check_and_set_codec_backend_cfg(struct audio_device* adev,
|
|||
int i, num_devices = 1;
|
||||
bool ret = false;
|
||||
struct platform_data *my_data = (struct platform_data *)adev->platform;
|
||||
audio_format_t format;
|
||||
|
||||
backend_idx = platform_get_backend_index(snd_device);
|
||||
|
||||
new_bit_width = usecase->stream.out->bit_width;
|
||||
new_sample_rate = usecase->stream.out->sample_rate;
|
||||
format = usecase->stream.out->format;
|
||||
|
||||
ALOGI("%s:becf: afe: bitwidth %d, samplerate %d"
|
||||
", backend_idx %d usecase = %d device (%s)", __func__, new_bit_width,
|
||||
|
@ -4073,7 +4076,7 @@ bool platform_check_and_set_codec_backend_cfg(struct audio_device* adev,
|
|||
if (platform_check_codec_backend_cfg(adev, usecase, new_snd_devices[i],
|
||||
&new_bit_width, &new_sample_rate)) {
|
||||
platform_set_codec_backend_cfg(adev, new_snd_devices[i],
|
||||
new_bit_width, new_sample_rate);
|
||||
new_bit_width, new_sample_rate, format);
|
||||
ret = true;
|
||||
}
|
||||
}
|
||||
|
@ -4591,8 +4594,8 @@ unsigned char platform_map_to_edid_format(int audio_format)
|
|||
format = DTS_HD;
|
||||
break;
|
||||
case AUDIO_FORMAT_PCM_16_BIT:
|
||||
case AUDIO_FORMAT_PCM_16_BIT_OFFLOAD:
|
||||
case AUDIO_FORMAT_PCM_24_BIT_OFFLOAD:
|
||||
case AUDIO_FORMAT_PCM_24_BIT_PACKED:
|
||||
case AUDIO_FORMAT_PCM_8_24_BIT:
|
||||
ALOGV("%s:PCM", __func__);
|
||||
format = LPCM;
|
||||
break;
|
||||
|
|
|
@ -109,7 +109,6 @@ void platform_snd_card_update(void *platform, int snd_scard_state);
|
|||
struct audio_offload_info_t;
|
||||
uint32_t platform_get_compress_offload_buffer_size(audio_offload_info_t* info);
|
||||
uint32_t platform_get_pcm_offload_buffer_size(audio_offload_info_t* info);
|
||||
bool platform_use_small_buffer(audio_offload_info_t* info);
|
||||
uint32_t platform_get_compress_passthrough_buffer_size(audio_offload_info_t* info);
|
||||
|
||||
bool platform_check_and_set_codec_backend_cfg(struct audio_device* adev,
|
||||
|
|
|
@ -209,7 +209,7 @@ bool effects_enabled()
|
|||
* Interface from audio HAL
|
||||
*/
|
||||
__attribute__ ((visibility ("default")))
|
||||
int offload_effects_bundle_hal_start_output(audio_io_handle_t output, int pcm_id)
|
||||
int offload_effects_bundle_hal_start_output(audio_io_handle_t output, int pcm_id, struct mixer *mixer)
|
||||
{
|
||||
int ret = 0;
|
||||
struct listnode *node;
|
||||
|
@ -245,19 +245,19 @@ int offload_effects_bundle_hal_start_output(audio_io_handle_t output, int pcm_id
|
|||
/* populate the mixer control to send offload parameters */
|
||||
snprintf(mixer_string, sizeof(mixer_string),
|
||||
"%s %d", "Audio Effects Config", out_ctxt->pcm_device_id);
|
||||
out_ctxt->mixer = mixer_open(MIXER_CARD);
|
||||
if (!out_ctxt->mixer) {
|
||||
ALOGE("Failed to open mixer");
|
||||
|
||||
if (!mixer) {
|
||||
ALOGE("Invalid mixer");
|
||||
out_ctxt->ctl = NULL;
|
||||
out_ctxt->ref_ctl = NULL;
|
||||
ret = -EINVAL;
|
||||
free(out_ctxt);
|
||||
goto exit;
|
||||
} else {
|
||||
out_ctxt->mixer = mixer;
|
||||
out_ctxt->ctl = mixer_get_ctl_by_name(out_ctxt->mixer, mixer_string);
|
||||
if (!out_ctxt->ctl) {
|
||||
ALOGE("mixer_get_ctl_by_name failed");
|
||||
mixer_close(out_ctxt->mixer);
|
||||
out_ctxt->mixer = NULL;
|
||||
ret = -EINVAL;
|
||||
free(out_ctxt);
|
||||
|
@ -314,9 +314,6 @@ int offload_effects_bundle_hal_stop_output(audio_io_handle_t output, int pcm_id)
|
|||
fx_ctxt->ops.stop(fx_ctxt, out_ctxt);
|
||||
}
|
||||
|
||||
if (out_ctxt->mixer)
|
||||
mixer_close(out_ctxt->mixer);
|
||||
|
||||
list_remove(&out_ctxt->outputs_list_node);
|
||||
|
||||
#ifdef DTS_EAGLE
|
||||
|
|
Loading…
Reference in New Issue