diff options
| author | André Pinela <sheffzor@gmail.com> | 2015-10-09 22:22:42 +0100 |
|---|---|---|
| committer | Ziyan <jaraidaniel@gmail.com> | 2016-02-19 00:15:25 +0100 |
| commit | 4edff9fc475dec9b13fc7a06824ee8b8992a545c (patch) | |
| tree | fc88af0359c406ed098c03d6ca094123b823bfbb /audio | |
| parent | 9d379eef376c0e460ccad73a12d21d4e254201b3 (diff) | |
[k3.4] audio: refine audio hal for kernel 3.4
Change-Id: Ieaa43cbc5ef62686c58d38b12671fff1171efede
Diffstat (limited to 'audio')
| -rw-r--r-- | audio/audio_hw.c | 130 | ||||
| -rw-r--r-- | audio/audio_policy.conf | 94 | ||||
| -rw-r--r-- | audio/mixer_paths.xml | 60 |
3 files changed, 157 insertions, 127 deletions
diff --git a/audio/audio_hw.c b/audio/audio_hw.c index bca0b36..49c9a54 100644 --- a/audio/audio_hw.c +++ b/audio/audio_hw.c @@ -57,11 +57,6 @@ #define SCO_PERIOD_COUNT 4 #define SCO_SAMPLING_RATE 8000 -/* minimum sleep time in out_write() when write threshold is not reached */ -#define MIN_WRITE_SLEEP_US 2000 -#define MAX_WRITE_SLEEP_US ((OUT_PERIOD_SIZE * OUT_SHORT_PERIOD_COUNT * 1000000) \ - / OUT_SAMPLING_RATE) - enum { OUT_BUFFER_TYPE_UNKNOWN, OUT_BUFFER_TYPE_SHORT, @@ -136,7 +131,6 @@ struct stream_out { int write_threshold; int cur_write_threshold; - int buffer_type; struct audio_device *dev; }; @@ -282,7 +276,6 @@ static int start_output_stream(struct stream_out *out) } else { device = PCM_DEVICE; out->pcm_config = &pcm_config_out; - out->buffer_type = OUT_BUFFER_TYPE_UNKNOWN; } /* @@ -623,16 +616,9 @@ static int out_set_volume(struct audio_stream_out *stream, float left, static ssize_t out_write(struct audio_stream_out *stream, const void* buffer, size_t bytes) { - int ret = 0; + int ret; struct stream_out *out = (struct stream_out *)stream; struct audio_device *adev = out->dev; - size_t frame_size = audio_stream_out_frame_size(stream); - int16_t *in_buffer = (int16_t *)buffer; - size_t in_frames = bytes / frame_size; - size_t out_frames; - int buffer_type; - int kernel_frames; - bool sco_on; /* * acquiring hw device mutex systematically is useful if a low @@ -650,125 +636,15 @@ static ssize_t out_write(struct audio_stream_out *stream, const void* buffer, } out->standby = false; } - buffer_type = (adev->screen_off && !adev->active_in) ? - OUT_BUFFER_TYPE_LONG : OUT_BUFFER_TYPE_SHORT; - sco_on = (adev->out_device & AUDIO_DEVICE_OUT_ALL_SCO); pthread_mutex_unlock(&adev->lock); - /* detect changes in screen ON/OFF state and adapt buffer size - * if needed. Do not change buffer size when routed to SCO device. */ - if (!sco_on && (buffer_type != out->buffer_type)) { - size_t period_count; - - if (buffer_type == OUT_BUFFER_TYPE_LONG) - period_count = OUT_LONG_PERIOD_COUNT; - else - period_count = OUT_SHORT_PERIOD_COUNT; - - out->write_threshold = out->pcm_config->period_size * period_count; - /* reset current threshold if exiting standby */ - if (out->buffer_type == OUT_BUFFER_TYPE_UNKNOWN) - out->cur_write_threshold = out->write_threshold; - out->buffer_type = buffer_type; - } - - /* Reduce number of channels, if necessary */ - if (audio_channel_count_from_out_mask(out_get_channels(&stream->common)) > - (int)out->pcm_config->channels) { - unsigned int i; - - /* Discard right channel */ - for (i = 1; i < in_frames; i++) - in_buffer[i] = in_buffer[i * 2]; - - /* The frame size is now half */ - frame_size /= 2; - } - - /* Change sample rate, if necessary */ - if (out_get_sample_rate(&stream->common) != out->pcm_config->rate) { - out_frames = out->buffer_frames; - out->resampler->resample_from_input(out->resampler, - in_buffer, &in_frames, - out->buffer, &out_frames); - in_buffer = out->buffer; - } else { - out_frames = in_frames; - } - - if (!sco_on) { - int total_sleep_time_us = 0; - size_t period_size = out->pcm_config->period_size; - - /* do not allow more than out->cur_write_threshold frames in kernel - * pcm driver buffer */ - do { - struct timespec time_stamp; - if (pcm_get_htimestamp(out->pcm, - (unsigned int *)&kernel_frames, - &time_stamp) < 0) - break; - kernel_frames = pcm_get_buffer_size(out->pcm) - kernel_frames; - - if (kernel_frames > out->cur_write_threshold) { - int sleep_time_us = - (int)(((int64_t)(kernel_frames - out->cur_write_threshold) - * 1000000) / out->pcm_config->rate); - if (sleep_time_us < MIN_WRITE_SLEEP_US) - break; - total_sleep_time_us += sleep_time_us; - if (total_sleep_time_us > MAX_WRITE_SLEEP_US) { - ALOGW("out_write() limiting sleep time %d to %d", - total_sleep_time_us, MAX_WRITE_SLEEP_US); - sleep_time_us = MAX_WRITE_SLEEP_US - - (total_sleep_time_us - sleep_time_us); - } - usleep(sleep_time_us); - } - - } while ((kernel_frames > out->cur_write_threshold) && - (total_sleep_time_us <= MAX_WRITE_SLEEP_US)); - - /* do not allow abrupt changes on buffer size. Increasing/decreasing - * the threshold by steps of 1/4th of the buffer size keeps the write - * time within a reasonable range during transitions. - * Also reset current threshold just above current filling status when - * kernel buffer is really depleted to allow for smooth catching up with - * target threshold. - */ - if (out->cur_write_threshold > out->write_threshold) { - out->cur_write_threshold -= period_size / 4; - if (out->cur_write_threshold < out->write_threshold) { - out->cur_write_threshold = out->write_threshold; - } - } else if (out->cur_write_threshold < out->write_threshold) { - out->cur_write_threshold += period_size / 4; - if (out->cur_write_threshold > out->write_threshold) { - out->cur_write_threshold = out->write_threshold; - } - } else if ((kernel_frames < out->write_threshold) && - ((out->write_threshold - kernel_frames) > - (int)(period_size * OUT_SHORT_PERIOD_COUNT))) { - out->cur_write_threshold = (kernel_frames / period_size + 1) * period_size; - out->cur_write_threshold += period_size / 4; - } - } - - ret = pcm_write(out->pcm, in_buffer, out_frames * frame_size); - if (ret == -EPIPE) { - /* In case of underrun, don't sleep since we want to catch up asap */ - pthread_mutex_unlock(&out->lock); - return ret; - } - if (ret == 0) { - out->written += out_frames; - } + pcm_write(out->pcm, (void *)buffer, bytes); exit: pthread_mutex_unlock(&out->lock); if (ret != 0) { - usleep(bytes * 1000000 / audio_stream_out_frame_size(&stream->common) / + usleep(bytes * 1000000 / audio_stream_frame_size(&stream->common) / out_get_sample_rate(&stream->common)); } diff --git a/audio/audio_policy.conf b/audio/audio_policy.conf new file mode 100644 index 0000000..ed5b00a --- /dev/null +++ b/audio/audio_policy.conf @@ -0,0 +1,94 @@ +# Global configuration section: lists input and output devices always present on the device +# as well as the output device selected by default. +# Devices are designated by a string that corresponds to the enum in audio.h + +global_configuration { + attached_output_devices AUDIO_DEVICE_OUT_SPEAKER + default_output_device AUDIO_DEVICE_OUT_SPEAKER + attached_input_devices AUDIO_DEVICE_IN_BUILTIN_MIC|AUDIO_DEVICE_IN_REMOTE_SUBMIX +} + +# audio hardware module section: contains descriptors for all audio hw modules present on the +# device. Each hw module node is named after the corresponding hw module library base name. +# For instance, "primary" corresponds to audio.primary.<device>.so. +# The "primary" module is mandatory and must include at least one output with +# AUDIO_OUTPUT_FLAG_PRIMARY flag. +# Each module descriptor contains one or more output profile descriptors and zero or more +# input profile descriptors. Each profile lists all the parameters supported by a given output +# or input stream category. +# The "channel_masks", "formats", "devices" and "flags" are specified using strings corresponding +# to enums in audio.h and audio_policy.h. They are concatenated by use of "|" without space or "\n". + +audio_hw_modules { + primary { + outputs { + primary { + sampling_rates 44100 + channel_masks AUDIO_CHANNEL_OUT_STEREO + formats AUDIO_FORMAT_PCM_16_BIT + devices AUDIO_DEVICE_OUT_SPEAKER|AUDIO_DEVICE_OUT_WIRED_HEADSET|AUDIO_DEVICE_OUT_WIRED_HEADPHONE|AUDIO_DEVICE_OUT_ALL_SCO|AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET + flags AUDIO_OUTPUT_FLAG_PRIMARY + } + } + inputs { + primary { + sampling_rates 8000|11025|16000|22050|24000|32000|44100|48000 + channel_masks AUDIO_CHANNEL_IN_MONO|AUDIO_CHANNEL_IN_STEREO + formats AUDIO_FORMAT_PCM_16_BIT + devices AUDIO_DEVICE_IN_BUILTIN_MIC|AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET|AUDIO_DEVICE_IN_WIRED_HEADSET + } + } + } + a2dp { + outputs { + a2dp { + sampling_rates 44100 + channel_masks AUDIO_CHANNEL_OUT_STEREO + formats AUDIO_FORMAT_PCM_16_BIT + devices AUDIO_DEVICE_OUT_ALL_A2DP + } + } + } + usb { + outputs { + usb_accessory { + sampling_rates 44100 + channel_masks AUDIO_CHANNEL_OUT_STEREO + formats AUDIO_FORMAT_PCM_16_BIT + devices AUDIO_DEVICE_OUT_USB_ACCESSORY + } + usb_device { + sampling_rates dynamic + channel_masks AUDIO_CHANNEL_OUT_STEREO + formats dynamic + devices AUDIO_DEVICE_OUT_USB_DEVICE + } + } + inputs { + usb_device { + sampling_rates dynamic + channel_masks AUDIO_CHANNEL_IN_STEREO + formats AUDIO_FORMAT_PCM_16_BIT + devices AUDIO_DEVICE_IN_USB_DEVICE + } + } + } + r_submix { + outputs { + submix { + sampling_rates 48000 + channel_masks AUDIO_CHANNEL_OUT_STEREO + formats AUDIO_FORMAT_PCM_16_BIT + devices AUDIO_DEVICE_OUT_REMOTE_SUBMIX + } + } + inputs { + submix { + sampling_rates 48000 + channel_masks AUDIO_CHANNEL_IN_STEREO + formats AUDIO_FORMAT_PCM_16_BIT + devices AUDIO_DEVICE_IN_REMOTE_SUBMIX + } + } + } +} diff --git a/audio/mixer_paths.xml b/audio/mixer_paths.xml new file mode 100644 index 0000000..9d490e5 --- /dev/null +++ b/audio/mixer_paths.xml @@ -0,0 +1,60 @@ +<mixer> + <!-- These are the initial mixer settings --> + <ctl name="Speaker Playback Switch" value="0" /> + <ctl name="Int Spk Switch" value="0" /> + <ctl name="HP Playback Switch" value="0" /> + <ctl name="Headphone Jack Switch" value="0" /> + <ctl name="AUX Switch" value="0" /> + <ctl name="OUT Playback Switch" value="0" /> + <ctl name="OUT Channel Switch" value="0" /> + + <!-- This is the dock volume --> + <ctl name="OUT Playback Volume" value="32" /> + + <!-- This is the dock (line out) source --> + <ctl name="LOUT MIX DAC L1 Switch" value="0" /> + <ctl name="LOUT MIX DAC R1 Switch" value="0" /> + <ctl name="LOUT MIX OUTVOL L Switch" value="1" /> + <ctl name="LOUT MIX OUTVOL R Switch" value="1" /> + + <ctl name="Int Mic Switch" value="0" /> + <ctl name="Mic Jack Switch" value="0" /> + <ctl name="DMIC Switch" value="Disable" /> + <ctl name="ADC Capture Volume" value="119" /> + + <path name="speaker"> + <ctl name="Speaker Playback Switch" value="1" /> + <ctl name="Int Spk Switch" value="1" /> + <ctl name="DAC IF1 SWITCH" value="swap" /> + </path> + + <path name="headphone"> + <ctl name="HP Playback Switch" value="1" /> + <ctl name="Headphone Jack Switch" value="1" /> + <!-- Even though the default is "Normal", this is used + to override the speaker setting --> + <ctl name="DAC IF1 SWITCH" value="Normal" /> + </path> + + <path name="dock"> + <ctl name="AUX Switch" value="1" /> + <ctl name="OUT Playback Switch" value="1" /> + <ctl name="OUT Channel Switch" value="1" /> + </path> + + <path name="main-mic-top"> + <ctl name="Int Mic Switch" value="1" /> + <ctl name="DMIC Switch" value="DMIC1" /> + <ctl name="ADC IF1 SWITCH" value="right copy to left" /> + </path> + + <path name="main-mic-left"> + <ctl name="Int Mic Switch" value="1" /> + <ctl name="DMIC Switch" value="DMIC1" /> + <ctl name="ADC IF1 SWITCH" value="left copy to right" /> + </path> + + <path name="headset-mic"> + <ctl name="Mic Jack Switch" value="1" /> + </path> +</mixer> |
