blob: a51a5c627208b965daa0f386403df6aef7e74656 [file] [log] [blame]
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001/*
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002 * Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -07003 * Not a Contribution.
4 *
Shiv Maliyappanahalli8911f282014-01-10 15:56:19 -08005 * Copyright (C) 2013 The Android Open Source Project
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 */
19
20#define LOG_TAG "audio_hw_primary"
Steve Kondik5a447012014-12-02 16:04:20 -080021//#define LOG_NDEBUG 0
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070022/*#define VERY_VERY_VERBOSE_LOGGING*/
23#ifdef VERY_VERY_VERBOSE_LOGGING
24#define ALOGVV ALOGV
25#else
26#define ALOGVV(a...) do { } while(0)
27#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080028#include <errno.h>
29#include <pthread.h>
30#include <stdint.h>
31#include <sys/time.h>
32#include <stdlib.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080033#include <math.h>
Eric Laurentc4aef752013-09-12 17:45:53 -070034#include <dlfcn.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070035#include <sys/resource.h>
36#include <sys/prctl.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080037
38#include <cutils/log.h>
39#include <cutils/str_parms.h>
40#include <cutils/properties.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070041#include <cutils/atomic.h>
42#include <cutils/sched_policy.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080043
Eric Laurentb23d5282013-05-14 15:27:20 -070044#include <hardware/audio_effect.h>
Steve Kondik3abbbc82014-11-29 14:14:43 -080045#include <hardware/audio_alsaops.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070046#include <system/thread_defs.h>
Eric Laurentb23d5282013-05-14 15:27:20 -070047#include <audio_effects/effect_aec.h>
48#include <audio_effects/effect_ns.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080049#include "audio_hw.h"
Eric Laurentb23d5282013-05-14 15:27:20 -070050#include "platform_api.h"
51#include <platform.h>
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -070052#include "audio_extn.h"
Narsinga Rao Chella05573b72013-11-15 15:21:40 -080053#include "voice_extn.h"
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080054
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070055#include "sound/compress_params.h"
ApurupaPattapu0c566872014-01-10 14:46:02 -080056#include "sound/asound.h"
57
Daniel Hillenbrand8373bc62013-05-23 10:10:00 +053058#ifdef USES_AUDIO_AMPLIFIER
59#include <audio_amplifier.h>
60#endif
61
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070062#define COMPRESS_OFFLOAD_NUM_FRAGMENTS 4
63/* ToDo: Check and update a proper value in msec */
Alexy Joseph62babb92015-03-03 19:01:03 -080064#define COMPRESS_OFFLOAD_PLAYBACK_LATENCY 50
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070065#define COMPRESS_PLAYBACK_VOLUME_MAX 0x2000
66
Divya Narayanan Poojaryab9b1ef2014-09-12 15:52:36 +053067#define PROXY_OPEN_RETRY_COUNT 100
68#define PROXY_OPEN_WAIT_TIME 20
ApurupaPattapu0c566872014-01-10 14:46:02 -080069
Steve Kondikb045f472014-11-12 23:24:07 -080070#ifdef LOW_LATENCY_PRIMARY
71#define USECASE_AUDIO_PLAYBACK_PRIMARY USECASE_AUDIO_PLAYBACK_LOW_LATENCY
72#else
Haynes Mathew Georgebf143712013-12-03 13:02:53 -080073#define USECASE_AUDIO_PLAYBACK_PRIMARY USECASE_AUDIO_PLAYBACK_DEEP_BUFFER
Steve Kondikb045f472014-11-12 23:24:07 -080074#endif
Haynes Mathew Georgebf143712013-12-03 13:02:53 -080075
Ravi Kumar Alamanda1c3de5e2014-09-08 15:59:58 -070076static unsigned int configured_low_latency_capture_period_size =
77 LOW_LATENCY_CAPTURE_PERIOD_SIZE;
78
Steve Kondik3abbbc82014-11-29 14:14:43 -080079/* This constant enables extended precision handling.
Steve Kondik3abbbc82014-11-29 14:14:43 -080080 */
81static const bool k_enable_extended_precision = true;
82
Eric Laurentb23d5282013-05-14 15:27:20 -070083struct pcm_config pcm_config_deep_buffer = {
84 .channels = 2,
85 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
86 .period_size = DEEP_BUFFER_OUTPUT_PERIOD_SIZE,
87 .period_count = DEEP_BUFFER_OUTPUT_PERIOD_COUNT,
88 .format = PCM_FORMAT_S16_LE,
89 .start_threshold = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
90 .stop_threshold = INT_MAX,
91 .avail_min = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
92};
93
94struct pcm_config pcm_config_low_latency = {
95 .channels = 2,
96 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
97 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
98 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
99 .format = PCM_FORMAT_S16_LE,
100 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
101 .stop_threshold = INT_MAX,
102 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
103};
104
105struct pcm_config pcm_config_hdmi_multi = {
106 .channels = HDMI_MULTI_DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
107 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
108 .period_size = HDMI_MULTI_PERIOD_SIZE,
109 .period_count = HDMI_MULTI_PERIOD_COUNT,
110 .format = PCM_FORMAT_S16_LE,
111 .start_threshold = 0,
112 .stop_threshold = INT_MAX,
113 .avail_min = 0,
114};
115
116struct pcm_config pcm_config_audio_capture = {
117 .channels = 2,
Eric Laurentb23d5282013-05-14 15:27:20 -0700118 .period_count = AUDIO_CAPTURE_PERIOD_COUNT,
119 .format = PCM_FORMAT_S16_LE,
120};
121
Divya Narayanan Poojaryab9b1ef2014-09-12 15:52:36 +0530122#define AFE_PROXY_CHANNEL_COUNT 2
123#define AFE_PROXY_SAMPLING_RATE 48000
124
125#define AFE_PROXY_PLAYBACK_PERIOD_SIZE 768
126#define AFE_PROXY_PLAYBACK_PERIOD_COUNT 4
127
128struct pcm_config pcm_config_afe_proxy_playback = {
129 .channels = AFE_PROXY_CHANNEL_COUNT,
130 .rate = AFE_PROXY_SAMPLING_RATE,
131 .period_size = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
132 .period_count = AFE_PROXY_PLAYBACK_PERIOD_COUNT,
133 .format = PCM_FORMAT_S16_LE,
134 .start_threshold = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
135 .stop_threshold = INT_MAX,
136 .avail_min = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
137};
138
139#define AFE_PROXY_RECORD_PERIOD_SIZE 768
140#define AFE_PROXY_RECORD_PERIOD_COUNT 4
141
142struct pcm_config pcm_config_afe_proxy_record = {
143 .channels = AFE_PROXY_CHANNEL_COUNT,
144 .rate = AFE_PROXY_SAMPLING_RATE,
145 .period_size = AFE_PROXY_RECORD_PERIOD_SIZE,
146 .period_count = AFE_PROXY_RECORD_PERIOD_COUNT,
147 .format = PCM_FORMAT_S16_LE,
148 .start_threshold = AFE_PROXY_RECORD_PERIOD_SIZE,
149 .stop_threshold = INT_MAX,
150 .avail_min = AFE_PROXY_RECORD_PERIOD_SIZE,
151};
152
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -0800153const char * const use_case_table[AUDIO_USECASE_MAX] = {
Eric Laurentb23d5282013-05-14 15:27:20 -0700154 [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = "deep-buffer-playback",
155 [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = "low-latency-playback",
156 [USECASE_AUDIO_PLAYBACK_MULTI_CH] = "multi-channel-playback",
Shruthi Krishnaace10852013-10-25 14:32:12 -0700157 [USECASE_AUDIO_PLAYBACK_OFFLOAD] = "compress-offload-playback",
Subhash Chandra Bose Naripeddy148144e2014-04-01 21:03:10 -0700158#ifdef MULTIPLE_OFFLOAD_ENABLED
159 [USECASE_AUDIO_PLAYBACK_OFFLOAD2] = "compress-offload-playback2",
160 [USECASE_AUDIO_PLAYBACK_OFFLOAD3] = "compress-offload-playback3",
161 [USECASE_AUDIO_PLAYBACK_OFFLOAD4] = "compress-offload-playback4",
162 [USECASE_AUDIO_PLAYBACK_OFFLOAD5] = "compress-offload-playback5",
163 [USECASE_AUDIO_PLAYBACK_OFFLOAD6] = "compress-offload-playback6",
164 [USECASE_AUDIO_PLAYBACK_OFFLOAD7] = "compress-offload-playback7",
165 [USECASE_AUDIO_PLAYBACK_OFFLOAD8] = "compress-offload-playback8",
166 [USECASE_AUDIO_PLAYBACK_OFFLOAD9] = "compress-offload-playback9",
167#endif
Eric Laurentb23d5282013-05-14 15:27:20 -0700168 [USECASE_AUDIO_RECORD] = "audio-record",
Mingming Yine62d7842013-10-25 16:26:03 -0700169 [USECASE_AUDIO_RECORD_COMPRESS] = "audio-record-compress",
Eric Laurentb23d5282013-05-14 15:27:20 -0700170 [USECASE_AUDIO_RECORD_LOW_LATENCY] = "low-latency-record",
Preetam Singh Ranawatde84f1a2013-11-01 14:58:16 -0700171 [USECASE_AUDIO_RECORD_FM_VIRTUAL] = "fm-virtual-record",
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700172 [USECASE_AUDIO_PLAYBACK_FM] = "play-fm",
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800173 [USECASE_AUDIO_HFP_SCO] = "hfp-sco",
Vimal Puthanveed47e64852013-12-20 13:23:39 -0800174 [USECASE_AUDIO_HFP_SCO_WB] = "hfp-sco-wb",
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700175 [USECASE_VOICE_CALL] = "voice-call",
Mingming Yinee733602014-04-03 17:47:22 -0700176
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700177 [USECASE_VOICE2_CALL] = "voice2-call",
178 [USECASE_VOLTE_CALL] = "volte-call",
179 [USECASE_QCHAT_CALL] = "qchat-call",
Vicky Sehrawat111aeb32014-02-12 17:58:59 -0800180 [USECASE_VOWLAN_CALL] = "vowlan-call",
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800181 [USECASE_COMPRESS_VOIP_CALL] = "compress-voip-call",
Shiv Maliyappanahallida107642013-10-17 11:16:13 -0700182 [USECASE_INCALL_REC_UPLINK] = "incall-rec-uplink",
183 [USECASE_INCALL_REC_DOWNLINK] = "incall-rec-downlink",
184 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK] = "incall-rec-uplink-and-downlink",
Helen Zenge56b4852013-12-03 16:54:40 -0800185 [USECASE_INCALL_REC_UPLINK_COMPRESS] = "incall-rec-uplink-compress",
186 [USECASE_INCALL_REC_DOWNLINK_COMPRESS] = "incall-rec-downlink-compress",
187 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK_COMPRESS] = "incall-rec-uplink-and-downlink-compress",
188
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -0700189 [USECASE_INCALL_MUSIC_UPLINK] = "incall_music_uplink",
190 [USECASE_INCALL_MUSIC_UPLINK2] = "incall_music_uplink2",
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700191 [USECASE_AUDIO_SPKR_CALIB_RX] = "spkr-rx-calib",
192 [USECASE_AUDIO_SPKR_CALIB_TX] = "spkr-vi-record",
Divya Narayanan Poojaryab9b1ef2014-09-12 15:52:36 +0530193
194 [USECASE_AUDIO_PLAYBACK_AFE_PROXY] = "afe-proxy-playback",
195 [USECASE_AUDIO_RECORD_AFE_PROXY] = "afe-proxy-record",
Eric Laurentb23d5282013-05-14 15:27:20 -0700196};
197
Subhash Chandra Bose Naripeddy148144e2014-04-01 21:03:10 -0700198static const audio_usecase_t offload_usecases[] = {
199 USECASE_AUDIO_PLAYBACK_OFFLOAD,
200#ifdef MULTIPLE_OFFLOAD_ENABLED
201 USECASE_AUDIO_PLAYBACK_OFFLOAD2,
202 USECASE_AUDIO_PLAYBACK_OFFLOAD3,
Steve Kondikac72feb2014-07-20 23:15:34 -0700203#ifndef PLATFORM_MSM8974
Subhash Chandra Bose Naripeddy148144e2014-04-01 21:03:10 -0700204 USECASE_AUDIO_PLAYBACK_OFFLOAD4,
205 USECASE_AUDIO_PLAYBACK_OFFLOAD5,
206 USECASE_AUDIO_PLAYBACK_OFFLOAD6,
207 USECASE_AUDIO_PLAYBACK_OFFLOAD7,
Steve Kondikac72feb2014-07-20 23:15:34 -0700208#endif
Subhash Chandra Bose Naripeddy148144e2014-04-01 21:03:10 -0700209 USECASE_AUDIO_PLAYBACK_OFFLOAD8,
Steve Kondikac72feb2014-07-20 23:15:34 -0700210#ifndef PLATFORM_MSM8974
Subhash Chandra Bose Naripeddy148144e2014-04-01 21:03:10 -0700211 USECASE_AUDIO_PLAYBACK_OFFLOAD9,
212#endif
Steve Kondikac72feb2014-07-20 23:15:34 -0700213#endif
Subhash Chandra Bose Naripeddy148144e2014-04-01 21:03:10 -0700214};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800215
216#define STRING_TO_ENUM(string) { #string, string }
217
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800218struct string_to_enum {
219 const char *name;
220 uint32_t value;
221};
222
223static const struct string_to_enum out_channels_name_to_enum_table[] = {
224 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
225 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1),
226 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
227};
228
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700229static struct audio_device *adev = NULL;
230static pthread_mutex_t adev_init_lock;
Kiran Kandi910e1862013-10-29 13:29:42 -0700231static unsigned int audio_device_ref_count;
232
Haynes Mathew George5191a852013-09-11 14:19:36 -0700233static int set_voice_volume_l(struct audio_device *adev, float volume);
Krishnankutty Kolathappilly9d1632f2014-01-09 12:45:31 -0800234
Krishnankutty Kolathappilly9d1632f2014-01-09 12:45:31 -0800235static int check_and_set_gapless_mode(struct audio_device *adev) {
236
237
238 char value[PROPERTY_VALUE_MAX] = {0};
239 bool gapless_enabled = false;
240 const char *mixer_ctl_name = "Compress Gapless Playback";
241 struct mixer_ctl *ctl;
242
243 ALOGV("%s:", __func__);
244 property_get("audio.offload.gapless.enabled", value, NULL);
245 gapless_enabled = atoi(value) || !strncmp("true", value, 4);
246
247 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
248 if (!ctl) {
249 ALOGE("%s: Could not get ctl for mixer cmd - %s",
250 __func__, mixer_ctl_name);
251 return -EINVAL;
252 }
253
254 if (mixer_ctl_set_value(ctl, 0, gapless_enabled) < 0) {
255 ALOGE("%s: Could not set gapless mode %d",
256 __func__, gapless_enabled);
257 return -EINVAL;
258 }
259 return 0;
260}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700261
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700262static bool is_supported_format(audio_format_t format)
263{
Steve Kondik3fdf4fc2014-12-10 21:15:43 -0800264 switch (format) {
Steve Kondik3abbbc82014-11-29 14:14:43 -0800265 case AUDIO_FORMAT_MP3:
Steve Kondik3fdf4fc2014-12-10 21:15:43 -0800266 case AUDIO_FORMAT_PCM_16_BIT_OFFLOAD:
267 case AUDIO_FORMAT_PCM_24_BIT_OFFLOAD:
Steve Kondik6bedcdf2014-07-21 11:48:30 -0700268#ifdef FLAC_OFFLOAD_ENABLED
Steve Kondik3abbbc82014-11-29 14:14:43 -0800269 case AUDIO_FORMAT_FLAC:
Steve Kondik6bedcdf2014-07-21 11:48:30 -0700270#endif
Steve Kondik3abbbc82014-11-29 14:14:43 -0800271#ifdef WMA_OFFLOAD_ENABLED
272 case AUDIO_FORMAT_WMA:
273 case AUDIO_FORMAT_WMA_PRO:
274#endif
275#ifdef MP2_OFFLOAD_ENABLED
276 case AUDIO_FORMAT_MP2:
277#endif
278 case AUDIO_FORMAT_AAC_LC:
279 case AUDIO_FORMAT_AAC_HE_V1:
280 case AUDIO_FORMAT_AAC_HE_V2:
Ashish Jaincff6e3e2014-08-25 20:36:25 +0530281 return true;
Steve Kondik3abbbc82014-11-29 14:14:43 -0800282
Steve Kondik3fdf4fc2014-12-10 21:15:43 -0800283 default:
284 return false;
Ashish Jaincff6e3e2014-08-25 20:36:25 +0530285 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700286 return false;
287}
288
289static int get_snd_codec_id(audio_format_t format)
290{
291 int id = 0;
292
Ashish Jaincff6e3e2014-08-25 20:36:25 +0530293 switch (format & AUDIO_FORMAT_MAIN_MASK) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700294 case AUDIO_FORMAT_MP3:
295 id = SND_AUDIOCODEC_MP3;
296 break;
297 case AUDIO_FORMAT_AAC:
298 id = SND_AUDIOCODEC_AAC;
299 break;
Ashish Jaincff6e3e2014-08-25 20:36:25 +0530300 case AUDIO_FORMAT_PCM_OFFLOAD:
ApurupaPattapu0c566872014-01-10 14:46:02 -0800301 id = SND_AUDIOCODEC_PCM;
302 break;
Steve Kondik6bedcdf2014-07-21 11:48:30 -0700303#ifdef FLAC_OFFLOAD_ENABLED
ApurupaPattapu9d6b4362014-02-27 10:24:11 -0800304 case AUDIO_FORMAT_FLAC:
305 id = SND_AUDIOCODEC_FLAC;
306 break;
Steve Kondik6bedcdf2014-07-21 11:48:30 -0700307#endif
Ethan Chenc856d972014-07-25 14:57:15 -0700308#ifdef WMA_OFFLOAD_ENABLED
Steve Kondikba3b35d2014-07-18 01:49:48 -0700309 case AUDIO_FORMAT_WMA:
310 id = SND_AUDIOCODEC_WMA;
311 break;
312 case AUDIO_FORMAT_WMA_PRO:
313 id = SND_AUDIOCODEC_WMA_PRO;
314 break;
Ethan Chenc856d972014-07-25 14:57:15 -0700315#endif
316#ifdef MP2_OFFLOAD_ENABLED
Steve Kondikba3b35d2014-07-18 01:49:48 -0700317 case AUDIO_FORMAT_MP2:
318 id = SND_AUDIOCODEC_MP2;
319 break;
Ethan Chenc856d972014-07-25 14:57:15 -0700320#endif
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700321 default:
Mingming Yin90310102013-11-13 16:57:00 -0800322 ALOGE("%s: Unsupported audio format :%x", __func__, format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700323 }
324
325 return id;
326}
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -0800327
Avinash Vaish8005dc82014-07-24 15:36:33 +0530328static int enable_audio_route_for_voice_usecases(struct audio_device *adev,
329 struct audio_usecase *uc_info)
330{
331 struct listnode *node;
332 struct audio_usecase *usecase;
333
334 if (uc_info == NULL)
335 return -EINVAL;
336
337 /* Re-route all voice usecases on the shared backend other than the
338 specified usecase to new snd devices */
339 list_for_each(node, &adev->usecase_list) {
340 usecase = node_to_item(node, struct audio_usecase, list);
341 if ((usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) &&
342 (usecase != uc_info))
343 enable_audio_route(adev, usecase);
344 }
345 return 0;
346}
347
Venkata Narendra Kumar Guttac9e9e2c2014-07-09 16:29:28 +0530348int get_snd_card_state(struct audio_device *adev)
Naresh Tannirucef332d2014-06-04 18:17:56 +0530349{
350 int snd_scard_state;
351
352 if (!adev)
353 return SND_CARD_STATE_OFFLINE;
354
355 pthread_mutex_lock(&adev->snd_card_status.lock);
356 snd_scard_state = adev->snd_card_status.state;
357 pthread_mutex_unlock(&adev->snd_card_status.lock);
358
359 return snd_scard_state;
360}
361
362static int set_snd_card_state(struct audio_device *adev, int snd_scard_state)
363{
364 if (!adev)
365 return -ENOSYS;
366
367 pthread_mutex_lock(&adev->snd_card_status.lock);
368 adev->snd_card_status.state = snd_scard_state;
369 pthread_mutex_unlock(&adev->snd_card_status.lock);
370
371 return 0;
372}
373
Ravi Kumar Alamanda1c3de5e2014-09-08 15:59:58 -0700374int pcm_ioctl(struct pcm *pcm, int request, ...)
375{
376 va_list ap;
377 void * arg;
378 int pcm_fd = *(int*)pcm;
379
380 va_start(ap, request);
381 arg = va_arg(ap, void *);
382 va_end(ap);
383
384 return ioctl(pcm_fd, request, arg);
385}
386
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700387int enable_audio_route(struct audio_device *adev,
Haynes Mathew Georgeea098922014-04-24 17:53:50 -0700388 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800389{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700390 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700391 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800392
393 if (usecase == NULL)
394 return -EINVAL;
395
396 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
397
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800398 if (usecase->type == PCM_CAPTURE)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700399 snd_device = usecase->in_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800400 else
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700401 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800402
Subhash Chandra Bose Naripeddye0a07122013-12-14 00:34:53 -0800403#ifdef DS1_DOLBY_DAP_ENABLED
404 audio_extn_dolby_set_dmid(adev);
405 audio_extn_dolby_set_endpoint(adev);
406#endif
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800407 strcpy(mixer_path, use_case_table[usecase->id]);
Eric Laurentb23d5282013-05-14 15:27:20 -0700408 platform_add_backend_name(mixer_path, snd_device);
Haynes Mathew Georgef9306752014-04-24 11:53:44 -0700409 ALOGV("%s: apply mixer and update path: %s", __func__, mixer_path);
410 audio_route_apply_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800411 ALOGV("%s: exit", __func__);
412 return 0;
413}
414
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700415int disable_audio_route(struct audio_device *adev,
Haynes Mathew Georgeea098922014-04-24 17:53:50 -0700416 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800417{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700418 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700419 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800420
421 if (usecase == NULL)
422 return -EINVAL;
423
424 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700425 if (usecase->type == PCM_CAPTURE)
426 snd_device = usecase->in_snd_device;
427 else
428 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800429 strcpy(mixer_path, use_case_table[usecase->id]);
Eric Laurentb23d5282013-05-14 15:27:20 -0700430 platform_add_backend_name(mixer_path, snd_device);
Haynes Mathew Georgef9306752014-04-24 11:53:44 -0700431 ALOGV("%s: reset and update mixer path: %s", __func__, mixer_path);
432 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800433 ALOGV("%s: exit", __func__);
434 return 0;
435}
436
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700437int enable_snd_device(struct audio_device *adev,
Haynes Mathew Georgeea098922014-04-24 17:53:50 -0700438 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800439{
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700440 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
441
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800442 if (snd_device < SND_DEVICE_MIN ||
443 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800444 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800445 return -EINVAL;
446 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700447
448 adev->snd_dev_ref_cnt[snd_device]++;
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700449
450 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
451 ALOGE("%s: Invalid sound device returned", __func__);
452 return -EINVAL;
453 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700454 if (adev->snd_dev_ref_cnt[snd_device] > 1) {
Eric Laurent994a6932013-07-17 11:51:42 -0700455 ALOGV("%s: snd_device(%d: %s) is already active",
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700456 __func__, snd_device, device_name);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700457 return 0;
458 }
459
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700460 /* start usb playback thread */
461 if(SND_DEVICE_OUT_USB_HEADSET == snd_device ||
462 SND_DEVICE_OUT_SPEAKER_AND_USB_HEADSET == snd_device)
463 audio_extn_usb_start_playback(adev);
464
465 /* start usb capture thread */
466 if(SND_DEVICE_IN_USB_HEADSET_MIC == snd_device)
467 audio_extn_usb_start_capture(adev);
468
Tony Layher692f19a2015-01-03 13:16:45 -0500469 if ((snd_device == SND_DEVICE_OUT_SPEAKER ||
470 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700471 audio_extn_spkr_prot_is_enabled()) {
472 if (audio_extn_spkr_prot_start_processing(snd_device)) {
473 ALOGE("%s: spkr_start_processing failed", __func__);
474 return -EINVAL;
475 }
476 } else {
477 ALOGV("%s: snd_device(%d: %s)", __func__,
Steve Kondik6288f9e2014-12-27 13:36:30 -0800478 snd_device, device_name);
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700479 if (platform_send_audio_calibration(adev->platform, snd_device) < 0) {
480 adev->snd_dev_ref_cnt[snd_device]--;
481 return -EINVAL;
482 }
Steve Kondik6288f9e2014-12-27 13:36:30 -0800483 audio_extn_listen_update_status(snd_device,
484 LISTEN_EVENT_SND_DEVICE_BUSY);
Kiran Kandide144c82013-11-20 15:58:32 -0800485
Haynes Mathew Georgef9306752014-04-24 11:53:44 -0700486 audio_route_apply_and_update_path(adev->audio_route, device_name);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800487 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800488 return 0;
489}
490
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700491int disable_snd_device(struct audio_device *adev,
Haynes Mathew Georgeea098922014-04-24 17:53:50 -0700492 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800493{
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700494 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
495
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800496 if (snd_device < SND_DEVICE_MIN ||
497 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800498 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800499 return -EINVAL;
500 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700501 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
502 ALOGE("%s: device ref cnt is already 0", __func__);
503 return -EINVAL;
504 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700505
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700506 adev->snd_dev_ref_cnt[snd_device]--;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700507
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700508 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
509 ALOGE("%s: Invalid sound device returned", __func__);
510 return -EINVAL;
511 }
512
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700513 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
Eric Laurent994a6932013-07-17 11:51:42 -0700514 ALOGV("%s: snd_device(%d: %s)", __func__,
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700515 snd_device, device_name);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -0800516 /* exit usb play back thread */
517 if(SND_DEVICE_OUT_USB_HEADSET == snd_device ||
518 SND_DEVICE_OUT_SPEAKER_AND_USB_HEADSET == snd_device)
519 audio_extn_usb_stop_playback();
520
521 /* exit usb capture thread */
522 if(SND_DEVICE_IN_USB_HEADSET_MIC == snd_device)
Rajshekar Eashwarappa4dfa0752014-10-02 20:18:20 +0530523 audio_extn_usb_stop_capture();
Tony Layher692f19a2015-01-03 13:16:45 -0500524
525 if ((snd_device == SND_DEVICE_OUT_SPEAKER ||
526 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700527 audio_extn_spkr_prot_is_enabled()) {
528 audio_extn_spkr_prot_stop_processing();
529 } else
Haynes Mathew Georgef9306752014-04-24 11:53:44 -0700530 audio_route_reset_and_update_path(adev->audio_route, device_name);
Kiran Kandide144c82013-11-20 15:58:32 -0800531
Steve Kondik6288f9e2014-12-27 13:36:30 -0800532 audio_extn_listen_update_status(snd_device,
Kiran Kandide144c82013-11-20 15:58:32 -0800533 LISTEN_EVENT_SND_DEVICE_FREE);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700534 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700535
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800536 return 0;
537}
538
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700539static void check_usecases_codec_backend(struct audio_device *adev,
540 struct audio_usecase *uc_info,
541 snd_device_t snd_device)
542{
543 struct listnode *node;
544 struct audio_usecase *usecase;
545 bool switch_device[AUDIO_USECASE_MAX];
546 int i, num_uc_to_switch = 0;
547
548 /*
549 * This function is to make sure that all the usecases that are active on
550 * the hardware codec backend are always routed to any one device that is
551 * handled by the hardware codec.
552 * For example, if low-latency and deep-buffer usecases are currently active
553 * on speaker and out_set_parameters(headset) is received on low-latency
554 * output, then we have to make sure deep-buffer is also switched to headset,
555 * because of the limitation that both the devices cannot be enabled
556 * at the same time as they share the same backend.
557 */
ApurupaPattapu9d6b4362014-02-27 10:24:11 -0800558 /*
559 * This call is to check if we need to force routing for a particular stream
560 * If there is a backend configuration change for the device when a
561 * new stream starts, then ADM needs to be closed and re-opened with the new
562 * configuraion. This call check if we need to re-route all the streams
563 * associated with the backend. Touch tone + 24 bit playback.
564 */
565 bool force_routing = platform_check_and_set_codec_backend_cfg(adev, uc_info);
566
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700567 /* Disable all the usecases on the shared backend other than the
568 specified usecase */
569 for (i = 0; i < AUDIO_USECASE_MAX; i++)
570 switch_device[i] = false;
571
572 list_for_each(node, &adev->usecase_list) {
573 usecase = node_to_item(node, struct audio_usecase, list);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800574 if (usecase->type != PCM_CAPTURE &&
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700575 usecase != uc_info &&
ApurupaPattapu9d6b4362014-02-27 10:24:11 -0800576 (usecase->out_snd_device != snd_device || force_routing) &&
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700577 usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) {
578 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
579 __func__, use_case_table[usecase->id],
Eric Laurentb23d5282013-05-14 15:27:20 -0700580 platform_get_snd_device_name(usecase->out_snd_device));
Haynes Mathew Georgeea098922014-04-24 17:53:50 -0700581 disable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700582 switch_device[usecase->id] = true;
583 num_uc_to_switch++;
584 }
585 }
586
587 if (num_uc_to_switch) {
Haynes Mathew Georgef9306752014-04-24 11:53:44 -0700588 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700589
590 list_for_each(node, &adev->usecase_list) {
591 usecase = node_to_item(node, struct audio_usecase, list);
592 if (switch_device[usecase->id]) {
Haynes Mathew Georgeea098922014-04-24 17:53:50 -0700593 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700594 }
595 }
596
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -0700597 list_for_each(node, &adev->usecase_list) {
598 usecase = node_to_item(node, struct audio_usecase, list);
599 if (switch_device[usecase->id]) {
Haynes Mathew Georgeea098922014-04-24 17:53:50 -0700600 enable_snd_device(adev, snd_device);
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -0700601 }
602 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700603
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700604 /* Re-route all the usecases on the shared backend other than the
605 specified usecase to new snd devices */
606 list_for_each(node, &adev->usecase_list) {
607 usecase = node_to_item(node, struct audio_usecase, list);
608 /* Update the out_snd_device only before enabling the audio route */
609 if (switch_device[usecase->id] ) {
610 usecase->out_snd_device = snd_device;
Avinash Vaish8005dc82014-07-24 15:36:33 +0530611 if (usecase->type != VOICE_CALL && usecase->type != VOIP_CALL)
612 enable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700613 }
614 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700615 }
616}
617
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700618static void check_and_route_capture_usecases(struct audio_device *adev,
619 struct audio_usecase *uc_info,
620 snd_device_t snd_device)
621{
622 struct listnode *node;
623 struct audio_usecase *usecase;
624 bool switch_device[AUDIO_USECASE_MAX];
625 int i, num_uc_to_switch = 0;
626
627 /*
628 * This function is to make sure that all the active capture usecases
629 * are always routed to the same input sound device.
630 * For example, if audio-record and voice-call usecases are currently
631 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
632 * is received for voice call then we have to make sure that audio-record
633 * usecase is also switched to earpiece i.e. voice-dmic-ef,
634 * because of the limitation that two devices cannot be enabled
635 * at the same time if they share the same backend.
636 */
637 for (i = 0; i < AUDIO_USECASE_MAX; i++)
638 switch_device[i] = false;
639
640 list_for_each(node, &adev->usecase_list) {
641 usecase = node_to_item(node, struct audio_usecase, list);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800642 if (usecase->type != PCM_PLAYBACK &&
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700643 usecase != uc_info &&
Avinash Vaish44014792015-03-27 14:46:04 +0530644 usecase->in_snd_device != snd_device &&
645 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700646 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
647 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -0700648 platform_get_snd_device_name(usecase->in_snd_device));
Haynes Mathew Georgeea098922014-04-24 17:53:50 -0700649 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700650 switch_device[usecase->id] = true;
651 num_uc_to_switch++;
652 }
653 }
654
655 if (num_uc_to_switch) {
Haynes Mathew Georgef9306752014-04-24 11:53:44 -0700656 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700657
658 list_for_each(node, &adev->usecase_list) {
659 usecase = node_to_item(node, struct audio_usecase, list);
660 if (switch_device[usecase->id]) {
Haynes Mathew Georgeea098922014-04-24 17:53:50 -0700661 disable_snd_device(adev, usecase->in_snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800662 }
663 }
664
665 list_for_each(node, &adev->usecase_list) {
666 usecase = node_to_item(node, struct audio_usecase, list);
667 if (switch_device[usecase->id]) {
Haynes Mathew Georgeea098922014-04-24 17:53:50 -0700668 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700669 }
670 }
671
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700672 /* Re-route all the usecases on the shared backend other than the
673 specified usecase to new snd devices */
674 list_for_each(node, &adev->usecase_list) {
675 usecase = node_to_item(node, struct audio_usecase, list);
676 /* Update the in_snd_device only before enabling the audio route */
677 if (switch_device[usecase->id] ) {
678 usecase->in_snd_device = snd_device;
Avinash Vaish8005dc82014-07-24 15:36:33 +0530679 if (usecase->type != VOICE_CALL && usecase->type != VOIP_CALL)
680 enable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700681 }
682 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700683 }
684}
685
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800686/* must be called with hw device mutex locked */
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700687static int read_hdmi_channel_masks(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800688{
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700689 int ret = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -0700690 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800691
692 switch (channels) {
693 /*
694 * Do not handle stereo output in Multi-channel cases
695 * Stereo case is handled in normal playback path
696 */
697 case 6:
698 ALOGV("%s: HDMI supports 5.1", __func__);
699 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_5POINT1;
700 break;
701 case 8:
702 ALOGV("%s: HDMI supports 5.1 and 7.1 channels", __func__);
703 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_5POINT1;
704 out->supported_channel_masks[1] = AUDIO_CHANNEL_OUT_7POINT1;
705 break;
706 default:
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700707 ALOGE("HDMI does not support multi channel playback");
708 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800709 break;
710 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700711 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800712}
713
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700714static audio_usecase_t get_voice_usecase_id_from_list(struct audio_device *adev)
715{
716 struct audio_usecase *usecase;
717 struct listnode *node;
718
719 list_for_each(node, &adev->usecase_list) {
720 usecase = node_to_item(node, struct audio_usecase, list);
721 if (usecase->type == VOICE_CALL) {
722 ALOGV("%s: usecase id %d", __func__, usecase->id);
723 return usecase->id;
724 }
725 }
726 return USECASE_INVALID;
727}
728
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700729struct audio_usecase *get_usecase_from_list(struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700730 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700731{
732 struct audio_usecase *usecase;
733 struct listnode *node;
734
735 list_for_each(node, &adev->usecase_list) {
736 usecase = node_to_item(node, struct audio_usecase, list);
737 if (usecase->id == uc_id)
738 return usecase;
739 }
740 return NULL;
741}
742
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700743int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800744{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800745 snd_device_t out_snd_device = SND_DEVICE_NONE;
746 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700747 struct audio_usecase *usecase = NULL;
748 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800749 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -0800750 struct audio_usecase *hfp_usecase = NULL;
Vimal Puthanveed739e7152014-01-23 15:56:53 -0800751 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800752 struct listnode *node;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700753 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800754
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700755 usecase = get_usecase_from_list(adev, uc_id);
756 if (usecase == NULL) {
757 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
758 return -EINVAL;
759 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800760
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800761 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800762 (usecase->type == VOIP_CALL) ||
763 (usecase->type == PCM_HFP_CALL)) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700764 out_snd_device = platform_get_output_snd_device(adev->platform,
765 usecase->stream.out->devices);
766 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700767 usecase->devices = usecase->stream.out->devices;
768 } else {
769 /*
770 * If the voice call is active, use the sound devices of voice call usecase
771 * so that it would not result any device switch. All the usecases will
772 * be switched to new device when select_devices() is called for voice call
773 * usecase. This is to avoid switching devices for voice call when
774 * check_usecases_codec_backend() is called below.
775 */
Vidyakumar Athotaf85f6a22014-08-05 18:20:42 -0700776 if (adev->voice.in_call && adev->mode == AUDIO_MODE_IN_CALL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700777 vc_usecase = get_usecase_from_list(adev,
778 get_voice_usecase_id_from_list(adev));
Mingming Yin6c23f382014-08-14 00:00:51 -0700779 if ((vc_usecase) && ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
780 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700781 in_snd_device = vc_usecase->in_snd_device;
782 out_snd_device = vc_usecase->out_snd_device;
783 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800784 } else if (voice_extn_compress_voip_is_active(adev)) {
785 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
Mingming Yin6c23f382014-08-14 00:00:51 -0700786 if ((voip_usecase) && ((voip_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Avinash Vaish6a4c3372014-06-25 12:20:37 +0530787 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Mingming Yin6c23f382014-08-14 00:00:51 -0700788 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800789 in_snd_device = voip_usecase->in_snd_device;
790 out_snd_device = voip_usecase->out_snd_device;
791 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -0800792 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed739e7152014-01-23 15:56:53 -0800793 hfp_ucid = audio_extn_hfp_get_usecase();
794 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Mingming Yin6c23f382014-08-14 00:00:51 -0700795 if ((hfp_usecase) && (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -0800796 in_snd_device = hfp_usecase->in_snd_device;
797 out_snd_device = hfp_usecase->out_snd_device;
798 }
Vimal Puthanveed8fa9eab2014-01-07 16:47:47 -0800799 } else if (audio_extn_hfp_is_active(adev)) {
800 hfp_usecase = get_usecase_from_list(adev, USECASE_AUDIO_HFP_SCO);
801 if (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) {
802 in_snd_device = hfp_usecase->in_snd_device;
803 out_snd_device = hfp_usecase->out_snd_device;
804 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700805 }
806 if (usecase->type == PCM_PLAYBACK) {
807 usecase->devices = usecase->stream.out->devices;
808 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700809 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700810 out_snd_device = platform_get_output_snd_device(adev->platform,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700811 usecase->stream.out->devices);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700812 if (usecase->stream.out == adev->primary_output &&
Shreyas Nagasandra Chandrasekhar23b3af22014-09-03 19:10:01 +0530813 adev->active_input ) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700814 select_devices(adev, adev->active_input->usecase);
815 }
816 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700817 } else if (usecase->type == PCM_CAPTURE) {
818 usecase->devices = usecase->stream.in->device;
819 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700820 if (in_snd_device == SND_DEVICE_NONE) {
Divya Narayanan Poojaryab9b1ef2014-09-12 15:52:36 +0530821 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Shreyas Nagasandra Chandrasekhar23b3af22014-09-03 19:10:01 +0530822 if ((adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION || (adev->mode == AUDIO_MODE_IN_COMMUNICATION && adev->active_input->source == AUDIO_SOURCE_MIC)) &&
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700823 adev->primary_output && !adev->primary_output->standby) {
Divya Narayanan Poojaryab9b1ef2014-09-12 15:52:36 +0530824 out_device = adev->primary_output->devices;
825 } else if(usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
826 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700827 }
Divya Narayanan Poojaryab9b1ef2014-09-12 15:52:36 +0530828 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700829 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700830 }
831 }
832
833 if (out_snd_device == usecase->out_snd_device &&
834 in_snd_device == usecase->in_snd_device) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800835 return 0;
836 }
837
sangwoobc677242013-08-08 16:53:43 +0900838 ALOGD("%s: out_snd_device(%d: %s) in_snd_device(%d: %s)", __func__,
Eric Laurentb23d5282013-05-14 15:27:20 -0700839 out_snd_device, platform_get_snd_device_name(out_snd_device),
840 in_snd_device, platform_get_snd_device_name(in_snd_device));
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800841
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800842 /*
843 * Limitation: While in call, to do a device switch we need to disable
844 * and enable both RX and TX devices though one of them is same as current
845 * device.
846 */
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800847 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700848 status = platform_switch_voice_call_device_pre(adev->platform);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -0800849 }
850
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700851 /* Disable current sound devices */
852 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew Georgeea098922014-04-24 17:53:50 -0700853 disable_audio_route(adev, usecase);
854 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800855 }
856
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700857 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew Georgeea098922014-04-24 17:53:50 -0700858 disable_audio_route(adev, usecase);
859 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800860 }
861
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700862 /* Enable new sound devices */
863 if (out_snd_device != SND_DEVICE_NONE) {
864 if (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)
865 check_usecases_codec_backend(adev, usecase, out_snd_device);
Haynes Mathew Georgeea098922014-04-24 17:53:50 -0700866 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800867 }
868
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700869 if (in_snd_device != SND_DEVICE_NONE) {
870 check_and_route_capture_usecases(adev, usecase, in_snd_device);
Haynes Mathew Georgeea098922014-04-24 17:53:50 -0700871 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700872 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700873
Avinash Vaish8005dc82014-07-24 15:36:33 +0530874 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700875 status = platform_switch_voice_call_device_post(adev->platform,
876 out_snd_device,
877 in_snd_device);
Avinash Vaish8005dc82014-07-24 15:36:33 +0530878 enable_audio_route_for_voice_usecases(adev, usecase);
879 }
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -0800880
sangwoo170731f2013-06-08 15:36:36 +0900881 usecase->in_snd_device = in_snd_device;
882 usecase->out_snd_device = out_snd_device;
883
Haynes Mathew Georgeea098922014-04-24 17:53:50 -0700884 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +0900885
Daniel Hillenbrand8373bc62013-05-23 10:10:00 +0530886#ifdef USES_AUDIO_AMPLIFIER
887 /* Rely on amplifier_set_devices to distinguish between in/out devices */
888 amplifier_set_devices(in_snd_device);
889 amplifier_set_devices(out_snd_device);
890#endif
891
892
Vidyakumar Athota1fd21792013-11-15 14:50:57 -0800893 /* Applicable only on the targets that has external modem.
894 * Enable device command should be sent to modem only after
895 * enabling voice call mixer controls
896 */
897 if (usecase->type == VOICE_CALL)
898 status = platform_switch_voice_call_usecase_route_post(adev->platform,
899 out_snd_device,
900 in_snd_device);
901
Sidipotu Ashoke4514fa2014-05-02 16:21:50 +0530902 ALOGD("%s: done",__func__);
903
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800904 return status;
905}
906
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800907static int stop_input_stream(struct stream_in *in)
908{
909 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800910 struct audio_usecase *uc_info;
911 struct audio_device *adev = in->dev;
912
Eric Laurentc8400632013-02-14 19:04:54 -0800913 adev->active_input = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800914
Eric Laurent994a6932013-07-17 11:51:42 -0700915 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700916 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800917 uc_info = get_usecase_from_list(adev, in->usecase);
918 if (uc_info == NULL) {
919 ALOGE("%s: Could not find the usecase (%d) in the list",
920 __func__, in->usecase);
921 return -EINVAL;
922 }
923
Vidyakumar Athota2850d532013-11-19 16:02:12 -0800924 /* Close in-call recording streams */
925 voice_check_and_stop_incall_rec_usecase(adev, in);
926
Eric Laurent150dbfe2013-02-27 14:31:02 -0800927 /* 1. Disable stream specific mixer controls */
Haynes Mathew Georgeea098922014-04-24 17:53:50 -0700928 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700929
930 /* 2. Disable the tx device */
Haynes Mathew Georgeea098922014-04-24 17:53:50 -0700931 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800932
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800933 list_remove(&uc_info->list);
934 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800935
Eric Laurent994a6932013-07-17 11:51:42 -0700936 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800937 return ret;
938}
939
940int start_input_stream(struct stream_in *in)
941{
942 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -0800943 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800944 struct audio_usecase *uc_info;
945 struct audio_device *adev = in->dev;
Naresh Tannirucef332d2014-06-04 18:17:56 +0530946 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800947
Ramjee Singh240ac652015-07-31 16:12:29 +0530948 int usecase = platform_update_usecase_from_source(in->source,in->usecase);
949 if (get_usecase_from_list(adev, usecase) == NULL)
950 in->usecase = usecase;
951
Sidipotu Ashoke4514fa2014-05-02 16:21:50 +0530952 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
953 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -0700954
Naresh Tannirucef332d2014-06-04 18:17:56 +0530955 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
956 ALOGE("%s: sound card is not active/SSR returning error ", __func__);
Naresh Tanniru2d19ab42014-05-11 19:56:25 +0530957 ret = -ENETRESET;
Naresh Tanniru2d19ab42014-05-11 19:56:25 +0530958 goto error_config;
959 }
Naresh Tanniru2d19ab42014-05-11 19:56:25 +0530960
Shiv Maliyappanahallida107642013-10-17 11:16:13 -0700961 /* Check if source matches incall recording usecase criteria */
962 ret = voice_check_and_set_incall_rec_usecase(adev, in);
963 if (ret)
964 goto error_config;
965 else
966 ALOGV("%s: usecase(%d)", __func__, in->usecase);
967
Ramjee Singh240ac652015-07-31 16:12:29 +0530968 if (get_usecase_from_list(adev, in->usecase) != NULL) {
969 ALOGE("%s: use case assigned already in use, stream(%p)usecase(%d: %s)",
970 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
971 goto error_config;
972 }
973
Eric Laurentb23d5282013-05-14 15:27:20 -0700974 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800975 if (in->pcm_device_id < 0) {
976 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
977 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -0800978 ret = -EINVAL;
979 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800980 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700981
982 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800983 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew George9f0254a2014-06-30 13:56:18 -0700984
985 if (!uc_info) {
986 ret = -ENOMEM;
987 goto error_config;
988 }
989
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800990 uc_info->id = in->usecase;
991 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800992 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700993 uc_info->devices = in->device;
994 uc_info->in_snd_device = SND_DEVICE_NONE;
995 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800996
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800997 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700998 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800999
Eric Laurentc8400632013-02-14 19:04:54 -08001000 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
Divya Narayanan Poojaryab9b1ef2014-09-12 15:52:36 +05301001 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
1002
1003 unsigned int flags = PCM_IN;
1004 unsigned int pcm_open_retry_entry_count = 0;
1005
1006 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1007 flags |= PCM_MMAP | PCM_NOIRQ;
1008 pcm_open_retry_entry_count = PROXY_OPEN_RETRY_COUNT;
1009 }
1010
1011 while(1) {
1012 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1013 flags, &in->config);
1014 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1015 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1016 if (in->pcm != NULL) {
1017 pcm_close(in->pcm);
1018 in->pcm = NULL;
1019 }
1020 if (pcm_open_retry_entry_count-- == 0) {
1021 ret = -EIO;
1022 goto error_open;
1023 }
1024 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1025 continue;
1026 }
1027 break;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001028 }
Naresh Tanniru2d19ab42014-05-11 19:56:25 +05301029
Eric Laurent994a6932013-07-17 11:51:42 -07001030 ALOGV("%s: exit", __func__);
Eric Laurentc8400632013-02-14 19:04:54 -08001031 return ret;
1032
1033error_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001034 stop_input_stream(in);
Eric Laurentc8400632013-02-14 19:04:54 -08001035
1036error_config:
1037 adev->active_input = NULL;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001038 ALOGD("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001039
1040 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001041}
1042
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001043/* must be called with out->lock locked */
1044static int send_offload_cmd_l(struct stream_out* out, int command)
1045{
1046 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1047
Haynes Mathew George9f0254a2014-06-30 13:56:18 -07001048 if (!cmd) {
1049 ALOGE("failed to allocate mem for command 0x%x", command);
1050 return -ENOMEM;
1051 }
1052
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001053 ALOGVV("%s %d", __func__, command);
1054
1055 cmd->cmd = command;
1056 list_add_tail(&out->offload_cmd_list, &cmd->node);
1057 pthread_cond_signal(&out->offload_cond);
1058 return 0;
1059}
1060
1061/* must be called iwth out->lock locked */
1062static void stop_compressed_output_l(struct stream_out *out)
1063{
1064 out->offload_state = OFFLOAD_STATE_IDLE;
1065 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001066 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001067 if (out->compr != NULL) {
1068 compress_stop(out->compr);
1069 while (out->offload_thread_blocked) {
1070 pthread_cond_wait(&out->cond, &out->lock);
1071 }
1072 }
1073}
1074
Subhash Chandra Bose Naripeddy148144e2014-04-01 21:03:10 -07001075bool is_offload_usecase(audio_usecase_t uc_id)
1076{
1077 unsigned int i;
1078 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
1079 if (uc_id == offload_usecases[i])
1080 return true;
1081 }
1082 return false;
1083}
1084
1085static audio_usecase_t get_offload_usecase(struct audio_device *adev)
1086{
1087 audio_usecase_t ret = USECASE_AUDIO_PLAYBACK_OFFLOAD;
1088 unsigned int i, num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
1089 char value[PROPERTY_VALUE_MAX] = {0};
1090
1091 property_get("audio.offload.multiple.enabled", value, NULL);
1092 if (!(atoi(value) || !strncmp("true", value, 4)))
1093 num_usecase = 1; /* If prop is not set, limit the num of offload usecases to 1 */
1094
1095 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
1096 for (i = 0; i < num_usecase; i++) {
1097 if (!(adev->offload_usecases_state & (0x1<<i))) {
1098 adev->offload_usecases_state |= 0x1 << i;
1099 ret = offload_usecases[i];
1100 break;
1101 }
1102 }
1103 ALOGV("%s: offload usecase is %d", __func__, ret);
1104 return ret;
1105}
1106
1107static void free_offload_usecase(struct audio_device *adev,
1108 audio_usecase_t uc_id)
1109{
1110 unsigned int i;
1111 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
1112 if (offload_usecases[i] == uc_id) {
1113 adev->offload_usecases_state &= ~(0x1<<i);
1114 break;
1115 }
1116 }
1117 ALOGV("%s: free offload usecase %d", __func__, uc_id);
1118}
1119
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001120static void *offload_thread_loop(void *context)
1121{
1122 struct stream_out *out = (struct stream_out *) context;
1123 struct listnode *item;
Krishnankutty Kolathappilly0fe78f02014-01-06 18:33:58 -08001124 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001125
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001126 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
1127 set_sched_policy(0, SP_FOREGROUND);
1128 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
1129
1130 ALOGV("%s", __func__);
1131 pthread_mutex_lock(&out->lock);
1132 for (;;) {
1133 struct offload_cmd *cmd = NULL;
1134 stream_callback_event_t event;
1135 bool send_callback = false;
1136
1137 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
1138 __func__, list_empty(&out->offload_cmd_list),
1139 out->offload_state);
1140 if (list_empty(&out->offload_cmd_list)) {
1141 ALOGV("%s SLEEPING", __func__);
1142 pthread_cond_wait(&out->offload_cond, &out->lock);
1143 ALOGV("%s RUNNING", __func__);
1144 continue;
1145 }
1146
1147 item = list_head(&out->offload_cmd_list);
1148 cmd = node_to_item(item, struct offload_cmd, node);
1149 list_remove(item);
1150
1151 ALOGVV("%s STATE %d CMD %d out->compr %p",
1152 __func__, out->offload_state, cmd->cmd, out->compr);
1153
1154 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
1155 free(cmd);
1156 break;
1157 }
1158
1159 if (out->compr == NULL) {
1160 ALOGE("%s: Compress handle is NULL", __func__);
1161 pthread_cond_signal(&out->cond);
1162 continue;
1163 }
1164 out->offload_thread_blocked = true;
1165 pthread_mutex_unlock(&out->lock);
1166 send_callback = false;
1167 switch(cmd->cmd) {
1168 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Steve Kondik05c17962015-02-25 00:55:50 -08001169 ALOGV("copl(%x):calling compress_wait", (unsigned int)out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001170 compress_wait(out->compr, -1);
Steve Kondik05c17962015-02-25 00:55:50 -08001171 ALOGV("copl(%x):out of compress_wait", (unsigned int)out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001172 send_callback = true;
1173 event = STREAM_CBK_EVENT_WRITE_READY;
1174 break;
1175 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappilly0fe78f02014-01-06 18:33:58 -08001176 ret = compress_next_track(out->compr);
Sidipotu Ashok5bfacf72014-02-10 16:16:38 +05301177 if(ret == 0) {
Steve Kondik05c17962015-02-25 00:55:50 -08001178 ALOGV("copl(%p):calling compress_partial_drain", out);
Dhanalakshmi Siddani5754e2c2014-12-23 16:57:43 +05301179 ret = compress_partial_drain(out->compr);
Steve Kondik05c17962015-02-25 00:55:50 -08001180 ALOGV("copl(%p):out of compress_partial_drain", out);
Dhanalakshmi Siddani5754e2c2014-12-23 16:57:43 +05301181 if (ret < 0)
1182 ret = -errno;
Sidipotu Ashok5bfacf72014-02-10 16:16:38 +05301183 }
Dhanalakshmi Siddani5754e2c2014-12-23 16:57:43 +05301184 else if (ret == -ETIMEDOUT)
Krishnankutty Kolathappilly0fe78f02014-01-06 18:33:58 -08001185 compress_drain(out->compr);
1186 else
1187 ALOGE("%s: Next track returned error %d",__func__, ret);
Dhanalakshmi Siddani5754e2c2014-12-23 16:57:43 +05301188
1189 if (ret != -ENETRESET) {
1190 send_callback = true;
1191 event = STREAM_CBK_EVENT_DRAIN_READY;
1192
1193 /* Resend the metadata for next iteration */
1194 out->send_new_metadata = 1;
1195 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
1196 } else
1197 ALOGE("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001198 break;
1199 case OFFLOAD_CMD_DRAIN:
Steve Kondik05c17962015-02-25 00:55:50 -08001200 ALOGV("copl(%x):calling compress_drain", (unsigned int)out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001201 compress_drain(out->compr);
Steve Kondik05c17962015-02-25 00:55:50 -08001202 ALOGV("copl(%x):out of compress_drain", (unsigned int)out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001203 send_callback = true;
1204 event = STREAM_CBK_EVENT_DRAIN_READY;
1205 break;
1206 default:
1207 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
1208 break;
1209 }
1210 pthread_mutex_lock(&out->lock);
1211 out->offload_thread_blocked = false;
1212 pthread_cond_signal(&out->cond);
Eric Laurent6e895242013-09-05 16:10:57 -07001213 if (send_callback) {
Ravi Kumar Alamanda3d316172014-12-02 19:21:51 -08001214 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001215 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07001216 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001217 free(cmd);
1218 }
1219
1220 pthread_cond_signal(&out->cond);
1221 while (!list_empty(&out->offload_cmd_list)) {
1222 item = list_head(&out->offload_cmd_list);
1223 list_remove(item);
1224 free(node_to_item(item, struct offload_cmd, node));
1225 }
1226 pthread_mutex_unlock(&out->lock);
1227
1228 return NULL;
1229}
1230
1231static int create_offload_callback_thread(struct stream_out *out)
1232{
1233 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
1234 list_init(&out->offload_cmd_list);
1235 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
1236 offload_thread_loop, out);
1237 return 0;
1238}
1239
1240static int destroy_offload_callback_thread(struct stream_out *out)
1241{
1242 pthread_mutex_lock(&out->lock);
1243 stop_compressed_output_l(out);
1244 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
1245
1246 pthread_mutex_unlock(&out->lock);
1247 pthread_join(out->offload_thread, (void **) NULL);
1248 pthread_cond_destroy(&out->offload_cond);
1249
1250 return 0;
1251}
1252
Eric Laurent07eeafd2013-10-06 12:52:49 -07001253static bool allow_hdmi_channel_config(struct audio_device *adev)
1254{
1255 struct listnode *node;
1256 struct audio_usecase *usecase;
1257 bool ret = true;
1258
1259 list_for_each(node, &adev->usecase_list) {
1260 usecase = node_to_item(node, struct audio_usecase, list);
1261 if (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
1262 /*
1263 * If voice call is already existing, do not proceed further to avoid
1264 * disabling/enabling both RX and TX devices, CSD calls, etc.
1265 * Once the voice call done, the HDMI channels can be configured to
1266 * max channels of remaining use cases.
1267 */
1268 if (usecase->id == USECASE_VOICE_CALL) {
1269 ALOGD("%s: voice call is active, no change in HDMI channels",
1270 __func__);
1271 ret = false;
1272 break;
1273 } else if (usecase->id == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
1274 ALOGD("%s: multi channel playback is active, "
1275 "no change in HDMI channels", __func__);
1276 ret = false;
1277 break;
Subhash Chandra Bose Naripeddy148144e2014-04-01 21:03:10 -07001278 } else if (is_offload_usecase(usecase->id) &&
Divya Narayanan Poojary69236ba2014-09-18 11:57:57 +05301279 audio_channel_count_from_out_mask(usecase->stream.out->channel_mask) > 2) {
Mingming Yin3ed162b2014-02-24 17:56:01 -08001280 ALOGD("%s: multi-channel(%x) compress offload playback is active, "
1281 "no change in HDMI channels", __func__, usecase->stream.out->channel_mask);
1282 ret = false;
1283 break;
Eric Laurent07eeafd2013-10-06 12:52:49 -07001284 }
1285 }
1286 }
1287 return ret;
1288}
1289
1290static int check_and_set_hdmi_channels(struct audio_device *adev,
1291 unsigned int channels)
1292{
1293 struct listnode *node;
1294 struct audio_usecase *usecase;
1295
1296 /* Check if change in HDMI channel config is allowed */
1297 if (!allow_hdmi_channel_config(adev))
1298 return 0;
1299
1300 if (channels == adev->cur_hdmi_channels) {
Mingming Yin10fef6a2013-11-26 17:17:01 -08001301 ALOGD("%s: Requested channels are same as current channels(%d)", __func__, channels);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001302 return 0;
1303 }
1304
1305 platform_set_hdmi_channels(adev->platform, channels);
1306 adev->cur_hdmi_channels = channels;
1307
1308 /*
1309 * Deroute all the playback streams routed to HDMI so that
1310 * the back end is deactivated. Note that backend will not
1311 * be deactivated if any one stream is connected to it.
1312 */
1313 list_for_each(node, &adev->usecase_list) {
1314 usecase = node_to_item(node, struct audio_usecase, list);
1315 if (usecase->type == PCM_PLAYBACK &&
1316 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Haynes Mathew Georgeea098922014-04-24 17:53:50 -07001317 disable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001318 }
1319 }
1320
1321 /*
1322 * Enable all the streams disabled above. Now the HDMI backend
1323 * will be activated with new channel configuration
1324 */
1325 list_for_each(node, &adev->usecase_list) {
1326 usecase = node_to_item(node, struct audio_usecase, list);
1327 if (usecase->type == PCM_PLAYBACK &&
1328 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Haynes Mathew Georgeea098922014-04-24 17:53:50 -07001329 enable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001330 }
1331 }
1332
1333 return 0;
1334}
1335
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001336static int stop_output_stream(struct stream_out *out)
1337{
1338 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001339 struct audio_usecase *uc_info;
1340 struct audio_device *adev = out->dev;
1341
Eric Laurent994a6932013-07-17 11:51:42 -07001342 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001343 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001344 uc_info = get_usecase_from_list(adev, out->usecase);
1345 if (uc_info == NULL) {
1346 ALOGE("%s: Could not find the usecase (%d) in the list",
1347 __func__, out->usecase);
1348 return -EINVAL;
1349 }
1350
Subhash Chandra Bose Naripeddy148144e2014-04-01 21:03:10 -07001351 if (is_offload_usecase(out->usecase)) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001352 if (adev->visualizer_stop_output != NULL)
1353 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
1354 if (adev->offload_effects_stop_output != NULL)
1355 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
1356 }
Eric Laurentc4aef752013-09-12 17:45:53 -07001357
Eric Laurent150dbfe2013-02-27 14:31:02 -08001358 /* 1. Get and set stream specific mixer controls */
Haynes Mathew Georgeea098922014-04-24 17:53:50 -07001359 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001360
1361 /* 2. Disable the rx device */
Haynes Mathew Georgeea098922014-04-24 17:53:50 -07001362 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001363
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001364 list_remove(&uc_info->list);
1365 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001366
Eric Laurentda46bfb2014-08-25 22:39:29 -05001367 audio_extn_extspk_update(adev->extspk);
1368
Eric Laurent07eeafd2013-10-06 12:52:49 -07001369 /* Must be called after removing the usecase from list */
1370 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
1371 check_and_set_hdmi_channels(adev, DEFAULT_HDMI_OUT_CHANNELS);
1372
Eric Laurent994a6932013-07-17 11:51:42 -07001373 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001374 return ret;
1375}
1376
1377int start_output_stream(struct stream_out *out)
1378{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001379 int ret = 0;
Mingming Yin6c344432014-05-01 15:37:31 -07001380 int sink_channels = 0;
1381 char prop_value[PROPERTY_VALUE_MAX] = {0};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001382 struct audio_usecase *uc_info;
1383 struct audio_device *adev = out->dev;
Naresh Tannirucef332d2014-06-04 18:17:56 +05301384 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001385
Haynes Mathew George9f0254a2014-06-30 13:56:18 -07001386 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
1387 ret = -EINVAL;
1388 goto error_config;
1389 }
1390
Sidipotu Ashoke4514fa2014-05-02 16:21:50 +05301391 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x)",
1392 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
1393 out->devices);
Naresh Tanniru2d19ab42014-05-11 19:56:25 +05301394
Naresh Tannirucef332d2014-06-04 18:17:56 +05301395 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru2d19ab42014-05-11 19:56:25 +05301396 ALOGE("%s: sound card is not active/SSR returning error", __func__);
1397 ret = -ENETRESET;
Naresh Tanniru2d19ab42014-05-11 19:56:25 +05301398 goto error_config;
1399 }
Naresh Tanniru2d19ab42014-05-11 19:56:25 +05301400
Sidipotu Ashok5bfacf72014-02-10 16:16:38 +05301401 ALOGD("%s: enter: usecase(%d: %s) devices(%#x)",
1402 __func__, out->usecase, use_case_table[out->usecase], out->devices);
Eric Laurentb23d5282013-05-14 15:27:20 -07001403 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001404 if (out->pcm_device_id < 0) {
1405 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
1406 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001407 ret = -EINVAL;
1408 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001409 }
1410
1411 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew George9f0254a2014-06-30 13:56:18 -07001412
1413 if (!uc_info) {
1414 ret = -ENOMEM;
1415 goto error_config;
1416 }
1417
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001418 uc_info->id = out->usecase;
1419 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001420 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001421 uc_info->devices = out->devices;
1422 uc_info->in_snd_device = SND_DEVICE_NONE;
1423 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001424
Eric Laurent07eeafd2013-10-06 12:52:49 -07001425 /* This must be called before adding this usecase to the list */
Mingming Yin10fef6a2013-11-26 17:17:01 -08001426 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Mingming Yin6c344432014-05-01 15:37:31 -07001427 property_get("audio.use.hdmi.sink.cap", prop_value, NULL);
1428 if (!strncmp("true", prop_value, 4)) {
1429 sink_channels = platform_edid_get_max_channels(out->dev->platform);
1430 ALOGD("%s: set HDMI channel count[%d] based on sink capability", __func__, sink_channels);
1431 check_and_set_hdmi_channels(adev, sink_channels);
1432 } else {
Subhash Chandra Bose Naripeddy148144e2014-04-01 21:03:10 -07001433 if (is_offload_usecase(out->usecase))
Mingming Yin6c344432014-05-01 15:37:31 -07001434 check_and_set_hdmi_channels(adev, out->compr_config.codec->ch_in);
1435 else
1436 check_and_set_hdmi_channels(adev, out->config.channels);
1437 }
Mingming Yin10fef6a2013-11-26 17:17:01 -08001438 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07001439
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001440 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001441
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001442 select_devices(adev, out->usecase);
1443
Eric Laurentda46bfb2014-08-25 22:39:29 -05001444 audio_extn_extspk_update(adev->extspk);
1445
Steve Kondik3abbbc82014-11-29 14:14:43 -08001446 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
1447 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
1448
Subhash Chandra Bose Naripeddy148144e2014-04-01 21:03:10 -07001449 if (!is_offload_usecase(out->usecase)) {
Divya Narayanan Poojaryab9b1ef2014-09-12 15:52:36 +05301450 unsigned int flags = PCM_OUT;
1451 unsigned int pcm_open_retry_count = 0;
1452 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
1453 flags |= PCM_MMAP | PCM_NOIRQ;
1454 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1455 } else
1456 flags |= PCM_MONOTONIC;
1457
1458 while (1) {
1459 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
1460 flags, &out->config);
1461 if (out->pcm && !pcm_is_ready(out->pcm)) {
1462 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
1463 if (out->pcm != NULL) {
1464 pcm_close(out->pcm);
1465 out->pcm = NULL;
1466 }
1467 if (pcm_open_retry_count-- == 0) {
1468 ret = -EIO;
1469 goto error_open;
1470 }
1471 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1472 continue;
1473 }
1474 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001475 }
1476 } else {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001477 out->pcm = NULL;
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08001478 out->compr = compress_open(adev->snd_card,
1479 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001480 COMPRESS_IN, &out->compr_config);
1481 if (out->compr && !is_compress_ready(out->compr)) {
1482 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
1483 compress_close(out->compr);
1484 out->compr = NULL;
1485 ret = -EIO;
1486 goto error_open;
1487 }
1488 if (out->offload_callback)
1489 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07001490
Fred Oh1483d8a2015-03-04 18:42:34 -08001491 /* Since small bufs uses blocking writes, a write will be blocked
1492 for the default max poll time (20s) in the event of an SSR.
1493 Reduce the poll time to observe and deal with SSR faster.
1494 */
1495 if (out->use_small_bufs) {
1496 compress_set_max_poll_wait(out->compr, 1000);
1497 }
1498
Subhash Chandra Bose Naripeddye0a07122013-12-14 00:34:53 -08001499#ifdef DS1_DOLBY_DDP_ENABLED
1500 if (audio_extn_is_dolby_format(out->format))
1501 audio_extn_dolby_send_ddp_endp_params(adev);
1502#endif
1503
Eric Laurentc4aef752013-09-12 17:45:53 -07001504 if (adev->visualizer_start_output != NULL)
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001505 adev->visualizer_start_output(out->handle, out->pcm_device_id);
1506 if (adev->offload_effects_start_output != NULL)
1507 adev->offload_effects_start_output(out->handle, out->pcm_device_id);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001508 }
Eric Laurent994a6932013-07-17 11:51:42 -07001509 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001510 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001511error_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001512 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001513error_config:
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001514 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001515}
1516
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001517static int check_input_parameters(uint32_t sample_rate,
1518 audio_format_t format,
1519 int channel_count)
1520{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001521 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001522
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001523 if ((format != AUDIO_FORMAT_PCM_16_BIT) &&
Mingming Yine62d7842013-10-25 16:26:03 -07001524 !voice_extn_compress_voip_is_format_supported(format) &&
1525 !audio_extn_compr_cap_format_supported(format)) ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001526
1527 switch (channel_count) {
1528 case 1:
1529 case 2:
1530 case 6:
1531 break;
1532 default:
1533 ret = -EINVAL;
1534 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001535
1536 switch (sample_rate) {
1537 case 8000:
1538 case 11025:
1539 case 12000:
1540 case 16000:
1541 case 22050:
1542 case 24000:
1543 case 32000:
1544 case 44100:
1545 case 48000:
1546 break;
1547 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001548 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001549 }
1550
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001551 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001552}
1553
1554static size_t get_input_buffer_size(uint32_t sample_rate,
1555 audio_format_t format,
Ravi Kumar Alamanda1c3de5e2014-09-08 15:59:58 -07001556 int channel_count,
1557 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001558{
1559 size_t size = 0;
1560
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001561 if (check_input_parameters(sample_rate, format, channel_count) != 0)
1562 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001563
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001564 size = (sample_rate * AUDIO_CAPTURE_PERIOD_DURATION_MSEC) / 1000;
Ravi Kumar Alamanda1c3de5e2014-09-08 15:59:58 -07001565 if (is_low_latency)
1566 size = configured_low_latency_capture_period_size;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001567 /* ToDo: should use frame_size computed based on the format and
1568 channel_count here. */
1569 size *= sizeof(short) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001570
Ravi Kumar Alamanda1c3de5e2014-09-08 15:59:58 -07001571 /* make sure the size is multiple of 32 bytes
1572 * At 48 kHz mono 16-bit PCM:
1573 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
1574 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
1575 */
1576 size += 0x1f;
1577 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001578
1579 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001580}
1581
1582static uint32_t out_get_sample_rate(const struct audio_stream *stream)
1583{
1584 struct stream_out *out = (struct stream_out *)stream;
1585
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001586 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001587}
1588
Divya Narayanan Poojarybd9f33f2014-09-17 17:35:59 +05301589static int out_set_sample_rate(struct audio_stream *stream __unused,
1590 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001591{
1592 return -ENOSYS;
1593}
1594
1595static size_t out_get_buffer_size(const struct audio_stream *stream)
1596{
1597 struct stream_out *out = (struct stream_out *)stream;
1598
Subhash Chandra Bose Naripeddy148144e2014-04-01 21:03:10 -07001599 if (is_offload_usecase(out->usecase))
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001600 return out->compr_config.fragment_size;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001601 else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
1602 return voice_extn_compress_voip_out_get_buffer_size(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001603
Divya Narayanan Poojary69236ba2014-09-18 11:57:57 +05301604 return out->config.period_size *
1605 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001606}
1607
1608static uint32_t out_get_channels(const struct audio_stream *stream)
1609{
1610 struct stream_out *out = (struct stream_out *)stream;
1611
1612 return out->channel_mask;
1613}
1614
1615static audio_format_t out_get_format(const struct audio_stream *stream)
1616{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001617 struct stream_out *out = (struct stream_out *)stream;
1618
1619 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001620}
1621
Divya Narayanan Poojarybd9f33f2014-09-17 17:35:59 +05301622static int out_set_format(struct audio_stream *stream __unused,
1623 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001624{
1625 return -ENOSYS;
1626}
1627
1628static int out_standby(struct audio_stream *stream)
1629{
1630 struct stream_out *out = (struct stream_out *)stream;
1631 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001632
Sidipotu Ashoke4514fa2014-05-02 16:21:50 +05301633 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
1634 stream, out->usecase, use_case_table[out->usecase]);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001635 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
1636 /* Ignore standby in case of voip call because the voip output
1637 * stream is closed in adev_close_output_stream()
1638 */
Sidipotu Ashoke4514fa2014-05-02 16:21:50 +05301639 ALOGD("%s: Ignore Standby in VOIP call", __func__);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001640 return 0;
1641 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001642
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001643 pthread_mutex_lock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001644 if (!out->standby) {
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08001645 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001646 out->standby = true;
Subhash Chandra Bose Naripeddy148144e2014-04-01 21:03:10 -07001647 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001648 if (out->pcm) {
1649 pcm_close(out->pcm);
1650 out->pcm = NULL;
1651 }
1652 } else {
Sidipotu Ashok5bfacf72014-02-10 16:16:38 +05301653 ALOGD("copl(%x):standby", (unsigned int)out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001654 stop_compressed_output_l(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001655 out->gapless_mdata.encoder_delay = 0;
1656 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001657 if (out->compr != NULL) {
1658 compress_close(out->compr);
1659 out->compr = NULL;
1660 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08001661 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001662 stop_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001663 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001664 }
1665 pthread_mutex_unlock(&out->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07001666 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001667 return 0;
1668}
1669
Divya Narayanan Poojarybd9f33f2014-09-17 17:35:59 +05301670static int out_dump(const struct audio_stream *stream __unused,
1671 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001672{
1673 return 0;
1674}
1675
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001676static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
1677{
1678 int ret = 0;
1679 char value[32];
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001680 bool is_meta_data_params = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001681 struct compr_gapless_mdata tmp_mdata;
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001682 tmp_mdata.encoder_delay = 0;
1683 tmp_mdata.encoder_padding = 0;
ApurupaPattapudaa708c2013-12-18 15:47:59 -08001684
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001685 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001686 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001687 return -EINVAL;
1688 }
1689
ApurupaPattapudaa708c2013-12-18 15:47:59 -08001690 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_FORMAT, value, sizeof(value));
1691 if (ret >= 0) {
1692 if (atoi(value) == SND_AUDIOSTREAMFORMAT_MP4ADTS) {
1693 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
1694 ALOGV("ADTS format is set in offload mode");
1695 }
1696 out->send_new_metadata = 1;
1697 }
1698
Steve Kondik6bedcdf2014-07-21 11:48:30 -07001699#ifdef FLAC_OFFLOAD_ENABLED
ApurupaPattapu9d6b4362014-02-27 10:24:11 -08001700 if (out->format == AUDIO_FORMAT_FLAC) {
1701 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_FLAC_MIN_BLK_SIZE, value, sizeof(value));
1702 if (ret >= 0) {
1703 out->compr_config.codec->options.flac_dec.min_blk_size = atoi(value);
1704 out->send_new_metadata = 1;
1705 }
1706 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_FLAC_MAX_BLK_SIZE, value, sizeof(value));
1707 if (ret >= 0) {
1708 out->compr_config.codec->options.flac_dec.max_blk_size = atoi(value);
1709 out->send_new_metadata = 1;
1710 }
1711 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_FLAC_MIN_FRAME_SIZE, value, sizeof(value));
1712 if (ret >= 0) {
1713 out->compr_config.codec->options.flac_dec.min_frame_size = atoi(value);
1714 out->send_new_metadata = 1;
1715 }
1716 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_FLAC_MAX_FRAME_SIZE, value, sizeof(value));
1717 if (ret >= 0) {
1718 out->compr_config.codec->options.flac_dec.max_frame_size = atoi(value);
1719 out->send_new_metadata = 1;
1720 }
1721 }
Steve Kondik6bedcdf2014-07-21 11:48:30 -07001722#endif
ApurupaPattapu9d6b4362014-02-27 10:24:11 -08001723
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001724 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_SAMPLE_RATE, value, sizeof(value));
1725 if(ret >= 0)
1726 is_meta_data_params = true;
1727 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_NUM_CHANNEL, value, sizeof(value));
1728 if(ret >= 0 )
1729 is_meta_data_params = true;
1730 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_AVG_BIT_RATE, value, sizeof(value));
1731 if(ret >= 0 )
1732 is_meta_data_params = true;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001733 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
1734 if (ret >= 0) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001735 is_meta_data_params = true;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001736 tmp_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001737 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001738 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
1739 if (ret >= 0) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001740 is_meta_data_params = true;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001741 tmp_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001742 }
1743
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001744 if(!is_meta_data_params) {
1745 ALOGV("%s: Not gapless meta data params", __func__);
1746 return 0;
1747 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001748 out->gapless_mdata = tmp_mdata;
1749 out->send_new_metadata = 1;
1750 ALOGV("%s new encoder delay %u and padding %u", __func__,
1751 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
1752
Steve Kondikba3b35d2014-07-18 01:49:48 -07001753 if(out->format == AUDIO_FORMAT_WMA || out->format == AUDIO_FORMAT_WMA_PRO) {
1754 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_WMA_FORMAT_TAG, value, sizeof(value));
1755 if (ret >= 0) {
1756 out->compr_config.codec->format = atoi(value);
1757 }
1758 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_WMA_BLOCK_ALIGN, value, sizeof(value));
1759 if (ret >= 0) {
1760 out->compr_config.codec->options.wma.super_block_align = atoi(value);
1761 }
1762 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_WMA_BIT_PER_SAMPLE, value, sizeof(value));
1763 if (ret >= 0) {
1764 out->compr_config.codec->options.wma.bits_per_sample = atoi(value);
1765 }
1766 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_WMA_CHANNEL_MASK, value, sizeof(value));
1767 if (ret >= 0) {
1768 out->compr_config.codec->options.wma.channelmask = atoi(value);
1769 }
1770 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_WMA_ENCODE_OPTION, value, sizeof(value));
1771 if (ret >= 0) {
1772 out->compr_config.codec->options.wma.encodeopt = atoi(value);
1773 }
1774 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_WMA_ENCODE_OPTION1, value, sizeof(value));
1775 if (ret >= 0) {
1776 out->compr_config.codec->options.wma.encodeopt1 = atoi(value);
1777 }
1778 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_WMA_ENCODE_OPTION2, value, sizeof(value));
1779 if (ret >= 0) {
1780 out->compr_config.codec->options.wma.encodeopt2 = atoi(value);
1781 }
1782 ALOGV("WMA params: fmt %x, balgn %x, sr %d, chmsk %x, encop %x, op1 %x, op2 %x",
1783 out->compr_config.codec->format,
1784 out->compr_config.codec->options.wma.super_block_align,
1785 out->compr_config.codec->options.wma.bits_per_sample,
1786 out->compr_config.codec->options.wma.channelmask,
1787 out->compr_config.codec->options.wma.encodeopt,
1788 out->compr_config.codec->options.wma.encodeopt1,
1789 out->compr_config.codec->options.wma.encodeopt2);
1790 }
1791
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001792 return 0;
1793}
1794
Divya Narayanan Poojaryab9b1ef2014-09-12 15:52:36 +05301795static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
1796{
1797 return out == adev->primary_output || out == adev->voice_tx_output;
1798}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001799
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001800static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
1801{
1802 struct stream_out *out = (struct stream_out *)stream;
1803 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001804 struct audio_usecase *usecase;
1805 struct listnode *node;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001806 struct str_parms *parms;
1807 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08001808 int ret = 0, val = 0, err;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001809 bool select_new_device = false;
Steve Kondik3abbbc82014-11-29 14:14:43 -08001810 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001811
sangwoobc677242013-08-08 16:53:43 +09001812 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001813 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001814 parms = str_parms_create_str(kvpairs);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08001815 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
1816 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001817 val = atoi(value);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001818 pthread_mutex_lock(&out->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001819 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001820
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001821 /*
Dhanalakshmi Siddani523ae412014-04-18 22:26:56 +05301822 * When HDMI cable is unplugged/usb hs is disconnected the
1823 * music playback is paused and the policy manager sends routing=0
1824 * But the audioflingercontinues to write data until standby time
1825 * (3sec). As the HDMI core is turned off, the write gets blocked.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001826 * Avoid this by routing audio to speaker until standby.
1827 */
Dhanalakshmi Siddani523ae412014-04-18 22:26:56 +05301828 if ((out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL ||
Steve Kondikeadb6c82014-09-03 18:40:06 -07001829 out->devices == AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET ||
1830 out->devices == AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET) &&
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001831 val == AUDIO_DEVICE_NONE) {
1832 val = AUDIO_DEVICE_OUT_SPEAKER;
1833 }
1834
1835 /*
1836 * select_devices() call below switches all the usecases on the same
1837 * backend to the new device. Refer to check_usecases_codec_backend() in
1838 * the select_devices(). But how do we undo this?
1839 *
1840 * For example, music playback is active on headset (deep-buffer usecase)
1841 * and if we go to ringtones and select a ringtone, low-latency usecase
1842 * will be started on headset+speaker. As we can't enable headset+speaker
1843 * and headset devices at the same time, select_devices() switches the music
1844 * playback to headset+speaker while starting low-lateny usecase for ringtone.
1845 * So when the ringtone playback is completed, how do we undo the same?
1846 *
1847 * We are relying on the out_set_parameters() call on deep-buffer output,
1848 * once the ringtone playback is ended.
1849 * NOTE: We should not check if the current devices are same as new devices.
1850 * Because select_devices() must be called to switch back the music
1851 * playback to headset.
1852 */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001853 if (val != 0) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001854 out->devices = val;
1855
1856 if (!out->standby)
1857 select_devices(adev, out->usecase);
1858
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001859 if ((adev->mode == AUDIO_MODE_IN_CALL) &&
Divya Narayanan Poojaryab9b1ef2014-09-12 15:52:36 +05301860 output_drives_call(adev, out)) {
1861 adev->current_call_output = out;
Vidyakumar Athotaf85f6a22014-08-05 18:20:42 -07001862 if (!adev->voice.in_call)
Divya Narayanan Poojaryab9b1ef2014-09-12 15:52:36 +05301863 ret = voice_start_call(adev);
1864 else
1865 voice_update_devices_for_all_voice_usecases(adev);
Vidyakumar Athotaf85f6a22014-08-05 18:20:42 -07001866 }
1867 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001868
Vidyakumar Athotaf85f6a22014-08-05 18:20:42 -07001869 if ((adev->mode == AUDIO_MODE_NORMAL) &&
1870 adev->voice.in_call &&
1871 output_drives_call(adev, out)) {
1872 ret = voice_stop_call(adev);
1873 adev->current_call_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001874 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001875
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001876 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001877 pthread_mutex_unlock(&out->lock);
Eric Laurentda46bfb2014-08-25 22:39:29 -05001878
1879 /*handles device and call state changes*/
1880 audio_extn_extspk_update(adev->extspk);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001881 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001882
1883 if (out == adev->primary_output) {
1884 pthread_mutex_lock(&adev->lock);
1885 audio_extn_set_parameters(adev, parms);
1886 pthread_mutex_unlock(&adev->lock);
1887 }
Subhash Chandra Bose Naripeddy148144e2014-04-01 21:03:10 -07001888 if (is_offload_usecase(out->usecase)) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001889 pthread_mutex_lock(&out->lock);
Steve Kondikba3b35d2014-07-18 01:49:48 -07001890 ret = parse_compress_metadata(out, parms);
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001891 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001892 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001893
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001894 str_parms_destroy(parms);
Steve Kondik3abbbc82014-11-29 14:14:43 -08001895 ALOGV("%s: exit: code(%d)", __func__, status);
1896 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001897}
1898
1899static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
1900{
1901 struct stream_out *out = (struct stream_out *)stream;
1902 struct str_parms *query = str_parms_create_str(keys);
1903 char *str;
1904 char value[256];
1905 struct str_parms *reply = str_parms_create();
1906 size_t i, j;
1907 int ret;
1908 bool first = true;
Haynes Mathew George9f0254a2014-06-30 13:56:18 -07001909
1910 if (!query || !reply) {
1911 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
1912 return NULL;
1913 }
1914
Eric Laurent994a6932013-07-17 11:51:42 -07001915 ALOGV("%s: enter: keys - %s", __func__, keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001916 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
1917 if (ret >= 0) {
1918 value[0] = '\0';
1919 i = 0;
1920 while (out->supported_channel_masks[i] != 0) {
1921 for (j = 0; j < ARRAY_SIZE(out_channels_name_to_enum_table); j++) {
1922 if (out_channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
1923 if (!first) {
1924 strcat(value, "|");
1925 }
1926 strcat(value, out_channels_name_to_enum_table[j].name);
1927 first = false;
1928 break;
1929 }
1930 }
1931 i++;
1932 }
1933 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
1934 str = str_parms_to_str(reply);
1935 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001936 voice_extn_out_get_parameters(out, query, reply);
1937 str = str_parms_to_str(reply);
1938 if (!strncmp(str, "", sizeof(""))) {
Narsinga Rao Chella2e032352014-01-29 12:52:19 -08001939 free(str);
1940 str = strdup(keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001941 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001942 }
1943 str_parms_destroy(query);
1944 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07001945 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001946 return str;
1947}
1948
1949static uint32_t out_get_latency(const struct audio_stream_out *stream)
1950{
1951 struct stream_out *out = (struct stream_out *)stream;
Alexy Joseph3a2fec32014-12-03 02:46:47 -08001952 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001953
Alexy Joseph3a2fec32014-12-03 02:46:47 -08001954 if (is_offload_usecase(out->usecase)) {
Alexy Joseph62babb92015-03-03 19:01:03 -08001955 latency = COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Alexy Joseph3a2fec32014-12-03 02:46:47 -08001956 } else {
1957 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001958 (out->config.rate);
Alexy Joseph3a2fec32014-12-03 02:46:47 -08001959 }
1960
Anish Kumar1a0594f2014-12-09 04:01:39 +05301961 ALOGV("%s: Latency %d", __func__, latency);
Alexy Joseph3a2fec32014-12-03 02:46:47 -08001962 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001963}
1964
1965static int out_set_volume(struct audio_stream_out *stream, float left,
1966 float right)
1967{
Eric Laurenta9024de2013-04-04 09:19:12 -07001968 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001969 int volume[2];
1970
Eric Laurenta9024de2013-04-04 09:19:12 -07001971 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
1972 /* only take left channel into account: the API is for stereo anyway */
1973 out->muted = (left == 0.0f);
1974 return 0;
Subhash Chandra Bose Naripeddy148144e2014-04-01 21:03:10 -07001975 } else if (is_offload_usecase(out->usecase)) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001976 char mixer_ctl_name[128];
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001977 struct audio_device *adev = out->dev;
1978 struct mixer_ctl *ctl;
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001979 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
1980 PCM_PLAYBACK);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001981
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001982 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
1983 "Compress Playback %d Volume", pcm_device_id);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001984 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
1985 if (!ctl) {
1986 ALOGE("%s: Could not get ctl for mixer cmd - %s",
1987 __func__, mixer_ctl_name);
1988 return -EINVAL;
1989 }
1990 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
1991 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
1992 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
1993 return 0;
Eric Laurenta9024de2013-04-04 09:19:12 -07001994 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001995
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001996 return -ENOSYS;
1997}
1998
1999static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
2000 size_t bytes)
2001{
2002 struct stream_out *out = (struct stream_out *)stream;
2003 struct audio_device *adev = out->dev;
Naresh Tannirucef332d2014-06-04 18:17:56 +05302004 int snd_scard_state = get_snd_card_state(adev);
Eric Laurent6e895242013-09-05 16:10:57 -07002005 ssize_t ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002006
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002007 pthread_mutex_lock(&out->lock);
Naresh Tanniru2d19ab42014-05-11 19:56:25 +05302008
Naresh Tannirucef332d2014-06-04 18:17:56 +05302009 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
2010 if (out->pcm) {
Naresh Tanniru2d19ab42014-05-11 19:56:25 +05302011 ALOGD(" %s: sound card is not active/SSR state", __func__);
2012 ret= -ENETRESET;
2013 goto exit;
Alexy Joseph55204352014-10-06 12:15:01 -07002014 } else if (is_offload_usecase(out->usecase)) {
Naresh Tannirucef332d2014-06-04 18:17:56 +05302015 //during SSR for compress usecase we should return error to flinger
2016 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
2017 pthread_mutex_unlock(&out->lock);
2018 return -ENETRESET;
Naresh Tanniru2d19ab42014-05-11 19:56:25 +05302019 }
2020 }
2021
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002022 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002023 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002024 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002025 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
2026 ret = voice_extn_compress_voip_start_output_stream(out);
2027 else
2028 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002029 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002030 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002031 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002032 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002033 goto exit;
2034 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002035 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002036
Subhash Chandra Bose Naripeddy148144e2014-04-01 21:03:10 -07002037 if (is_offload_usecase(out->usecase)) {
Alexy Joseph62babb92015-03-03 19:01:03 -08002038 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002039 if (out->send_new_metadata) {
Sidipotu Ashok5bfacf72014-02-10 16:16:38 +05302040 ALOGD("copl(%x):send new gapless metadata", (unsigned int)out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002041 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
2042 out->send_new_metadata = 0;
2043 }
2044
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002045 ret = compress_write(out->compr, buffer, bytes);
Dhanalakshmi Siddani834b22f2014-08-20 12:28:34 +05302046 if (ret < 0)
2047 ret = -errno;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002048 ALOGVV("%s: writing buffer (%d bytes) to compress device returned %d", __func__, bytes, ret);
Eric Laurent6e895242013-09-05 16:10:57 -07002049 if (ret >= 0 && ret < (ssize_t)bytes) {
Sidipotu Ashok5bfacf72014-02-10 16:16:38 +05302050 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002051 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tannirucef332d2014-06-04 18:17:56 +05302052 } else if (-ENETRESET == ret) {
2053 ALOGE("copl %s: received sound card offline state on compress write", __func__);
2054 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2055 pthread_mutex_unlock(&out->lock);
2056 out_standby(&out->stream.common);
2057 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002058 }
Naresh Tannirucef332d2014-06-04 18:17:56 +05302059 if (!out->playback_started && ret >= 0) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002060 compress_start(out->compr);
2061 out->playback_started = 1;
2062 out->offload_state = OFFLOAD_STATE_PLAYING;
2063 }
2064 pthread_mutex_unlock(&out->lock);
2065 return ret;
2066 } else {
2067 if (out->pcm) {
2068 if (out->muted)
2069 memset((void *)buffer, 0, bytes);
2070 ALOGVV("%s: writing buffer (%d bytes) to pcm device", __func__, bytes);
Divya Narayanan Poojaryab9b1ef2014-09-12 15:52:36 +05302071 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY)
2072 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
2073 else
2074 ret = pcm_write(out->pcm, (void *)buffer, bytes);
Dhanalakshmi Siddani834b22f2014-08-20 12:28:34 +05302075 if (ret < 0)
2076 ret = -errno;
2077 else if (ret == 0)
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002078 out->written += bytes / (out->config.channels * sizeof(short));
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002079 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002080 }
2081
2082exit:
Dhanalakshmi Siddani4fe3e512014-05-26 18:03:42 +05302083 /* ToDo: There may be a corner case when SSR happens back to back during
2084 start/stop. Need to post different error to handle that. */
Naresh Tanniru2d19ab42014-05-11 19:56:25 +05302085 if (-ENETRESET == ret) {
Naresh Tannirucef332d2014-06-04 18:17:56 +05302086 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru2d19ab42014-05-11 19:56:25 +05302087 }
2088
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002089 pthread_mutex_unlock(&out->lock);
2090
2091 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002092 if (out->pcm)
2093 ALOGE("%s: error %d - %s", __func__, ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Gutta369dd682014-06-25 20:38:03 +05302094 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta593b7c12014-08-11 18:20:49 +05302095 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Gutta369dd682014-06-25 20:38:03 +05302096 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Venkata Narendra Kumar Gutta593b7c12014-08-11 18:20:49 +05302097 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Gutta369dd682014-06-25 20:38:03 +05302098 out->standby = true;
2099 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002100 out_standby(&out->stream.common);
Steve Kondik3abbbc82014-11-29 14:14:43 -08002101 usleep(bytes * 1000000 / audio_stream_out_frame_size(stream) /
2102 out_get_sample_rate(&out->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002103 }
2104 return bytes;
2105}
2106
2107static int out_get_render_position(const struct audio_stream_out *stream,
2108 uint32_t *dsp_frames)
2109{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002110 struct stream_out *out = (struct stream_out *)stream;
Subhash Chandra Bose Naripeddy148144e2014-04-01 21:03:10 -07002111 if (is_offload_usecase(out->usecase) && (dsp_frames != NULL)) {
2112 ssize_t ret = 0;
Haynes Mathew George9f0254a2014-06-30 13:56:18 -07002113 *dsp_frames = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002114 pthread_mutex_lock(&out->lock);
2115 if (out->compr != NULL) {
Naresh Tannirucef332d2014-06-04 18:17:56 +05302116 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002117 &out->sample_rate);
Dhanalakshmi Siddani834b22f2014-08-20 12:28:34 +05302118 if (ret < 0)
2119 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002120 ALOGVV("%s rendered frames %d sample_rate %d",
2121 __func__, *dsp_frames, out->sample_rate);
2122 }
2123 pthread_mutex_unlock(&out->lock);
Naresh Tannirucef332d2014-06-04 18:17:56 +05302124 if (-ENETRESET == ret) {
2125 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
2126 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2127 return -EINVAL;
2128 } else if(ret < 0) {
Steve Kondik81506242014-07-21 16:12:57 -07002129 if (out->compr == NULL) {
2130 return 0;
2131 }
2132 ALOGE(" ERROR: Unable to get time stamp from compress driver ret=%d", ret);
Naresh Tannirucef332d2014-06-04 18:17:56 +05302133 return -EINVAL;
2134 } else {
2135 return 0;
2136 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002137 } else
2138 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002139}
2140
Divya Narayanan Poojarybd9f33f2014-09-17 17:35:59 +05302141static int out_add_audio_effect(const struct audio_stream *stream __unused,
2142 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002143{
2144 return 0;
2145}
2146
Divya Narayanan Poojarybd9f33f2014-09-17 17:35:59 +05302147static int out_remove_audio_effect(const struct audio_stream *stream __unused,
2148 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002149{
2150 return 0;
2151}
2152
Divya Narayanan Poojarybd9f33f2014-09-17 17:35:59 +05302153static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
2154 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002155{
2156 return -EINVAL;
2157}
2158
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002159static int out_get_presentation_position(const struct audio_stream_out *stream,
2160 uint64_t *frames, struct timespec *timestamp)
2161{
2162 struct stream_out *out = (struct stream_out *)stream;
2163 int ret = -1;
Eric Laurent949a0892013-09-20 09:20:13 -07002164 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002165
2166 pthread_mutex_lock(&out->lock);
2167
Subhash Chandra Bose Naripeddy148144e2014-04-01 21:03:10 -07002168 if (is_offload_usecase(out->usecase)) {
Eric Laurent949a0892013-09-20 09:20:13 -07002169 if (out->compr != NULL) {
2170 compress_get_tstamp(out->compr, &dsp_frames,
2171 &out->sample_rate);
2172 ALOGVV("%s rendered frames %ld sample_rate %d",
2173 __func__, dsp_frames, out->sample_rate);
2174 *frames = dsp_frames;
2175 ret = 0;
2176 /* this is the best we can do */
2177 clock_gettime(CLOCK_MONOTONIC, timestamp);
2178 }
2179 } else {
2180 if (out->pcm) {
2181 size_t avail;
2182 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
2183 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07002184 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07002185 // This adjustment accounts for buffering after app processor.
2186 // It is based on estimated DSP latency per use case, rather than exact.
2187 signed_frames -=
2188 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
2189
Eric Laurent949a0892013-09-20 09:20:13 -07002190 // It would be unusual for this value to be negative, but check just in case ...
2191 if (signed_frames >= 0) {
2192 *frames = signed_frames;
2193 ret = 0;
2194 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002195 }
2196 }
2197 }
2198
2199 pthread_mutex_unlock(&out->lock);
2200
2201 return ret;
2202}
2203
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002204static int out_set_callback(struct audio_stream_out *stream,
2205 stream_callback_t callback, void *cookie)
2206{
2207 struct stream_out *out = (struct stream_out *)stream;
2208
2209 ALOGV("%s", __func__);
2210 pthread_mutex_lock(&out->lock);
2211 out->offload_callback = callback;
2212 out->offload_cookie = cookie;
2213 pthread_mutex_unlock(&out->lock);
2214 return 0;
2215}
2216
2217static int out_pause(struct audio_stream_out* stream)
2218{
2219 struct stream_out *out = (struct stream_out *)stream;
2220 int status = -ENOSYS;
2221 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy148144e2014-04-01 21:03:10 -07002222 if (is_offload_usecase(out->usecase)) {
Sidipotu Ashok5bfacf72014-02-10 16:16:38 +05302223 ALOGD("copl(%x):pause compress driver", (unsigned int)out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002224 pthread_mutex_lock(&out->lock);
2225 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Naresh Tannirucef332d2014-06-04 18:17:56 +05302226 struct audio_device *adev = out->dev;
2227 int snd_scard_state = get_snd_card_state(adev);
2228
2229 if (SND_CARD_STATE_ONLINE == snd_scard_state)
2230 status = compress_pause(out->compr);
2231
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002232 out->offload_state = OFFLOAD_STATE_PAUSED;
2233 }
2234 pthread_mutex_unlock(&out->lock);
2235 }
2236 return status;
2237}
2238
2239static int out_resume(struct audio_stream_out* stream)
2240{
2241 struct stream_out *out = (struct stream_out *)stream;
2242 int status = -ENOSYS;
2243 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy148144e2014-04-01 21:03:10 -07002244 if (is_offload_usecase(out->usecase)) {
Sidipotu Ashok5bfacf72014-02-10 16:16:38 +05302245 ALOGD("copl(%x):resume compress driver", (unsigned int)out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002246 status = 0;
2247 pthread_mutex_lock(&out->lock);
2248 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Naresh Tannirucef332d2014-06-04 18:17:56 +05302249 struct audio_device *adev = out->dev;
2250 int snd_scard_state = get_snd_card_state(adev);
2251
2252 if (SND_CARD_STATE_ONLINE == snd_scard_state)
2253 status = compress_resume(out->compr);
2254
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002255 out->offload_state = OFFLOAD_STATE_PLAYING;
2256 }
2257 pthread_mutex_unlock(&out->lock);
2258 }
2259 return status;
2260}
2261
2262static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
2263{
2264 struct stream_out *out = (struct stream_out *)stream;
2265 int status = -ENOSYS;
2266 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy148144e2014-04-01 21:03:10 -07002267 if (is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002268 pthread_mutex_lock(&out->lock);
2269 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
2270 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
2271 else
2272 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
2273 pthread_mutex_unlock(&out->lock);
2274 }
2275 return status;
2276}
2277
2278static int out_flush(struct audio_stream_out* stream)
2279{
2280 struct stream_out *out = (struct stream_out *)stream;
2281 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy148144e2014-04-01 21:03:10 -07002282 if (is_offload_usecase(out->usecase)) {
Sidipotu Ashok5bfacf72014-02-10 16:16:38 +05302283 ALOGD("copl(%x):calling compress flush", (unsigned int)out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002284 pthread_mutex_lock(&out->lock);
2285 stop_compressed_output_l(out);
2286 pthread_mutex_unlock(&out->lock);
Sidipotu Ashok5bfacf72014-02-10 16:16:38 +05302287 ALOGD("copl(%x):out of compress flush", (unsigned int)out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002288 return 0;
2289 }
2290 return -ENOSYS;
2291}
2292
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002293/** audio_stream_in implementation **/
2294static uint32_t in_get_sample_rate(const struct audio_stream *stream)
2295{
2296 struct stream_in *in = (struct stream_in *)stream;
2297
2298 return in->config.rate;
2299}
2300
Divya Narayanan Poojarybd9f33f2014-09-17 17:35:59 +05302301static int in_set_sample_rate(struct audio_stream *stream __unused,
2302 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002303{
2304 return -ENOSYS;
2305}
2306
2307static size_t in_get_buffer_size(const struct audio_stream *stream)
2308{
2309 struct stream_in *in = (struct stream_in *)stream;
2310
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002311 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
2312 return voice_extn_compress_voip_in_get_buffer_size(in);
Mingming Yine62d7842013-10-25 16:26:03 -07002313 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
2314 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002315
Divya Narayanan Poojary69236ba2014-09-18 11:57:57 +05302316 return in->config.period_size *
Steve Kondik3abbbc82014-11-29 14:14:43 -08002317 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002318}
2319
2320static uint32_t in_get_channels(const struct audio_stream *stream)
2321{
2322 struct stream_in *in = (struct stream_in *)stream;
2323
2324 return in->channel_mask;
2325}
2326
2327static audio_format_t in_get_format(const struct audio_stream *stream)
2328{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002329 struct stream_in *in = (struct stream_in *)stream;
2330
2331 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002332}
2333
Divya Narayanan Poojarybd9f33f2014-09-17 17:35:59 +05302334static int in_set_format(struct audio_stream *stream __unused,
2335 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002336{
2337 return -ENOSYS;
2338}
2339
2340static int in_standby(struct audio_stream *stream)
2341{
2342 struct stream_in *in = (struct stream_in *)stream;
2343 struct audio_device *adev = in->dev;
2344 int status = 0;
Sidipotu Ashoke4514fa2014-05-02 16:21:50 +05302345 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
2346 stream, in->usecase, use_case_table[in->usecase]);
2347
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002348
2349 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
2350 /* Ignore standby in case of voip call because the voip input
2351 * stream is closed in adev_close_input_stream()
2352 */
2353 ALOGV("%s: Ignore Standby in VOIP call", __func__);
2354 return status;
2355 }
2356
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002357 pthread_mutex_lock(&in->lock);
2358 if (!in->standby) {
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002359 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002360 in->standby = true;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002361 if (in->pcm) {
2362 pcm_close(in->pcm);
2363 in->pcm = NULL;
2364 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002365 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002366 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002367 }
2368 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07002369 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002370 return status;
2371}
2372
Divya Narayanan Poojarybd9f33f2014-09-17 17:35:59 +05302373static int in_dump(const struct audio_stream *stream __unused,
2374 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002375{
2376 return 0;
2377}
2378
2379static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
2380{
2381 struct stream_in *in = (struct stream_in *)stream;
2382 struct audio_device *adev = in->dev;
2383 struct str_parms *parms;
2384 char *str;
2385 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002386 int ret = 0, val = 0, err;
Steve Kondik3abbbc82014-11-29 14:14:43 -08002387 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002388
Sidipotu Ashoke4514fa2014-05-02 16:21:50 +05302389 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002390 parms = str_parms_create_str(kvpairs);
2391
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002392 pthread_mutex_lock(&in->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002393 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002394
2395 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
2396 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002397 val = atoi(value);
2398 /* no audio source uses val == 0 */
2399 if ((in->source != val) && (val != 0)) {
2400 in->source = val;
Narsinga Rao Chellab0668ee2014-01-24 15:33:23 -08002401 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
2402 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
2403 (voice_extn_compress_voip_is_format_supported(in->format)) &&
2404 (in->config.rate == 8000 || in->config.rate == 16000) &&
Steve Kondikb6ab1fa2015-02-06 16:55:26 -08002405 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
Narsinga Rao Chella287b8162014-02-04 16:23:52 -08002406 err = voice_extn_compress_voip_open_input_stream(in);
2407 if (err != 0) {
Narsinga Rao Chellab0668ee2014-01-24 15:33:23 -08002408 ALOGE("%s: Compress voip input cannot be opened, error:%d",
Narsinga Rao Chella287b8162014-02-04 16:23:52 -08002409 __func__, err);
Narsinga Rao Chellab0668ee2014-01-24 15:33:23 -08002410 }
2411 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002412 }
2413 }
2414
Steve Kondik3abbbc82014-11-29 14:14:43 -08002415 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2416
2417 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002418 val = atoi(value);
Divya Narayanan Poojaryab9b1ef2014-09-12 15:52:36 +05302419 if (((int)in->device != val) && (val != 0)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002420 in->device = val;
2421 /* If recording is in progress, change the tx device to new device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002422 if (!in->standby)
Steve Kondik3abbbc82014-11-29 14:14:43 -08002423 status = select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002424 }
2425 }
2426
Narsinga Rao Chellab0668ee2014-01-24 15:33:23 -08002427done:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002428 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002429 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002430
2431 str_parms_destroy(parms);
Steve Kondik3abbbc82014-11-29 14:14:43 -08002432 ALOGV("%s: exit: status(%d)", __func__, status);
2433 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002434}
2435
2436static char* in_get_parameters(const struct audio_stream *stream,
2437 const char *keys)
2438{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002439 struct stream_in *in = (struct stream_in *)stream;
2440 struct str_parms *query = str_parms_create_str(keys);
2441 char *str;
2442 char value[256];
2443 struct str_parms *reply = str_parms_create();
Haynes Mathew George9f0254a2014-06-30 13:56:18 -07002444
2445 if (!query || !reply) {
2446 ALOGE("in_get_parameters: failed to create query or reply");
2447 return NULL;
2448 }
2449
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002450 ALOGV("%s: enter: keys - %s", __func__, keys);
2451
2452 voice_extn_in_get_parameters(in, query, reply);
2453
2454 str = str_parms_to_str(reply);
2455 str_parms_destroy(query);
2456 str_parms_destroy(reply);
2457
2458 ALOGV("%s: exit: returns - %s", __func__, str);
2459 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002460}
2461
Divya Narayanan Poojarybd9f33f2014-09-17 17:35:59 +05302462static int in_set_gain(struct audio_stream_in *stream __unused,
2463 float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002464{
2465 return 0;
2466}
2467
2468static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
2469 size_t bytes)
2470{
2471 struct stream_in *in = (struct stream_in *)stream;
2472 struct audio_device *adev = in->dev;
2473 int i, ret = -1;
Naresh Tannirucef332d2014-06-04 18:17:56 +05302474 int snd_scard_state = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002475
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002476 pthread_mutex_lock(&in->lock);
Naresh Tanniru2d19ab42014-05-11 19:56:25 +05302477
2478 if (in->pcm) {
Naresh Tannirucef332d2014-06-04 18:17:56 +05302479 if(SND_CARD_STATE_OFFLINE == snd_scard_state) {
Naresh Tanniru2d19ab42014-05-11 19:56:25 +05302480 ALOGD(" %s: sound card is not active/SSR state", __func__);
2481 ret= -ENETRESET;
2482 goto exit;
Naresh Tanniru2d19ab42014-05-11 19:56:25 +05302483 }
2484 }
2485
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002486 if (in->standby) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002487 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002488 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
2489 ret = voice_extn_compress_voip_start_input_stream(in);
2490 else
2491 ret = start_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002492 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002493 if (ret != 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002494 goto exit;
2495 }
2496 in->standby = 0;
2497 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002498
2499 if (in->pcm) {
Divya Narayanan Poojary69236ba2014-09-18 11:57:57 +05302500 if (audio_extn_ssr_get_enabled() &&
2501 audio_channel_count_from_in_mask(in->channel_mask) == 6)
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07002502 ret = audio_extn_ssr_read(stream, buffer, bytes);
Mingming Yine62d7842013-10-25 16:26:03 -07002503 else if (audio_extn_compr_cap_usecase_supported(in->usecase))
2504 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Divya Narayanan Poojaryab9b1ef2014-09-12 15:52:36 +05302505 else if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY)
2506 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07002507 else
2508 ret = pcm_read(in->pcm, buffer, bytes);
Dhanalakshmi Siddani834b22f2014-08-20 12:28:34 +05302509 if (ret < 0)
2510 ret = -errno;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002511 }
2512
2513 /*
2514 * Instead of writing zeroes here, we could trust the hardware
2515 * to always provide zeroes when muted.
2516 */
Pavan Chikkala6c183fd2014-12-04 10:48:28 +05302517 if (ret == 0 && voice_get_mic_mute(adev) && !voice_is_in_call_rec_stream(in) &&
2518 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002519 memset(buffer, 0, bytes);
2520
2521exit:
Dhanalakshmi Siddani4fe3e512014-05-26 18:03:42 +05302522 /* ToDo: There may be a corner case when SSR happens back to back during
2523 start/stop. Need to post different error to handle that. */
Naresh Tanniru2d19ab42014-05-11 19:56:25 +05302524 if (-ENETRESET == ret) {
Naresh Tannirucef332d2014-06-04 18:17:56 +05302525 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru2d19ab42014-05-11 19:56:25 +05302526 memset(buffer, 0, bytes);
Naresh Tanniru2d19ab42014-05-11 19:56:25 +05302527 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002528 pthread_mutex_unlock(&in->lock);
2529
2530 if (ret != 0) {
Venkata Narendra Kumar Gutta369dd682014-06-25 20:38:03 +05302531 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta593b7c12014-08-11 18:20:49 +05302532 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Gutta369dd682014-06-25 20:38:03 +05302533 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta593b7c12014-08-11 18:20:49 +05302534 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Gutta369dd682014-06-25 20:38:03 +05302535 in->standby = true;
2536 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002537 in_standby(&in->stream.common);
2538 ALOGV("%s: read failed - sleeping for buffer duration", __func__);
Steve Kondik3abbbc82014-11-29 14:14:43 -08002539 usleep(bytes * 1000000 / audio_stream_in_frame_size(stream) /
2540 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002541 }
2542 return bytes;
2543}
2544
Divya Narayanan Poojarybd9f33f2014-09-17 17:35:59 +05302545static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002546{
2547 return 0;
2548}
2549
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002550static int add_remove_audio_effect(const struct audio_stream *stream,
2551 effect_handle_t effect,
2552 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002553{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002554 struct stream_in *in = (struct stream_in *)stream;
2555 int status = 0;
2556 effect_descriptor_t desc;
2557
2558 status = (*effect)->get_descriptor(effect, &desc);
2559 if (status != 0)
2560 return status;
2561
2562 pthread_mutex_lock(&in->lock);
2563 pthread_mutex_lock(&in->dev->lock);
2564 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
2565 in->enable_aec != enable &&
2566 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
2567 in->enable_aec = enable;
2568 if (!in->standby)
2569 select_devices(in->dev, in->usecase);
2570 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08002571 if (in->enable_ns != enable &&
2572 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
2573 in->enable_ns = enable;
2574 if (!in->standby)
2575 select_devices(in->dev, in->usecase);
2576 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002577 pthread_mutex_unlock(&in->dev->lock);
2578 pthread_mutex_unlock(&in->lock);
2579
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002580 return 0;
2581}
2582
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002583static int in_add_audio_effect(const struct audio_stream *stream,
2584 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002585{
Eric Laurent994a6932013-07-17 11:51:42 -07002586 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002587 return add_remove_audio_effect(stream, effect, true);
2588}
2589
2590static int in_remove_audio_effect(const struct audio_stream *stream,
2591 effect_handle_t effect)
2592{
Eric Laurent994a6932013-07-17 11:51:42 -07002593 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002594 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002595}
2596
2597static int adev_open_output_stream(struct audio_hw_device *dev,
2598 audio_io_handle_t handle,
2599 audio_devices_t devices,
2600 audio_output_flags_t flags,
2601 struct audio_config *config,
Divya Narayanan Poojarybd9f33f2014-09-17 17:35:59 +05302602 struct audio_stream_out **stream_out,
2603 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002604{
2605 struct audio_device *adev = (struct audio_device *)dev;
2606 struct stream_out *out;
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08002607 int i, ret = 0;
Steve Kondik5a447012014-12-02 16:04:20 -08002608 int32_t sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002609
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002610 *stream_out = NULL;
Naresh Tannirucef332d2014-06-04 18:17:56 +05302611
2612 if ((flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
2613 (SND_CARD_STATE_OFFLINE == get_snd_card_state(adev))) {
2614 ALOGE(" sound card is not active rejecting compress output open request");
2615 return -EINVAL;
2616 }
2617
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002618 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
2619
Sidipotu Ashoke4514fa2014-05-02 16:21:50 +05302620 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
2621 stream_handle(%p)",__func__, config->sample_rate, config->channel_mask,
2622 devices, flags, &out->stream);
2623
2624
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08002625 if (!out) {
2626 return -ENOMEM;
2627 }
2628
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002629 if (devices == AUDIO_DEVICE_NONE)
2630 devices = AUDIO_DEVICE_OUT_SPEAKER;
2631
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002632 out->flags = flags;
2633 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07002634 out->dev = adev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002635 out->format = config->format;
2636 out->sample_rate = config->sample_rate;
2637 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
2638 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07002639 out->handle = handle;
ApurupaPattapu9d6b4362014-02-27 10:24:11 -08002640 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Joseph3a2fec32014-12-03 02:46:47 -08002641 out->non_blocking = 0;
2642 out->use_small_bufs = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002643
2644 /* Init use case and pcm_config */
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08002645 if ((out->flags == AUDIO_OUTPUT_FLAG_DIRECT) &&
Mingming Yinee733602014-04-03 17:47:22 -07002646 (
2647#ifdef AFE_PROXY_ENABLED
2648 out->devices & AUDIO_DEVICE_OUT_PROXY ||
2649#endif
2650 out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08002651
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002652 pthread_mutex_lock(&adev->lock);
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08002653 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
2654 ret = read_hdmi_channel_masks(out);
2655
Mingming Yinee733602014-04-03 17:47:22 -07002656#ifdef AFE_PROXY_ENABLED
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08002657 if (out->devices & AUDIO_DEVICE_OUT_PROXY)
2658 ret = audio_extn_read_afe_proxy_channel_masks(out);
Mingming Yinee733602014-04-03 17:47:22 -07002659#endif
2660
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002661 pthread_mutex_unlock(&adev->lock);
Eric Laurent07eeafd2013-10-06 12:52:49 -07002662 if (ret != 0)
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002663 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002664
2665 if (config->sample_rate == 0)
2666 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
2667 if (config->channel_mask == 0)
2668 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
2669
2670 out->channel_mask = config->channel_mask;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002671 out->sample_rate = config->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002672 out->usecase = USECASE_AUDIO_PLAYBACK_MULTI_CH;
2673 out->config = pcm_config_hdmi_multi;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002674 out->config.rate = config->sample_rate;
Divya Narayanan Poojary69236ba2014-09-18 11:57:57 +05302675 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002676 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels * 2);
Mingming Yinee733602014-04-03 17:47:22 -07002677#ifdef COMPRESS_VOIP_ENABLED
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002678 } else if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
2679 (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX)) &&
Narsinga Rao Chella1eceff82013-12-02 19:25:28 -08002680 (voice_extn_compress_voip_is_config_supported(config))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002681 ret = voice_extn_compress_voip_open_output_stream(out);
2682 if (ret != 0) {
2683 ALOGE("%s: Compress voip output cannot be opened, error:%d",
2684 __func__, ret);
2685 goto error_open;
2686 }
Mingming Yinee733602014-04-03 17:47:22 -07002687#endif
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002688 } else if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Sidipotu Ashok5bfacf72014-02-10 16:16:38 +05302689 ALOGD("%s: copl(%x): sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)",
2690 __func__, (unsigned int)out, config->sample_rate, config->channel_mask, devices, flags);
2691
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002692 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
2693 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
2694 ALOGE("%s: Unsupported Offload information", __func__);
2695 ret = -EINVAL;
2696 goto error_open;
2697 }
Mingming Yin90310102013-11-13 16:57:00 -08002698 if (!is_supported_format(config->offload_info.format) &&
Subhash Chandra Bose Naripeddye0a07122013-12-14 00:34:53 -08002699 !audio_extn_is_dolby_format(config->offload_info.format)) {
Steve Kondik3fdf4fc2014-12-10 21:15:43 -08002700 ALOGE("%s: Unsupported offload audio format %x", __func__, config->offload_info.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002701 ret = -EINVAL;
2702 goto error_open;
2703 }
2704
2705 out->compr_config.codec = (struct snd_codec *)
2706 calloc(1, sizeof(struct snd_codec));
2707
Haynes Mathew George9f0254a2014-06-30 13:56:18 -07002708 if (!out->compr_config.codec) {
2709 ret = -ENOMEM;
2710 goto error_open;
2711 }
2712
Subhash Chandra Bose Naripeddy148144e2014-04-01 21:03:10 -07002713 out->usecase = get_offload_usecase(adev);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002714 if (config->offload_info.channel_mask)
2715 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapu0c566872014-01-10 14:46:02 -08002716 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002717 out->channel_mask = config->channel_mask;
ApurupaPattapu0c566872014-01-10 14:46:02 -08002718 config->offload_info.channel_mask = config->channel_mask;
2719 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002720 out->format = config->offload_info.format;
2721 out->sample_rate = config->offload_info.sample_rate;
2722
2723 out->stream.set_callback = out_set_callback;
2724 out->stream.pause = out_pause;
2725 out->stream.resume = out_resume;
2726 out->stream.drain = out_drain;
2727 out->stream.flush = out_flush;
ApurupaPattapu9d6b4362014-02-27 10:24:11 -08002728 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002729
Subhash Chandra Bose Naripeddye0a07122013-12-14 00:34:53 -08002730 if (audio_extn_is_dolby_format(config->offload_info.format))
Mingming Yin90310102013-11-13 16:57:00 -08002731 out->compr_config.codec->id =
Subhash Chandra Bose Naripeddye0a07122013-12-14 00:34:53 -08002732 audio_extn_dolby_get_snd_codec_id(adev, out,
2733 config->offload_info.format);
Mingming Yin90310102013-11-13 16:57:00 -08002734 else
2735 out->compr_config.codec->id =
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002736 get_snd_codec_id(config->offload_info.format);
Steve Kondik3abbbc82014-11-29 14:14:43 -08002737
ApurupaPattapu0c566872014-01-10 14:46:02 -08002738 if (audio_is_offload_pcm(config->offload_info.format)) {
2739 out->compr_config.fragment_size =
2740 platform_get_pcm_offload_buffer_size(&config->offload_info);
Steve Kondik3abbbc82014-11-29 14:14:43 -08002741 } else {
ApurupaPattapu0c566872014-01-10 14:46:02 -08002742 out->compr_config.fragment_size =
2743 platform_get_compress_offload_buffer_size(&config->offload_info);
2744 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002745 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
2746 out->compr_config.codec->sample_rate =
2747 compress_get_alsa_rate(config->offload_info.sample_rate);
2748 out->compr_config.codec->bit_rate =
2749 config->offload_info.bit_rate;
2750 out->compr_config.codec->ch_in =
Divya Narayanan Poojary69236ba2014-09-18 11:57:57 +05302751 audio_channel_count_from_out_mask(config->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002752 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
ApurupaPattapu9d6b4362014-02-27 10:24:11 -08002753 out->bit_width = config->offload_info.bit_width;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002754
Steve Kondik3fdf4fc2014-12-10 21:15:43 -08002755 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
Steve Kondik37454012014-11-23 19:54:21 -08002756 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
ApurupaPattapu0c566872014-01-10 14:46:02 -08002757 if (config->offload_info.format == AUDIO_FORMAT_PCM_16_BIT_OFFLOAD)
2758 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S16_LE;
ApurupaPattapu0c566872014-01-10 14:46:02 -08002759
Steve Kondik3abbbc82014-11-29 14:14:43 -08002760 if (config->offload_info.format == AUDIO_FORMAT_PCM_24_BIT_OFFLOAD)
ApurupaPattapu9d6b4362014-02-27 10:24:11 -08002761 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S24_LE;
ApurupaPattapu9d6b4362014-02-27 10:24:11 -08002762
Steve Kondik3abbbc82014-11-29 14:14:43 -08002763 if (out->bit_width == 24)
2764 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S24_LE;
ApurupaPattapu9d6b4362014-02-27 10:24:11 -08002765
Steve Kondik6bedcdf2014-07-21 11:48:30 -07002766#ifdef FLAC_OFFLOAD_ENABLED
Steve Kondik37454012014-11-23 19:54:21 -08002767 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
2768 out->compr_config.codec->options.flac_dec.sample_size = config->offload_info.bit_width;
Steve Kondik6bedcdf2014-07-21 11:48:30 -07002769#endif
ApurupaPattapu9d6b4362014-02-27 10:24:11 -08002770
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002771 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
2772 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002773
Alexy Joseph3a2fec32014-12-03 02:46:47 -08002774 if (config->offload_info.use_small_bufs) {
2775 //this flag is set from framework only if its for PCM formats
2776 //no need to check for PCM format again
2777 out->non_blocking = 0;
2778 out->use_small_bufs = true;
2779 ALOGI("Keep write blocking for small buff: non_blockling %d",
2780 out->non_blocking);
2781 }
2782
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002783 out->send_new_metadata = 1;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08002784 out->offload_state = OFFLOAD_STATE_IDLE;
2785 out->playback_started = 0;
2786
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002787 create_offload_callback_thread(out);
2788 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
2789 __func__, config->offload_info.version,
2790 config->offload_info.bit_rate);
Krishnankutty Kolathappillyb165a8a2014-01-07 11:25:51 -08002791 //Decide if we need to use gapless mode by default
Krishnankutty Kolathappilly9d1632f2014-01-09 12:45:31 -08002792 check_and_set_gapless_mode(adev);
Krishnankutty Kolathappillyb165a8a2014-01-07 11:25:51 -08002793
Mingming Yinee733602014-04-03 17:47:22 -07002794#ifdef INCALL_MUSIC_ENABLED
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07002795 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
2796 ret = voice_check_and_set_incall_music_usecase(adev, out);
2797 if (ret != 0) {
2798 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
2799 __func__, ret);
2800 goto error_open;
2801 }
Mingming Yinee733602014-04-03 17:47:22 -07002802#endif
Divya Narayanan Poojaryab9b1ef2014-09-12 15:52:36 +05302803 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
2804 if (config->sample_rate == 0)
2805 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
2806 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
2807 config->sample_rate != 8000) {
2808 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
2809 ret = -EINVAL;
2810 goto error_open;
2811 }
2812 out->sample_rate = config->sample_rate;
2813 out->config.rate = config->sample_rate;
2814 if (config->format == AUDIO_FORMAT_DEFAULT)
2815 config->format = AUDIO_FORMAT_PCM_16_BIT;
2816 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
2817 config->format = AUDIO_FORMAT_PCM_16_BIT;
2818 ret = -EINVAL;
2819 goto error_open;
2820 }
2821 out->format = config->format;
2822 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
2823 out->config = pcm_config_afe_proxy_playback;
2824 adev->voice_tx_output = out;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07002825 } else {
Steve Kondik3abbbc82014-11-29 14:14:43 -08002826#ifndef LOW_LATENCY_PRIMARY
2827 if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
2828 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
2829 out->config = pcm_config_low_latency;
Steve Kondikb045f472014-11-12 23:24:07 -08002830#endif
Steve Kondik3abbbc82014-11-29 14:14:43 -08002831#ifdef LOW_LATENCY_PRIMARY
2832 if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
2833 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
2834 out->config = pcm_config_deep_buffer;
2835#endif
2836 } else {
2837 /* primary path is the default path selected if no other outputs are available/suitable */
2838 out->usecase = USECASE_AUDIO_PLAYBACK_PRIMARY;
2839#ifdef LOW_LATENCY_PRIMARY
2840 out->config = pcm_config_low_latency;
2841#else
2842 out->config = pcm_config_deep_buffer;
2843#endif
2844 }
2845 if (config->format != audio_format_from_pcm_format(out->config.format)) {
2846 if (k_enable_extended_precision
2847 && pcm_params_format_test(adev->use_case_table[out->usecase],
2848 pcm_format_from_audio_format(config->format))) {
2849 out->config.format = pcm_format_from_audio_format(config->format);
2850 /* out->format already set to config->format */
2851 } else {
2852 /* deny the externally proposed config format
2853 * and use the one specified in audio_hw layer configuration.
2854 * Note: out->format is returned by out->stream.common.get_format()
2855 * and is used to set config->format in the code several lines below.
2856 */
Steve Kondik5a447012014-12-02 16:04:20 -08002857 ALOGW("Audio format %x is not available on this output", out->format);
Steve Kondik3abbbc82014-11-29 14:14:43 -08002858 out->format = audio_format_from_pcm_format(out->config.format);
2859 }
2860 }
2861
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07002862 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002863 }
2864
Steve Kondik5a447012014-12-02 16:04:20 -08002865 ALOGV("%s flags %x, format %x, sample_rate %d, out->bit_width %d",
2866 __func__, flags, out->format, out->sample_rate, out->bit_width);
2867
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08002868 if ((out->usecase == USECASE_AUDIO_PLAYBACK_PRIMARY) ||
Steve Kondik3abbbc82014-11-29 14:14:43 -08002869 flags & AUDIO_OUTPUT_FLAG_PRIMARY) {
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08002870 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002871 if(adev->primary_output == NULL)
2872 adev->primary_output = out;
2873 else {
2874 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002875 ret = -EEXIST;
2876 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002877 }
2878 }
2879
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002880 /* Check if this usecase is already existing */
2881 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella0d06c8e2014-04-17 20:00:41 -07002882 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
2883 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002884 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002885 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002886 ret = -EEXIST;
2887 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002888 }
2889 pthread_mutex_unlock(&adev->lock);
2890
2891 out->stream.common.get_sample_rate = out_get_sample_rate;
2892 out->stream.common.set_sample_rate = out_set_sample_rate;
2893 out->stream.common.get_buffer_size = out_get_buffer_size;
2894 out->stream.common.get_channels = out_get_channels;
2895 out->stream.common.get_format = out_get_format;
2896 out->stream.common.set_format = out_set_format;
2897 out->stream.common.standby = out_standby;
2898 out->stream.common.dump = out_dump;
2899 out->stream.common.set_parameters = out_set_parameters;
2900 out->stream.common.get_parameters = out_get_parameters;
2901 out->stream.common.add_audio_effect = out_add_audio_effect;
2902 out->stream.common.remove_audio_effect = out_remove_audio_effect;
2903 out->stream.get_latency = out_get_latency;
2904 out->stream.set_volume = out_set_volume;
2905 out->stream.write = out_write;
2906 out->stream.get_render_position = out_get_render_position;
2907 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002908 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002909
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002910 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07002911 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002912 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002913
Divya Narayanan Poojary69236ba2014-09-18 11:57:57 +05302914 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
2915 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
2916
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002917 config->format = out->stream.common.get_format(&out->stream.common);
2918 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
2919 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
2920
2921 *stream_out = &out->stream;
Sidipotu Ashoke4514fa2014-05-02 16:21:50 +05302922 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
2923 use_case_table[out->usecase]);
Eric Laurent994a6932013-07-17 11:51:42 -07002924 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002925 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002926
2927error_open:
2928 free(out);
2929 *stream_out = NULL;
2930 ALOGD("%s: exit: ret %d", __func__, ret);
2931 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002932}
2933
Divya Narayanan Poojarybd9f33f2014-09-17 17:35:59 +05302934static void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002935 struct audio_stream_out *stream)
2936{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002937 struct stream_out *out = (struct stream_out *)stream;
2938 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002939 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002940
Sidipotu Ashoke4514fa2014-05-02 16:21:50 +05302941 ALOGD("%s: enter:stream_handle(%p)",__func__, out);
2942
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002943 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta593b7c12014-08-11 18:20:49 +05302944 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002945 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Venkata Narendra Kumar Gutta593b7c12014-08-11 18:20:49 +05302946 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002947 if(ret != 0)
2948 ALOGE("%s: Compress voip output cannot be closed, error:%d",
2949 __func__, ret);
2950 }
2951 else
2952 out_standby(&stream->common);
2953
Subhash Chandra Bose Naripeddy148144e2014-04-01 21:03:10 -07002954 if (is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002955 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy148144e2014-04-01 21:03:10 -07002956 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002957 if (out->compr_config.codec != NULL)
2958 free(out->compr_config.codec);
2959 }
2960 pthread_cond_destroy(&out->cond);
2961 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002962 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07002963 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002964}
2965
Alexy Joseph55204352014-10-06 12:15:01 -07002966static void close_compress_sessions(struct audio_device *adev)
2967{
2968 struct stream_out *out = NULL;
2969 struct listnode *node = NULL;
2970 struct listnode *tmp = NULL;
2971 struct audio_usecase *usecase = NULL;
2972 pthread_mutex_lock(&adev->lock);
2973 list_for_each_safe(node, tmp, &adev->usecase_list) {
2974 usecase = node_to_item(node, struct audio_usecase, list);
2975 if (is_offload_usecase(usecase->id)) {
2976 if (usecase && usecase->stream.out) {
2977 ALOGI(" %s closing compress session %d on OFFLINE state", __func__, usecase->id);
2978 out = usecase->stream.out;
2979 pthread_mutex_unlock(&adev->lock);
2980 out_standby(&out->stream.common);
2981 pthread_mutex_lock(&adev->lock);
2982 }
2983 }
2984 }
2985 pthread_mutex_unlock(&adev->lock);
2986}
2987
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002988static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
2989{
2990 struct audio_device *adev = (struct audio_device *)dev;
2991 struct str_parms *parms;
2992 char *str;
2993 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07002994 int val;
Divya Narayanan Poojary69236ba2014-09-18 11:57:57 +05302995 int ret;
2996 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002997
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08002998 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002999 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003000
Naresh Tanniru2d19ab42014-05-11 19:56:25 +05303001 ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
3002 if (ret >= 0) {
3003 char *snd_card_status = value+2;
Naresh Tanniru2d19ab42014-05-11 19:56:25 +05303004 if (strstr(snd_card_status, "OFFLINE")) {
Naresh Tannirucef332d2014-06-04 18:17:56 +05303005 struct listnode *node;
3006 struct audio_usecase *usecase;
3007
Naresh Tanniru2d19ab42014-05-11 19:56:25 +05303008 ALOGD("Received sound card OFFLINE status");
Naresh Tannirucef332d2014-06-04 18:17:56 +05303009 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
3010
Alexy Joseph55204352014-10-06 12:15:01 -07003011 //close compress sessions on OFFLINE status
3012 close_compress_sessions(adev);
Naresh Tanniru2d19ab42014-05-11 19:56:25 +05303013 } else if (strstr(snd_card_status, "ONLINE")) {
3014 ALOGD("Received sound card ONLINE status");
Naresh Tannirucef332d2014-06-04 18:17:56 +05303015 set_snd_card_state(adev,SND_CARD_STATE_ONLINE);
Naresh Tanniru2d19ab42014-05-11 19:56:25 +05303016 }
Naresh Tanniru2d19ab42014-05-11 19:56:25 +05303017 }
3018
3019 pthread_mutex_lock(&adev->lock);
Divya Narayanan Poojary69236ba2014-09-18 11:57:57 +05303020 status = voice_set_parameters(adev, parms);
3021 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003022 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003023
Divya Narayanan Poojary69236ba2014-09-18 11:57:57 +05303024 status = platform_set_parameters(adev->platform, parms);
3025 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003026 goto done;
3027
Divya Narayanan Poojary69236ba2014-09-18 11:57:57 +05303028 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
3029 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003030 /* When set to false, HAL should disable EC and NS
3031 * But it is currently not supported.
3032 */
3033 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3034 adev->bluetooth_nrec = true;
3035 else
3036 adev->bluetooth_nrec = false;
3037 }
3038
Divya Narayanan Poojary69236ba2014-09-18 11:57:57 +05303039 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
3040 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003041 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3042 adev->screen_off = false;
3043 else
3044 adev->screen_off = true;
3045 }
3046
Divya Narayanan Poojary69236ba2014-09-18 11:57:57 +05303047 ret = str_parms_get_int(parms, "rotation", &val);
3048 if (ret >= 0) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003049 bool reverse_speakers = false;
3050 switch(val) {
3051 // FIXME: note that the code below assumes that the speakers are in the correct placement
3052 // relative to the user when the device is rotated 90deg from its default rotation. This
3053 // assumption is device-specific, not platform-specific like this code.
3054 case 270:
3055 reverse_speakers = true;
3056 break;
3057 case 0:
3058 case 90:
3059 case 180:
3060 break;
3061 default:
3062 ALOGE("%s: unexpected rotation of %d", __func__, val);
Divya Narayanan Poojary69236ba2014-09-18 11:57:57 +05303063 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003064 }
Divya Narayanan Poojary69236ba2014-09-18 11:57:57 +05303065 if (status == 0) {
3066 if (adev->speaker_lr_swap != reverse_speakers) {
3067 adev->speaker_lr_swap = reverse_speakers;
3068 // only update the selected device if there is active pcm playback
3069 struct audio_usecase *usecase;
3070 struct listnode *node;
3071 list_for_each(node, &adev->usecase_list) {
3072 usecase = node_to_item(node, struct audio_usecase, list);
3073 if (usecase->type == PCM_PLAYBACK) {
Steve Kondik3abbbc82014-11-29 14:14:43 -08003074 status = select_devices(adev, usecase->id);
Divya Narayanan Poojary69236ba2014-09-18 11:57:57 +05303075 break;
3076 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003077 }
3078 }
3079 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003080 }
3081
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -07003082 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003083
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003084done:
3085 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003086 pthread_mutex_unlock(&adev->lock);
Divya Narayanan Poojary69236ba2014-09-18 11:57:57 +05303087 ALOGV("%s: exit with code(%d)", __func__, status);
3088 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003089}
3090
3091static char* adev_get_parameters(const struct audio_hw_device *dev,
3092 const char *keys)
3093{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003094 struct audio_device *adev = (struct audio_device *)dev;
3095 struct str_parms *reply = str_parms_create();
3096 struct str_parms *query = str_parms_create_str(keys);
3097 char *str;
Naresh Tanniruc6ca6352014-06-20 02:54:48 +05303098 char value[256] = {0};
3099 int ret = 0;
3100
Haynes Mathew George9f0254a2014-06-30 13:56:18 -07003101 if (!query || !reply) {
3102 ALOGE("adev_get_parameters: failed to create query or reply");
3103 return NULL;
3104 }
3105
Naresh Tanniruc6ca6352014-06-20 02:54:48 +05303106 ret = str_parms_get_str(query, AUDIO_PARAMETER_KEY_SND_CARD_STATUS, value,
3107 sizeof(value));
3108 if (ret >=0) {
3109 int val = 1;
3110 pthread_mutex_lock(&adev->snd_card_status.lock);
3111 if (SND_CARD_STATE_OFFLINE == adev->snd_card_status.state)
3112 val = 0;
3113 pthread_mutex_unlock(&adev->snd_card_status.lock);
3114 str_parms_add_int(reply, AUDIO_PARAMETER_KEY_SND_CARD_STATUS, val);
3115 goto exit;
3116 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003117
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003118 pthread_mutex_lock(&adev->lock);
Naresh Tanniruc6ca6352014-06-20 02:54:48 +05303119
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003120 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08003121 voice_get_parameters(adev, query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003122 platform_get_parameters(adev->platform, query, reply);
Naresh Tannirucef332d2014-06-04 18:17:56 +05303123 pthread_mutex_unlock(&adev->lock);
3124
Naresh Tanniruc6ca6352014-06-20 02:54:48 +05303125exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003126 str = str_parms_to_str(reply);
3127 str_parms_destroy(query);
3128 str_parms_destroy(reply);
3129
3130 ALOGV("%s: exit: returns - %s", __func__, str);
3131 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003132}
3133
Divya Narayanan Poojarybd9f33f2014-09-17 17:35:59 +05303134static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003135{
3136 return 0;
3137}
3138
3139static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
3140{
Haynes Mathew George5191a852013-09-11 14:19:36 -07003141 int ret;
3142 struct audio_device *adev = (struct audio_device *)dev;
Eric Laurent321b96d2014-09-10 13:21:01 -05003143
3144 audio_extn_extspk_set_voice_vol(adev->extspk, volume);
3145
Haynes Mathew George5191a852013-09-11 14:19:36 -07003146 pthread_mutex_lock(&adev->lock);
3147 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07003148 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07003149 pthread_mutex_unlock(&adev->lock);
3150 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003151}
3152
Divya Narayanan Poojarybd9f33f2014-09-17 17:35:59 +05303153static int adev_set_master_volume(struct audio_hw_device *dev __unused,
3154 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003155{
3156 return -ENOSYS;
3157}
3158
Divya Narayanan Poojarybd9f33f2014-09-17 17:35:59 +05303159static int adev_get_master_volume(struct audio_hw_device *dev __unused,
3160 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003161{
3162 return -ENOSYS;
3163}
3164
Divya Narayanan Poojarybd9f33f2014-09-17 17:35:59 +05303165static int adev_set_master_mute(struct audio_hw_device *dev __unused,
3166 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003167{
3168 return -ENOSYS;
3169}
3170
Divya Narayanan Poojarybd9f33f2014-09-17 17:35:59 +05303171static int adev_get_master_mute(struct audio_hw_device *dev __unused,
3172 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003173{
3174 return -ENOSYS;
3175}
3176
3177static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
3178{
3179 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003180 pthread_mutex_lock(&adev->lock);
3181 if (adev->mode != mode) {
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07003182 ALOGD("%s mode %d\n", __func__, mode);
Daniel Hillenbrand8373bc62013-05-23 10:10:00 +05303183#ifdef USES_AUDIO_AMPLIFIER
3184 if (amplifier_set_mode(mode) != 0)
3185 ALOGE("Failed setting amplifier mode");
3186#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003187 adev->mode = mode;
3188 }
3189 pthread_mutex_unlock(&adev->lock);
Eric Laurentda46bfb2014-08-25 22:39:29 -05003190
3191 audio_extn_extspk_set_mode(adev->extspk, mode);
3192
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003193 return 0;
3194}
3195
3196static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
3197{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003198 int ret;
3199
3200 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08003201 ALOGD("%s state %d\n", __func__, state);
Shreyas Nagasandra Chandrasekhar9781c6c2014-12-01 05:49:35 -08003202 ret = voice_set_mic_mute((struct audio_device *)dev, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003203 pthread_mutex_unlock(&adev->lock);
3204
3205 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003206}
3207
3208static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
3209{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003210 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003211 return 0;
3212}
3213
Divya Narayanan Poojarybd9f33f2014-09-17 17:35:59 +05303214static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003215 const struct audio_config *config)
3216{
Divya Narayanan Poojary69236ba2014-09-18 11:57:57 +05303217 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003218
Ravi Kumar Alamanda1c3de5e2014-09-08 15:59:58 -07003219 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
3220 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003221}
3222
3223static int adev_open_input_stream(struct audio_hw_device *dev,
Divya Narayanan Poojarybd9f33f2014-09-17 17:35:59 +05303224 audio_io_handle_t handle __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003225 audio_devices_t devices,
3226 struct audio_config *config,
Divya Narayanan Poojarybd9f33f2014-09-17 17:35:59 +05303227 struct audio_stream_in **stream_in,
3228 audio_input_flags_t flags __unused,
3229 const char *address __unused,
Vidyakumar Athota7e6ba2e2015-03-31 21:53:21 -07003230 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003231{
3232 struct audio_device *adev = (struct audio_device *)dev;
3233 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003234 int ret = 0, buffer_size, frame_size;
Divya Narayanan Poojary69236ba2014-09-18 11:57:57 +05303235 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda1c3de5e2014-09-08 15:59:58 -07003236 bool is_low_latency = false;
Sidipotu Ashoke4514fa2014-05-02 16:21:50 +05303237
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003238 *stream_in = NULL;
3239 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0)
3240 return -EINVAL;
3241
3242 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew George9f0254a2014-06-30 13:56:18 -07003243
3244 if (!in) {
3245 ALOGE("failed to allocate input stream");
3246 return -ENOMEM;
3247 }
3248
Sidipotu Ashoke4514fa2014-05-02 16:21:50 +05303249 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Vidyakumar Athota7e6ba2e2015-03-31 21:53:21 -07003250 stream_handle(%p) io_handle(%d) source(%d)",__func__, config->sample_rate, config->channel_mask,
3251 devices, &in->stream, handle, source);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003252
Ravi Kumar Alamanda33de8142014-04-24 10:34:41 -07003253 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
3254
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003255 in->stream.common.get_sample_rate = in_get_sample_rate;
3256 in->stream.common.set_sample_rate = in_set_sample_rate;
3257 in->stream.common.get_buffer_size = in_get_buffer_size;
3258 in->stream.common.get_channels = in_get_channels;
3259 in->stream.common.get_format = in_get_format;
3260 in->stream.common.set_format = in_set_format;
3261 in->stream.common.standby = in_standby;
3262 in->stream.common.dump = in_dump;
3263 in->stream.common.set_parameters = in_set_parameters;
3264 in->stream.common.get_parameters = in_get_parameters;
3265 in->stream.common.add_audio_effect = in_add_audio_effect;
3266 in->stream.common.remove_audio_effect = in_remove_audio_effect;
3267 in->stream.set_gain = in_set_gain;
3268 in->stream.read = in_read;
3269 in->stream.get_input_frames_lost = in_get_input_frames_lost;
3270
3271 in->device = devices;
Vidyakumar Athota7e6ba2e2015-03-31 21:53:21 -07003272 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003273 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003274 in->standby = 1;
3275 in->channel_mask = config->channel_mask;
3276
3277 /* Update config params with the requested sample rate and channels */
3278 in->usecase = USECASE_AUDIO_RECORD;
Ravi Kumar Alamanda1c3de5e2014-09-08 15:59:58 -07003279 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
3280 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
3281 is_low_latency = true;
3282#if LOW_LATENCY_CAPTURE_USE_CASE
3283 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
3284#endif
3285 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003286 in->config = pcm_config_audio_capture;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003287 in->config.rate = config->sample_rate;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003288 in->format = config->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003289
Divya Narayanan Poojaryab9b1ef2014-09-12 15:52:36 +05303290 if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
Pavan Chikkala3c0036d2014-12-17 16:45:10 +05303291 if (adev->mode != AUDIO_MODE_IN_CALL) {
3292 ret = -EINVAL;
3293 goto err_open;
Pavan Chikkala3ec42ef2014-11-21 20:57:48 +05303294 }
Divya Narayanan Poojaryab9b1ef2014-09-12 15:52:36 +05303295 if (config->sample_rate == 0)
3296 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3297 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
3298 config->sample_rate != 8000) {
3299 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3300 ret = -EINVAL;
3301 goto err_open;
3302 }
3303 if (config->format == AUDIO_FORMAT_DEFAULT)
3304 config->format = AUDIO_FORMAT_PCM_16_BIT;
3305 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
3306 config->format = AUDIO_FORMAT_PCM_16_BIT;
3307 ret = -EINVAL;
3308 goto err_open;
3309 }
3310 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
3311 in->config = pcm_config_afe_proxy_record;
3312 in->config.channels = channel_count;
3313 in->config.rate = config->sample_rate;
3314 } else if (channel_count == 6) {
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003315 if(audio_extn_ssr_get_enabled()) {
Divya Narayanan Poojarybd9f33f2014-09-17 17:35:59 +05303316 if(audio_extn_ssr_init(in)) {
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003317 ALOGE("%s: audio_extn_ssr_init failed", __func__);
3318 ret = -EINVAL;
3319 goto err_open;
3320 }
3321 } else {
Mingming Yindaf9c542014-09-16 17:41:33 -07003322 ALOGW("%s: surround sound recording is not supported", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003323 }
Mingming Yine62d7842013-10-25 16:26:03 -07003324 } else if (audio_extn_compr_cap_enabled() &&
Narsinga Rao Chellab0668ee2014-01-24 15:33:23 -08003325 audio_extn_compr_cap_format_supported(config->format) &&
3326 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
Divya Narayanan Poojarybd9f33f2014-09-17 17:35:59 +05303327 audio_extn_compr_cap_init(in);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003328 } else {
3329 in->config.channels = channel_count;
Divya Narayanan Poojary69236ba2014-09-18 11:57:57 +05303330 frame_size = audio_stream_in_frame_size(&in->stream);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003331 buffer_size = get_input_buffer_size(config->sample_rate,
3332 config->format,
Ravi Kumar Alamanda1c3de5e2014-09-08 15:59:58 -07003333 channel_count,
3334 is_low_latency);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003335 in->config.period_size = buffer_size / frame_size;
Vidyakumar Athota7e6ba2e2015-03-31 21:53:21 -07003336 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
3337 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
3338 (voice_extn_compress_voip_is_format_supported(in->format)) &&
3339 (in->config.rate == 8000 || in->config.rate == 16000) &&
3340 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
3341 voice_extn_compress_voip_open_input_stream(in);
3342 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003343 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003344
3345 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07003346 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003347 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003348
3349err_open:
3350 free(in);
3351 *stream_in = NULL;
3352 return ret;
3353}
3354
Divya Narayanan Poojarybd9f33f2014-09-17 17:35:59 +05303355static void adev_close_input_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003356 struct audio_stream_in *stream)
3357{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003358 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003359 struct stream_in *in = (struct stream_in *)stream;
Venkata Narendra Kumar Gutta593b7c12014-08-11 18:20:49 +05303360 struct audio_device *adev = in->dev;
3361
Sidipotu Ashoke4514fa2014-05-02 16:21:50 +05303362 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003363
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003364 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta593b7c12014-08-11 18:20:49 +05303365 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003366 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta593b7c12014-08-11 18:20:49 +05303367 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003368 if (ret != 0)
3369 ALOGE("%s: Compress voip input cannot be closed, error:%d",
3370 __func__, ret);
3371 } else
3372 in_standby(&stream->common);
3373
Divya Narayanan Poojary69236ba2014-09-18 11:57:57 +05303374 if (audio_extn_ssr_get_enabled() &&
3375 (audio_channel_count_from_in_mask(in->channel_mask) == 6)) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003376 audio_extn_ssr_deinit();
3377 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003378 free(stream);
3379
Mingming Yine62d7842013-10-25 16:26:03 -07003380 if(audio_extn_compr_cap_enabled() &&
3381 audio_extn_compr_cap_format_supported(in->config.format))
3382 audio_extn_compr_cap_deinit();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003383 return;
3384}
3385
Divya Narayanan Poojarybd9f33f2014-09-17 17:35:59 +05303386static int adev_dump(const audio_hw_device_t *device __unused,
3387 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003388{
3389 return 0;
3390}
3391
Steve Kondik3abbbc82014-11-29 14:14:43 -08003392/* verifies input and output devices and their capabilities.
3393 *
3394 * This verification is required when enabling extended bit-depth or
3395 * sampling rates, as not all qcom products support it.
3396 *
3397 * Suitable for calling only on initialization such as adev_open().
3398 * It fills the audio_device use_case_table[] array.
3399 *
3400 * Has a side-effect that it needs to configure audio routing / devices
3401 * in order to power up the devices and read the device parameters.
3402 * It does not acquire any hw device lock. Should restore the devices
3403 * back to "normal state" upon completion.
3404 */
3405static int adev_verify_devices(struct audio_device *adev)
3406{
3407 /* enumeration is a bit difficult because one really wants to pull
3408 * the use_case, device id, etc from the hidden pcm_device_table[].
3409 * In this case there are the following use cases and device ids.
3410 *
3411 * [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {0, 0},
3412 * [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {15, 15},
3413 * [USECASE_AUDIO_PLAYBACK_MULTI_CH] = {1, 1},
3414 * [USECASE_AUDIO_PLAYBACK_OFFLOAD] = {9, 9},
3415 * [USECASE_AUDIO_RECORD] = {0, 0},
3416 * [USECASE_AUDIO_RECORD_LOW_LATENCY] = {15, 15},
3417 * [USECASE_VOICE_CALL] = {2, 2},
3418 *
3419 * USECASE_AUDIO_PLAYBACK_OFFLOAD, USECASE_AUDIO_PLAYBACK_MULTI_CH omitted.
3420 * USECASE_VOICE_CALL omitted, but possible for either input or output.
3421 */
3422
3423 /* should be the usecases enabled in adev_open_input_stream() */
3424 static const int test_in_usecases[] = {
3425 USECASE_AUDIO_RECORD,
3426 USECASE_AUDIO_RECORD_LOW_LATENCY, /* does not appear to be used */
3427 };
3428 /* should be the usecases enabled in adev_open_output_stream()*/
3429 static const int test_out_usecases[] = {
3430 USECASE_AUDIO_PLAYBACK_DEEP_BUFFER,
3431 USECASE_AUDIO_PLAYBACK_LOW_LATENCY,
3432 };
3433 static const usecase_type_t usecase_type_by_dir[] = {
3434 PCM_PLAYBACK,
3435 PCM_CAPTURE,
3436 };
3437 static const unsigned flags_by_dir[] = {
3438 PCM_OUT,
3439 PCM_IN,
3440 };
3441
3442 size_t i;
3443 unsigned dir;
3444 const unsigned card_id = adev->snd_card;
3445 char info[512]; /* for possible debug info */
3446
3447 for (dir = 0; dir < 2; ++dir) {
3448 const usecase_type_t usecase_type = usecase_type_by_dir[dir];
3449 const unsigned flags_dir = flags_by_dir[dir];
3450 const size_t testsize =
3451 dir ? ARRAY_SIZE(test_in_usecases) : ARRAY_SIZE(test_out_usecases);
3452 const int *testcases =
3453 dir ? test_in_usecases : test_out_usecases;
3454 const audio_devices_t audio_device =
3455 dir ? AUDIO_DEVICE_IN_BUILTIN_MIC : AUDIO_DEVICE_OUT_SPEAKER;
3456
3457 for (i = 0; i < testsize; ++i) {
3458 const audio_usecase_t audio_usecase = testcases[i];
3459 int device_id;
3460 snd_device_t snd_device;
3461 struct pcm_params **pparams;
3462 struct stream_out out;
3463 struct stream_in in;
3464 struct audio_usecase uc_info;
3465 int retval;
3466
3467 pparams = &adev->use_case_table[audio_usecase];
3468 pcm_params_free(*pparams); /* can accept null input */
3469 *pparams = NULL;
3470
3471 /* find the device ID for the use case (signed, for error) */
3472 device_id = platform_get_pcm_device_id(audio_usecase, usecase_type);
3473 if (device_id < 0)
3474 continue;
3475
3476 /* prepare structures for device probing */
3477 memset(&uc_info, 0, sizeof(uc_info));
3478 uc_info.id = audio_usecase;
3479 uc_info.type = usecase_type;
3480 if (dir) {
3481 adev->active_input = &in;
3482 memset(&in, 0, sizeof(in));
3483 in.device = audio_device;
3484 in.source = AUDIO_SOURCE_VOICE_COMMUNICATION;
3485 uc_info.stream.in = &in;
3486 } else {
3487 adev->active_input = NULL;
3488 }
3489 memset(&out, 0, sizeof(out));
3490 out.devices = audio_device; /* only field needed in select_devices */
3491 uc_info.stream.out = &out;
3492 uc_info.devices = audio_device;
3493 uc_info.in_snd_device = SND_DEVICE_NONE;
3494 uc_info.out_snd_device = SND_DEVICE_NONE;
3495 list_add_tail(&adev->usecase_list, &uc_info.list);
3496
3497 /* select device - similar to start_(in/out)put_stream() */
3498 retval = select_devices(adev, audio_usecase);
3499 if (retval >= 0) {
3500 *pparams = pcm_params_get(card_id, device_id, flags_dir);
3501#if LOG_NDEBUG == 0
3502 if (*pparams) {
3503 ALOGV("%s: (%s) card %d device %d", __func__,
3504 dir ? "input" : "output", card_id, device_id);
3505 pcm_params_to_string(*pparams, info, ARRAY_SIZE(info));
3506 ALOGV(info); /* print parameters */
3507 } else {
3508 ALOGV("%s: cannot locate card %d device %d", __func__, card_id, device_id);
3509 }
3510#endif
3511 }
3512
3513 /* deselect device - similar to stop_(in/out)put_stream() */
3514 /* 1. Get and set stream specific mixer controls */
3515 retval = disable_audio_route(adev, &uc_info);
3516 /* 2. Disable the rx device */
3517 retval = disable_snd_device(adev,
3518 dir ? uc_info.in_snd_device : uc_info.out_snd_device);
3519 list_remove(&uc_info.list);
3520 }
3521 }
3522 adev->active_input = NULL; /* restore adev state */
3523 return 0;
3524}
3525
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003526static int adev_close(hw_device_t *device)
3527{
Steve Kondik3abbbc82014-11-29 14:14:43 -08003528 size_t i;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003529 struct audio_device *adev = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -07003530
3531 if (!adev)
3532 return 0;
3533
3534 pthread_mutex_lock(&adev_init_lock);
3535
3536 if ((--audio_device_ref_count) == 0) {
Daniel Hillenbrand8373bc62013-05-23 10:10:00 +05303537#ifdef USES_AUDIO_AMPLIFIER
3538 if (amplifier_close() != 0)
3539 ALOGE("Amplifier close failed");
3540#endif
Kiran Kandide144c82013-11-20 15:58:32 -08003541 audio_extn_listen_deinit(adev);
Kiran Kandi910e1862013-10-29 13:29:42 -07003542 audio_route_free(adev->audio_route);
3543 free(adev->snd_dev_ref_cnt);
3544 platform_deinit(adev->platform);
Eric Laurentda46bfb2014-08-25 22:39:29 -05003545 audio_extn_extspk_deinit(adev->extspk);
Steve Kondik3abbbc82014-11-29 14:14:43 -08003546 for (i = 0; i < ARRAY_SIZE(adev->use_case_table); ++i) {
3547 pcm_params_free(adev->use_case_table[i]);
3548 }
Kiran Kandi910e1862013-10-29 13:29:42 -07003549 free(device);
3550 adev = NULL;
3551 }
3552 pthread_mutex_unlock(&adev_init_lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003553 return 0;
3554}
3555
Ravi Kumar Alamanda1c3de5e2014-09-08 15:59:58 -07003556/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
3557 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
3558 * just that it _might_ work.
3559 */
3560static int period_size_is_plausible_for_low_latency(int period_size)
3561{
3562 switch (period_size) {
3563 case 160:
3564 case 240:
3565 case 320:
3566 case 480:
3567 return 1;
3568 default:
3569 return 0;
3570 }
3571}
3572
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003573static int adev_open(const hw_module_t *module, const char *name,
3574 hw_device_t **device)
3575{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003576 int i, ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003577
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003578 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003579 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
3580
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003581 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -07003582 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003583 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -07003584 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003585 ALOGD("%s: returning existing instance of adev", __func__);
3586 ALOGD("%s: exit", __func__);
3587 pthread_mutex_unlock(&adev_init_lock);
3588 return 0;
3589 }
3590
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003591 adev = calloc(1, sizeof(struct audio_device));
3592
Haynes Mathew George9f0254a2014-06-30 13:56:18 -07003593 if (!adev) {
3594 pthread_mutex_unlock(&adev_init_lock);
3595 return -ENOMEM;
3596 }
3597
Ravi Kumar Alamanda33de8142014-04-24 10:34:41 -07003598 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
3599
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003600 adev->device.common.tag = HARDWARE_DEVICE_TAG;
3601 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
3602 adev->device.common.module = (struct hw_module_t *)module;
3603 adev->device.common.close = adev_close;
3604
3605 adev->device.init_check = adev_init_check;
3606 adev->device.set_voice_volume = adev_set_voice_volume;
3607 adev->device.set_master_volume = adev_set_master_volume;
3608 adev->device.get_master_volume = adev_get_master_volume;
3609 adev->device.set_master_mute = adev_set_master_mute;
3610 adev->device.get_master_mute = adev_get_master_mute;
3611 adev->device.set_mode = adev_set_mode;
3612 adev->device.set_mic_mute = adev_set_mic_mute;
3613 adev->device.get_mic_mute = adev_get_mic_mute;
3614 adev->device.set_parameters = adev_set_parameters;
3615 adev->device.get_parameters = adev_get_parameters;
3616 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
3617 adev->device.open_output_stream = adev_open_output_stream;
3618 adev->device.close_output_stream = adev_close_output_stream;
3619 adev->device.open_input_stream = adev_open_input_stream;
3620 adev->device.close_input_stream = adev_close_input_stream;
3621 adev->device.dump = adev_dump;
3622
3623 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003624 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08003625 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003626 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003627 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003628 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08003629 adev->acdb_settings = TTY_MODE_OFF;
Eric Laurent07eeafd2013-10-06 12:52:49 -07003630 /* adev->cur_hdmi_channels = 0; by calloc() */
ApurupaPattapu9d6b4362014-02-27 10:24:11 -08003631 adev->cur_codec_backend_samplerate = CODEC_BACKEND_DEFAULT_SAMPLE_RATE;
3632 adev->cur_codec_backend_bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Eric Laurentb23d5282013-05-14 15:27:20 -07003633 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003634 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003635 list_init(&adev->usecase_list);
Krishnankutty Kolathappilly9b7e96b2014-02-14 14:45:49 -08003636 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy148144e2014-04-01 21:03:10 -07003637 adev->offload_usecases_state = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003638
Naresh Tanniru2d19ab42014-05-11 19:56:25 +05303639 pthread_mutex_init(&adev->snd_card_status.lock, (const pthread_mutexattr_t *) NULL);
3640 adev->snd_card_status.state = SND_CARD_STATE_OFFLINE;
3641
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003642 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07003643 adev->platform = platform_init(adev);
3644 if (!adev->platform) {
3645 free(adev->snd_dev_ref_cnt);
3646 free(adev);
3647 ALOGE("%s: Failed to init platform data, aborting.", __func__);
3648 *device = NULL;
Apoorv Raghuvanshi6e57d7e2013-12-16 16:02:45 -08003649 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07003650 return -EINVAL;
3651 }
Eric Laurentc4aef752013-09-12 17:45:53 -07003652
Naresh Tanniru2d19ab42014-05-11 19:56:25 +05303653 adev->snd_card_status.state = SND_CARD_STATE_ONLINE;
Eric Laurentda46bfb2014-08-25 22:39:29 -05003654 adev->extspk = audio_extn_extspk_init(adev);
Naresh Tanniru2d19ab42014-05-11 19:56:25 +05303655
Eric Laurentc4aef752013-09-12 17:45:53 -07003656 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
3657 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
3658 if (adev->visualizer_lib == NULL) {
3659 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
3660 } else {
3661 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
3662 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003663 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07003664 "visualizer_hal_start_output");
3665 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003666 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07003667 "visualizer_hal_stop_output");
3668 }
3669 }
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08003670 audio_extn_listen_init(adev, adev->snd_card);
Eric Laurentc4aef752013-09-12 17:45:53 -07003671
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003672 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
3673 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
3674 if (adev->offload_effects_lib == NULL) {
3675 ALOGE("%s: DLOPEN failed for %s", __func__,
3676 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
3677 } else {
3678 ALOGV("%s: DLOPEN successful for %s", __func__,
3679 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
3680 adev->offload_effects_start_output =
3681 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
3682 "offload_effects_bundle_hal_start_output");
3683 adev->offload_effects_stop_output =
3684 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
3685 "offload_effects_bundle_hal_stop_output");
3686 }
3687 }
3688
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003689 *device = &adev->device.common;
Steve Kondik3abbbc82014-11-29 14:14:43 -08003690 if (k_enable_extended_precision)
3691 adev_verify_devices(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003692
Daniel Hillenbrand8373bc62013-05-23 10:10:00 +05303693#ifdef USES_AUDIO_AMPLIFIER
3694 if (amplifier_open() != 0)
3695 ALOGE("Amplifier initialization failed");
3696#endif
3697
Kiran Kandi910e1862013-10-29 13:29:42 -07003698 audio_device_ref_count++;
Ravi Kumar Alamanda1c3de5e2014-09-08 15:59:58 -07003699
3700 char value[PROPERTY_VALUE_MAX];
3701 int trial;
3702 if (property_get("audio_hal.period_size", value, NULL) > 0) {
3703 trial = atoi(value);
3704 if (period_size_is_plausible_for_low_latency(trial)) {
3705 pcm_config_low_latency.period_size = trial;
3706 pcm_config_low_latency.start_threshold = trial / 4;
3707 pcm_config_low_latency.avail_min = trial / 4;
3708 configured_low_latency_capture_period_size = trial;
3709 }
3710 }
3711 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
3712 trial = atoi(value);
3713 if (period_size_is_plausible_for_low_latency(trial)) {
3714 configured_low_latency_capture_period_size = trial;
3715 }
3716 }
3717
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003718 pthread_mutex_unlock(&adev_init_lock);
3719
Eric Laurent994a6932013-07-17 11:51:42 -07003720 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003721 return 0;
3722}
3723
3724static struct hw_module_methods_t hal_module_methods = {
3725 .open = adev_open,
3726};
3727
3728struct audio_module HAL_MODULE_INFO_SYM = {
3729 .common = {
3730 .tag = HARDWARE_MODULE_TAG,
3731 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
3732 .hal_api_version = HARDWARE_HAL_API_VERSION,
3733 .id = AUDIO_HARDWARE_MODULE_ID,
3734 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -08003735 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003736 .methods = &hal_module_methods,
3737 },
3738};