blob: 238db4e6be3d973fba1fbc87202f12a9218b8371 [file] [log] [blame]
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001/*
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05302 * Copyright (c) 2013-2017, 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.
Jitendra Naruka1b6513f2014-11-22 19:34:13 -080018 *
19 * This file was modified by DTS, Inc. The portions of the
20 * code modified by DTS, Inc are copyrighted and
21 * licensed separately, as follows:
22 *
23 * (C) 2014 DTS, Inc.
24 *
25 * Licensed under the Apache License, Version 2.0 (the "License");
26 * you may not use this file except in compliance with the License.
27 * You may obtain a copy of the License at
28 *
29 * http://www.apache.org/licenses/LICENSE-2.0
30 *
31 * Unless required by applicable law or agreed to in writing, software
32 * distributed under the License is distributed on an "AS IS" BASIS,
33 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
34 * See the License for the specific language governing permissions and
35 * limitations under the License.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080036 */
37
38#define LOG_TAG "audio_hw_primary"
Haynes Mathew George5beddd42016-06-27 18:33:40 -070039#define ATRACE_TAG (ATRACE_TAG_AUDIO|ATRACE_TAG_HAL)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080040/*#define LOG_NDEBUG 0*/
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070041/*#define VERY_VERY_VERBOSE_LOGGING*/
42#ifdef VERY_VERY_VERBOSE_LOGGING
43#define ALOGVV ALOGV
44#else
45#define ALOGVV(a...) do { } while(0)
46#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080047
48#include <errno.h>
49#include <pthread.h>
50#include <stdint.h>
51#include <sys/time.h>
52#include <stdlib.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080053#include <math.h>
Eric Laurentc4aef752013-09-12 17:45:53 -070054#include <dlfcn.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070055#include <sys/resource.h>
56#include <sys/prctl.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080057
58#include <cutils/log.h>
Haynes Mathew George5beddd42016-06-27 18:33:40 -070059#include <cutils/trace.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080060#include <cutils/str_parms.h>
61#include <cutils/properties.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070062#include <cutils/atomic.h>
63#include <cutils/sched_policy.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080064
Eric Laurentb23d5282013-05-14 15:27:20 -070065#include <hardware/audio_effect.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070066#include <system/thread_defs.h>
Eric Laurentb23d5282013-05-14 15:27:20 -070067#include <audio_effects/effect_aec.h>
68#include <audio_effects/effect_ns.h>
Ashish Jainf1eaa582016-05-23 20:54:24 +053069#include <audio_utils/format.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080070#include "audio_hw.h"
Eric Laurentb23d5282013-05-14 15:27:20 -070071#include "platform_api.h"
72#include <platform.h>
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -070073#include "audio_extn.h"
Narsinga Rao Chella05573b72013-11-15 15:21:40 -080074#include "voice_extn.h"
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080075
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070076#include "sound/compress_params.h"
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -080077#include "sound/asound.h"
ApurupaPattapu2e084df2013-12-18 15:47:59 -080078
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070079#define COMPRESS_OFFLOAD_NUM_FRAGMENTS 4
Ashish Jain5106d362016-05-11 19:23:33 +053080/*DIRECT PCM has same buffer sizes as DEEP Buffer*/
81#define DIRECT_PCM_NUM_FRAGMENTS 2
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070082#define COMPRESS_PLAYBACK_VOLUME_MAX 0x2000
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +053083#define DSD_VOLUME_MIN_DB (-110)
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070084
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -070085#define PROXY_OPEN_RETRY_COUNT 100
86#define PROXY_OPEN_WAIT_TIME 20
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -080087
Mingming Yin08c7e312015-03-16 18:10:58 -070088#ifdef USE_LL_AS_PRIMARY_OUTPUT
89#define USECASE_AUDIO_PLAYBACK_PRIMARY USECASE_AUDIO_PLAYBACK_LOW_LATENCY
90#define PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY pcm_config_low_latency
91#else
Haynes Mathew Georgebf143712013-12-03 13:02:53 -080092#define USECASE_AUDIO_PLAYBACK_PRIMARY USECASE_AUDIO_PLAYBACK_DEEP_BUFFER
Mingming Yin08c7e312015-03-16 18:10:58 -070093#define PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY pcm_config_deep_buffer
94#endif
Haynes Mathew Georgebf143712013-12-03 13:02:53 -080095
Haynes Mathew George5beddd42016-06-27 18:33:40 -070096#define ULL_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
97
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070098static unsigned int configured_low_latency_capture_period_size =
99 LOW_LATENCY_CAPTURE_PERIOD_SIZE;
100
Eric Laurentb23d5282013-05-14 15:27:20 -0700101struct pcm_config pcm_config_deep_buffer = {
102 .channels = 2,
103 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
104 .period_size = DEEP_BUFFER_OUTPUT_PERIOD_SIZE,
105 .period_count = DEEP_BUFFER_OUTPUT_PERIOD_COUNT,
106 .format = PCM_FORMAT_S16_LE,
107 .start_threshold = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
108 .stop_threshold = INT_MAX,
109 .avail_min = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
110};
111
112struct pcm_config pcm_config_low_latency = {
113 .channels = 2,
114 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
115 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
116 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
117 .format = PCM_FORMAT_S16_LE,
118 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
119 .stop_threshold = INT_MAX,
120 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
121};
122
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700123static int af_period_multiplier = 4;
124struct pcm_config pcm_config_rt = {
125 .channels = 2,
126 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
127 .period_size = ULL_PERIOD_SIZE, //1 ms
128 .period_count = 512, //=> buffer size is 512ms
129 .format = PCM_FORMAT_S16_LE,
130 .start_threshold = ULL_PERIOD_SIZE*8, //8ms
131 .stop_threshold = INT_MAX,
132 .silence_threshold = 0,
133 .silence_size = 0,
134 .avail_min = ULL_PERIOD_SIZE, //1 ms
135};
136
Eric Laurentb23d5282013-05-14 15:27:20 -0700137struct pcm_config pcm_config_hdmi_multi = {
138 .channels = HDMI_MULTI_DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
139 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
140 .period_size = HDMI_MULTI_PERIOD_SIZE,
141 .period_count = HDMI_MULTI_PERIOD_COUNT,
142 .format = PCM_FORMAT_S16_LE,
143 .start_threshold = 0,
144 .stop_threshold = INT_MAX,
145 .avail_min = 0,
146};
147
148struct pcm_config pcm_config_audio_capture = {
149 .channels = 2,
Eric Laurentb23d5282013-05-14 15:27:20 -0700150 .period_count = AUDIO_CAPTURE_PERIOD_COUNT,
151 .format = PCM_FORMAT_S16_LE,
152};
153
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700154struct pcm_config pcm_config_audio_capture_rt = {
155 .channels = 2,
156 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
157 .period_size = ULL_PERIOD_SIZE,
158 .period_count = 512,
159 .format = PCM_FORMAT_S16_LE,
160 .start_threshold = 0,
161 .stop_threshold = INT_MAX,
162 .silence_threshold = 0,
163 .silence_size = 0,
164 .avail_min = ULL_PERIOD_SIZE, //1 ms
165};
166
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700167#define AFE_PROXY_CHANNEL_COUNT 2
168#define AFE_PROXY_SAMPLING_RATE 48000
169
170#define AFE_PROXY_PLAYBACK_PERIOD_SIZE 768
171#define AFE_PROXY_PLAYBACK_PERIOD_COUNT 4
172
173struct pcm_config pcm_config_afe_proxy_playback = {
174 .channels = AFE_PROXY_CHANNEL_COUNT,
175 .rate = AFE_PROXY_SAMPLING_RATE,
176 .period_size = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
177 .period_count = AFE_PROXY_PLAYBACK_PERIOD_COUNT,
178 .format = PCM_FORMAT_S16_LE,
179 .start_threshold = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
180 .stop_threshold = INT_MAX,
181 .avail_min = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
182};
183
184#define AFE_PROXY_RECORD_PERIOD_SIZE 768
185#define AFE_PROXY_RECORD_PERIOD_COUNT 4
186
187struct pcm_config pcm_config_afe_proxy_record = {
188 .channels = AFE_PROXY_CHANNEL_COUNT,
189 .rate = AFE_PROXY_SAMPLING_RATE,
190 .period_size = AFE_PROXY_RECORD_PERIOD_SIZE,
191 .period_count = AFE_PROXY_RECORD_PERIOD_COUNT,
192 .format = PCM_FORMAT_S16_LE,
193 .start_threshold = AFE_PROXY_RECORD_PERIOD_SIZE,
194 .stop_threshold = INT_MAX,
195 .avail_min = AFE_PROXY_RECORD_PERIOD_SIZE,
196};
197
Ashish Jainf1eaa582016-05-23 20:54:24 +0530198#define AUDIO_MAX_PCM_FORMATS 7
199
200const uint32_t format_to_bitwidth_table[AUDIO_MAX_PCM_FORMATS] = {
201 [AUDIO_FORMAT_DEFAULT] = 0,
202 [AUDIO_FORMAT_PCM_16_BIT] = sizeof(uint16_t),
203 [AUDIO_FORMAT_PCM_8_BIT] = sizeof(uint8_t),
204 [AUDIO_FORMAT_PCM_32_BIT] = sizeof(uint32_t),
205 [AUDIO_FORMAT_PCM_8_24_BIT] = sizeof(uint32_t),
206 [AUDIO_FORMAT_PCM_FLOAT] = sizeof(float),
207 [AUDIO_FORMAT_PCM_24_BIT_PACKED] = sizeof(uint8_t) * 3,
208};
209
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -0800210const char * const use_case_table[AUDIO_USECASE_MAX] = {
Eric Laurentb23d5282013-05-14 15:27:20 -0700211 [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = "deep-buffer-playback",
212 [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = "low-latency-playback",
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -0700213 [USECASE_AUDIO_PLAYBACK_ULL] = "audio-ull-playback",
214 [USECASE_AUDIO_PLAYBACK_MULTI_CH] = "multi-channel-playback",
Shruthi Krishnaace10852013-10-25 14:32:12 -0700215 [USECASE_AUDIO_PLAYBACK_OFFLOAD] = "compress-offload-playback",
vivek mehta446c3962015-09-14 10:57:35 -0700216 //Enabled for Direct_PCM
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700217 [USECASE_AUDIO_PLAYBACK_OFFLOAD2] = "compress-offload-playback2",
218 [USECASE_AUDIO_PLAYBACK_OFFLOAD3] = "compress-offload-playback3",
219 [USECASE_AUDIO_PLAYBACK_OFFLOAD4] = "compress-offload-playback4",
220 [USECASE_AUDIO_PLAYBACK_OFFLOAD5] = "compress-offload-playback5",
221 [USECASE_AUDIO_PLAYBACK_OFFLOAD6] = "compress-offload-playback6",
222 [USECASE_AUDIO_PLAYBACK_OFFLOAD7] = "compress-offload-playback7",
223 [USECASE_AUDIO_PLAYBACK_OFFLOAD8] = "compress-offload-playback8",
224 [USECASE_AUDIO_PLAYBACK_OFFLOAD9] = "compress-offload-playback9",
vivek mehta0ea887a2015-08-26 14:01:20 -0700225
Eric Laurentb23d5282013-05-14 15:27:20 -0700226 [USECASE_AUDIO_RECORD] = "audio-record",
Mingming Yine62d7842013-10-25 16:26:03 -0700227 [USECASE_AUDIO_RECORD_COMPRESS] = "audio-record-compress",
Dhananjay Kumaree4d2002016-10-25 18:02:58 +0530228 [USECASE_AUDIO_RECORD_COMPRESS2] = "audio-record-compress2",
229 [USECASE_AUDIO_RECORD_COMPRESS3] = "audio-record-compress3",
230 [USECASE_AUDIO_RECORD_COMPRESS4] = "audio-record-compress4",
Eric Laurentb23d5282013-05-14 15:27:20 -0700231 [USECASE_AUDIO_RECORD_LOW_LATENCY] = "low-latency-record",
Preetam Singh Ranawatde84f1a2013-11-01 14:58:16 -0700232 [USECASE_AUDIO_RECORD_FM_VIRTUAL] = "fm-virtual-record",
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700233 [USECASE_AUDIO_PLAYBACK_FM] = "play-fm",
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800234 [USECASE_AUDIO_HFP_SCO] = "hfp-sco",
Vimal Puthanveed47e64852013-12-20 13:23:39 -0800235 [USECASE_AUDIO_HFP_SCO_WB] = "hfp-sco-wb",
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700236 [USECASE_VOICE_CALL] = "voice-call",
Mingming Yin3ee55c62014-08-04 14:23:35 -0700237
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700238 [USECASE_VOICE2_CALL] = "voice2-call",
239 [USECASE_VOLTE_CALL] = "volte-call",
240 [USECASE_QCHAT_CALL] = "qchat-call",
Vicky Sehrawat7e4fc152014-02-12 17:58:59 -0800241 [USECASE_VOWLAN_CALL] = "vowlan-call",
Vidyakumar Athota0e109352015-02-12 17:38:22 -0800242 [USECASE_VOICEMMODE1_CALL] = "voicemmode1-call",
243 [USECASE_VOICEMMODE2_CALL] = "voicemmode2-call",
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800244 [USECASE_COMPRESS_VOIP_CALL] = "compress-voip-call",
Shiv Maliyappanahallida107642013-10-17 11:16:13 -0700245 [USECASE_INCALL_REC_UPLINK] = "incall-rec-uplink",
246 [USECASE_INCALL_REC_DOWNLINK] = "incall-rec-downlink",
247 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK] = "incall-rec-uplink-and-downlink",
Helen Zenge56b4852013-12-03 16:54:40 -0800248 [USECASE_INCALL_REC_UPLINK_COMPRESS] = "incall-rec-uplink-compress",
249 [USECASE_INCALL_REC_DOWNLINK_COMPRESS] = "incall-rec-downlink-compress",
250 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK_COMPRESS] = "incall-rec-uplink-and-downlink-compress",
251
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -0700252 [USECASE_INCALL_MUSIC_UPLINK] = "incall_music_uplink",
253 [USECASE_INCALL_MUSIC_UPLINK2] = "incall_music_uplink2",
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700254 [USECASE_AUDIO_SPKR_CALIB_RX] = "spkr-rx-calib",
255 [USECASE_AUDIO_SPKR_CALIB_TX] = "spkr-vi-record",
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700256
257 [USECASE_AUDIO_PLAYBACK_AFE_PROXY] = "afe-proxy-playback",
258 [USECASE_AUDIO_RECORD_AFE_PROXY] = "afe-proxy-record",
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -0700259 [USECASE_AUDIO_PLAYBACK_EXT_DISP_SILENCE] = "silence-playback",
Eric Laurentb23d5282013-05-14 15:27:20 -0700260};
261
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700262static const audio_usecase_t offload_usecases[] = {
263 USECASE_AUDIO_PLAYBACK_OFFLOAD,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700264 USECASE_AUDIO_PLAYBACK_OFFLOAD2,
265 USECASE_AUDIO_PLAYBACK_OFFLOAD3,
266 USECASE_AUDIO_PLAYBACK_OFFLOAD4,
267 USECASE_AUDIO_PLAYBACK_OFFLOAD5,
268 USECASE_AUDIO_PLAYBACK_OFFLOAD6,
269 USECASE_AUDIO_PLAYBACK_OFFLOAD7,
270 USECASE_AUDIO_PLAYBACK_OFFLOAD8,
271 USECASE_AUDIO_PLAYBACK_OFFLOAD9,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700272};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800273
274#define STRING_TO_ENUM(string) { #string, string }
275
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800276struct string_to_enum {
277 const char *name;
278 uint32_t value;
279};
280
281static const struct string_to_enum out_channels_name_to_enum_table[] = {
282 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
Mingming Yin3a941d42016-02-17 18:08:05 -0800283 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_2POINT1),
284 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_QUAD),
285 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_SURROUND),
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700286 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_PENTA),
Mingming Yin3a941d42016-02-17 18:08:05 -0800287 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1),
288 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_6POINT1),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800289 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
290};
291
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700292static const struct string_to_enum out_formats_name_to_enum_table[] = {
293 STRING_TO_ENUM(AUDIO_FORMAT_AC3),
294 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3),
295 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3_JOC),
Mingming Yin3a941d42016-02-17 18:08:05 -0800296 STRING_TO_ENUM(AUDIO_FORMAT_DTS),
297 STRING_TO_ENUM(AUDIO_FORMAT_DTS_HD),
298};
299
300//list of all supported sample rates by HDMI specification.
301static const int out_hdmi_sample_rates[] = {
302 32000, 44100, 48000, 88200, 96000, 176400, 192000,
303};
304
305static const struct string_to_enum out_hdmi_sample_rates_name_to_enum_table[] = {
306 STRING_TO_ENUM(32000),
307 STRING_TO_ENUM(44100),
308 STRING_TO_ENUM(48000),
309 STRING_TO_ENUM(88200),
310 STRING_TO_ENUM(96000),
311 STRING_TO_ENUM(176400),
312 STRING_TO_ENUM(192000),
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700313};
314
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700315static struct audio_device *adev = NULL;
316static pthread_mutex_t adev_init_lock;
Kiran Kandi910e1862013-10-29 13:29:42 -0700317static unsigned int audio_device_ref_count;
vivek mehtab72d08d2016-04-29 03:16:47 -0700318//cache last MBDRC cal step level
319static int last_known_cal_step = -1 ;
Kiran Kandi910e1862013-10-29 13:29:42 -0700320
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700321static bool may_use_noirq_mode(struct audio_device *adev, audio_usecase_t uc_id,
322 int flags __unused)
323{
324 int dir = 0;
325 switch (uc_id) {
326 case USECASE_AUDIO_RECORD_LOW_LATENCY:
327 dir = 1;
328 case USECASE_AUDIO_PLAYBACK_ULL:
329 break;
330 default:
331 return false;
332 }
333
334 int dev_id = platform_get_pcm_device_id(uc_id, dir == 0 ?
335 PCM_PLAYBACK : PCM_CAPTURE);
336 if (adev->adm_is_noirq_avail)
337 return adev->adm_is_noirq_avail(adev->adm_data,
338 adev->snd_card, dev_id, dir);
339 return false;
340}
341
342static void register_out_stream(struct stream_out *out)
343{
344 struct audio_device *adev = out->dev;
345 if (is_offload_usecase(out->usecase) ||
346 !adev->adm_register_output_stream)
347 return;
348
349 // register stream first for backward compatibility
350 adev->adm_register_output_stream(adev->adm_data,
351 out->handle,
352 out->flags);
353
354 if (!adev->adm_set_config)
355 return;
356
357 if (out->realtime)
358 adev->adm_set_config(adev->adm_data,
359 out->handle,
360 out->pcm, &out->config);
361}
362
363static void register_in_stream(struct stream_in *in)
364{
365 struct audio_device *adev = in->dev;
366 if (!adev->adm_register_input_stream)
367 return;
368
369 adev->adm_register_input_stream(adev->adm_data,
370 in->capture_handle,
371 in->flags);
372
373 if (!adev->adm_set_config)
374 return;
375
376 if (in->realtime)
377 adev->adm_set_config(adev->adm_data,
378 in->capture_handle,
379 in->pcm,
380 &in->config);
381}
382
383static void request_out_focus(struct stream_out *out, long ns)
384{
385 struct audio_device *adev = out->dev;
386
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700387 if (adev->adm_request_focus_v2)
388 adev->adm_request_focus_v2(adev->adm_data, out->handle, ns);
389 else if (adev->adm_request_focus)
390 adev->adm_request_focus(adev->adm_data, out->handle);
391}
392
393static void request_in_focus(struct stream_in *in, long ns)
394{
395 struct audio_device *adev = in->dev;
396
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700397 if (adev->adm_request_focus_v2)
398 adev->adm_request_focus_v2(adev->adm_data, in->capture_handle, ns);
399 else if (adev->adm_request_focus)
400 adev->adm_request_focus(adev->adm_data, in->capture_handle);
401}
402
403static void release_out_focus(struct stream_out *out)
404{
405 struct audio_device *adev = out->dev;
406
407 if (adev->adm_abandon_focus)
408 adev->adm_abandon_focus(adev->adm_data, out->handle);
409}
410
411static void release_in_focus(struct stream_in *in)
412{
413 struct audio_device *adev = in->dev;
414 if (adev->adm_abandon_focus)
415 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
416}
417
vivek mehtaa76401a2015-04-24 14:12:15 -0700418__attribute__ ((visibility ("default")))
419bool audio_hw_send_gain_dep_calibration(int level) {
420 bool ret_val = false;
vivek mehtab72d08d2016-04-29 03:16:47 -0700421 ALOGV("%s: called ...", __func__);
vivek mehtaa76401a2015-04-24 14:12:15 -0700422
423 pthread_mutex_lock(&adev_init_lock);
424
425 if (adev != NULL && adev->platform != NULL) {
426 pthread_mutex_lock(&adev->lock);
427 ret_val = platform_send_gain_dep_cal(adev->platform, level);
vivek mehtab72d08d2016-04-29 03:16:47 -0700428
429 // if cal set fails, cache level info
430 // if cal set succeds, reset known last cal set
431 if (!ret_val)
432 last_known_cal_step = level;
433 else if (last_known_cal_step != -1)
434 last_known_cal_step = -1;
435
vivek mehtaa76401a2015-04-24 14:12:15 -0700436 pthread_mutex_unlock(&adev->lock);
437 } else {
438 ALOGE("%s: %s is NULL", __func__, adev == NULL ? "adev" : "adev->platform");
439 }
440
441 pthread_mutex_unlock(&adev_init_lock);
442
443 return ret_val;
444}
445
Ashish Jain5106d362016-05-11 19:23:33 +0530446static int check_and_set_gapless_mode(struct audio_device *adev, bool enable_gapless)
447{
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800448 bool gapless_enabled = false;
449 const char *mixer_ctl_name = "Compress Gapless Playback";
450 struct mixer_ctl *ctl;
451
452 ALOGV("%s:", __func__);
Ashish Jain5106d362016-05-11 19:23:33 +0530453 gapless_enabled = property_get_bool("audio.offload.gapless.enabled", false);
454
455 /*Disable gapless if its AV playback*/
456 gapless_enabled = gapless_enabled && enable_gapless;
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800457
458 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
459 if (!ctl) {
460 ALOGE("%s: Could not get ctl for mixer cmd - %s",
461 __func__, mixer_ctl_name);
462 return -EINVAL;
463 }
464
465 if (mixer_ctl_set_value(ctl, 0, gapless_enabled) < 0) {
466 ALOGE("%s: Could not set gapless mode %d",
467 __func__, gapless_enabled);
468 return -EINVAL;
469 }
470 return 0;
471}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700472
Aniket Kumar Lataf56b6402016-10-27 12:03:18 -0700473__attribute__ ((visibility ("default")))
474int audio_hw_get_gain_level_mapping(struct amp_db_and_gain_table *mapping_tbl,
475 int table_size) {
476 int ret_val = 0;
477 ALOGV("%s: enter ... ", __func__);
478
479 pthread_mutex_lock(&adev_init_lock);
480 if (adev == NULL) {
481 ALOGW("%s: adev is NULL .... ", __func__);
482 goto done;
483 }
484
485 pthread_mutex_lock(&adev->lock);
486 ret_val = platform_get_gain_level_mapping(mapping_tbl, table_size);
487 pthread_mutex_unlock(&adev->lock);
488done:
489 pthread_mutex_unlock(&adev_init_lock);
490 ALOGV("%s: exit ... ", __func__);
491 return ret_val;
492}
493
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700494static bool is_supported_format(audio_format_t format)
495{
Eric Laurent86e17132013-09-12 17:49:30 -0700496 if (format == AUDIO_FORMAT_MP3 ||
Satish Babu Patakokila0c313922016-12-08 12:07:08 +0530497 format == AUDIO_FORMAT_MP2 ||
Ashish Jainf9b78162014-08-25 20:36:25 +0530498 format == AUDIO_FORMAT_AAC_LC ||
499 format == AUDIO_FORMAT_AAC_HE_V1 ||
500 format == AUDIO_FORMAT_AAC_HE_V2 ||
Manish Dewangana6fc5442015-08-24 20:30:31 +0530501 format == AUDIO_FORMAT_AAC_ADTS_LC ||
502 format == AUDIO_FORMAT_AAC_ADTS_HE_V1 ||
503 format == AUDIO_FORMAT_AAC_ADTS_HE_V2 ||
Arun Kumar Dasari3b174182016-12-27 13:01:14 +0530504 format == AUDIO_FORMAT_AAC_LATM_LC ||
505 format == AUDIO_FORMAT_AAC_LATM_HE_V1 ||
506 format == AUDIO_FORMAT_AAC_LATM_HE_V2 ||
Ashish Jain5106d362016-05-11 19:23:33 +0530507 format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
508 format == AUDIO_FORMAT_PCM_8_24_BIT ||
Ashish Jainf1eaa582016-05-23 20:54:24 +0530509 format == AUDIO_FORMAT_PCM_FLOAT ||
510 format == AUDIO_FORMAT_PCM_32_BIT ||
vivek mehta0ea887a2015-08-26 14:01:20 -0700511 format == AUDIO_FORMAT_PCM_16_BIT ||
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530512 format == AUDIO_FORMAT_AC3 ||
513 format == AUDIO_FORMAT_E_AC3 ||
514 format == AUDIO_FORMAT_DTS ||
515 format == AUDIO_FORMAT_DTS_HD ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800516 format == AUDIO_FORMAT_FLAC ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530517 format == AUDIO_FORMAT_ALAC ||
518 format == AUDIO_FORMAT_APE ||
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +0530519 format == AUDIO_FORMAT_DSD ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530520 format == AUDIO_FORMAT_VORBIS ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800521 format == AUDIO_FORMAT_WMA ||
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +0530522 format == AUDIO_FORMAT_WMA_PRO ||
523 format == AUDIO_FORMAT_APTX)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800524 return true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700525
526 return false;
527}
528
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700529static inline bool is_mmap_usecase(audio_usecase_t uc_id)
530{
531 return (uc_id == USECASE_AUDIO_RECORD_AFE_PROXY) ||
532 (uc_id == USECASE_AUDIO_PLAYBACK_AFE_PROXY);
533}
534
Venkata Narendra Kumar Guttaed0f94f2014-07-09 16:29:28 +0530535int get_snd_card_state(struct audio_device *adev)
Naresh Tanniru80659832014-06-04 18:17:56 +0530536{
537 int snd_scard_state;
538
539 if (!adev)
540 return SND_CARD_STATE_OFFLINE;
541
542 pthread_mutex_lock(&adev->snd_card_status.lock);
543 snd_scard_state = adev->snd_card_status.state;
544 pthread_mutex_unlock(&adev->snd_card_status.lock);
545
546 return snd_scard_state;
547}
548
549static int set_snd_card_state(struct audio_device *adev, int snd_scard_state)
550{
551 if (!adev)
552 return -ENOSYS;
553
554 pthread_mutex_lock(&adev->snd_card_status.lock);
Ben Rombergerfeca4b82015-07-07 20:40:44 -0700555 if (adev->snd_card_status.state != snd_scard_state) {
556 adev->snd_card_status.state = snd_scard_state;
557 platform_snd_card_update(adev->platform, snd_scard_state);
558 }
Naresh Tanniru80659832014-06-04 18:17:56 +0530559 pthread_mutex_unlock(&adev->snd_card_status.lock);
560
561 return 0;
562}
563
Avinash Vaish71a8b972014-07-24 15:36:33 +0530564static int enable_audio_route_for_voice_usecases(struct audio_device *adev,
565 struct audio_usecase *uc_info)
566{
567 struct listnode *node;
568 struct audio_usecase *usecase;
569
570 if (uc_info == NULL)
571 return -EINVAL;
572
573 /* Re-route all voice usecases on the shared backend other than the
574 specified usecase to new snd devices */
575 list_for_each(node, &adev->usecase_list) {
576 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800577 if ((usecase->type == VOICE_CALL) && (usecase != uc_info))
Avinash Vaish71a8b972014-07-24 15:36:33 +0530578 enable_audio_route(adev, usecase);
579 }
580 return 0;
581}
582
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530583static void enable_asrc_mode(struct audio_device *adev)
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530584{
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530585 ALOGV("%s", __func__);
586 audio_route_apply_and_update_path(adev->audio_route,
587 "asrc-mode");
588 adev->asrc_mode_enabled = true;
589}
590
591static void disable_asrc_mode(struct audio_device *adev)
592{
593 ALOGV("%s", __func__);
594 audio_route_reset_and_update_path(adev->audio_route,
595 "asrc-mode");
596 adev->asrc_mode_enabled = false;
597}
598
599/*
600 * - Enable ASRC mode for incoming mix path use case(Headphone backend)if Headphone
601 * 44.1 or Native DSD backends are enabled for any of current use case.
602 * e.g. 48-> + (Naitve DSD or Headphone 44.1)
603 * - Disable current mix path use case(Headphone backend) and re-enable it with
604 * ASRC mode for incoming Headphone 44.1 or Native DSD use case.
605 * e.g. Naitve DSD or Headphone 44.1 -> + 48
606 */
607static void check_and_set_asrc_mode(struct audio_device *adev, snd_device_t snd_device)
608{
609 ALOGV("%s snd device %d", __func__, snd_device);
610 int new_backend_idx = platform_get_backend_index(snd_device);
611
612 if (((new_backend_idx == HEADPHONE_BACKEND) ||
613 (new_backend_idx == HEADPHONE_44_1_BACKEND) ||
614 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
615 !adev->asrc_mode_enabled) {
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530616 struct listnode *node = NULL;
617 struct audio_usecase *uc = NULL;
618 struct stream_out *curr_out = NULL;
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530619 int usecase_backend_idx = DEFAULT_CODEC_BACKEND;
Garmond Leung50058f62017-02-08 09:49:30 -0800620 int i, num_devices, ret = 0;
621 snd_device_t split_snd_devices[SND_DEVICE_OUT_END];
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530622
623 list_for_each(node, &adev->usecase_list) {
624 uc = node_to_item(node, struct audio_usecase, list);
625 curr_out = (struct stream_out*) uc->stream.out;
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530626
Garmond Leung50058f62017-02-08 09:49:30 -0800627 if (curr_out && PCM_PLAYBACK == uc->type) {
628 ret = platform_split_snd_device(adev->platform,
629 uc->out_snd_device,
630 &num_devices,
631 split_snd_devices);
632 if (ret < 0 || num_devices == 0) {
633 ALOGV("%s: Unable to split uc->out_snd_device: %d",__func__, uc->out_snd_device);
634 split_snd_devices[0] = uc->out_snd_device;
635 num_devices = 1;
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530636 }
Garmond Leung50058f62017-02-08 09:49:30 -0800637 for (i = 0; i < num_devices; i++) {
638 usecase_backend_idx = platform_get_backend_index(split_snd_devices[i]);
639 ALOGD("%s:snd_dev %d usecase_backend_idx %d",__func__, split_snd_devices[i],usecase_backend_idx);
640 if((new_backend_idx == HEADPHONE_BACKEND) &&
641 ((usecase_backend_idx == HEADPHONE_44_1_BACKEND) ||
642 (usecase_backend_idx == DSD_NATIVE_BACKEND))) {
643 ALOGD("%s:DSD or native stream detected enabling asrcmode in hardware",
644 __func__);
645 enable_asrc_mode(adev);
646 break;
647 } else if(((new_backend_idx == HEADPHONE_44_1_BACKEND) ||
648 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
649 (usecase_backend_idx == HEADPHONE_BACKEND)) {
650 ALOGD("%s:48K stream detected, disabling and enabling it with asrcmode in hardware",
651 __func__);
652 disable_audio_route(adev, uc);
653 disable_snd_device(adev, uc->out_snd_device);
654 // Apply true-high-quality-mode if DSD or > 44.1KHz or >=24-bit
655 if (new_backend_idx == DSD_NATIVE_BACKEND)
656 audio_route_apply_and_update_path(adev->audio_route,
657 "hph-true-highquality-mode");
658 else if ((new_backend_idx == HEADPHONE_44_1_BACKEND) &&
659 (curr_out->bit_width >= 24))
660 audio_route_apply_and_update_path(adev->audio_route,
661 "hph-highquality-mode");
662 enable_asrc_mode(adev);
663 enable_snd_device(adev, uc->out_snd_device);
664 enable_audio_route(adev, uc);
665 break;
666 }
667 }
668 // reset split devices count
669 num_devices = 0;
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530670 }
Garmond Leung50058f62017-02-08 09:49:30 -0800671 if (adev->asrc_mode_enabled)
672 break;
673
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530674 }
675 }
676}
677
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -0700678int pcm_ioctl(struct pcm *pcm, int request, ...)
679{
680 va_list ap;
681 void * arg;
682 int pcm_fd = *(int*)pcm;
683
684 va_start(ap, request);
685 arg = va_arg(ap, void *);
686 va_end(ap);
687
688 return ioctl(pcm_fd, request, arg);
689}
690
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700691int enable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700692 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800693{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700694 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700695 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800696
697 if (usecase == NULL)
698 return -EINVAL;
699
700 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
701
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800702 if (usecase->type == PCM_CAPTURE)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700703 snd_device = usecase->in_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800704 else
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700705 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800706
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -0800707#ifdef DS1_DOLBY_DAP_ENABLED
708 audio_extn_dolby_set_dmid(adev);
709 audio_extn_dolby_set_endpoint(adev);
710#endif
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700711 audio_extn_dolby_ds2_set_endpoint(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700712 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530713 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_BUSY);
Ben Romberger1fafdde2015-09-09 19:43:15 -0700714 audio_extn_utils_send_app_type_cfg(adev, usecase);
Dhananjay Kumar14170dd2015-08-28 13:24:16 +0530715 audio_extn_utils_send_audio_calibration(adev, usecase);
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -0800716 strlcpy(mixer_path, use_case_table[usecase->id], MIXER_PATH_MAX_LENGTH);
Banajit Goswami20cdd212015-09-11 01:11:30 -0700717 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700718 ALOGD("%s: apply mixer and update path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700719 audio_route_apply_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800720 ALOGV("%s: exit", __func__);
721 return 0;
722}
723
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700724int disable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700725 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800726{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700727 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700728 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800729
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +0530730 if (usecase == NULL || usecase->id == USECASE_INVALID)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800731 return -EINVAL;
732
733 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700734 if (usecase->type == PCM_CAPTURE)
735 snd_device = usecase->in_snd_device;
736 else
737 snd_device = usecase->out_snd_device;
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -0800738 strlcpy(mixer_path, use_case_table[usecase->id], MIXER_PATH_MAX_LENGTH);
Banajit Goswami20cdd212015-09-11 01:11:30 -0700739 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700740 ALOGD("%s: reset and update mixer path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700741 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700742 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530743 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_FREE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800744 ALOGV("%s: exit", __func__);
745 return 0;
746}
747
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700748int enable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700749 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800750{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530751 int i, num_devices = 0;
752 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700753 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
754
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800755 if (snd_device < SND_DEVICE_MIN ||
756 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800757 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800758 return -EINVAL;
759 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700760
761 adev->snd_dev_ref_cnt[snd_device]++;
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700762
763 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
764 ALOGE("%s: Invalid sound device returned", __func__);
765 return -EINVAL;
766 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700767 if (adev->snd_dev_ref_cnt[snd_device] > 1) {
Eric Laurent994a6932013-07-17 11:51:42 -0700768 ALOGV("%s: snd_device(%d: %s) is already active",
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700769 __func__, snd_device, device_name);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700770 return 0;
771 }
772
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530773
Gopikrishnaiah Anandane85d0462014-06-30 21:41:20 -0700774 if (audio_extn_spkr_prot_is_enabled())
775 audio_extn_spkr_prot_calib_cancel(adev);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700776
Xiaojun Sang040cc9f2015-08-03 19:38:28 +0800777 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
778 audio_extn_spkr_prot_is_enabled()) {
779 if (platform_get_spkr_prot_acdb_id(snd_device) < 0) {
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700780 adev->snd_dev_ref_cnt[snd_device]--;
781 return -EINVAL;
782 }
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200783 audio_extn_dev_arbi_acquire(snd_device);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -0800784 if (audio_extn_spkr_prot_start_processing(snd_device)) {
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800785 ALOGE("%s: spkr_start_processing failed", __func__);
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200786 audio_extn_dev_arbi_release(snd_device);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800787 return -EINVAL;
788 }
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -0700789 } else if (platform_split_snd_device(adev->platform,
790 snd_device,
791 &num_devices,
792 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530793 for (i = 0; i < num_devices; i++) {
794 enable_snd_device(adev, new_snd_devices[i]);
795 }
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -0800796 } else {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700797 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tannirucd2353e2016-08-19 00:37:25 +0530798
Preetam Singh Ranawatf1d417c2017-01-10 17:00:32 +0530799 if (platform_check_codec_asrc_support(adev->platform))
800 check_and_set_asrc_mode(adev, snd_device);
801
Naresh Tannirucd2353e2016-08-19 00:37:25 +0530802 if ((SND_DEVICE_OUT_BT_A2DP == snd_device) &&
803 (audio_extn_a2dp_start_playback() < 0)) {
804 ALOGE(" fail to configure A2dp control path ");
805 return -EINVAL;
806 }
807
Bharath Ramachandramurthy0de16782014-03-28 21:34:33 -0700808 /* due to the possibility of calibration overwrite between listen
809 and audio, notify listen hal before audio calibration is sent */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700810 audio_extn_sound_trigger_update_device_status(snd_device,
811 ST_EVENT_SND_DEVICE_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530812 audio_extn_listen_update_device_status(snd_device,
813 LISTEN_EVENT_SND_DEVICE_BUSY);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -0700814 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700815 adev->snd_dev_ref_cnt[snd_device]--;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700816 audio_extn_sound_trigger_update_device_status(snd_device,
817 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530818 audio_extn_listen_update_device_status(snd_device,
819 LISTEN_EVENT_SND_DEVICE_FREE);
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700820 return -EINVAL;
821 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300822 audio_extn_dev_arbi_acquire(snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700823 audio_route_apply_and_update_path(adev->audio_route, device_name);
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530824
825 if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
826 !adev->native_playback_enabled &&
827 audio_is_true_native_stream_active(adev)) {
828 ALOGD("%s: %d: napb: enabling native mode in hardware",
829 __func__, __LINE__);
830 audio_route_apply_and_update_path(adev->audio_route,
831 "true-native-mode");
832 adev->native_playback_enabled = true;
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530833 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800834 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800835 return 0;
836}
837
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700838int disable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -0700839 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800840{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530841 int i, num_devices = 0;
842 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700843 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
844
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800845 if (snd_device < SND_DEVICE_MIN ||
846 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800847 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800848 return -EINVAL;
849 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700850 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
851 ALOGE("%s: device ref cnt is already 0", __func__);
852 return -EINVAL;
853 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700854
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700855 adev->snd_dev_ref_cnt[snd_device]--;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700856
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700857 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
858 ALOGE("%s: Invalid sound device returned", __func__);
859 return -EINVAL;
860 }
861
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700862 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -0700863 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tanniru9d027a62015-03-13 01:32:10 +0530864
Xiaojun Sang040cc9f2015-08-03 19:38:28 +0800865 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
866 audio_extn_spkr_prot_is_enabled()) {
Anish Kumar46c7b872014-09-09 01:49:44 -0700867 audio_extn_spkr_prot_stop_processing(snd_device);
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -0700868 } else if (platform_split_snd_device(adev->platform,
869 snd_device,
870 &num_devices,
871 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +0530872 for (i = 0; i < num_devices; i++) {
873 disable_snd_device(adev, new_snd_devices[i]);
874 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300875 } else {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -0700876 audio_route_reset_and_update_path(adev->audio_route, device_name);
Lior Barenboim0b61bc72014-05-13 13:01:37 +0300877 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700878
Naresh Tannirucd2353e2016-08-19 00:37:25 +0530879 if (SND_DEVICE_OUT_BT_A2DP == snd_device)
880 audio_extn_a2dp_stop_playback();
881
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -0700882 if (snd_device == SND_DEVICE_OUT_HDMI || snd_device == SND_DEVICE_OUT_DISPLAY_PORT)
Ashish Jain81eb2a82015-05-13 10:52:34 +0530883 adev->is_channel_status_set = false;
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530884 else if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
885 adev->native_playback_enabled) {
886 ALOGD("%s: %d: napb: disabling native mode in hardware",
887 __func__, __LINE__);
888 audio_route_reset_and_update_path(adev->audio_route,
889 "true-native-mode");
890 adev->native_playback_enabled = false;
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530891 } else if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
892 adev->asrc_mode_enabled) {
893 ALOGD("%s: %d: disabling asrc mode in hardware", __func__, __LINE__);
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530894 disable_asrc_mode(adev);
895 audio_route_apply_and_update_path(adev->audio_route, "hph-lowpower-mode");
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +0530896 }
Ashish Jain81eb2a82015-05-13 10:52:34 +0530897
Ravit Dennisaaee49c2015-02-04 21:26:22 +0200898 audio_extn_dev_arbi_release(snd_device);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -0700899 audio_extn_sound_trigger_update_device_status(snd_device,
900 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +0530901 audio_extn_listen_update_device_status(snd_device,
Kiran Kandide144c82013-11-20 15:58:32 -0800902 LISTEN_EVENT_SND_DEVICE_FREE);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700903 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700904
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800905 return 0;
906}
907
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -0700908/*
909 legend:
910 uc - existing usecase
911 new_uc - new usecase
912 d1, d11, d2 - SND_DEVICE enums
913 a1, a2 - corresponding ANDROID device enums
914 B1, B2 - backend strings
915
916case 1
917 uc->dev d1 (a1) B1
918 new_uc->dev d1 (a1), d2 (a2) B1, B2
919
920 resolution: disable and enable uc->dev on d1
921
922case 2
923 uc->dev d1 (a1) B1
924 new_uc->dev d11 (a1) B1
925
926 resolution: need to switch uc since d1 and d11 are related
927 (e.g. speaker and voice-speaker)
928 use ANDROID_DEVICE_OUT enums to match devices since SND_DEVICE enums may vary
929
930case 3
931 uc->dev d1 (a1) B1
932 new_uc->dev d2 (a2) B2
933
934 resolution: no need to switch uc
935
936case 4
937 uc->dev d1 (a1) B1
938 new_uc->dev d2 (a2) B1
939
940 resolution: disable enable uc-dev on d2 since backends match
941 we cannot enable two streams on two different devices if they
942 share the same backend. e.g. if offload is on speaker device using
943 QUAD_MI2S backend and a low-latency stream is started on voice-handset
944 using the same backend, offload must also be switched to voice-handset.
945
946case 5
947 uc->dev d1 (a1) B1
948 new_uc->dev d1 (a1), d2 (a2) B1
949
950 resolution: disable enable uc-dev on d2 since backends match
951 we cannot enable two streams on two different devices if they
952 share the same backend.
953
954case 6
955 uc->dev d1 (a1) B1
956 new_uc->dev d2 (a1) B2
957
958 resolution: no need to switch
959
960case 7
961 uc->dev d1 (a1), d2 (a2) B1, B2
962 new_uc->dev d1 (a1) B1
963
964 resolution: no need to switch
965
966*/
967static snd_device_t derive_playback_snd_device(void * platform,
968 struct audio_usecase *uc,
969 struct audio_usecase *new_uc,
970 snd_device_t new_snd_device)
971{
972 audio_devices_t a1 = uc->stream.out->devices;
973 audio_devices_t a2 = new_uc->stream.out->devices;
974
975 snd_device_t d1 = uc->out_snd_device;
976 snd_device_t d2 = new_snd_device;
977
978 // Treat as a special case when a1 and a2 are not disjoint
979 if ((a1 != a2) && (a1 & a2)) {
980 snd_device_t d3[2];
981 int num_devices = 0;
982 int ret = platform_split_snd_device(platform,
983 popcount(a1) > 1 ? d1 : d2,
984 &num_devices,
985 d3);
986 if (ret < 0) {
987 if (ret != -ENOSYS) {
988 ALOGW("%s failed to split snd_device %d",
989 __func__,
990 popcount(a1) > 1 ? d1 : d2);
991 }
992 goto end;
993 }
994
995 // NB: case 7 is hypothetical and isn't a practical usecase yet.
996 // But if it does happen, we need to give priority to d2 if
997 // the combo devices active on the existing usecase share a backend.
998 // This is because we cannot have a usecase active on a combo device
999 // and a new usecase requests one device in this combo pair.
1000 if (platform_check_backends_match(d3[0], d3[1])) {
1001 return d2; // case 5
1002 } else {
1003 return d1; // case 1
1004 }
1005 } else {
1006 if (platform_check_backends_match(d1, d2)) {
1007 return d2; // case 2, 4
1008 } else {
1009 return d1; // case 6, 3
1010 }
1011 }
1012
1013end:
1014 return d2; // return whatever was calculated before.
1015}
1016
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001017static void check_usecases_codec_backend(struct audio_device *adev,
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301018 struct audio_usecase *uc_info,
1019 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001020{
1021 struct listnode *node;
1022 struct audio_usecase *usecase;
1023 bool switch_device[AUDIO_USECASE_MAX];
1024 int i, num_uc_to_switch = 0;
kunleiz5cd52b82016-11-07 17:22:52 +08001025 int status = 0;
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301026 bool force_restart_session = false;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001027 /*
1028 * This function is to make sure that all the usecases that are active on
1029 * the hardware codec backend are always routed to any one device that is
1030 * handled by the hardware codec.
1031 * For example, if low-latency and deep-buffer usecases are currently active
1032 * on speaker and out_set_parameters(headset) is received on low-latency
1033 * output, then we have to make sure deep-buffer is also switched to headset,
1034 * because of the limitation that both the devices cannot be enabled
1035 * at the same time as they share the same backend.
1036 */
Mingming Yin3ee55c62014-08-04 14:23:35 -07001037 /*
1038 * This call is to check if we need to force routing for a particular stream
1039 * If there is a backend configuration change for the device when a
1040 * new stream starts, then ADM needs to be closed and re-opened with the new
1041 * configuraion. This call check if we need to re-route all the streams
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001042 * associated with the backend. Touch tone + 24 bit + native playback.
Mingming Yin3ee55c62014-08-04 14:23:35 -07001043 */
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001044 bool force_routing = platform_check_and_set_codec_backend_cfg(adev, uc_info,
1045 snd_device);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301046 /* For a2dp device reconfigure all active sessions
1047 * with new AFE encoder format based on a2dp state
1048 */
1049 if ((SND_DEVICE_OUT_BT_A2DP == snd_device ||
1050 SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP == snd_device) &&
1051 audio_extn_a2dp_is_force_device_switch()) {
1052 force_routing = true;
1053 force_restart_session = true;
1054 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301055 ALOGD("%s:becf: force routing %d", __func__, force_routing);
1056
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001057 /* Disable all the usecases on the shared backend other than the
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001058 * specified usecase.
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001059 */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001060 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1061 switch_device[i] = false;
1062
1063 list_for_each(node, &adev->usecase_list) {
1064 usecase = node_to_item(node, struct audio_usecase, list);
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001065
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301066 ALOGD("%s:becf: (%d) check_usecases curr device: %s, usecase device:%s "
1067 "backends match %d",__func__, i,
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301068 platform_get_snd_device_name(snd_device),
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301069 platform_get_snd_device_name(usecase->out_snd_device),
1070 platform_check_backends_match(snd_device, usecase->out_snd_device));
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001071 if (usecase->type != PCM_CAPTURE &&
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301072 usecase != uc_info &&
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001073 (derive_playback_snd_device(adev->platform,
1074 usecase, uc_info,
1075 snd_device) != usecase->out_snd_device || force_routing) &&
Ashish Jaind84fd6a2016-07-27 12:33:25 +05301076 ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1077 (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) ||
Ashish Jainb26edfb2016-08-25 00:10:11 +05301078 (usecase->devices & AUDIO_DEVICE_OUT_USB_DEVICE) ||
Ashish Jainc597d102016-12-12 10:31:34 +05301079 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP) ||
1080 (usecase->devices & AUDIO_DEVICE_OUT_ALL_SCO)) &&
1081 ((force_restart_session) ||
1082 (platform_check_backends_match(snd_device, usecase->out_snd_device)))) {
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301083
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301084 ALOGD("%s:becf: check_usecases (%s) is active on (%s) - disabling ..",
1085 __func__, use_case_table[usecase->id],
1086 platform_get_snd_device_name(usecase->out_snd_device));
1087 disable_audio_route(adev, usecase);
1088 switch_device[usecase->id] = true;
1089 num_uc_to_switch++;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001090 }
1091 }
1092
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301093 ALOGD("%s:becf: check_usecases num.of Usecases to switch %d", __func__,
1094 num_uc_to_switch);
1095
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001096 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001097 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001098
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301099 /* Make sure the previous devices to be disabled first and then enable the
1100 selected devices */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001101 list_for_each(node, &adev->usecase_list) {
1102 usecase = node_to_item(node, struct audio_usecase, list);
1103 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001104 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001105 }
1106 }
1107
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001108 list_for_each(node, &adev->usecase_list) {
1109 usecase = node_to_item(node, struct audio_usecase, list);
1110 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001111 enable_snd_device(adev, snd_device);
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001112 }
1113 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001114
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001115 /* Re-route all the usecases on the shared backend other than the
1116 specified usecase to new snd devices */
1117 list_for_each(node, &adev->usecase_list) {
1118 usecase = node_to_item(node, struct audio_usecase, list);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301119 /* Update the out_snd_device only before enabling the audio route */
1120 if (switch_device[usecase->id]) {
1121 usecase->out_snd_device = snd_device;
1122 if (usecase->type != VOICE_CALL) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301123 ALOGD("%s:becf: enabling usecase (%s) on (%s)", __func__,
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301124 use_case_table[usecase->id],
1125 platform_get_snd_device_name(usecase->out_snd_device));
kunleiz5cd52b82016-11-07 17:22:52 +08001126 /* Update voc calibration before enabling VoIP route */
1127 if (usecase->type == VOIP_CALL)
1128 status = platform_switch_voice_call_device_post(adev->platform,
1129 usecase->out_snd_device,
kunleizab514ca2017-01-09 14:59:50 +08001130 platform_get_input_snd_device(adev->platform, uc_info->devices));
Avinash Vaish71a8b972014-07-24 15:36:33 +05301131 enable_audio_route(adev, usecase);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301132 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001133 }
1134 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001135 }
1136}
1137
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301138static void check_usecases_capture_codec_backend(struct audio_device *adev,
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001139 struct audio_usecase *uc_info,
1140 snd_device_t snd_device)
1141{
1142 struct listnode *node;
1143 struct audio_usecase *usecase;
1144 bool switch_device[AUDIO_USECASE_MAX];
1145 int i, num_uc_to_switch = 0;
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301146 int backend_check_cond = AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND;
kunleiz5cd52b82016-11-07 17:22:52 +08001147 int status = 0;
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001148
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301149 bool force_routing = platform_check_and_set_capture_codec_backend_cfg(adev, uc_info,
1150 snd_device);
1151 ALOGD("%s:becf: force routing %d", __func__, force_routing);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301152
1153 /*
1154 * Make sure out devices is checked against out codec backend device and
1155 * also in devices against in codec backend. Checking out device against in
1156 * codec backend or vice versa causes issues.
1157 */
1158 if (uc_info->type == PCM_CAPTURE)
1159 backend_check_cond = AUDIO_DEVICE_IN_ALL_CODEC_BACKEND;
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001160 /*
1161 * This function is to make sure that all the active capture usecases
1162 * are always routed to the same input sound device.
1163 * For example, if audio-record and voice-call usecases are currently
1164 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
1165 * is received for voice call then we have to make sure that audio-record
1166 * usecase is also switched to earpiece i.e. voice-dmic-ef,
1167 * because of the limitation that two devices cannot be enabled
1168 * at the same time if they share the same backend.
1169 */
1170 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1171 switch_device[i] = false;
1172
1173 list_for_each(node, &adev->usecase_list) {
1174 usecase = node_to_item(node, struct audio_usecase, list);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301175 /*
1176 * TODO: Enhance below condition to handle BT sco/USB multi recording
1177 */
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001178 if (usecase->type != PCM_PLAYBACK &&
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001179 usecase != uc_info &&
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301180 (usecase->in_snd_device != snd_device || force_routing) &&
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301181 ((uc_info->devices & backend_check_cond) &&
Karthik Reddy Katta0d471762015-08-20 13:36:07 +05301182 (((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND) ||
kunleiz303ff1a2016-03-15 17:40:20 +08001183 (usecase->type == VOICE_CALL) || (usecase->type == VOIP_CALL))) &&
Anish Kumara020a7c2014-10-17 11:13:22 -07001184 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001185 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
1186 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -07001187 platform_get_snd_device_name(usecase->in_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001188 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001189 switch_device[usecase->id] = true;
1190 num_uc_to_switch++;
1191 }
1192 }
1193
1194 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001195 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001196
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301197 /* Make sure the previous devices to be disabled first and then enable the
1198 selected devices */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001199 list_for_each(node, &adev->usecase_list) {
1200 usecase = node_to_item(node, struct audio_usecase, list);
1201 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001202 disable_snd_device(adev, usecase->in_snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001203 }
1204 }
1205
1206 list_for_each(node, &adev->usecase_list) {
1207 usecase = node_to_item(node, struct audio_usecase, list);
1208 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001209 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001210 }
1211 }
1212
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001213 /* Re-route all the usecases on the shared backend other than the
1214 specified usecase to new snd devices */
1215 list_for_each(node, &adev->usecase_list) {
1216 usecase = node_to_item(node, struct audio_usecase, list);
1217 /* Update the in_snd_device only before enabling the audio route */
1218 if (switch_device[usecase->id] ) {
1219 usecase->in_snd_device = snd_device;
kunleiz5cd52b82016-11-07 17:22:52 +08001220 if (usecase->type != VOICE_CALL) {
1221 /* Update voc calibration before enabling VoIP route */
1222 if (usecase->type == VOIP_CALL)
1223 status = platform_switch_voice_call_device_post(adev->platform,
1224 usecase->out_snd_device,
1225 usecase->in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05301226 enable_audio_route(adev, usecase);
kunleiz5cd52b82016-11-07 17:22:52 +08001227 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001228 }
1229 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001230 }
1231}
1232
Mingming Yin3a941d42016-02-17 18:08:05 -08001233static void reset_hdmi_sink_caps(struct stream_out *out) {
1234 int i = 0;
1235
1236 for (i = 0; i<= MAX_SUPPORTED_CHANNEL_MASKS; i++) {
1237 out->supported_channel_masks[i] = 0;
1238 }
1239 for (i = 0; i<= MAX_SUPPORTED_FORMATS; i++) {
1240 out->supported_formats[i] = 0;
1241 }
1242 for (i = 0; i<= MAX_SUPPORTED_SAMPLE_RATES; i++) {
1243 out->supported_sample_rates[i] = 0;
1244 }
1245}
1246
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001247/* must be called with hw device mutex locked */
Mingming Yin3a941d42016-02-17 18:08:05 -08001248static int read_hdmi_sink_caps(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001249{
Mingming Yin3a941d42016-02-17 18:08:05 -08001250 int ret = 0, i = 0, j = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07001251 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001252
Mingming Yin3a941d42016-02-17 18:08:05 -08001253 reset_hdmi_sink_caps(out);
1254
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001255 /* Cache ext disp type */
Garmond Leung37850ab2016-10-06 11:42:18 -07001256 if (platform_get_ext_disp_type(adev->platform) <= 0) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001257 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Garmond Leung37850ab2016-10-06 11:42:18 -07001258 return -EINVAL;
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001259 }
1260
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001261 switch (channels) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001262 case 8:
Mingming Yin3a941d42016-02-17 18:08:05 -08001263 ALOGV("%s: HDMI supports 7.1 channels", __func__);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001264 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_7POINT1;
Mingming Yin3a941d42016-02-17 18:08:05 -08001265 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_6POINT1;
1266 case 6:
1267 ALOGV("%s: HDMI supports 5.1 channels", __func__);
1268 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
1269 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
1270 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
1271 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_SURROUND;
1272 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_2POINT1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001273 break;
1274 default:
Mingming Yin3a941d42016-02-17 18:08:05 -08001275 ALOGE("invalid/nonstandard channal count[%d]",channels);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001276 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001277 break;
1278 }
Mingming Yin3a941d42016-02-17 18:08:05 -08001279
1280 // check channel format caps
1281 i = 0;
1282 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_AC3)) {
1283 ALOGV(":%s HDMI supports AC3/EAC3 formats", __func__);
1284 out->supported_formats[i++] = AUDIO_FORMAT_AC3;
1285 //Adding EAC3/EAC3_JOC formats if AC3 is supported by the sink.
1286 //EAC3/EAC3_JOC will be converted to AC3 for decoding if needed
1287 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3;
1288 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3_JOC;
1289 }
1290
1291 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DTS)) {
1292 ALOGV(":%s HDMI supports DTS format", __func__);
1293 out->supported_formats[i++] = AUDIO_FORMAT_DTS;
1294 }
1295
1296 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DTS_HD)) {
1297 ALOGV(":%s HDMI supports DTS HD format", __func__);
1298 out->supported_formats[i++] = AUDIO_FORMAT_DTS_HD;
1299 }
1300
1301
1302 // check sample rate caps
1303 i = 0;
1304 for (j = 0; j < MAX_SUPPORTED_SAMPLE_RATES; j++) {
1305 if (platform_is_edid_supported_sample_rate(out->dev->platform, out_hdmi_sample_rates[j])) {
1306 ALOGV(":%s HDMI supports sample rate:%d", __func__, out_hdmi_sample_rates[j]);
1307 out->supported_sample_rates[i++] = out_hdmi_sample_rates[j];
1308 }
1309 }
1310
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001311 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001312}
1313
Alexy Josephb1379942016-01-29 15:49:38 -08001314audio_usecase_t get_usecase_id_from_usecase_type(const struct audio_device *adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001315 usecase_type_t type)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001316{
1317 struct audio_usecase *usecase;
1318 struct listnode *node;
1319
1320 list_for_each(node, &adev->usecase_list) {
1321 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001322 if (usecase->type == type) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001323 ALOGV("%s: usecase id %d", __func__, usecase->id);
1324 return usecase->id;
1325 }
1326 }
1327 return USECASE_INVALID;
1328}
1329
Alexy Josephb1379942016-01-29 15:49:38 -08001330struct audio_usecase *get_usecase_from_list(const struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001331 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001332{
1333 struct audio_usecase *usecase;
1334 struct listnode *node;
1335
1336 list_for_each(node, &adev->usecase_list) {
1337 usecase = node_to_item(node, struct audio_usecase, list);
1338 if (usecase->id == uc_id)
1339 return usecase;
1340 }
1341 return NULL;
1342}
1343
Dhananjay Kumard4833242016-10-06 22:09:12 +05301344struct stream_in *get_next_active_input(const struct audio_device *adev)
1345{
1346 struct audio_usecase *usecase;
1347 struct listnode *node;
1348
1349 list_for_each_reverse(node, &adev->usecase_list) {
1350 usecase = node_to_item(node, struct audio_usecase, list);
1351 if (usecase->type == PCM_CAPTURE)
1352 return usecase->stream.in;
1353 }
1354 return NULL;
1355}
1356
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301357/*
1358 * is a true native playback active
1359 */
1360bool audio_is_true_native_stream_active(struct audio_device *adev)
1361{
1362 bool active = false;
1363 int i = 0;
1364 struct listnode *node;
1365
1366 if (NATIVE_AUDIO_MODE_TRUE_44_1 != platform_get_native_support()) {
1367 ALOGV("%s:napb: not in true mode or non hdphones device",
1368 __func__);
1369 active = false;
1370 goto exit;
1371 }
1372
1373 list_for_each(node, &adev->usecase_list) {
1374 struct audio_usecase *uc;
1375 uc = node_to_item(node, struct audio_usecase, list);
1376 struct stream_out *curr_out =
1377 (struct stream_out*) uc->stream.out;
1378
1379 if (curr_out && PCM_PLAYBACK == uc->type) {
1380 ALOGD("%s:napb: (%d) (%s)id (%d) sr %d bw "
1381 "(%d) device %s", __func__, i++, use_case_table[uc->id],
1382 uc->id, curr_out->sample_rate,
1383 curr_out->bit_width,
1384 platform_get_snd_device_name(uc->out_snd_device));
1385
1386 if (is_offload_usecase(uc->id) &&
1387 (curr_out->sample_rate == OUTPUT_SAMPLING_RATE_44100)) {
1388 active = true;
1389 ALOGD("%s:napb:native stream detected", __func__);
1390 }
1391 }
1392 }
1393exit:
1394 return active;
1395}
1396
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05301397/*
1398 * if native DSD playback active
1399 */
1400bool audio_is_dsd_native_stream_active(struct audio_device *adev)
1401{
1402 bool active = false;
1403 struct listnode *node = NULL;
1404 struct audio_usecase *uc = NULL;
1405 struct stream_out *curr_out = NULL;
1406
1407 list_for_each(node, &adev->usecase_list) {
1408 uc = node_to_item(node, struct audio_usecase, list);
1409 curr_out = (struct stream_out*) uc->stream.out;
1410
1411 if (curr_out && PCM_PLAYBACK == uc->type &&
1412 (DSD_NATIVE_BACKEND == platform_get_backend_index(uc->out_snd_device))) {
1413 active = true;
1414 ALOGV("%s:DSD playback is active", __func__);
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05301415 break;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05301416 }
1417 }
1418 return active;
1419}
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301420
1421static bool force_device_switch(struct audio_usecase *usecase)
1422{
1423 bool ret = false;
1424 bool is_it_true_mode = false;
1425
1426 if (is_offload_usecase(usecase->id) &&
1427 (usecase->stream.out) &&
Xiaojun Sang869f2012016-02-23 16:33:07 +08001428 (usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) &&
1429 (usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADSET ||
1430 usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADPHONE)) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301431 is_it_true_mode = (NATIVE_AUDIO_MODE_TRUE_44_1 == platform_get_native_support()? true : false);
1432 if ((is_it_true_mode && !adev->native_playback_enabled) ||
1433 (!is_it_true_mode && adev->native_playback_enabled)){
1434 ret = true;
1435 ALOGD("napb: time to toggle native mode");
1436 }
1437 }
1438
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301439 // Force all a2dp output devices to reconfigure for proper AFE encode format
Ashish Jainc597d102016-12-12 10:31:34 +05301440 //Also handle a case where in earlier a2dp start failed as A2DP stream was
1441 //in suspended state, hence try to trigger a retry when we again get a routing request.
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301442 if((usecase->stream.out) &&
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07001443 (usecase->stream.out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Ashish Jainc597d102016-12-12 10:31:34 +05301444 audio_extn_a2dp_is_force_device_switch()) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301445 ALOGD("Force a2dp device switch to update new encoder config");
1446 ret = true;
1447 }
1448
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301449 return ret;
1450}
1451
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001452int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001453{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001454 snd_device_t out_snd_device = SND_DEVICE_NONE;
1455 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001456 struct audio_usecase *usecase = NULL;
1457 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001458 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08001459 struct audio_usecase *hfp_usecase = NULL;
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08001460 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001461 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001462
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301463 ALOGD("%s for use case (%s)", __func__, use_case_table[uc_id]);
1464
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001465 usecase = get_usecase_from_list(adev, uc_id);
1466 if (usecase == NULL) {
1467 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
1468 return -EINVAL;
1469 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001470
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001471 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -08001472 (usecase->type == VOIP_CALL) ||
1473 (usecase->type == PCM_HFP_CALL)) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05301474 if(usecase->stream.out == NULL) {
1475 ALOGE("%s: stream.out is NULL", __func__);
1476 return -EINVAL;
1477 }
Eric Laurentb23d5282013-05-14 15:27:20 -07001478 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001479 usecase->stream.out);
Eric Laurentb23d5282013-05-14 15:27:20 -07001480 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001481 usecase->devices = usecase->stream.out->devices;
1482 } else {
1483 /*
1484 * If the voice call is active, use the sound devices of voice call usecase
1485 * so that it would not result any device switch. All the usecases will
1486 * be switched to new device when select_devices() is called for voice call
1487 * usecase. This is to avoid switching devices for voice call when
1488 * check_usecases_codec_backend() is called below.
Alexy Joseph79dfa3c2016-04-20 18:44:56 -07001489 * choose voice call device only if the use case device is
1490 * also using the codec backend
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001491 */
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08001492 if (voice_is_in_call(adev) && adev->mode != AUDIO_MODE_NORMAL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001493 vc_usecase = get_usecase_from_list(adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001494 get_usecase_id_from_usecase_type(adev, VOICE_CALL));
Alexy Josephdbcddf22016-05-16 17:54:09 -07001495 if ((vc_usecase) && (((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
1496 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) ||
Preetam Singh Ranawat097cb1f2016-07-19 13:49:04 +05301497 ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
1498 (usecase->devices & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) ||
Alexy Josephdbcddf22016-05-16 17:54:09 -07001499 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001500 in_snd_device = vc_usecase->in_snd_device;
1501 out_snd_device = vc_usecase->out_snd_device;
1502 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001503 } else if (voice_extn_compress_voip_is_active(adev)) {
1504 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001505 if ((voip_usecase) && ((voip_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Zhou Song0154bf12016-08-04 10:48:16 +08001506 ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1507 ((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) &&
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001508 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001509 in_snd_device = voip_usecase->in_snd_device;
1510 out_snd_device = voip_usecase->out_snd_device;
1511 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08001512 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08001513 hfp_ucid = audio_extn_hfp_get_usecase();
1514 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07001515 if ((hfp_usecase) && (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08001516 in_snd_device = hfp_usecase->in_snd_device;
1517 out_snd_device = hfp_usecase->out_snd_device;
1518 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001519 }
1520 if (usecase->type == PCM_PLAYBACK) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05301521 if (usecase->stream.out == NULL) {
1522 ALOGE("%s: stream.out is NULL", __func__);
1523 return -EINVAL;
1524 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001525 usecase->devices = usecase->stream.out->devices;
1526 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001527 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001528 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001529 usecase->stream.out);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001530 if (usecase->stream.out == adev->primary_output &&
1531 adev->active_input &&
Ravi Kumar Alamandad1c85bb2014-11-17 18:36:24 -08001532 out_snd_device != usecase->out_snd_device) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001533 select_devices(adev, adev->active_input->usecase);
1534 }
1535 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001536 } else if (usecase->type == PCM_CAPTURE) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05301537 if (usecase->stream.in == NULL) {
1538 ALOGE("%s: stream.in is NULL", __func__);
1539 return -EINVAL;
1540 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001541 usecase->devices = usecase->stream.in->device;
1542 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001543 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001544 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Leena Winterrowd3c8fbae2016-01-12 15:05:53 -08001545 if (adev->active_input &&
1546 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Karthik Reddy Kattaf621ec72014-11-21 16:37:38 +05301547 (adev->mode == AUDIO_MODE_IN_COMMUNICATION &&
1548 adev->active_input->source == AUDIO_SOURCE_MIC)) &&
1549 adev->primary_output && !adev->primary_output->standby) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001550 out_device = adev->primary_output->devices;
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07001551 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001552 } else if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
1553 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001554 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001555 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001556 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001557 }
1558 }
1559
1560 if (out_snd_device == usecase->out_snd_device &&
1561 in_snd_device == usecase->in_snd_device) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301562
1563 if (!force_device_switch(usecase))
1564 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001565 }
1566
sangwoobc677242013-08-08 16:53:43 +09001567 ALOGD("%s: out_snd_device(%d: %s) in_snd_device(%d: %s)", __func__,
Eric Laurentb23d5282013-05-14 15:27:20 -07001568 out_snd_device, platform_get_snd_device_name(out_snd_device),
1569 in_snd_device, platform_get_snd_device_name(in_snd_device));
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001570
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001571 /*
1572 * Limitation: While in call, to do a device switch we need to disable
1573 * and enable both RX and TX devices though one of them is same as current
1574 * device.
1575 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001576 if ((usecase->type == VOICE_CALL) &&
1577 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1578 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001579 status = platform_switch_voice_call_device_pre(adev->platform);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07001580 }
1581
1582 if (((usecase->type == VOICE_CALL) ||
1583 (usecase->type == VOIP_CALL)) &&
1584 (usecase->out_snd_device != SND_DEVICE_NONE)) {
1585 /* Disable sidetone only if voice/voip call already exists */
1586 if (voice_is_call_state_active(adev) ||
1587 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -07001588 voice_set_sidetone(adev, usecase->out_snd_device, false);
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07001589
1590 /* Disable aanc only if voice call exists */
1591 if (voice_is_call_state_active(adev))
1592 voice_check_and_update_aanc_path(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001593 }
1594
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001595 /* Disable current sound devices */
1596 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001597 disable_audio_route(adev, usecase);
1598 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001599 }
1600
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001601 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001602 disable_audio_route(adev, usecase);
1603 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001604 }
1605
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001606 /* Applicable only on the targets that has external modem.
1607 * New device information should be sent to modem before enabling
1608 * the devices to reduce in-call device switch time.
1609 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001610 if ((usecase->type == VOICE_CALL) &&
1611 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1612 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001613 status = platform_switch_voice_call_enable_device_config(adev->platform,
1614 out_snd_device,
1615 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07001616 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08001617
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001618 /* Enable new sound devices */
1619 if (out_snd_device != SND_DEVICE_NONE) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08001620 check_usecases_codec_backend(adev, usecase, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001621 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001622 }
1623
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001624 if (in_snd_device != SND_DEVICE_NONE) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301625 check_usecases_capture_codec_backend(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001626 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001627 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001628
Avinash Vaish71a8b972014-07-24 15:36:33 +05301629 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001630 status = platform_switch_voice_call_device_post(adev->platform,
1631 out_snd_device,
1632 in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05301633 enable_audio_route_for_voice_usecases(adev, usecase);
1634 }
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001635
sangwoo170731f2013-06-08 15:36:36 +09001636 usecase->in_snd_device = in_snd_device;
1637 usecase->out_snd_device = out_snd_device;
1638
Dhananjay Kumard6d32152016-10-13 16:11:03 +05301639 audio_extn_utils_update_stream_app_type_cfg_for_usecase(adev,
1640 usecase);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301641 if (usecase->type == PCM_PLAYBACK) {
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08001642 if ((24 == usecase->stream.out->bit_width) &&
1643 (usecase->stream.out->devices & AUDIO_DEVICE_OUT_SPEAKER)) {
1644 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
1645 } else if ((out_snd_device == SND_DEVICE_OUT_HDMI ||
1646 out_snd_device == SND_DEVICE_OUT_USB_HEADSET ||
1647 out_snd_device == SND_DEVICE_OUT_DISPLAY_PORT) &&
1648 (usecase->stream.out->sample_rate >= OUTPUT_SAMPLING_RATE_44100)) {
1649 /*
1650 * To best utlize DSP, check if the stream sample rate is supported/multiple of
1651 * configured device sample rate, if not update the COPP rate to be equal to the
1652 * device sample rate, else open COPP at stream sample rate
1653 */
1654 platform_check_and_update_copp_sample_rate(adev->platform, out_snd_device,
1655 usecase->stream.out->sample_rate,
1656 &usecase->stream.out->app_type_cfg.sample_rate);
Ashish Jain4826f6c2017-02-06 13:33:20 +05301657 } else if (((out_snd_device != SND_DEVICE_OUT_HEADPHONES_44_1 &&
1658 !audio_is_true_native_stream_active(adev)) &&
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08001659 usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) ||
1660 (usecase->stream.out->sample_rate < OUTPUT_SAMPLING_RATE_44100)) {
1661 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
1662 }
1663
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08001664 /* Notify device change info to effect clients registered */
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08001665 pthread_mutex_unlock(&adev->lock);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08001666 audio_extn_gef_notify_device_config(
1667 usecase->stream.out->devices,
1668 usecase->stream.out->channel_mask,
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08001669 usecase->stream.out->app_type_cfg.sample_rate,
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08001670 platform_get_snd_device_acdb_id(usecase->out_snd_device));
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08001671 pthread_mutex_lock(&adev->lock);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05301672 }
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001673 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09001674
Vidyakumar Athota493f2892016-08-14 11:56:55 -07001675 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07001676 /* Enable aanc only if voice call exists */
1677 if (voice_is_call_state_active(adev))
1678 voice_check_and_update_aanc_path(adev, out_snd_device, true);
1679
Vidyakumar Athota493f2892016-08-14 11:56:55 -07001680 /* Enable sidetone only if other voice/voip call already exists */
1681 if (voice_is_call_state_active(adev) ||
1682 voice_extn_compress_voip_is_started(adev))
1683 voice_set_sidetone(adev, out_snd_device, true);
1684 }
1685
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001686 /* Applicable only on the targets that has external modem.
1687 * Enable device command should be sent to modem only after
1688 * enabling voice call mixer controls
1689 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -07001690 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001691 status = platform_switch_voice_call_usecase_route_post(adev->platform,
1692 out_snd_device,
1693 in_snd_device);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301694 ALOGD("%s: done",__func__);
1695
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001696 return status;
1697}
1698
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001699static int stop_input_stream(struct stream_in *in)
1700{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05301701 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001702 struct audio_usecase *uc_info;
1703 struct audio_device *adev = in->dev;
1704
Eric Laurent994a6932013-07-17 11:51:42 -07001705 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001706 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001707 uc_info = get_usecase_from_list(adev, in->usecase);
1708 if (uc_info == NULL) {
1709 ALOGE("%s: Could not find the usecase (%d) in the list",
1710 __func__, in->usecase);
1711 return -EINVAL;
1712 }
1713
Vidyakumar Athota2850d532013-11-19 16:02:12 -08001714 /* Close in-call recording streams */
1715 voice_check_and_stop_incall_rec_usecase(adev, in);
1716
Eric Laurent150dbfe2013-02-27 14:31:02 -08001717 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001718 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001719
1720 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001721 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001722
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001723 list_remove(&uc_info->list);
1724 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001725
Aalique Grahame2e9b2e42016-12-07 12:43:48 -08001726 adev->active_input = get_next_active_input(adev);
1727
Eric Laurent994a6932013-07-17 11:51:42 -07001728 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001729 return ret;
1730}
1731
1732int start_input_stream(struct stream_in *in)
1733{
1734 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08001735 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001736 struct audio_usecase *uc_info;
1737 struct audio_device *adev = in->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05301738 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001739
Mingming Yin2664a5b2015-09-03 10:53:11 -07001740 int usecase = platform_update_usecase_from_source(in->source,in->usecase);
1741 if (get_usecase_from_list(adev, usecase) == NULL)
1742 in->usecase = usecase;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05301743 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
1744 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001745
Naresh Tanniru80659832014-06-04 18:17:56 +05301746
1747 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05301748 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05301749 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05301750 goto error_config;
1751 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05301752
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001753 /* Check if source matches incall recording usecase criteria */
1754 ret = voice_check_and_set_incall_rec_usecase(adev, in);
1755 if (ret)
1756 goto error_config;
1757 else
Mingming Yin2664a5b2015-09-03 10:53:11 -07001758 ALOGV("%s: usecase(%d)", __func__, in->usecase);
1759
1760 if (get_usecase_from_list(adev, in->usecase) != NULL) {
1761 ALOGE("%s: use case assigned already in use, stream(%p)usecase(%d: %s)",
1762 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Zhou Song4e0704d2016-04-20 13:00:14 +08001763 return -EINVAL;
Mingming Yin2664a5b2015-09-03 10:53:11 -07001764 }
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001765
Eric Laurentb23d5282013-05-14 15:27:20 -07001766 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001767 if (in->pcm_device_id < 0) {
1768 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1769 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001770 ret = -EINVAL;
1771 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001772 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001773
1774 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001775 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001776
1777 if (!uc_info) {
1778 ret = -ENOMEM;
1779 goto error_config;
1780 }
1781
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001782 uc_info->id = in->usecase;
1783 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001784 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001785 uc_info->devices = in->device;
1786 uc_info->in_snd_device = SND_DEVICE_NONE;
1787 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001788
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001789 list_add_tail(&adev->usecase_list, &uc_info->list);
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301790 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
1791 adev->perf_lock_opts,
1792 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001793 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001794
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301795 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d format %d",
1796 __func__, adev->snd_card, in->pcm_device_id, in->config.channels, in->config.format);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001797
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05301798 if (audio_extn_cin_attached_usecase(in->usecase)) {
1799 ret = audio_extn_cin_start_input_stream(in);
1800 if (ret)
1801 goto error_open;
1802 else
1803 goto done_open;
1804 }
1805
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001806 unsigned int flags = PCM_IN;
1807 unsigned int pcm_open_retry_count = 0;
1808
1809 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1810 flags |= PCM_MMAP | PCM_NOIRQ;
1811 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07001812 } else if (in->realtime) {
1813 flags |= PCM_MMAP | PCM_NOIRQ;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07001814 }
1815
1816 while (1) {
1817 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1818 flags, &in->config);
1819 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1820 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1821 if (in->pcm != NULL) {
1822 pcm_close(in->pcm);
1823 in->pcm = NULL;
1824 }
1825 if (pcm_open_retry_count-- == 0) {
1826 ret = -EIO;
1827 goto error_open;
1828 }
1829 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1830 continue;
1831 }
1832 break;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001833 }
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001834
1835 ALOGV("%s: pcm_prepare", __func__);
1836 ret = pcm_prepare(in->pcm);
1837 if (ret < 0) {
1838 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
1839 pcm_close(in->pcm);
1840 in->pcm = NULL;
1841 goto error_open;
1842 }
1843
Haynes Mathew George5beddd42016-06-27 18:33:40 -07001844 register_in_stream(in);
1845 if (in->realtime) {
1846 ret = pcm_start(in->pcm);
1847 if (ret < 0)
1848 goto error_open;
1849 }
1850
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05301851done_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301852 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001853 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07001854
Eric Laurentc8400632013-02-14 19:04:54 -08001855 return ret;
1856
1857error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05301858 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001859 stop_input_stream(in);
Eric Laurentc8400632013-02-14 19:04:54 -08001860error_config:
Dhananjay Kumard4833242016-10-06 22:09:12 +05301861 adev->active_input = get_next_active_input(adev);
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05301862 /*
1863 * sleep 50ms to allow sufficient time for kernel
1864 * drivers to recover incases like SSR.
1865 */
1866 usleep(50000);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001867 ALOGD("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001868
1869 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001870}
1871
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001872void lock_input_stream(struct stream_in *in)
1873{
1874 pthread_mutex_lock(&in->pre_lock);
1875 pthread_mutex_lock(&in->lock);
1876 pthread_mutex_unlock(&in->pre_lock);
1877}
1878
1879void lock_output_stream(struct stream_out *out)
1880{
1881 pthread_mutex_lock(&out->pre_lock);
1882 pthread_mutex_lock(&out->lock);
1883 pthread_mutex_unlock(&out->pre_lock);
1884}
1885
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001886/* must be called with out->lock locked */
1887static int send_offload_cmd_l(struct stream_out* out, int command)
1888{
1889 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1890
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07001891 if (!cmd) {
1892 ALOGE("failed to allocate mem for command 0x%x", command);
1893 return -ENOMEM;
1894 }
1895
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001896 ALOGVV("%s %d", __func__, command);
1897
1898 cmd->cmd = command;
1899 list_add_tail(&out->offload_cmd_list, &cmd->node);
1900 pthread_cond_signal(&out->offload_cond);
1901 return 0;
1902}
1903
1904/* must be called iwth out->lock locked */
1905static void stop_compressed_output_l(struct stream_out *out)
1906{
1907 out->offload_state = OFFLOAD_STATE_IDLE;
1908 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001909 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001910 if (out->compr != NULL) {
1911 compress_stop(out->compr);
1912 while (out->offload_thread_blocked) {
1913 pthread_cond_wait(&out->cond, &out->lock);
1914 }
1915 }
1916}
1917
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001918bool is_offload_usecase(audio_usecase_t uc_id)
1919{
1920 unsigned int i;
1921 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
1922 if (uc_id == offload_usecases[i])
1923 return true;
1924 }
1925 return false;
1926}
1927
vivek mehta446c3962015-09-14 10:57:35 -07001928static audio_usecase_t get_offload_usecase(struct audio_device *adev, bool is_direct_pcm)
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001929{
vivek mehta446c3962015-09-14 10:57:35 -07001930 audio_usecase_t ret_uc = USECASE_INVALID;
1931 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08001932 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07001933 if (!adev->multi_offload_enable) {
1934 if (is_direct_pcm)
1935 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD2;
1936 else
1937 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001938
vivek mehta446c3962015-09-14 10:57:35 -07001939 pthread_mutex_lock(&adev->lock);
1940 if (get_usecase_from_list(adev, ret_uc) != NULL)
1941 ret_uc = USECASE_INVALID;
1942 pthread_mutex_unlock(&adev->lock);
1943
1944 return ret_uc;
1945 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001946
1947 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
vivek mehta446c3962015-09-14 10:57:35 -07001948 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
1949 if (!(adev->offload_usecases_state & (0x1 << offload_uc_index))) {
1950 adev->offload_usecases_state |= 0x1 << offload_uc_index;
1951 ret_uc = offload_usecases[offload_uc_index];
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001952 break;
1953 }
1954 }
vivek mehta446c3962015-09-14 10:57:35 -07001955
1956 ALOGV("%s: offload usecase is %d", __func__, ret_uc);
1957 return ret_uc;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001958}
1959
1960static void free_offload_usecase(struct audio_device *adev,
1961 audio_usecase_t uc_id)
1962{
vivek mehta446c3962015-09-14 10:57:35 -07001963 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08001964 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07001965
1966 if (!adev->multi_offload_enable)
1967 return;
1968
1969 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
1970 if (offload_usecases[offload_uc_index] == uc_id) {
1971 adev->offload_usecases_state &= ~(0x1 << offload_uc_index);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07001972 break;
1973 }
1974 }
1975 ALOGV("%s: free offload usecase %d", __func__, uc_id);
1976}
1977
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001978static void *offload_thread_loop(void *context)
1979{
1980 struct stream_out *out = (struct stream_out *) context;
1981 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08001982 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001983
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001984 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
1985 set_sched_policy(0, SP_FOREGROUND);
1986 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
1987
1988 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07001989 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001990 for (;;) {
1991 struct offload_cmd *cmd = NULL;
1992 stream_callback_event_t event;
1993 bool send_callback = false;
1994
1995 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
1996 __func__, list_empty(&out->offload_cmd_list),
1997 out->offload_state);
1998 if (list_empty(&out->offload_cmd_list)) {
1999 ALOGV("%s SLEEPING", __func__);
2000 pthread_cond_wait(&out->offload_cond, &out->lock);
2001 ALOGV("%s RUNNING", __func__);
2002 continue;
2003 }
2004
2005 item = list_head(&out->offload_cmd_list);
2006 cmd = node_to_item(item, struct offload_cmd, node);
2007 list_remove(item);
2008
2009 ALOGVV("%s STATE %d CMD %d out->compr %p",
2010 __func__, out->offload_state, cmd->cmd, out->compr);
2011
2012 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
2013 free(cmd);
2014 break;
2015 }
2016
2017 if (out->compr == NULL) {
2018 ALOGE("%s: Compress handle is NULL", __func__);
Haynes Mathew Georgea9abb202016-06-02 14:13:20 -07002019 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002020 pthread_cond_signal(&out->cond);
2021 continue;
2022 }
2023 out->offload_thread_blocked = true;
2024 pthread_mutex_unlock(&out->lock);
2025 send_callback = false;
2026 switch(cmd->cmd) {
2027 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002028 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002029 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002030 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002031 send_callback = true;
2032 event = STREAM_CBK_EVENT_WRITE_READY;
2033 break;
2034 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08002035 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05302036 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002037 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302038 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002039 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302040 if (ret < 0)
2041 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05302042 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302043 else if (ret == -ETIMEDOUT)
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08002044 compress_drain(out->compr);
2045 else
2046 ALOGE("%s: Next track returned error %d",__func__, ret);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302047 if (ret != -ENETRESET) {
2048 send_callback = true;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302049 pthread_mutex_lock(&out->lock);
2050 out->send_new_metadata = 1;
2051 out->send_next_track_params = true;
2052 pthread_mutex_unlock(&out->lock);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05302053 event = STREAM_CBK_EVENT_DRAIN_READY;
2054 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
2055 } else
2056 ALOGE("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002057 break;
2058 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002059 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002060 compress_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002061 ALOGD("copl(%p):calling compress_drain", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002062 send_callback = true;
2063 event = STREAM_CBK_EVENT_DRAIN_READY;
2064 break;
2065 default:
2066 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
2067 break;
2068 }
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002069 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002070 out->offload_thread_blocked = false;
2071 pthread_cond_signal(&out->cond);
vivek mehtaf1f47432015-09-25 14:07:43 -07002072 if (send_callback && out->offload_callback) {
Ravi Kumar Alamanda38e6fe32014-12-02 19:21:51 -08002073 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002074 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07002075 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002076 free(cmd);
2077 }
2078
2079 pthread_cond_signal(&out->cond);
2080 while (!list_empty(&out->offload_cmd_list)) {
2081 item = list_head(&out->offload_cmd_list);
2082 list_remove(item);
2083 free(node_to_item(item, struct offload_cmd, node));
2084 }
2085 pthread_mutex_unlock(&out->lock);
2086
2087 return NULL;
2088}
2089
2090static int create_offload_callback_thread(struct stream_out *out)
2091{
2092 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
2093 list_init(&out->offload_cmd_list);
2094 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
2095 offload_thread_loop, out);
2096 return 0;
2097}
2098
2099static int destroy_offload_callback_thread(struct stream_out *out)
2100{
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002101 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002102 stop_compressed_output_l(out);
2103 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
2104
2105 pthread_mutex_unlock(&out->lock);
2106 pthread_join(out->offload_thread, (void **) NULL);
2107 pthread_cond_destroy(&out->offload_cond);
2108
2109 return 0;
2110}
2111
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002112static int stop_output_stream(struct stream_out *out)
2113{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05302114 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002115 struct audio_usecase *uc_info;
2116 struct audio_device *adev = out->dev;
2117
Eric Laurent994a6932013-07-17 11:51:42 -07002118 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002119 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002120 uc_info = get_usecase_from_list(adev, out->usecase);
2121 if (uc_info == NULL) {
2122 ALOGE("%s: Could not find the usecase (%d) in the list",
2123 __func__, out->usecase);
2124 return -EINVAL;
2125 }
2126
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002127 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302128 !(audio_extn_passthru_is_passthrough_stream(out))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002129 if (adev->visualizer_stop_output != NULL)
2130 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002131
2132 audio_extn_dts_remove_state_notifier_node(out->usecase);
2133
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002134 if (adev->offload_effects_stop_output != NULL)
2135 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
2136 }
Eric Laurentc4aef752013-09-12 17:45:53 -07002137
Eric Laurent150dbfe2013-02-27 14:31:02 -08002138 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002139 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002140
2141 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002142 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002143
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002144 list_remove(&uc_info->list);
2145 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002146
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002147 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302148 (audio_extn_passthru_is_passthrough_stream(out))) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002149 ALOGV("Disable passthrough , reset mixer to pcm");
2150 /* NO_PASSTHROUGH */
2151 out->compr_config.codec->compr_passthr = 0;
Mingming Yin21854652016-04-13 11:54:02 -07002152 audio_extn_passthru_on_stop(out);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002153 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
2154 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07002155
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302156 /* Must be called after removing the usecase from list */
2157 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
Ashish Jaind84fd6a2016-07-27 12:33:25 +05302158 audio_extn_keep_alive_start();
2159
Eric Laurent994a6932013-07-17 11:51:42 -07002160 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002161 return ret;
2162}
2163
2164int start_output_stream(struct stream_out *out)
2165{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002166 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002167 struct audio_usecase *uc_info;
2168 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05302169 int snd_card_status = get_snd_card_state(adev);
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08002170 char mixer_ctl_name[128];
2171 struct mixer_ctl *ctl = NULL;
2172 char* perf_mode[] = {"ULL", "ULL_PP", "LL"};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002173
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002174 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
2175 ret = -EINVAL;
2176 goto error_config;
2177 }
2178
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302179 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x)",
2180 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
2181 out->devices);
Naresh Tanniru4c630392014-05-12 01:05:52 +05302182
Naresh Tanniru80659832014-06-04 18:17:56 +05302183 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05302184 ALOGE("%s: sound card is not active/SSR returning error", __func__);
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302185 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302186 goto error_config;
2187 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05302188
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05302189 if (out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) {
2190 if (!audio_extn_a2dp_is_ready()) {
2191 if (out->devices & AUDIO_DEVICE_OUT_SPEAKER) {
2192 //combo usecase just by pass a2dp
2193 ALOGW("%s: A2DP profile is not ready, route it to speaker", __func__);
2194 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
2195 } else {
2196 ALOGE("%s: A2DP profile is not ready, return error", __func__);
2197 ret = -EAGAIN;
2198 goto error_config;
2199 }
2200 }
2201 }
Eric Laurentb23d5282013-05-14 15:27:20 -07002202 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002203 if (out->pcm_device_id < 0) {
2204 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
2205 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002206 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002207 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002208 }
2209
2210 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002211
2212 if (!uc_info) {
2213 ret = -ENOMEM;
2214 goto error_config;
2215 }
2216
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002217 uc_info->id = out->usecase;
2218 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002219 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002220 uc_info->devices = out->devices;
2221 uc_info->in_snd_device = SND_DEVICE_NONE;
2222 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002223 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002224
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302225 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
2226 adev->perf_lock_opts,
2227 adev->perf_lock_opts_size);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05302228
2229 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
2230 audio_extn_keep_alive_stop();
2231 if (audio_extn_passthru_is_enabled() &&
2232 audio_extn_passthru_is_passthrough_stream(out)) {
2233 audio_extn_passthru_on_start(out);
2234 audio_extn_passthru_update_stream_configuration(adev, out);
2235 }
2236 }
2237
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002238 select_devices(adev, out->usecase);
2239
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002240 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
2241 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002242 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002243 unsigned int flags = PCM_OUT;
2244 unsigned int pcm_open_retry_count = 0;
2245 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
2246 flags |= PCM_MMAP | PCM_NOIRQ;
2247 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002248 } else if (out->realtime) {
2249 flags |= PCM_MMAP | PCM_NOIRQ;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002250 } else
2251 flags |= PCM_MONOTONIC;
2252
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08002253 if ((adev->vr_audio_mode_enabled) &&
2254 (out->flags & AUDIO_OUTPUT_FLAG_RAW)) {
2255 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
2256 "PCM_Dev %d Topology", out->pcm_device_id);
2257 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2258 if (!ctl) {
2259 ALOGI("%s: Could not get ctl for mixer cmd might be ULL - %s",
2260 __func__, mixer_ctl_name);
2261 } else {
2262 //if success use ULLPP
2263 ALOGI("%s: mixer ctrl %s succeeded setting up ULL for %d",
2264 __func__, mixer_ctl_name, out->pcm_device_id);
2265 //There is a still a possibility that some sessions
2266 // that request for FAST|RAW when 3D audio is active
2267 //can go through ULLPP. Ideally we expects apps to
2268 //listen to audio focus and stop concurrent playback
2269 //Also, we will look for mode flag (voice_in_communication)
2270 //before enabling the realtime flag.
2271 mixer_ctl_set_enum_by_string(ctl, perf_mode[1]);
2272 }
2273 }
2274
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002275 while (1) {
2276 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
2277 flags, &out->config);
2278 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
2279 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
2280 if (out->pcm != NULL) {
2281 pcm_close(out->pcm);
2282 out->pcm = NULL;
2283 }
2284 if (pcm_open_retry_count-- == 0) {
2285 ret = -EIO;
2286 goto error_open;
2287 }
2288 usleep(PROXY_OPEN_WAIT_TIME * 1000);
2289 continue;
2290 }
2291 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002292 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002293
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07002294 platform_set_stream_channel_map(adev->platform, out->channel_mask,
2295 out->pcm_device_id);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002296
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07002297 ALOGV("%s: pcm_prepare", __func__);
2298 if (pcm_is_ready(out->pcm)) {
2299 ret = pcm_prepare(out->pcm);
2300 if (ret < 0) {
2301 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
2302 pcm_close(out->pcm);
2303 out->pcm = NULL;
2304 goto error_open;
2305 }
2306 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002307 } else {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07002308 platform_set_stream_channel_map(adev->platform, out->channel_mask,
2309 out->pcm_device_id);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002310 out->pcm = NULL;
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08002311 out->compr = compress_open(adev->snd_card,
2312 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002313 COMPRESS_IN, &out->compr_config);
2314 if (out->compr && !is_compress_ready(out->compr)) {
2315 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
2316 compress_close(out->compr);
2317 out->compr = NULL;
2318 ret = -EIO;
2319 goto error_open;
2320 }
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302321 /* compress_open sends params of the track, so reset the flag here */
2322 out->is_compr_metadata_avail = false;
2323
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002324 if (out->offload_callback)
2325 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07002326
Fred Oh3f43e742015-03-04 18:42:34 -08002327 /* Since small bufs uses blocking writes, a write will be blocked
2328 for the default max poll time (20s) in the event of an SSR.
2329 Reduce the poll time to observe and deal with SSR faster.
2330 */
Ashish Jain5106d362016-05-11 19:23:33 +05302331 if (!out->non_blocking) {
Fred Oh3f43e742015-03-04 18:42:34 -08002332 compress_set_max_poll_wait(out->compr, 1000);
2333 }
2334
Manish Dewangan69426c82017-01-30 17:35:36 +05302335 audio_extn_utils_compress_set_render_mode(out);
2336
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002337 audio_extn_dts_create_state_notifier_node(out->usecase);
2338 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2339 popcount(out->channel_mask),
2340 out->playback_started);
2341
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08002342#ifdef DS1_DOLBY_DDP_ENABLED
2343 if (audio_extn_is_dolby_format(out->format))
2344 audio_extn_dolby_send_ddp_endp_params(adev);
2345#endif
Preetam Singh Ranawatd18d8832017-02-08 17:34:54 +05302346 if (!(audio_extn_passthru_is_passthrough_stream(out)) &&
2347 (out->sample_rate != 176400 && out->sample_rate <= 192000)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002348 if (adev->visualizer_start_output != NULL)
2349 adev->visualizer_start_output(out->handle, out->pcm_device_id);
2350 if (adev->offload_effects_start_output != NULL)
Ashish Jain5106d362016-05-11 19:23:33 +05302351 adev->offload_effects_start_output(out->handle, out->pcm_device_id, adev->mixer);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002352 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002353 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002354 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002355
2356 if (ret == 0) {
2357 register_out_stream(out);
2358 if (out->realtime) {
2359 ret = pcm_start(out->pcm);
2360 if (ret < 0)
2361 goto error_open;
2362 }
2363 }
2364
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302365 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07002366 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002367
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002368 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002369error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302370 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002371 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002372error_config:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05302373 /*
2374 * sleep 50ms to allow sufficient time for kernel
2375 * drivers to recover incases like SSR.
2376 */
2377 usleep(50000);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002378 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002379}
2380
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002381static int check_input_parameters(uint32_t sample_rate,
2382 audio_format_t format,
2383 int channel_count)
2384{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002385 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002386
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302387 if (((format != AUDIO_FORMAT_PCM_16_BIT) && (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
2388 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) && (format != AUDIO_FORMAT_PCM_32_BIT) &&
2389 (format != AUDIO_FORMAT_PCM_FLOAT)) &&
Mingming Yine62d7842013-10-25 16:26:03 -07002390 !voice_extn_compress_voip_is_format_supported(format) &&
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302391 !audio_extn_compr_cap_format_supported(format)) ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002392
2393 switch (channel_count) {
2394 case 1:
2395 case 2:
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05302396 case 3:
2397 case 4:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002398 case 6:
2399 break;
2400 default:
2401 ret = -EINVAL;
2402 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002403
2404 switch (sample_rate) {
2405 case 8000:
2406 case 11025:
2407 case 12000:
2408 case 16000:
2409 case 22050:
2410 case 24000:
2411 case 32000:
2412 case 44100:
2413 case 48000:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302414 case 96000:
2415 case 192000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002416 break;
2417 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002418 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002419 }
2420
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08002421 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002422}
2423
2424static size_t get_input_buffer_size(uint32_t sample_rate,
2425 audio_format_t format,
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002426 int channel_count,
2427 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002428{
2429 size_t size = 0;
2430
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002431 if (check_input_parameters(sample_rate, format, channel_count) != 0)
2432 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002433
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002434 size = (sample_rate * AUDIO_CAPTURE_PERIOD_DURATION_MSEC) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002435 if (is_low_latency)
2436 size = configured_low_latency_capture_period_size;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302437
2438 size *= audio_bytes_per_sample(format) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002439
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07002440 /* make sure the size is multiple of 32 bytes
2441 * At 48 kHz mono 16-bit PCM:
2442 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
2443 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
2444 */
2445 size += 0x1f;
2446 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002447
2448 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002449}
2450
Ashish Jain058165c2016-09-28 23:18:48 +05302451static size_t get_output_period_size(uint32_t sample_rate,
2452 audio_format_t format,
2453 int channel_count,
2454 int duration /*in millisecs*/)
2455{
2456 size_t size = 0;
2457 uint32_t bytes_per_sample = audio_bytes_per_sample(format);
2458
2459 if ((duration == 0) || (sample_rate == 0) ||
2460 (bytes_per_sample == 0) || (channel_count == 0)) {
2461 ALOGW("Invalid config duration %d sr %d bps %d ch %d", duration, sample_rate,
2462 bytes_per_sample, channel_count);
2463 return -EINVAL;
2464 }
2465
2466 size = (sample_rate *
2467 duration *
2468 bytes_per_sample *
2469 channel_count) / 1000;
2470 /*
2471 * To have same PCM samples for all channels, the buffer size requires to
2472 * be multiple of (number of channels * bytes per sample)
2473 * For writes to succeed, the buffer must be written at address which is multiple of 32
2474 */
2475 size = ALIGN(size, (bytes_per_sample * channel_count * 32));
2476
2477 return (size/(channel_count * bytes_per_sample));
2478}
2479
Ashish Jain5106d362016-05-11 19:23:33 +05302480static uint64_t get_actual_pcm_frames_rendered(struct stream_out *out)
2481{
2482 uint64_t actual_frames_rendered = 0;
2483 size_t kernel_buffer_size = out->compr_config.fragment_size * out->compr_config.fragments;
2484
2485 /* This adjustment accounts for buffering after app processor.
2486 * It is based on estimated DSP latency per use case, rather than exact.
2487 */
2488 int64_t platform_latency = platform_render_latency(out->usecase) *
2489 out->sample_rate / 1000000LL;
2490
2491 /* not querying actual state of buffering in kernel as it would involve an ioctl call
2492 * which then needs protection, this causes delay in TS query for pcm_offload usecase
2493 * hence only estimate.
2494 */
2495 int64_t signed_frames = out->written - kernel_buffer_size;
2496
2497 signed_frames = signed_frames / (audio_bytes_per_sample(out->format) * popcount(out->channel_mask)) - platform_latency;
2498
2499 if (signed_frames > 0)
2500 actual_frames_rendered = signed_frames;
2501
2502 ALOGVV("%s signed frames %lld out_written %lld kernel_buffer_size %d"
2503 "bytes/sample %zu channel count %d", __func__,(long long int)signed_frames,
2504 (long long int)out->written, (int)kernel_buffer_size,
2505 audio_bytes_per_sample(out->compr_config.codec->format),
2506 popcount(out->channel_mask));
2507
2508 return actual_frames_rendered;
2509}
2510
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002511static uint32_t out_get_sample_rate(const struct audio_stream *stream)
2512{
2513 struct stream_out *out = (struct stream_out *)stream;
2514
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002515 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002516}
2517
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002518static int out_set_sample_rate(struct audio_stream *stream __unused,
2519 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002520{
2521 return -ENOSYS;
2522}
2523
2524static size_t out_get_buffer_size(const struct audio_stream *stream)
2525{
2526 struct stream_out *out = (struct stream_out *)stream;
2527
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002528 if (is_offload_usecase(out->usecase))
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002529 return out->compr_config.fragment_size;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002530 else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
2531 return voice_extn_compress_voip_out_get_buffer_size(out);
Ashish Jainf1eaa582016-05-23 20:54:24 +05302532 else if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)
Ashish Jain83a6cc22016-06-28 14:34:17 +05302533 return out->hal_fragment_size;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002534
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002535 return out->config.period_size * out->af_period_multiplier *
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07002536 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002537}
2538
2539static uint32_t out_get_channels(const struct audio_stream *stream)
2540{
2541 struct stream_out *out = (struct stream_out *)stream;
2542
2543 return out->channel_mask;
2544}
2545
2546static audio_format_t out_get_format(const struct audio_stream *stream)
2547{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002548 struct stream_out *out = (struct stream_out *)stream;
2549
2550 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002551}
2552
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002553static int out_set_format(struct audio_stream *stream __unused,
2554 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002555{
2556 return -ENOSYS;
2557}
2558
2559static int out_standby(struct audio_stream *stream)
2560{
2561 struct stream_out *out = (struct stream_out *)stream;
2562 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002563
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302564 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
2565 stream, out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002566
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002567 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002568 if (!out->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07002569 if (adev->adm_deregister_stream)
2570 adev->adm_deregister_stream(adev->adm_data, out->handle);
2571
Haynes Mathew George7fce0a52016-06-23 18:22:27 -07002572 if (is_offload_usecase(out->usecase))
2573 stop_compressed_output_l(out);
2574
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002575 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002576 out->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08002577 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
2578 voice_extn_compress_voip_close_output_stream(stream);
2579 pthread_mutex_unlock(&adev->lock);
2580 pthread_mutex_unlock(&out->lock);
2581 ALOGD("VOIP output entered standby");
2582 return 0;
2583 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002584 if (out->pcm) {
2585 pcm_close(out->pcm);
2586 out->pcm = NULL;
2587 }
2588 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07002589 ALOGD("copl(%p):standby", out);
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05302590 out->send_next_track_params = false;
2591 out->is_compr_metadata_avail = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002592 out->gapless_mdata.encoder_delay = 0;
2593 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002594 if (out->compr != NULL) {
2595 compress_close(out->compr);
2596 out->compr = NULL;
2597 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002598 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002599 stop_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002600 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002601 }
2602 pthread_mutex_unlock(&out->lock);
Ashish Jainbbce4322016-02-16 13:25:27 +05302603 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002604 return 0;
2605}
2606
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07002607static int out_dump(const struct audio_stream *stream __unused,
2608 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002609{
2610 return 0;
2611}
2612
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002613static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
2614{
2615 int ret = 0;
2616 char value[32];
ApurupaPattapu2e084df2013-12-18 15:47:59 -08002617
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002618 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08002619 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002620 return -EINVAL;
2621 }
2622
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302623 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08002624
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002625 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
2626 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302627 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002628 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002629 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
2630 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05302631 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002632 }
2633
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002634 ALOGV("%s new encoder delay %u and padding %u", __func__,
2635 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
2636
2637 return 0;
2638}
2639
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002640static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
2641{
2642 return out == adev->primary_output || out == adev->voice_tx_output;
2643}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002644
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002645static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
2646{
2647 struct stream_out *out = (struct stream_out *)stream;
2648 struct audio_device *adev = out->dev;
2649 struct str_parms *parms;
2650 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002651 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002652
sangwoobc677242013-08-08 16:53:43 +09002653 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002654 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002655 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302656 if (!parms)
2657 goto error;
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002658 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2659 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002660 val = atoi(value);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002661 lock_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002662 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002663
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002664 /*
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08002665 * When HDMI cable is unplugged the music playback is paused and
2666 * the policy manager sends routing=0. But the audioflinger continues
2667 * to write data until standby time (3sec). As the HDMI core is
2668 * turned off, the write gets blocked.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002669 * Avoid this by routing audio to speaker until standby.
2670 */
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08002671 if ((out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
2672 (val == AUDIO_DEVICE_NONE) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302673 !audio_extn_passthru_is_passthrough_stream(out) &&
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08002674 (platform_get_edid_info(adev->platform) != 0) /* HDMI disconnected */) {
2675 val = AUDIO_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002676 }
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302677 /*
2678 * When A2DP is disconnected the
2679 * music playback is paused and the policy manager sends routing=0
2680 * But the audioflingercontinues to write data until standby time
2681 * (3sec). As BT is turned off, the write gets blocked.
2682 * Avoid this by routing audio to speaker until standby.
2683 */
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07002684 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302685 (val == AUDIO_DEVICE_NONE)) {
2686 val = AUDIO_DEVICE_OUT_SPEAKER;
2687 }
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05302688 /* To avoid a2dp to sco overlapping / BT device improper state
2689 * check with BT lib about a2dp streaming support before routing
Naresh Tanniru03f9dd52016-10-19 18:46:22 +05302690 */
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05302691 if (val & AUDIO_DEVICE_OUT_ALL_A2DP) {
2692 if (!audio_extn_a2dp_is_ready()) {
2693 if (val & AUDIO_DEVICE_OUT_SPEAKER) {
2694 //combo usecase just by pass a2dp
2695 ALOGW("%s: A2DP profile is not ready,routing to speaker only", __func__);
2696 val = AUDIO_DEVICE_OUT_SPEAKER;
2697 } else {
2698 ALOGE("%s: A2DP profile is not ready,ignoring routing request", __func__);
2699 /* update device to a2dp and don't route as BT returned error
2700 * However it is still possible a2dp routing called because
2701 * of current active device disconnection (like wired headset)
2702 */
2703 out->devices = val;
2704 pthread_mutex_unlock(&out->lock);
2705 pthread_mutex_unlock(&adev->lock);
2706 goto error;
2707 }
2708 }
Naresh Tanniru03f9dd52016-10-19 18:46:22 +05302709 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002710 /*
2711 * select_devices() call below switches all the usecases on the same
2712 * backend to the new device. Refer to check_usecases_codec_backend() in
2713 * the select_devices(). But how do we undo this?
2714 *
2715 * For example, music playback is active on headset (deep-buffer usecase)
2716 * and if we go to ringtones and select a ringtone, low-latency usecase
2717 * will be started on headset+speaker. As we can't enable headset+speaker
2718 * and headset devices at the same time, select_devices() switches the music
2719 * playback to headset+speaker while starting low-lateny usecase for ringtone.
2720 * So when the ringtone playback is completed, how do we undo the same?
2721 *
2722 * We are relying on the out_set_parameters() call on deep-buffer output,
2723 * once the ringtone playback is ended.
2724 * NOTE: We should not check if the current devices are same as new devices.
2725 * Because select_devices() must be called to switch back the music
2726 * playback to headset.
2727 */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002728 if (val != 0) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002729 audio_devices_t new_dev = val;
2730 bool same_dev = out->devices == new_dev;
2731 out->devices = new_dev;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002732
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07002733 if (output_drives_call(adev, out)) {
2734 if(!voice_is_in_call(adev)) {
2735 if (adev->mode == AUDIO_MODE_IN_CALL) {
2736 adev->current_call_output = out;
2737 ret = voice_start_call(adev);
2738 }
2739 } else {
2740 adev->current_call_output = out;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002741 voice_update_devices_for_all_voice_usecases(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07002742 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002743 }
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08002744
2745 if (!out->standby) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002746 if (!same_dev) {
2747 ALOGV("update routing change");
Sudheer Papothi80266982016-08-16 02:36:18 +05302748 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
2749 adev->perf_lock_opts,
2750 adev->perf_lock_opts_size);
Haynes Mathew George822b5492016-07-01 16:57:24 -07002751 if (adev->adm_on_routing_change)
2752 adev->adm_on_routing_change(adev->adm_data,
2753 out->handle);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002754 }
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08002755 select_devices(adev, out->usecase);
Sudheer Papothi80266982016-08-16 02:36:18 +05302756 if (!same_dev)
2757 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08002758 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002759 }
2760
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002761 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002762 pthread_mutex_unlock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002763 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07002764
2765 if (out == adev->primary_output) {
2766 pthread_mutex_lock(&adev->lock);
2767 audio_extn_set_parameters(adev, parms);
2768 pthread_mutex_unlock(&adev->lock);
2769 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002770 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002771 lock_output_stream(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002772 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08002773
2774 audio_extn_dts_create_state_notifier_node(out->usecase);
2775 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
2776 popcount(out->channel_mask),
2777 out->playback_started);
2778
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08002779 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002780 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07002781
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05302782 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
2783 if (err >= 0) {
2784 strlcpy(out->profile, value, sizeof(out->profile));
2785 ALOGV("updating stream profile with value '%s'", out->profile);
2786 lock_output_stream(out);
2787 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
2788 &adev->streams_output_cfg_list,
2789 out->devices, out->flags, out->format,
2790 out->sample_rate, out->bit_width,
2791 out->channel_mask, out->profile,
2792 &out->app_type_cfg);
2793 pthread_mutex_unlock(&out->lock);
2794 }
2795
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002796 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05302797error:
Eric Laurent994a6932013-07-17 11:51:42 -07002798 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002799 return ret;
2800}
2801
2802static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
2803{
2804 struct stream_out *out = (struct stream_out *)stream;
2805 struct str_parms *query = str_parms_create_str(keys);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002806 char *str = (char*) NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002807 char value[256];
2808 struct str_parms *reply = str_parms_create();
2809 size_t i, j;
2810 int ret;
2811 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002812
2813 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002814 if (reply) {
2815 str_parms_destroy(reply);
2816 }
2817 if (query) {
2818 str_parms_destroy(query);
2819 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002820 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
2821 return NULL;
2822 }
2823
Eric Laurent994a6932013-07-17 11:51:42 -07002824 ALOGV("%s: enter: keys - %s", __func__, keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002825 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
2826 if (ret >= 0) {
2827 value[0] = '\0';
2828 i = 0;
2829 while (out->supported_channel_masks[i] != 0) {
2830 for (j = 0; j < ARRAY_SIZE(out_channels_name_to_enum_table); j++) {
2831 if (out_channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
2832 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002833 strlcat(value, "|", sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002834 }
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002835 strlcat(value, out_channels_name_to_enum_table[j].name, sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002836 first = false;
2837 break;
2838 }
2839 }
2840 i++;
2841 }
2842 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
2843 str = str_parms_to_str(reply);
2844 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002845 voice_extn_out_get_parameters(out, query, reply);
2846 str = str_parms_to_str(reply);
Mingming Yin7b762e72015-03-04 13:47:32 -08002847 if (str && !strncmp(str, "", sizeof(""))) {
Narsinga Rao Chella29b8fc72014-01-29 12:52:19 -08002848 free(str);
2849 str = strdup(keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002850 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002851 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002852
Alexy Joseph62142aa2015-11-16 15:10:34 -08002853
2854 ret = str_parms_get_str(query, "is_direct_pcm_track", value, sizeof(value));
2855 if (ret >= 0) {
2856 value[0] = '\0';
2857 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) {
2858 ALOGV("in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05302859 strlcat(value, "true", sizeof(value ));
Alexy Joseph62142aa2015-11-16 15:10:34 -08002860 } else {
2861 ALOGV("not in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05302862 strlcat(value, "false", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08002863 }
2864 str_parms_add_str(reply, "is_direct_pcm_track", value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002865 if (str)
2866 free(str);
Alexy Joseph62142aa2015-11-16 15:10:34 -08002867 str = str_parms_to_str(reply);
2868 }
2869
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002870 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
2871 if (ret >= 0) {
2872 value[0] = '\0';
2873 i = 0;
2874 first = true;
2875 while (out->supported_formats[i] != 0) {
2876 for (j = 0; j < ARRAY_SIZE(out_formats_name_to_enum_table); j++) {
2877 if (out_formats_name_to_enum_table[j].value == out->supported_formats[i]) {
2878 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08002879 strlcat(value, "|", sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002880 }
2881 strlcat(value, out_formats_name_to_enum_table[j].name, sizeof(value));
2882 first = false;
2883 break;
2884 }
2885 }
2886 i++;
2887 }
2888 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08002889 if (str)
2890 free(str);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002891 str = str_parms_to_str(reply);
2892 }
Mingming Yin3a941d42016-02-17 18:08:05 -08002893
2894 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value, sizeof(value));
2895 if (ret >= 0) {
2896 value[0] = '\0';
2897 i = 0;
2898 first = true;
2899 while (out->supported_sample_rates[i] != 0) {
2900 for (j = 0; j < ARRAY_SIZE(out_hdmi_sample_rates_name_to_enum_table); j++) {
2901 if (out_hdmi_sample_rates_name_to_enum_table[j].value == out->supported_sample_rates[i]) {
2902 if (!first) {
2903 strlcat(value, "|", sizeof(value));
2904 }
2905 strlcat(value, out_hdmi_sample_rates_name_to_enum_table[j].name, sizeof(value));
2906 first = false;
2907 break;
2908 }
2909 }
2910 i++;
2911 }
2912 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value);
2913 if (str)
2914 free(str);
2915 str = str_parms_to_str(reply);
2916 }
2917
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002918 str_parms_destroy(query);
2919 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07002920 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002921 return str;
2922}
2923
2924static uint32_t out_get_latency(const struct audio_stream_out *stream)
2925{
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002926 uint32_t period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002927 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08002928 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002929
Alexy Josephaa54c872014-12-03 02:46:47 -08002930 if (is_offload_usecase(out->usecase)) {
Manish Dewangan07de2142017-02-27 19:27:20 +05302931 lock_output_stream(out);
2932 latency = audio_extn_utils_compress_get_dsp_latency(out);
2933 pthread_mutex_unlock(&out->lock);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002934 } else if (out->realtime) {
2935 // since the buffer won't be filled up faster than realtime,
2936 // return a smaller number
2937 if (out->config.rate)
2938 period_ms = (out->af_period_multiplier * out->config.period_size *
2939 1000) / (out->config.rate);
2940 else
2941 period_ms = 0;
2942 latency = period_ms + platform_render_latency(out->usecase)/1000;
Alexy Josephaa54c872014-12-03 02:46:47 -08002943 } else {
2944 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002945 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08002946 }
2947
Aniket Kumar Latad5972fa2017-02-08 13:53:48 -08002948 if ((AUDIO_DEVICE_OUT_BLUETOOTH_A2DP == out->devices) &&
2949 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))
2950 latency += audio_extn_a2dp_get_encoder_latency();
2951
Anish Kumar50ebcbf2014-12-09 04:01:39 +05302952 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08002953 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002954}
2955
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302956static float AmpToDb(float amplification)
2957{
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05302958 float db = DSD_VOLUME_MIN_DB;
2959 if (amplification > 0) {
2960 db = 20 * log10(amplification);
2961 if(db < DSD_VOLUME_MIN_DB)
2962 return DSD_VOLUME_MIN_DB;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302963 }
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05302964 return db;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302965}
2966
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002967static int out_set_volume(struct audio_stream_out *stream, float left,
2968 float right)
2969{
Eric Laurenta9024de2013-04-04 09:19:12 -07002970 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002971 int volume[2];
2972
Eric Laurenta9024de2013-04-04 09:19:12 -07002973 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
2974 /* only take left channel into account: the API is for stereo anyway */
2975 out->muted = (left == 0.0f);
2976 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002977 } else if (is_offload_usecase(out->usecase)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302978 if (audio_extn_passthru_is_passthrough_stream(out)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002979 /*
2980 * Set mute or umute on HDMI passthrough stream.
2981 * Only take left channel into account.
2982 * Mute is 0 and unmute 1
2983 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05302984 audio_extn_passthru_set_volume(out, (left == 0.0f));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302985 } else if (out->format == AUDIO_FORMAT_DSD){
2986 char mixer_ctl_name[128] = "DSD Volume";
2987 struct audio_device *adev = out->dev;
2988 struct mixer_ctl *ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2989
2990 if (!ctl) {
2991 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2992 __func__, mixer_ctl_name);
2993 return -EINVAL;
2994 }
2995 volume[0] = (int)(AmpToDb(left));
2996 volume[1] = (int)(AmpToDb(right));
2997 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
2998 return 0;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07002999 } else {
3000 char mixer_ctl_name[128];
3001 struct audio_device *adev = out->dev;
3002 struct mixer_ctl *ctl;
3003 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003004 PCM_PLAYBACK);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003005
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003006 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
3007 "Compress Playback %d Volume", pcm_device_id);
3008 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
3009 if (!ctl) {
3010 ALOGE("%s: Could not get ctl for mixer cmd - %s",
3011 __func__, mixer_ctl_name);
3012 return -EINVAL;
3013 }
3014 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
3015 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
3016 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
3017 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003018 }
Eric Laurenta9024de2013-04-04 09:19:12 -07003019 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003020
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003021 return -ENOSYS;
3022}
3023
3024static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
3025 size_t bytes)
3026{
3027 struct stream_out *out = (struct stream_out *)stream;
3028 struct audio_device *adev = out->dev;
Naresh Tanniru80659832014-06-04 18:17:56 +05303029 int snd_scard_state = get_snd_card_state(adev);
Eric Laurent6e895242013-09-05 16:10:57 -07003030 ssize_t ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003031
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003032 lock_output_stream(out);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303033
Naresh Tanniru80659832014-06-04 18:17:56 +05303034 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08003035
Dhanalakshmi Siddani44db0cc2016-06-30 16:40:38 +05303036 if ((!(out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) && is_offload_usecase(out->usecase)) {
Ashish Jainbbce4322016-02-16 13:25:27 +05303037 /*during SSR for compress usecase we should return error to flinger*/
Naresh Tanniru80659832014-06-04 18:17:56 +05303038 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
3039 pthread_mutex_unlock(&out->lock);
3040 return -ENETRESET;
Ashish Jainbbce4322016-02-16 13:25:27 +05303041 } else {
3042 /* increase written size during SSR to avoid mismatch
3043 * with the written frames count in AF
3044 */
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07003045 // bytes per frame
3046 size_t bpf = audio_bytes_per_sample(out->format) *
3047 audio_channel_count_from_out_mask(out->channel_mask);
3048 if (bpf != 0)
3049 out->written += bytes / bpf;
Ashish Jainbbce4322016-02-16 13:25:27 +05303050 ALOGD(" %s: sound card is not active/SSR state", __func__);
3051 ret= -EIO;
3052 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303053 }
3054 }
3055
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303056 if (audio_extn_passthru_should_drop_data(out)) {
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303057 ALOGV(" %s : Drop data as compress passthrough session is going on", __func__);
3058 if (audio_bytes_per_sample(out->format) != 0)
3059 out->written += bytes / (out->config.channels * audio_bytes_per_sample(out->format));
3060 ret = -EIO;
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303061 goto exit;
3062 }
3063
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003064 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07003065 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08003066 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003067 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
3068 ret = voice_extn_compress_voip_start_output_stream(out);
3069 else
3070 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003071 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003072 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003073 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07003074 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003075 goto exit;
3076 }
vivek mehtab72d08d2016-04-29 03:16:47 -07003077
3078 if (last_known_cal_step != -1) {
3079 ALOGD("%s: retry previous failed cal level set", __func__);
3080 audio_hw_send_gain_dep_calibration(last_known_cal_step);
3081 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003082 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003083
Ashish Jain81eb2a82015-05-13 10:52:34 +05303084 if (adev->is_channel_status_set == false && (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)){
Alexy Josephb1379942016-01-29 15:49:38 -08003085 audio_utils_set_hdmi_channel_status(out, (void *)buffer, bytes);
Ashish Jain81eb2a82015-05-13 10:52:34 +05303086 adev->is_channel_status_set = true;
3087 }
3088
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003089 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08003090 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003091 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003092 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003093 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
3094 out->send_new_metadata = 0;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303095 if (out->send_next_track_params && out->is_compr_metadata_avail) {
3096 ALOGD("copl(%p):send next track params in gapless", out);
3097 compress_set_next_track_param(out->compr, &(out->compr_config.codec->options));
3098 out->send_next_track_params = false;
3099 out->is_compr_metadata_avail = false;
3100 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003101 }
Ashish Jainf1eaa582016-05-23 20:54:24 +05303102 if ((out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05303103 (out->convert_buffer) != NULL) {
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003104
Ashish Jain83a6cc22016-06-28 14:34:17 +05303105 if ((bytes > out->hal_fragment_size)) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05303106 ALOGW("Error written bytes %zu > %d (fragment_size)",
Ashish Jain83a6cc22016-06-28 14:34:17 +05303107 bytes, out->hal_fragment_size);
Ashish Jainf1eaa582016-05-23 20:54:24 +05303108 pthread_mutex_unlock(&out->lock);
3109 return -EINVAL;
3110 } else {
Ashish Jain83a6cc22016-06-28 14:34:17 +05303111 audio_format_t dst_format = out->hal_op_format;
3112 audio_format_t src_format = out->hal_ip_format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05303113
3114 uint32_t frames = bytes / format_to_bitwidth_table[src_format];
3115 uint32_t bytes_to_write = frames * format_to_bitwidth_table[dst_format];
3116
Ashish Jain83a6cc22016-06-28 14:34:17 +05303117 memcpy_by_audio_format(out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05303118 dst_format,
3119 buffer,
3120 src_format,
3121 frames);
3122
Ashish Jain83a6cc22016-06-28 14:34:17 +05303123 ret = compress_write(out->compr, out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05303124 bytes_to_write);
3125
3126 /*Convert written bytes in audio flinger format*/
3127 if (ret > 0)
3128 ret = ((ret * format_to_bitwidth_table[out->format]) /
3129 format_to_bitwidth_table[dst_format]);
3130 }
3131 } else
3132 ret = compress_write(out->compr, buffer, bytes);
3133
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05303134 if (ret < 0)
3135 ret = -errno;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303136 ALOGVV("%s: writing buffer (%zu bytes) to compress device returned %zd", __func__, bytes, ret);
Ashish Jainb26edfb2016-08-25 00:10:11 +05303137 /*msg to cb thread only if non blocking write is enabled*/
3138 if (ret >= 0 && ret < (ssize_t)bytes && out->non_blocking) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05303139 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003140 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05303141 } else if (-ENETRESET == ret) {
3142 ALOGE("copl %s: received sound card offline state on compress write", __func__);
3143 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
3144 pthread_mutex_unlock(&out->lock);
3145 out_standby(&out->stream.common);
3146 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003147 }
Ashish Jain5106d362016-05-11 19:23:33 +05303148 if ( ret == (ssize_t)bytes && !out->non_blocking)
3149 out->written += bytes;
3150
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05303151 /* Call compr start only when non-zero bytes of data is there to be rendered */
3152 if (!out->playback_started && ret > 0) {
3153 int status = compress_start(out->compr);
3154 if (status < 0) {
3155 ret = status;
3156 ALOGE("%s: compr start failed with err %d", __func__, errno);
3157 goto exit;
3158 }
Alexy Joseph7de344d2015-03-30 10:40:03 -07003159 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003160 out->playback_started = 1;
3161 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003162
3163 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3164 popcount(out->channel_mask),
3165 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003166 }
3167 pthread_mutex_unlock(&out->lock);
3168 return ret;
3169 } else {
3170 if (out->pcm) {
3171 if (out->muted)
3172 memset((void *)buffer, 0, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003173
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303174 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003175
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003176 long ns = 0;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003177
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003178 if (out->config.rate)
3179 ns = pcm_bytes_to_frames(out->pcm, bytes)*1000000000LL/
3180 out->config.rate;
3181
3182 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
3183
3184 request_out_focus(out, ns);
3185
3186 if (use_mmap)
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003187 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003188 else if (out->hal_op_format != out->hal_ip_format &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05303189 out->convert_buffer != NULL) {
3190
3191 memcpy_by_audio_format(out->convert_buffer,
3192 out->hal_op_format,
3193 buffer,
3194 out->hal_ip_format,
3195 out->config.period_size * out->config.channels);
3196
3197 ret = pcm_write(out->pcm, out->convert_buffer,
3198 (out->config.period_size *
3199 out->config.channels *
3200 format_to_bitwidth_table[out->hal_op_format]));
3201 } else {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003202 ret = pcm_write(out->pcm, (void *)buffer, bytes);
Ashish Jain83a6cc22016-06-28 14:34:17 +05303203 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003204
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003205 release_out_focus(out);
3206
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05303207 if (ret < 0)
3208 ret = -errno;
Ashish Jain83a6cc22016-06-28 14:34:17 +05303209 else if (ret == 0 && (audio_bytes_per_sample(out->format) != 0))
3210 out->written += bytes / (out->config.channels * audio_bytes_per_sample(out->format));
3211 else
3212 ret = -EINVAL;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003213 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003214 }
3215
3216exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05303217 /* ToDo: There may be a corner case when SSR happens back to back during
3218 start/stop. Need to post different error to handle that. */
Naresh Tanniru4c630392014-05-12 01:05:52 +05303219 if (-ENETRESET == ret) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303220 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303221 }
3222
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003223 pthread_mutex_unlock(&out->lock);
3224
3225 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003226 if (out->pcm)
Alexy Josephb1379942016-01-29 15:49:38 -08003227 ALOGE("%s: error %d, %s", __func__, (int)ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303228 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303229 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303230 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303231 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303232 out->standby = true;
3233 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003234 out_standby(&out->stream.common);
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05303235 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))
3236 usleep((uint64_t)bytes * 1000000 / audio_stream_out_frame_size(stream) /
3237 out_get_sample_rate(&out->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003238 }
3239 return bytes;
3240}
3241
3242static int out_get_render_position(const struct audio_stream_out *stream,
3243 uint32_t *dsp_frames)
3244{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003245 struct stream_out *out = (struct stream_out *)stream;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303246 struct audio_device *adev = out->dev;
Zhou Song32a556e2015-05-05 10:46:56 +08003247
3248 if (dsp_frames == NULL)
3249 return -EINVAL;
3250
3251 *dsp_frames = 0;
3252 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08003253 ssize_t ret = 0;
Ashish Jain5106d362016-05-11 19:23:33 +05303254
3255 /* Below piece of code is not guarded against any lock beacuse audioFliner serializes
3256 * this operation and adev_close_output_stream(where out gets reset).
3257 */
3258 if (!out->non_blocking && (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) {
3259 *dsp_frames = get_actual_pcm_frames_rendered(out);
3260 ALOGVV("dsp_frames %d sampleRate %d",(int)*dsp_frames,out->sample_rate);
3261 return 0;
3262 }
3263
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003264 lock_output_stream(out);
Ashish Jain5106d362016-05-11 19:23:33 +05303265 if (out->compr != NULL && out->non_blocking) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303266 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003267 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05303268 if (ret < 0)
3269 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003270 ALOGVV("%s rendered frames %d sample_rate %d",
Ashish Jain5106d362016-05-11 19:23:33 +05303271 __func__, *dsp_frames, out->sample_rate);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003272 }
3273 pthread_mutex_unlock(&out->lock);
Naresh Tanniru80659832014-06-04 18:17:56 +05303274 if (-ENETRESET == ret) {
3275 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
3276 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
3277 return -EINVAL;
3278 } else if(ret < 0) {
3279 ALOGE(" ERROR: Unable to get time stamp from compress driver");
3280 return -EINVAL;
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303281 } else if (get_snd_card_state(adev) == SND_CARD_STATE_OFFLINE){
3282 /*
3283 * Handle corner case where compress session is closed during SSR
3284 * and timestamp is queried
3285 */
3286 ALOGE(" ERROR: sound card not active, return error");
3287 return -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05303288 } else {
3289 return 0;
3290 }
Zhou Song32a556e2015-05-05 10:46:56 +08003291 } else if (audio_is_linear_pcm(out->format)) {
3292 *dsp_frames = out->written;
3293 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003294 } else
3295 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003296}
3297
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003298static int out_add_audio_effect(const struct audio_stream *stream __unused,
3299 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003300{
3301 return 0;
3302}
3303
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003304static int out_remove_audio_effect(const struct audio_stream *stream __unused,
3305 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003306{
3307 return 0;
3308}
3309
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003310static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
3311 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003312{
3313 return -EINVAL;
3314}
3315
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003316static int out_get_presentation_position(const struct audio_stream_out *stream,
3317 uint64_t *frames, struct timespec *timestamp)
3318{
3319 struct stream_out *out = (struct stream_out *)stream;
3320 int ret = -1;
Eric Laurent949a0892013-09-20 09:20:13 -07003321 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003322
Ashish Jain5106d362016-05-11 19:23:33 +05303323 /* below piece of code is not guarded against any lock because audioFliner serializes
3324 * this operation and adev_close_output_stream( where out gets reset).
3325 */
3326 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
3327 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) {
3328 *frames = get_actual_pcm_frames_rendered(out);
3329 /* this is the best we can do */
3330 clock_gettime(CLOCK_MONOTONIC, timestamp);
3331 ALOGVV("frames %lld playedat %lld",(long long int)*frames,
3332 timestamp->tv_sec * 1000000LL + timestamp->tv_nsec / 1000);
3333 return 0;
3334 }
3335
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003336 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003337
Ashish Jain5106d362016-05-11 19:23:33 +05303338 if (is_offload_usecase(out->usecase) && out->compr != NULL && out->non_blocking) {
3339 ret = compress_get_tstamp(out->compr, &dsp_frames,
3340 &out->sample_rate);
3341 ALOGVV("%s rendered frames %ld sample_rate %d",
3342 __func__, dsp_frames, out->sample_rate);
3343 *frames = dsp_frames;
3344 if (ret < 0)
3345 ret = -errno;
3346 if (-ENETRESET == ret) {
3347 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
3348 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
3349 ret = -EINVAL;
3350 } else
3351 ret = 0;
3352 /* this is the best we can do */
3353 clock_gettime(CLOCK_MONOTONIC, timestamp);
Eric Laurent949a0892013-09-20 09:20:13 -07003354 } else {
3355 if (out->pcm) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003356 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07003357 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
3358 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07003359 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07003360 // This adjustment accounts for buffering after app processor.
3361 // It is based on estimated DSP latency per use case, rather than exact.
3362 signed_frames -=
3363 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
3364
Eric Laurent949a0892013-09-20 09:20:13 -07003365 // It would be unusual for this value to be negative, but check just in case ...
3366 if (signed_frames >= 0) {
3367 *frames = signed_frames;
3368 ret = 0;
3369 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003370 }
Ashish Jainbbce4322016-02-16 13:25:27 +05303371 } else if (adev->snd_card_status.state == SND_CARD_STATE_OFFLINE) {
3372 *frames = out->written;
3373 clock_gettime(CLOCK_MONOTONIC, timestamp);
3374 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003375 }
3376 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003377 pthread_mutex_unlock(&out->lock);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003378 return ret;
3379}
3380
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003381static int out_set_callback(struct audio_stream_out *stream,
3382 stream_callback_t callback, void *cookie)
3383{
3384 struct stream_out *out = (struct stream_out *)stream;
3385
3386 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003387 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003388 out->offload_callback = callback;
3389 out->offload_cookie = cookie;
3390 pthread_mutex_unlock(&out->lock);
3391 return 0;
3392}
3393
3394static int out_pause(struct audio_stream_out* stream)
3395{
3396 struct stream_out *out = (struct stream_out *)stream;
3397 int status = -ENOSYS;
3398 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003399 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003400 ALOGD("copl(%p):pause compress driver", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003401 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003402 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303403 struct audio_device *adev = out->dev;
3404 int snd_scard_state = get_snd_card_state(adev);
3405
3406 if (SND_CARD_STATE_ONLINE == snd_scard_state)
3407 status = compress_pause(out->compr);
3408
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003409 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003410
Mingming Yin21854652016-04-13 11:54:02 -07003411 if (audio_extn_passthru_is_active()) {
3412 ALOGV("offload use case, pause passthru");
3413 audio_extn_passthru_on_pause(out);
3414 }
3415
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05303416 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003417 audio_extn_dts_notify_playback_state(out->usecase, 0,
3418 out->sample_rate, popcount(out->channel_mask),
3419 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003420 }
3421 pthread_mutex_unlock(&out->lock);
3422 }
3423 return status;
3424}
3425
3426static int out_resume(struct audio_stream_out* stream)
3427{
3428 struct stream_out *out = (struct stream_out *)stream;
3429 int status = -ENOSYS;
3430 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003431 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003432 ALOGD("copl(%p):resume compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003433 status = 0;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003434 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003435 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Naresh Tanniru80659832014-06-04 18:17:56 +05303436 struct audio_device *adev = out->dev;
3437 int snd_scard_state = get_snd_card_state(adev);
3438
Mingming Yin21854652016-04-13 11:54:02 -07003439 if (SND_CARD_STATE_ONLINE == snd_scard_state) {
3440 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3441 pthread_mutex_lock(&out->dev->lock);
3442 ALOGV("offload resume, check and set hdmi backend again");
Mingming Yin21854652016-04-13 11:54:02 -07003443 pthread_mutex_unlock(&out->dev->lock);
3444 }
Naresh Tanniru80659832014-06-04 18:17:56 +05303445 status = compress_resume(out->compr);
Mingming Yin21854652016-04-13 11:54:02 -07003446 }
3447 if (!status) {
3448 out->offload_state = OFFLOAD_STATE_PLAYING;
3449 }
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05303450 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003451 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3452 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003453 }
3454 pthread_mutex_unlock(&out->lock);
3455 }
3456 return status;
3457}
3458
3459static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
3460{
3461 struct stream_out *out = (struct stream_out *)stream;
3462 int status = -ENOSYS;
3463 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003464 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003465 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003466 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
3467 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
3468 else
3469 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
3470 pthread_mutex_unlock(&out->lock);
3471 }
3472 return status;
3473}
3474
3475static int out_flush(struct audio_stream_out* stream)
3476{
3477 struct stream_out *out = (struct stream_out *)stream;
3478 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003479 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003480 ALOGD("copl(%p):calling compress flush", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003481 lock_output_stream(out);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07003482 if (out->offload_state == OFFLOAD_STATE_PAUSED) {
3483 stop_compressed_output_l(out);
3484 out->written = 0;
3485 } else {
3486 ALOGW("%s called in invalid state %d", __func__, out->offload_state);
3487 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003488 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003489 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003490 return 0;
3491 }
3492 return -ENOSYS;
3493}
3494
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003495/** audio_stream_in implementation **/
3496static uint32_t in_get_sample_rate(const struct audio_stream *stream)
3497{
3498 struct stream_in *in = (struct stream_in *)stream;
3499
3500 return in->config.rate;
3501}
3502
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003503static int in_set_sample_rate(struct audio_stream *stream __unused,
3504 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003505{
3506 return -ENOSYS;
3507}
3508
3509static size_t in_get_buffer_size(const struct audio_stream *stream)
3510{
3511 struct stream_in *in = (struct stream_in *)stream;
3512
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003513 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
3514 return voice_extn_compress_voip_in_get_buffer_size(in);
Mingming Yine62d7842013-10-25 16:26:03 -07003515 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
3516 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303517 else if(audio_extn_cin_attached_usecase(in->usecase))
3518 return audio_extn_cin_get_buffer_size(in);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003519
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003520 return in->config.period_size * in->af_period_multiplier *
3521 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003522}
3523
3524static uint32_t in_get_channels(const struct audio_stream *stream)
3525{
3526 struct stream_in *in = (struct stream_in *)stream;
3527
3528 return in->channel_mask;
3529}
3530
3531static audio_format_t in_get_format(const struct audio_stream *stream)
3532{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003533 struct stream_in *in = (struct stream_in *)stream;
3534
3535 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003536}
3537
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003538static int in_set_format(struct audio_stream *stream __unused,
3539 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003540{
3541 return -ENOSYS;
3542}
3543
3544static int in_standby(struct audio_stream *stream)
3545{
3546 struct stream_in *in = (struct stream_in *)stream;
3547 struct audio_device *adev = in->dev;
3548 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303549 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
3550 stream, in->usecase, use_case_table[in->usecase]);
3551
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003552 lock_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003553 if (!in->standby && in->is_st_session) {
3554 ALOGD("%s: sound trigger pcm stop lab", __func__);
3555 audio_extn_sound_trigger_stop_lab(in);
3556 in->standby = 1;
3557 }
3558
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003559 if (!in->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003560 if (adev->adm_deregister_stream)
3561 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
3562
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08003563 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003564 in->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08003565 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
3566 voice_extn_compress_voip_close_input_stream(stream);
3567 ALOGD("VOIP input entered standby");
3568 } else {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303569 if (audio_extn_cin_attached_usecase(in->usecase))
3570 audio_extn_cin_stop_input_stream(in);
Zhou Songa8895042016-07-05 17:54:22 +08003571 if (in->pcm) {
3572 pcm_close(in->pcm);
3573 in->pcm = NULL;
3574 }
3575 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003576 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003577 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003578 }
3579 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07003580 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003581 return status;
3582}
3583
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003584static int in_dump(const struct audio_stream *stream __unused,
3585 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003586{
3587 return 0;
3588}
3589
3590static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
3591{
3592 struct stream_in *in = (struct stream_in *)stream;
3593 struct audio_device *adev = in->dev;
3594 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003595 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003596 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003597
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303598 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003599 parms = str_parms_create_str(kvpairs);
3600
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303601 if (!parms)
3602 goto error;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003603 lock_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003604 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003605
3606 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
3607 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003608 val = atoi(value);
3609 /* no audio source uses val == 0 */
3610 if ((in->source != val) && (val != 0)) {
3611 in->source = val;
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003612 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
3613 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
3614 (voice_extn_compress_voip_is_format_supported(in->format)) &&
Shiv Maliyappanahallie66aba22016-01-27 16:08:57 -08003615 (in->config.rate == 8000 || in->config.rate == 16000 ||
3616 in->config.rate == 32000 || in->config.rate == 48000 ) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003617 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08003618 err = voice_extn_compress_voip_open_input_stream(in);
3619 if (err != 0) {
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003620 ALOGE("%s: Compress voip input cannot be opened, error:%d",
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08003621 __func__, err);
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08003622 }
3623 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003624 }
3625 }
3626
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003627 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
3628 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003629 val = atoi(value);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003630 if (((int)in->device != val) && (val != 0)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003631 in->device = val;
3632 /* If recording is in progress, change the tx device to new device */
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003633 if (!in->standby && !in->is_st_session) {
3634 ALOGV("update input routing change");
Haynes Mathew George822b5492016-07-01 16:57:24 -07003635 if (adev->adm_on_routing_change)
3636 adev->adm_on_routing_change(adev->adm_data,
3637 in->capture_handle);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003638 ret = select_devices(adev, in->usecase);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003639 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003640 }
3641 }
3642
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05303643 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
3644 if (err >= 0) {
3645 strlcpy(in->profile, value, sizeof(in->profile));
3646 ALOGV("updating stream profile with value '%s'", in->profile);
3647 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
3648 &adev->streams_input_cfg_list,
3649 in->device, in->flags, in->format,
3650 in->sample_rate, in->bit_width,
3651 in->profile, &in->app_type_cfg);
3652 }
3653
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003654 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003655 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003656
3657 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05303658error:
Eric Laurent994a6932013-07-17 11:51:42 -07003659 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003660 return ret;
3661}
3662
3663static char* in_get_parameters(const struct audio_stream *stream,
3664 const char *keys)
3665{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003666 struct stream_in *in = (struct stream_in *)stream;
3667 struct str_parms *query = str_parms_create_str(keys);
3668 char *str;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003669 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003670
3671 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08003672 if (reply) {
3673 str_parms_destroy(reply);
3674 }
3675 if (query) {
3676 str_parms_destroy(query);
3677 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003678 ALOGE("in_get_parameters: failed to create query or reply");
3679 return NULL;
3680 }
3681
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003682 ALOGV("%s: enter: keys - %s", __func__, keys);
3683
3684 voice_extn_in_get_parameters(in, query, reply);
3685
3686 str = str_parms_to_str(reply);
3687 str_parms_destroy(query);
3688 str_parms_destroy(reply);
3689
3690 ALOGV("%s: exit: returns - %s", __func__, str);
3691 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003692}
3693
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003694static int in_set_gain(struct audio_stream_in *stream __unused,
3695 float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003696{
3697 return 0;
3698}
3699
3700static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
3701 size_t bytes)
3702{
3703 struct stream_in *in = (struct stream_in *)stream;
3704 struct audio_device *adev = in->dev;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303705 int ret = -1;
Naresh Tanniru80659832014-06-04 18:17:56 +05303706 int snd_scard_state = get_snd_card_state(adev);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303707 size_t bytes_read = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003708
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003709 lock_input_stream(in);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303710
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003711 if (in->is_st_session) {
3712 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
3713 /* Read from sound trigger HAL */
3714 audio_extn_sound_trigger_read(in, buffer, bytes);
3715 pthread_mutex_unlock(&in->lock);
3716 return bytes;
3717 }
3718
Ashish Jainbbce4322016-02-16 13:25:27 +05303719 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003720 ALOGD(" %s: sound card is not active/SSR state", __func__);
3721 ret= -EIO;;
3722 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303723 }
3724
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003725 if (in->standby) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003726 pthread_mutex_lock(&adev->lock);
3727 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
3728 ret = voice_extn_compress_voip_start_input_stream(in);
3729 else
3730 ret = start_input_stream(in);
3731 pthread_mutex_unlock(&adev->lock);
3732 if (ret != 0) {
3733 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003734 }
3735 in->standby = 0;
3736 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003737
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003738 // what's the duration requested by the client?
3739 long ns = 0;
3740
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303741 if (in->pcm && in->config.rate)
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003742 ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
3743 in->config.rate;
3744
3745 request_in_focus(in, ns);
3746 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003747
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303748 if (audio_extn_cin_attached_usecase(in->usecase)) {
3749 ret = audio_extn_cin_read(in, buffer, bytes, &bytes_read);
3750 } else if (in->pcm) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303751 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003752 ret = audio_extn_ssr_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303753 } else if (audio_extn_compr_cap_usecase_supported(in->usecase)) {
Mingming Yine62d7842013-10-25 16:26:03 -07003754 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003755 } else if (use_mmap) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003756 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303757 } else {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003758 ret = pcm_read(in->pcm, buffer, bytes);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303759 /* data from DSP comes in 24_8 format, convert it to 8_24 */
3760 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
3761 if (audio_extn_utils_convert_format_24_8_to_8_24(buffer, bytes)
3762 != bytes) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303763 ret = -EINVAL;
3764 goto exit;
3765 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303766 } else if (ret < 0) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303767 ret = -errno;
3768 }
3769 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303770 /* bytes read is always set to bytes for non compress usecases */
3771 bytes_read = bytes;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003772 }
3773
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003774 release_in_focus(in);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003775
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003776 /*
3777 * Instead of writing zeroes here, we could trust the hardware
3778 * to always provide zeroes when muted.
3779 */
Pavan Chikkala63964842014-12-04 10:48:28 +05303780 if (ret == 0 && voice_get_mic_mute(adev) && !voice_is_in_call_rec_stream(in) &&
3781 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003782 memset(buffer, 0, bytes);
3783
3784exit:
Dhanalakshmi Siddani8fc6d912014-05-26 18:03:42 +05303785 /* ToDo: There may be a corner case when SSR happens back to back during
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303786 start/stop. Need to post different error to handle that. */
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07003787 if (-ENETRESET == ret)
3788 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
3789
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003790 pthread_mutex_unlock(&in->lock);
3791
3792 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303793 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303794 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303795 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05303796 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05303797 in->standby = true;
3798 }
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303799 memset(buffer, 0, bytes);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003800 in_standby(&in->stream.common);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07003801 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ashish Jainbbce4322016-02-16 13:25:27 +05303802 usleep((uint64_t)bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05303803 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003804 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303805 return bytes_read;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003806}
3807
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003808static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003809{
3810 return 0;
3811}
3812
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003813static int add_remove_audio_effect(const struct audio_stream *stream,
3814 effect_handle_t effect,
3815 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003816{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003817 struct stream_in *in = (struct stream_in *)stream;
3818 int status = 0;
3819 effect_descriptor_t desc;
3820
3821 status = (*effect)->get_descriptor(effect, &desc);
3822 if (status != 0)
3823 return status;
3824
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003825 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003826 pthread_mutex_lock(&in->dev->lock);
3827 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
3828 in->enable_aec != enable &&
3829 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
3830 in->enable_aec = enable;
3831 if (!in->standby)
3832 select_devices(in->dev, in->usecase);
3833 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08003834 if (in->enable_ns != enable &&
3835 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
3836 in->enable_ns = enable;
3837 if (!in->standby)
3838 select_devices(in->dev, in->usecase);
3839 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003840 pthread_mutex_unlock(&in->dev->lock);
3841 pthread_mutex_unlock(&in->lock);
3842
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003843 return 0;
3844}
3845
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003846static int in_add_audio_effect(const struct audio_stream *stream,
3847 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003848{
Eric Laurent994a6932013-07-17 11:51:42 -07003849 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003850 return add_remove_audio_effect(stream, effect, true);
3851}
3852
3853static int in_remove_audio_effect(const struct audio_stream *stream,
3854 effect_handle_t effect)
3855{
Eric Laurent994a6932013-07-17 11:51:42 -07003856 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003857 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003858}
3859
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05303860int adev_open_output_stream(struct audio_hw_device *dev,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003861 audio_io_handle_t handle,
3862 audio_devices_t devices,
3863 audio_output_flags_t flags,
3864 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003865 struct audio_stream_out **stream_out,
3866 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003867{
3868 struct audio_device *adev = (struct audio_device *)dev;
3869 struct stream_out *out;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303870 int ret = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003871 audio_format_t format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003872
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003873 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05303874
3875 if ((flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
3876 (SND_CARD_STATE_OFFLINE == get_snd_card_state(adev))) {
vivek mehta0ea887a2015-08-26 14:01:20 -07003877 ALOGE("sound card is not active rejecting compress output open request");
Naresh Tanniru80659832014-06-04 18:17:56 +05303878 return -EINVAL;
3879 }
3880
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003881 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
3882
Mingming Yin3a941d42016-02-17 18:08:05 -08003883 ALOGD("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
3884 stream_handle(%p)", __func__, config->format, config->sample_rate, config->channel_mask,
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303885 devices, flags, &out->stream);
3886
3887
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08003888 if (!out) {
3889 return -ENOMEM;
3890 }
3891
Haynes Mathew George204045b2015-02-25 20:32:03 -08003892 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003893 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Haynes Mathew George204045b2015-02-25 20:32:03 -08003894 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
3895
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003896 if (devices == AUDIO_DEVICE_NONE)
3897 devices = AUDIO_DEVICE_OUT_SPEAKER;
3898
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003899 out->flags = flags;
3900 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07003901 out->dev = adev;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07003902 format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003903 out->sample_rate = config->sample_rate;
3904 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
3905 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07003906 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07003907 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08003908 out->non_blocking = 0;
Ashish Jain83a6cc22016-06-28 14:34:17 +05303909 out->convert_buffer = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003910
Mingming Yin3a941d42016-02-17 18:08:05 -08003911 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL &&
3912 (flags & AUDIO_OUTPUT_FLAG_DIRECT)) {
3913 pthread_mutex_lock(&adev->lock);
3914 ALOGV("AUDIO_DEVICE_OUT_AUX_DIGITAL and DIRECT|OFFLOAD, check hdmi caps");
3915 ret = read_hdmi_sink_caps(out);
3916 pthread_mutex_unlock(&adev->lock);
3917 if (ret != 0) {
3918 if (ret == -ENOSYS) {
3919 /* ignore and go with default */
3920 ret = 0;
3921 } else {
3922 ALOGE("error reading hdmi sink caps");
3923 goto error_open;
3924 }
3925 }
3926 }
3927
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003928 /* Init use case and pcm_config */
Mingming Yin57c46622015-07-21 15:22:22 -07003929 if ((out->flags & AUDIO_OUTPUT_FLAG_DIRECT) &&
Satya Krishna Pindiproli125900e2016-01-22 14:32:15 +05303930 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD ||
3931 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) &&
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08003932 (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL ||
3933 out->devices & AUDIO_DEVICE_OUT_PROXY)) {
3934
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003935 pthread_mutex_lock(&adev->lock);
Mingming Yin3a941d42016-02-17 18:08:05 -08003936 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
3937 /*
3938 * Do not handle stereo output in Multi-channel cases
3939 * Stereo case is handled in normal playback path
3940 */
3941 if (out->supported_channel_masks[0] == AUDIO_CHANNEL_OUT_STEREO)
3942 ret = AUDIO_CHANNEL_OUT_STEREO;
3943 }
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08003944
3945 if (out->devices & AUDIO_DEVICE_OUT_PROXY)
3946 ret = audio_extn_read_afe_proxy_channel_masks(out);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003947 pthread_mutex_unlock(&adev->lock);
Eric Laurent07eeafd2013-10-06 12:52:49 -07003948 if (ret != 0)
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003949 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003950
3951 if (config->sample_rate == 0)
3952 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
3953 if (config->channel_mask == 0)
3954 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
Mingming Yin3a941d42016-02-17 18:08:05 -08003955 if (config->format == 0)
3956 config->format = AUDIO_FORMAT_PCM_16_BIT;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003957
3958 out->channel_mask = config->channel_mask;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003959 out->sample_rate = config->sample_rate;
Mingming Yin3a941d42016-02-17 18:08:05 -08003960 out->format = config->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003961 out->usecase = USECASE_AUDIO_PLAYBACK_MULTI_CH;
3962 out->config = pcm_config_hdmi_multi;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003963 out->config.rate = config->sample_rate;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003964 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003965 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels * 2);
kunleizc5fefba2016-11-15 11:20:56 +08003966 } else if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION || voice_extn_compress_voip_is_active(out->dev)) &&
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003967 (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX)) &&
Narsinga Rao Chella1eceff82013-12-02 19:25:28 -08003968 (voice_extn_compress_voip_is_config_supported(config))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003969 ret = voice_extn_compress_voip_open_output_stream(out);
3970 if (ret != 0) {
3971 ALOGE("%s: Compress voip output cannot be opened, error:%d",
3972 __func__, ret);
3973 goto error_open;
3974 }
vivek mehta0ea887a2015-08-26 14:01:20 -07003975 } else if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
3976 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) {
3977
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003978 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
3979 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
3980 ALOGE("%s: Unsupported Offload information", __func__);
3981 ret = -EINVAL;
3982 goto error_open;
3983 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003984
Mingming Yin3a941d42016-02-17 18:08:05 -08003985 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003986 if(config->offload_info.format == 0)
3987 config->offload_info.format = out->supported_formats[0];
Mingming Yin3a941d42016-02-17 18:08:05 -08003988 if (config->offload_info.sample_rate == 0)
3989 config->offload_info.sample_rate = out->supported_sample_rates[0];
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003990 }
3991
Mingming Yin90310102013-11-13 16:57:00 -08003992 if (!is_supported_format(config->offload_info.format) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303993 !audio_extn_passthru_is_supported_format(config->offload_info.format)) {
vivek mehta0ea887a2015-08-26 14:01:20 -07003994 ALOGE("%s: Unsupported audio format %x " , __func__, config->offload_info.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003995 ret = -EINVAL;
3996 goto error_open;
3997 }
3998
3999 out->compr_config.codec = (struct snd_codec *)
4000 calloc(1, sizeof(struct snd_codec));
4001
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004002 if (!out->compr_config.codec) {
4003 ret = -ENOMEM;
4004 goto error_open;
4005 }
4006
vivek mehta0ea887a2015-08-26 14:01:20 -07004007 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) {
Ashish Jain5106d362016-05-11 19:23:33 +05304008 out->stream.pause = out_pause;
4009 out->stream.flush = out_flush;
4010 out->stream.resume = out_resume;
vivek mehta446c3962015-09-14 10:57:35 -07004011 out->usecase = get_offload_usecase(adev, true);
4012 ALOGV("DIRECT_PCM usecase ... usecase selected %d ", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07004013 } else {
Mingming Yin21d60472015-09-30 13:56:25 -07004014 out->stream.set_callback = out_set_callback;
4015 out->stream.pause = out_pause;
4016 out->stream.resume = out_resume;
4017 out->stream.drain = out_drain;
4018 out->stream.flush = out_flush;
vivek mehta446c3962015-09-14 10:57:35 -07004019 out->usecase = get_offload_usecase(adev, false);
4020 ALOGV("Compress Offload usecase .. usecase selected %d", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07004021 }
vivek mehta446c3962015-09-14 10:57:35 -07004022
4023 if (out->usecase == USECASE_INVALID) {
Mingming Yin3a941d42016-02-17 18:08:05 -08004024 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL &&
4025 config->format == 0 && config->sample_rate == 0 &&
4026 config->channel_mask == 0) {
Mingming Yin21854652016-04-13 11:54:02 -07004027 ALOGI("%s dummy open to query sink capability",__func__);
Mingming Yin3a941d42016-02-17 18:08:05 -08004028 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
4029 } else {
4030 ALOGE("%s, Max allowed OFFLOAD usecase reached ... ", __func__);
4031 ret = -EEXIST;
4032 goto error_open;
4033 }
vivek mehta446c3962015-09-14 10:57:35 -07004034 }
4035
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004036 if (config->offload_info.channel_mask)
4037 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08004038 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004039 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08004040 config->offload_info.channel_mask = config->channel_mask;
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07004041 } else {
4042 ALOGE("out->channel_mask not set for OFFLOAD/DIRECT_PCM");
4043 ret = -EINVAL;
4044 goto error_open;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08004045 }
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07004046
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07004047 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004048 out->sample_rate = config->offload_info.sample_rate;
4049
Mingming Yin3ee55c62014-08-04 14:23:35 -07004050 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004051
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304052 out->compr_config.codec->id = get_snd_codec_id(config->offload_info.format);
4053 if (audio_extn_is_dolby_format(config->offload_info.format)) {
4054 audio_extn_dolby_send_ddp_endp_params(adev);
4055 audio_extn_dolby_set_dmid(adev);
4056 }
vivek mehta0ea887a2015-08-26 14:01:20 -07004057
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004058 out->compr_config.codec->sample_rate =
Ravi Kumar Alamandab91bff32014-11-14 12:05:54 -08004059 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004060 out->compr_config.codec->bit_rate =
4061 config->offload_info.bit_rate;
4062 out->compr_config.codec->ch_in =
Dhanalakshmi Siddania15c6792016-08-10 15:33:53 +05304063 audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004064 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satish Babu Patakokilaa395a9e2016-11-01 12:18:49 +05304065 /* Update bit width only for non passthrough usecases.
4066 * For passthrough usecases, the output will always be opened @16 bit
4067 */
4068 if (!audio_extn_passthru_is_passthrough_stream(out))
4069 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004070 /*TODO: Do we need to change it for passthrough */
4071 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004072
Manish Dewangana6fc5442015-08-24 20:30:31 +05304073 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
4074 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05304075 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS)
Manish Dewangana6fc5442015-08-24 20:30:31 +05304076 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05304077 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_LATM)
4078 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4LATM;
Ashish Jainf1eaa582016-05-23 20:54:24 +05304079
4080 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) ==
4081 AUDIO_FORMAT_PCM) {
4082
4083 /*Based on platform support, configure appropriate alsa format for corresponding
4084 *hal input format.
4085 */
4086 out->compr_config.codec->format = hal_format_to_alsa(
4087 config->offload_info.format);
4088
Ashish Jain83a6cc22016-06-28 14:34:17 +05304089 out->hal_op_format = alsa_format_to_hal(
Ashish Jainf1eaa582016-05-23 20:54:24 +05304090 out->compr_config.codec->format);
Ashish Jain83a6cc22016-06-28 14:34:17 +05304091 out->hal_ip_format = out->format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05304092
4093 /*for direct PCM playback populate bit_width based on selected alsa format as
4094 *hal input format and alsa format might differ based on platform support.
4095 */
4096 out->bit_width = audio_bytes_per_sample(
Ashish Jain83a6cc22016-06-28 14:34:17 +05304097 out->hal_op_format) << 3;
Ashish Jainf1eaa582016-05-23 20:54:24 +05304098
4099 out->compr_config.fragments = DIRECT_PCM_NUM_FRAGMENTS;
4100
4101 /* Check if alsa session is configured with the same format as HAL input format,
4102 * if not then derive correct fragment size needed to accomodate the
4103 * conversion of HAL input format to alsa format.
4104 */
4105 audio_extn_utils_update_direct_pcm_fragment_size(out);
4106
4107 /*if hal input and output fragment size is different this indicates HAL input format is
4108 *not same as the alsa format
4109 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05304110 if (out->hal_fragment_size != out->compr_config.fragment_size) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05304111 /*Allocate a buffer to convert input data to the alsa configured format.
4112 *size of convert buffer is equal to the size required to hold one fragment size
4113 *worth of pcm data, this is because flinger does not write more than fragment_size
4114 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05304115 out->convert_buffer = calloc(1,out->compr_config.fragment_size);
4116 if (out->convert_buffer == NULL){
Ashish Jainf1eaa582016-05-23 20:54:24 +05304117 ALOGE("Allocation failed for convert buffer for size %d", out->compr_config.fragment_size);
4118 ret = -ENOMEM;
4119 goto error_open;
4120 }
4121 }
4122 } else if (audio_extn_passthru_is_passthrough_stream(out)) {
4123 out->compr_config.fragment_size =
4124 audio_extn_passthru_get_buffer_size(&config->offload_info);
4125 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
4126 } else {
4127 out->compr_config.fragment_size =
4128 platform_get_compress_offload_buffer_size(&config->offload_info);
4129 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
4130 }
Mingming Yin3ee55c62014-08-04 14:23:35 -07004131
Amit Shekhar6f461b12014-08-01 14:52:58 -07004132 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05304133 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Mingming Yin3ee55c62014-08-04 14:23:35 -07004134
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +05304135 if (config->offload_info.format == AUDIO_FORMAT_APTX) {
4136 audio_extn_send_aptx_dec_bt_addr_to_dsp(out);
4137 }
4138
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004139 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
4140 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004141
Manish Dewangan69426c82017-01-30 17:35:36 +05304142 if ((flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) &&
4143 (flags & AUDIO_OUTPUT_FLAG_HW_AV_SYNC)) {
4144 out->render_mode = RENDER_MODE_AUDIO_STC_MASTER;
4145 } else if(flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
4146 out->render_mode = RENDER_MODE_AUDIO_MASTER;
4147 } else {
4148 out->render_mode = RENDER_MODE_AUDIO_NO_TIMESTAMP;
4149 }
Alexy Josephaa54c872014-12-03 02:46:47 -08004150
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004151 out->send_new_metadata = 1;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05304152 out->send_next_track_params = false;
4153 out->is_compr_metadata_avail = false;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08004154 out->offload_state = OFFLOAD_STATE_IDLE;
4155 out->playback_started = 0;
4156
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004157 audio_extn_dts_create_state_notifier_node(out->usecase);
4158
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004159 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
4160 __func__, config->offload_info.version,
4161 config->offload_info.bit_rate);
Ashish Jain5106d362016-05-11 19:23:33 +05304162
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05304163 /* Check if DSD audio format is supported in codec
4164 * and there is no active native DSD use case
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304165 */
4166
4167 if ((config->format == AUDIO_FORMAT_DSD) &&
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05304168 (!platform_check_codec_dsd_support(adev->platform) ||
4169 audio_is_dsd_native_stream_active(adev))) {
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304170 ret = -EINVAL;
4171 goto error_open;
4172 }
4173
Ashish Jain5106d362016-05-11 19:23:33 +05304174 /* Disable gapless if any of the following is true
4175 * passthrough playback
4176 * AV playback
4177 * Direct PCM playback
4178 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304179 if (audio_extn_passthru_is_passthrough_stream(out) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05304180 (config->format == AUDIO_FORMAT_DSD) ||
4181 config->offload_info.has_video ||
4182 out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) {
Ashish Jain5106d362016-05-11 19:23:33 +05304183 check_and_set_gapless_mode(adev, false);
4184 } else
4185 check_and_set_gapless_mode(adev, true);
Mingming Yin21854652016-04-13 11:54:02 -07004186
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304187 if (audio_extn_passthru_is_passthrough_stream(out)) {
Mingming Yin21854652016-04-13 11:54:02 -07004188 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
4189 }
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304190 if (config->format == AUDIO_FORMAT_DSD) {
4191 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
4192 out->compr_config.codec->compr_passthr = PASSTHROUGH_DSD;
4193 }
Aalique Grahame0359a1f2016-09-08 16:54:22 -07004194
4195 create_offload_callback_thread(out);
4196
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07004197 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05304198 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07004199 if (ret != 0) {
4200 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
4201 __func__, ret);
4202 goto error_open;
4203 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004204 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
4205 if (config->sample_rate == 0)
4206 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4207 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
4208 config->sample_rate != 8000) {
4209 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4210 ret = -EINVAL;
4211 goto error_open;
4212 }
4213 out->sample_rate = config->sample_rate;
4214 out->config.rate = config->sample_rate;
4215 if (config->format == AUDIO_FORMAT_DEFAULT)
4216 config->format = AUDIO_FORMAT_PCM_16_BIT;
4217 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
4218 config->format = AUDIO_FORMAT_PCM_16_BIT;
4219 ret = -EINVAL;
4220 goto error_open;
4221 }
4222 out->format = config->format;
4223 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
4224 out->config = pcm_config_afe_proxy_playback;
4225 adev->voice_tx_output = out;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07004226 } else {
Ashish Jain058165c2016-09-28 23:18:48 +05304227 unsigned int channels = 0;
4228 /*Update config params to default if not set by the caller*/
4229 if (config->sample_rate == 0)
4230 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
4231 if (config->channel_mask == AUDIO_CHANNEL_NONE)
4232 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4233 if (config->format == AUDIO_FORMAT_DEFAULT)
4234 config->format = AUDIO_FORMAT_PCM_16_BIT;
4235
4236 channels = audio_channel_count_from_out_mask(out->channel_mask);
4237
Ashish Jain83a6cc22016-06-28 14:34:17 +05304238 if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
4239 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004240 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL,
4241 out->flags);
4242 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Ashish Jain83a6cc22016-06-28 14:34:17 +05304243 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
4244 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
4245 out->config = pcm_config_low_latency;
4246 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
4247 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
4248 out->config = pcm_config_deep_buffer;
Ashish Jain058165c2016-09-28 23:18:48 +05304249 out->config.period_size = get_output_period_size(config->sample_rate, out->format,
4250 channels, DEEP_BUFFER_OUTPUT_PERIOD_DURATION);
4251 if (out->config.period_size <= 0) {
4252 ALOGE("Invalid configuration period size is not valid");
4253 ret = -EINVAL;
4254 goto error_open;
4255 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05304256 } else {
4257 /* primary path is the default path selected if no other outputs are available/suitable */
4258 out->usecase = USECASE_AUDIO_PLAYBACK_PRIMARY;
4259 out->config = PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY;
4260 }
4261 out->hal_ip_format = format = out->format;
4262 out->config.format = hal_format_to_pcm(out->hal_ip_format);
4263 out->hal_op_format = pcm_format_to_hal(out->config.format);
4264 out->bit_width = format_to_bitwidth_table[out->hal_op_format] << 3;
4265 out->config.rate = config->sample_rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07004266 out->sample_rate = out->config.rate;
Ashish Jain058165c2016-09-28 23:18:48 +05304267 out->config.channels = channels;
Ashish Jain83a6cc22016-06-28 14:34:17 +05304268 if (out->hal_ip_format != out->hal_op_format) {
4269 uint32_t buffer_size = out->config.period_size *
4270 format_to_bitwidth_table[out->hal_op_format] *
4271 out->config.channels;
4272 out->convert_buffer = calloc(1, buffer_size);
4273 if (out->convert_buffer == NULL){
4274 ALOGE("Allocation failed for convert buffer for size %d",
4275 out->compr_config.fragment_size);
4276 ret = -ENOMEM;
4277 goto error_open;
4278 }
4279 ALOGD("Convert buffer allocated of size %d", buffer_size);
4280 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004281 }
4282
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08004283 ALOGV("%s devices:%d, format:%x, out->sample_rate:%d,out->bit_width:%d out->format:%d out->flags:%x, flags: %x usecase %d",
4284 __func__, devices, format, out->sample_rate, out->bit_width, out->format, out->flags, flags, out->usecase);
Ashish Jain83a6cc22016-06-28 14:34:17 +05304285
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004286 /* TODO remove this hardcoding and check why width is zero*/
4287 if (out->bit_width == 0)
4288 out->bit_width = 16;
Dhananjay Kumard6d32152016-10-13 16:11:03 +05304289 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07004290 &adev->streams_output_cfg_list,
Preetam Singh Ranawat4277a5a2017-01-18 19:02:24 +05304291 devices, out->flags, format, out->sample_rate,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05304292 out->bit_width, out->channel_mask, out->profile,
Manish Dewangan837dc462015-05-27 10:17:41 +05304293 &out->app_type_cfg);
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08004294 if ((out->usecase == USECASE_AUDIO_PLAYBACK_PRIMARY) ||
4295 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
4296 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004297 if(adev->primary_output == NULL)
4298 adev->primary_output = out;
4299 else {
4300 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004301 ret = -EEXIST;
4302 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004303 }
4304 }
4305
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004306 /* Check if this usecase is already existing */
4307 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07004308 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
4309 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004310 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004311 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004312 ret = -EEXIST;
4313 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004314 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08004315
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004316 pthread_mutex_unlock(&adev->lock);
4317
4318 out->stream.common.get_sample_rate = out_get_sample_rate;
4319 out->stream.common.set_sample_rate = out_set_sample_rate;
4320 out->stream.common.get_buffer_size = out_get_buffer_size;
4321 out->stream.common.get_channels = out_get_channels;
4322 out->stream.common.get_format = out_get_format;
4323 out->stream.common.set_format = out_set_format;
4324 out->stream.common.standby = out_standby;
4325 out->stream.common.dump = out_dump;
4326 out->stream.common.set_parameters = out_set_parameters;
4327 out->stream.common.get_parameters = out_get_parameters;
4328 out->stream.common.add_audio_effect = out_add_audio_effect;
4329 out->stream.common.remove_audio_effect = out_remove_audio_effect;
4330 out->stream.get_latency = out_get_latency;
4331 out->stream.set_volume = out_set_volume;
4332 out->stream.write = out_write;
4333 out->stream.get_render_position = out_get_render_position;
4334 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004335 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004336
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004337 out->af_period_multiplier = out->realtime ? af_period_multiplier : 1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004338 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07004339 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004340 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004341
4342 config->format = out->stream.common.get_format(&out->stream.common);
4343 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
4344 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
4345
4346 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304347 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
vivek mehta0ea887a2015-08-26 14:01:20 -07004348 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004349
4350 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
4351 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
4352 popcount(out->channel_mask), out->playback_started);
4353
Eric Laurent994a6932013-07-17 11:51:42 -07004354 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004355 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004356
4357error_open:
Ashish Jain83a6cc22016-06-28 14:34:17 +05304358 if (out->convert_buffer)
4359 free(out->convert_buffer);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004360 free(out);
4361 *stream_out = NULL;
4362 ALOGD("%s: exit: ret %d", __func__, ret);
4363 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004364}
4365
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05304366void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004367 struct audio_stream_out *stream)
4368{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004369 struct stream_out *out = (struct stream_out *)stream;
4370 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004371 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004372
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304373 ALOGD("%s: enter:stream_handle(%p)",__func__, out);
4374
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004375 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304376 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004377 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05304378 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004379 if(ret != 0)
4380 ALOGE("%s: Compress voip output cannot be closed, error:%d",
4381 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004382 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004383 out_standby(&stream->common);
4384
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004385 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004386 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004387 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004388 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004389 if (out->compr_config.codec != NULL)
4390 free(out->compr_config.codec);
4391 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004392
Ashish Jain83a6cc22016-06-28 14:34:17 +05304393 if (out->convert_buffer != NULL) {
4394 free(out->convert_buffer);
4395 out->convert_buffer = NULL;
4396 }
4397
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004398 if (adev->voice_tx_output == out)
4399 adev->voice_tx_output = NULL;
4400
Dhanalakshmi Siddani6c3d0992017-01-16 16:52:33 +05304401 if (adev->primary_output == out)
4402 adev->primary_output = NULL;
4403
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004404 pthread_cond_destroy(&out->cond);
4405 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004406 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07004407 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004408}
4409
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004410static void close_compress_sessions(struct audio_device *adev)
4411{
Mingming Yin7b762e72015-03-04 13:47:32 -08004412 struct stream_out *out;
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05304413 struct listnode *node, *tempnode;
Mingming Yin7b762e72015-03-04 13:47:32 -08004414 struct audio_usecase *usecase;
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004415 pthread_mutex_lock(&adev->lock);
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05304416
4417 list_for_each_safe(node, tempnode, &adev->usecase_list) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004418 usecase = node_to_item(node, struct audio_usecase, list);
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05304419 if (is_offload_usecase(usecase->id)) {
4420 if (usecase->stream.out) {
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004421 ALOGI(" %s closing compress session %d on OFFLINE state", __func__, usecase->id);
4422 out = usecase->stream.out;
4423 pthread_mutex_unlock(&adev->lock);
4424 out_standby(&out->stream.common);
4425 pthread_mutex_lock(&adev->lock);
Aalique Grahame6379b8d2016-12-22 13:02:32 -08004426 tempnode = list_head(&adev->usecase_list);
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004427 }
Naresh Tanniruf0bbefb2015-06-03 01:50:57 +05304428 }
Alexy Joseph2beb67f2014-10-06 12:15:01 -07004429 }
4430 pthread_mutex_unlock(&adev->lock);
4431}
4432
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004433static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
4434{
4435 struct audio_device *adev = (struct audio_device *)dev;
4436 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004437 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004438 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004439 int ret;
4440 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004441
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004442 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004443 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004444
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304445 if (!parms)
4446 goto error;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004447 ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
4448 if (ret >= 0) {
Naresh Tanniru4c630392014-05-12 01:05:52 +05304449 char *snd_card_status = value+2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05304450 if (strstr(snd_card_status, "OFFLINE")) {
4451 ALOGD("Received sound card OFFLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05304452 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru726c71d2016-02-23 04:46:02 -08004453 //close compress sessions on OFFLINE status
4454 close_compress_sessions(adev);
Naresh Tanniru4c630392014-05-12 01:05:52 +05304455 } else if (strstr(snd_card_status, "ONLINE")) {
4456 ALOGD("Received sound card ONLINE status");
Naresh Tanniru80659832014-06-04 18:17:56 +05304457 set_snd_card_state(adev,SND_CARD_STATE_ONLINE);
Mingming Yin15dae802015-04-16 18:36:10 -07004458 //send dts hpx license if enabled
4459 audio_extn_dts_eagle_send_lic();
Naresh Tanniru4c630392014-05-12 01:05:52 +05304460 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05304461 }
4462
4463 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004464 status = voice_set_parameters(adev, parms);
4465 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004466 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004467
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004468 status = platform_set_parameters(adev->platform, parms);
4469 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004470 goto done;
4471
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004472 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
4473 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07004474 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004475 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4476 adev->bluetooth_nrec = true;
4477 else
4478 adev->bluetooth_nrec = false;
4479 }
4480
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004481 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
4482 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004483 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4484 adev->screen_off = false;
4485 else
4486 adev->screen_off = true;
4487 }
4488
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004489 ret = str_parms_get_int(parms, "rotation", &val);
4490 if (ret >= 0) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004491 bool reverse_speakers = false;
4492 switch(val) {
4493 // FIXME: note that the code below assumes that the speakers are in the correct placement
4494 // relative to the user when the device is rotated 90deg from its default rotation. This
4495 // assumption is device-specific, not platform-specific like this code.
4496 case 270:
4497 reverse_speakers = true;
4498 break;
4499 case 0:
4500 case 90:
4501 case 180:
4502 break;
4503 default:
4504 ALOGE("%s: unexpected rotation of %d", __func__, val);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004505 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004506 }
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004507 if (status == 0) {
4508 if (adev->speaker_lr_swap != reverse_speakers) {
4509 adev->speaker_lr_swap = reverse_speakers;
4510 // only update the selected device if there is active pcm playback
4511 struct audio_usecase *usecase;
4512 struct listnode *node;
4513 list_for_each(node, &adev->usecase_list) {
4514 usecase = node_to_item(node, struct audio_usecase, list);
4515 if (usecase->type == PCM_PLAYBACK) {
4516 select_devices(adev, usecase->id);
4517 break;
4518 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004519 }
4520 }
4521 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004522 }
4523
Mingming Yin514a8bc2014-07-29 15:22:21 -07004524 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
4525 if (ret >= 0) {
4526 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4527 adev->bt_wb_speech_enabled = true;
4528 else
4529 adev->bt_wb_speech_enabled = false;
4530 }
4531
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004532 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
4533 if (ret >= 0) {
4534 val = atoi(value);
4535 if (val & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07004536 ALOGV("cache new ext disp type and edid");
4537 ret = platform_get_ext_disp_type(adev->platform);
4538 if (ret < 0) {
4539 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Weiyin Jiangf50ce4e2016-10-13 14:22:03 +08004540 status = ret;
4541 goto done;
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07004542 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004543 platform_cache_edid(adev->platform);
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004544 } else if ((val & AUDIO_DEVICE_OUT_USB_DEVICE) ||
yidongh86ca17d2016-08-30 18:28:01 +08004545 !(val ^ AUDIO_DEVICE_IN_USB_DEVICE)) {
vivek mehta344576a2016-04-12 18:56:03 -07004546 /*
4547 * Do not allow AFE proxy port usage by WFD source when USB headset is connected.
4548 * Per AudioPolicyManager, USB device is higher priority than WFD.
4549 * For Voice call over USB headset, voice call audio is routed to AFE proxy ports.
4550 * If WFD use case occupies AFE proxy, it may result unintended behavior while
4551 * starting voice call on USB
4552 */
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004553 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4554 if (ret >= 0) {
Kuirong Wang27152a12016-11-11 10:20:30 -08004555 audio_extn_usb_add_device(AUDIO_DEVICE_OUT_USB_DEVICE, atoi(value));
4556 audio_extn_usb_add_device(AUDIO_DEVICE_IN_USB_DEVICE, atoi(value));
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004557 }
vivek mehta344576a2016-04-12 18:56:03 -07004558 ALOGV("detected USB connect .. disable proxy");
4559 adev->allow_afe_proxy_usage = false;
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004560 }
4561 }
4562
4563 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
4564 if (ret >= 0) {
4565 val = atoi(value);
Garmond Leunge3b6d482016-10-25 16:48:01 -07004566 /*
4567 * The HDMI / Displayport disconnect handling has been moved to
4568 * audio extension to ensure that its parameters are not
4569 * invalidated prior to updating sysfs of the disconnect event
4570 * Invalidate will be handled by audio_extn_ext_disp_set_parameters()
4571 */
4572 if ((val & AUDIO_DEVICE_OUT_USB_DEVICE) ||
yidongh86ca17d2016-08-30 18:28:01 +08004573 !(val ^ AUDIO_DEVICE_IN_USB_DEVICE)) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004574 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4575 if (ret >= 0) {
Ashish Jain3e37a702016-11-25 12:27:15 +05304576 audio_extn_usb_remove_device(AUDIO_DEVICE_OUT_USB_DEVICE, atoi(value));
4577 audio_extn_usb_remove_device(AUDIO_DEVICE_IN_USB_DEVICE, atoi(value));
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08004578 }
vivek mehta344576a2016-04-12 18:56:03 -07004579 ALOGV("detected USB disconnect .. enable proxy");
4580 adev->allow_afe_proxy_usage = true;
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07004581 }
4582 }
4583
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304584 ret = str_parms_get_str(parms,"reconfigA2dp", value, sizeof(value));
4585 if (ret >= 0) {
4586 struct audio_usecase *usecase;
4587 struct listnode *node;
4588 list_for_each(node, &adev->usecase_list) {
4589 usecase = node_to_item(node, struct audio_usecase, list);
4590 if ((usecase->type == PCM_PLAYBACK) &&
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07004591 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP)){
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304592 ALOGD("reconfigure a2dp... forcing device switch");
Naresh Tannirucd2353e2016-08-19 00:37:25 +05304593 lock_output_stream(usecase->stream.out);
4594 audio_extn_a2dp_set_handoff_mode(true);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304595 //force device switch to re configure encoder
4596 select_devices(adev, usecase->id);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05304597 audio_extn_a2dp_set_handoff_mode(false);
4598 pthread_mutex_unlock(&usecase->stream.out->lock);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304599 break;
4600 }
4601 }
4602 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08004603
4604 //handle vr audio setparam
4605 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
4606 value, sizeof(value));
4607 if (ret >= 0) {
4608 ALOGI("Setting vr mode to be %s", value);
4609 if (!strncmp(value, "true", 4)) {
4610 adev->vr_audio_mode_enabled = true;
4611 ALOGI("Setting vr mode to true");
4612 } else if (!strncmp(value, "false", 5)) {
4613 adev->vr_audio_mode_enabled = false;
4614 ALOGI("Setting vr mode to false");
4615 } else {
4616 ALOGI("wrong vr mode set");
4617 }
4618 }
4619
Naresh Tannirucd2353e2016-08-19 00:37:25 +05304620 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004621done:
4622 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004623 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304624error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004625 ALOGV("%s: exit with code(%d)", __func__, status);
4626 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004627}
4628
4629static char* adev_get_parameters(const struct audio_hw_device *dev,
4630 const char *keys)
4631{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004632 struct audio_device *adev = (struct audio_device *)dev;
4633 struct str_parms *reply = str_parms_create();
4634 struct str_parms *query = str_parms_create_str(keys);
4635 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05304636 char value[256] = {0};
4637 int ret = 0;
4638
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004639 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004640 if (reply) {
4641 str_parms_destroy(reply);
4642 }
4643 if (query) {
4644 str_parms_destroy(query);
4645 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004646 ALOGE("adev_get_parameters: failed to create query or reply");
4647 return NULL;
4648 }
4649
Naresh Tannirud7205b62014-06-20 02:54:48 +05304650 ret = str_parms_get_str(query, "SND_CARD_STATUS", value,
4651 sizeof(value));
4652 if (ret >=0) {
4653 int val = 1;
4654 pthread_mutex_lock(&adev->snd_card_status.lock);
4655 if (SND_CARD_STATE_OFFLINE == adev->snd_card_status.state)
4656 val = 0;
4657 pthread_mutex_unlock(&adev->snd_card_status.lock);
4658 str_parms_add_int(reply, "SND_CARD_STATUS", val);
4659 goto exit;
4660 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08004661 //handle vr audio getparam
4662
4663 ret = str_parms_get_str(query,
4664 AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
4665 value, sizeof(value));
4666
4667 if (ret >= 0) {
4668 bool vr_audio_enabled = false;
4669 pthread_mutex_lock(&adev->lock);
4670 vr_audio_enabled = adev->vr_audio_mode_enabled;
4671 pthread_mutex_unlock(&adev->lock);
4672
4673 ALOGI("getting vr mode to %d", vr_audio_enabled);
4674
4675 if (vr_audio_enabled) {
4676 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
4677 "true");
4678 goto exit;
4679 } else {
4680 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
4681 "false");
4682 goto exit;
4683 }
4684 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004685
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004686 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004687 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08004688 voice_get_parameters(adev, query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004689 platform_get_parameters(adev->platform, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05304690 pthread_mutex_unlock(&adev->lock);
4691
Naresh Tannirud7205b62014-06-20 02:54:48 +05304692exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004693 str = str_parms_to_str(reply);
4694 str_parms_destroy(query);
4695 str_parms_destroy(reply);
4696
4697 ALOGV("%s: exit: returns - %s", __func__, str);
4698 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004699}
4700
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004701static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004702{
4703 return 0;
4704}
4705
4706static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
4707{
Haynes Mathew George5191a852013-09-11 14:19:36 -07004708 int ret;
4709 struct audio_device *adev = (struct audio_device *)dev;
4710 pthread_mutex_lock(&adev->lock);
4711 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07004712 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07004713 pthread_mutex_unlock(&adev->lock);
4714 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004715}
4716
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004717static int adev_set_master_volume(struct audio_hw_device *dev __unused,
4718 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004719{
4720 return -ENOSYS;
4721}
4722
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004723static int adev_get_master_volume(struct audio_hw_device *dev __unused,
4724 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004725{
4726 return -ENOSYS;
4727}
4728
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004729static int adev_set_master_mute(struct audio_hw_device *dev __unused,
4730 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004731{
4732 return -ENOSYS;
4733}
4734
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004735static int adev_get_master_mute(struct audio_hw_device *dev __unused,
4736 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004737{
4738 return -ENOSYS;
4739}
4740
4741static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
4742{
4743 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004744
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004745 pthread_mutex_lock(&adev->lock);
4746 if (adev->mode != mode) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004747 ALOGD("%s: mode %d\n", __func__, mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004748 adev->mode = mode;
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08004749 if ((mode == AUDIO_MODE_NORMAL) && voice_is_in_call(adev)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004750 voice_stop_call(adev);
Banajit Goswami20cdd212015-09-11 01:11:30 -07004751 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004752 adev->current_call_output = NULL;
4753 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004754 }
4755 pthread_mutex_unlock(&adev->lock);
4756 return 0;
4757}
4758
4759static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
4760{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004761 int ret;
4762
4763 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08004764 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08004765 ret = voice_set_mic_mute((struct audio_device *)dev, state);
4766 pthread_mutex_unlock(&adev->lock);
4767
4768 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004769}
4770
4771static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
4772{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07004773 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004774 return 0;
4775}
4776
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004777static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004778 const struct audio_config *config)
4779{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004780 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004781
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004782 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
4783 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004784}
4785
4786static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07004787 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004788 audio_devices_t devices,
4789 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004790 struct audio_stream_in **stream_in,
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304791 audio_input_flags_t flags,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004792 const char *address __unused,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004793 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004794{
4795 struct audio_device *adev = (struct audio_device *)dev;
4796 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004797 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004798 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004799 bool is_low_latency = false;
Divya Narayanan Poojary45f19192016-09-30 18:52:13 +05304800 bool channel_mask_updated = false;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304801
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004802 *stream_in = NULL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05304803 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0) {
4804 ALOGE("%s: invalid input parameters", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004805 return -EINVAL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05304806 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004807
4808 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004809
4810 if (!in) {
4811 ALOGE("failed to allocate input stream");
4812 return -ENOMEM;
4813 }
4814
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304815 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304816 stream_handle(%p) io_handle(%d) source(%d) format %x",__func__, config->sample_rate,
4817 config->channel_mask, devices, &in->stream, handle, source, config->format);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07004818 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004819 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07004820
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004821 in->stream.common.get_sample_rate = in_get_sample_rate;
4822 in->stream.common.set_sample_rate = in_set_sample_rate;
4823 in->stream.common.get_buffer_size = in_get_buffer_size;
4824 in->stream.common.get_channels = in_get_channels;
4825 in->stream.common.get_format = in_get_format;
4826 in->stream.common.set_format = in_set_format;
4827 in->stream.common.standby = in_standby;
4828 in->stream.common.dump = in_dump;
4829 in->stream.common.set_parameters = in_set_parameters;
4830 in->stream.common.get_parameters = in_get_parameters;
4831 in->stream.common.add_audio_effect = in_add_audio_effect;
4832 in->stream.common.remove_audio_effect = in_remove_audio_effect;
4833 in->stream.set_gain = in_set_gain;
4834 in->stream.read = in_read;
4835 in->stream.get_input_frames_lost = in_get_input_frames_lost;
4836
4837 in->device = devices;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004838 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004839 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004840 in->standby = 1;
4841 in->channel_mask = config->channel_mask;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004842 in->capture_handle = handle;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004843 in->flags = flags;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004844
Dhananjay Kumar973fc362017-01-09 18:48:15 +05304845 in->usecase = USECASE_AUDIO_RECORD;
4846 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
4847 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
4848 is_low_latency = true;
4849#if LOW_LATENCY_CAPTURE_USE_CASE
4850 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
4851#endif
4852 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
4853 }
4854
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004855 in->format = config->format;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004856 if (in->realtime) {
4857 in->config = pcm_config_audio_capture_rt;
4858 in->sample_rate = in->config.rate;
4859 in->af_period_multiplier = af_period_multiplier;
4860 } else {
4861 in->config = pcm_config_audio_capture;
4862 in->config.rate = config->sample_rate;
4863 in->sample_rate = config->sample_rate;
4864 in->af_period_multiplier = 1;
4865 }
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304866 in->bit_width = 16;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004867
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304868 /* restrict 24 bit capture for unprocessed source only
4869 * for other sources if 24 bit requested reject 24 and set 16 bit capture only
4870 */
4871 if (config->format == AUDIO_FORMAT_DEFAULT) {
4872 config->format = AUDIO_FORMAT_PCM_16_BIT;
4873 } else if ((config->format == AUDIO_FORMAT_PCM_FLOAT) ||
4874 (config->format == AUDIO_FORMAT_PCM_32_BIT) ||
4875 (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) ||
4876 (config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
4877 bool ret_error = false;
4878 in->bit_width = 24;
4879 /* 24 bit is restricted to UNPROCESSED source only,also format supported
4880 from HAL is 24_packed and 8_24
4881 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
4882 24_packed return error indicating supported format is 24_packed
4883 *> In case of any other source requesting 24 bit or float return error
4884 indicating format supported is 16 bit only.
4885
4886 on error flinger will retry with supported format passed
4887 */
4888 if ((source != AUDIO_SOURCE_UNPROCESSED) &&
4889 (source != AUDIO_SOURCE_CAMCORDER)) {
4890 config->format = AUDIO_FORMAT_PCM_16_BIT;
4891 if (config->sample_rate > 48000)
4892 config->sample_rate = 48000;
4893 ret_error = true;
4894 } else if (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) {
4895 in->config.format = PCM_FORMAT_S24_3LE;
4896 } else if (config->format == AUDIO_FORMAT_PCM_8_24_BIT) {
4897 in->config.format = PCM_FORMAT_S24_LE;
4898 } else {
4899 config->format = AUDIO_FORMAT_PCM_24_BIT_PACKED;
4900 ret_error = true;
4901 }
4902
4903 if (ret_error) {
4904 ret = -EINVAL;
4905 goto err_open;
4906 }
4907 }
4908
Dhanalakshmi Siddani74cf00b2016-12-02 13:55:57 +05304909 /* Update config params with the requested sample rate and channels */
Dhanalakshmi Siddani0b1488e2016-09-06 12:58:42 +05304910 if ((in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) &&
4911 (adev->mode != AUDIO_MODE_IN_CALL)) {
4912 ret = -EINVAL;
4913 goto err_open;
4914 }
4915
4916 if ((in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) ||
4917 (in->device == AUDIO_DEVICE_IN_PROXY)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004918 if (config->sample_rate == 0)
4919 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4920 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
4921 config->sample_rate != 8000) {
4922 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4923 ret = -EINVAL;
4924 goto err_open;
4925 }
4926 if (config->format == AUDIO_FORMAT_DEFAULT)
4927 config->format = AUDIO_FORMAT_PCM_16_BIT;
4928 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
4929 config->format = AUDIO_FORMAT_PCM_16_BIT;
4930 ret = -EINVAL;
4931 goto err_open;
4932 }
4933
4934 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
4935 in->config = pcm_config_afe_proxy_record;
4936 in->config.channels = channel_count;
4937 in->config.rate = config->sample_rate;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304938 in->sample_rate = config->sample_rate;
Divya Narayanan Poojary45f19192016-09-30 18:52:13 +05304939 } else if (!audio_extn_check_and_set_multichannel_usecase(adev,
4940 in, config, &channel_mask_updated)) {
4941 if (channel_mask_updated == true) {
4942 ALOGD("%s: return error to retry with updated channel mask (%#x)",
4943 __func__, config->channel_mask);
4944 ret = -EINVAL;
4945 goto err_open;
4946 }
Naresh Tanniruc9093982015-10-16 18:05:29 +05304947 ALOGD("%s: created surround sound session succesfully",__func__);
Mingming Yine62d7842013-10-25 16:26:03 -07004948 } else if (audio_extn_compr_cap_enabled() &&
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08004949 audio_extn_compr_cap_format_supported(config->format) &&
4950 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004951 audio_extn_compr_cap_init(in);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05304952 } else if (audio_extn_cin_applicable_stream(in)) {
4953 ret = audio_extn_cin_configure_input_stream(in);
4954 if (ret)
4955 goto err_open;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004956 } else {
4957 in->config.channels = channel_count;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004958 if (!in->realtime) {
4959 in->format = config->format;
4960 frame_size = audio_stream_in_frame_size(&in->stream);
4961 buffer_size = get_input_buffer_size(config->sample_rate,
4962 config->format,
4963 channel_count,
4964 is_low_latency);
4965 in->config.period_size = buffer_size / frame_size;
4966 }
4967
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004968 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
kunleizc5fefba2016-11-15 11:20:56 +08004969 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION || voice_extn_compress_voip_is_active(in->dev)) &&
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004970 (voice_extn_compress_voip_is_format_supported(in->format)) &&
Shiv Maliyappanahallie66aba22016-01-27 16:08:57 -08004971 (in->config.rate == 8000 || in->config.rate == 16000 ||
4972 in->config.rate == 32000 || in->config.rate == 48000) &&
Vidyakumar Athota5c398212015-03-31 21:53:21 -07004973 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
4974 voice_extn_compress_voip_open_input_stream(in);
4975 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07004976 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004977
Dhananjay Kumard6d32152016-10-13 16:11:03 +05304978 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
4979 &adev->streams_input_cfg_list,
4980 devices, flags, in->format, in->sample_rate,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05304981 in->bit_width, in->profile, &in->app_type_cfg);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05304982
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07004983 /* This stream could be for sound trigger lab,
4984 get sound trigger pcm if present */
4985 audio_extn_sound_trigger_check_and_get_session(in);
4986
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004987 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07004988 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004989 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004990
4991err_open:
4992 free(in);
4993 *stream_in = NULL;
4994 return ret;
4995}
4996
4997static void adev_close_input_stream(struct audio_hw_device *dev,
4998 struct audio_stream_in *stream)
4999{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005000 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07005001 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005002 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05305003
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05305004 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08005005
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05305006 /* Disable echo reference while closing input stream */
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07005007 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05305008
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005009 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05305010 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005011 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05305012 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005013 if (ret != 0)
5014 ALOGE("%s: Compress voip input cannot be closed, error:%d",
5015 __func__, ret);
5016 } else
5017 in_standby(&stream->common);
5018
Shiv Maliyappanahalli5a10aea2015-07-02 10:36:23 -07005019 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07005020 audio_extn_ssr_deinit();
5021 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005022
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305023 if (audio_extn_compr_cap_enabled() &&
Mingming Yine62d7842013-10-25 16:26:03 -07005024 audio_extn_compr_cap_format_supported(in->config.format))
5025 audio_extn_compr_cap_deinit();
Dhanalakshmi Siddani74cf00b2016-12-02 13:55:57 +05305026
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305027 if (audio_extn_cin_attached_usecase(in->usecase))
5028 audio_extn_cin_close_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07005029
Mingming Yinfd7607b2016-01-22 12:48:44 -08005030 if (in->is_st_session) {
5031 ALOGV("%s: sound trigger pcm stop lab", __func__);
5032 audio_extn_sound_trigger_stop_lab(in);
5033 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07005034 free(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005035 return;
5036}
5037
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005038static int adev_dump(const audio_hw_device_t *device __unused,
5039 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005040{
5041 return 0;
5042}
5043
5044static int adev_close(hw_device_t *device)
5045{
5046 struct audio_device *adev = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -07005047
5048 if (!adev)
5049 return 0;
5050
5051 pthread_mutex_lock(&adev_init_lock);
5052
5053 if ((--audio_device_ref_count) == 0) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07005054 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -08005055 audio_extn_listen_deinit(adev);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05305056 audio_extn_utils_release_streams_cfg_lists(
5057 &adev->streams_output_cfg_list,
5058 &adev->streams_input_cfg_list);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05305059 if (audio_extn_qaf_is_enabled())
5060 audio_extn_qaf_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -07005061 audio_route_free(adev->audio_route);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08005062 audio_extn_gef_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -07005063 free(adev->snd_dev_ref_cnt);
5064 platform_deinit(adev->platform);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005065 if (adev->adm_deinit)
5066 adev->adm_deinit(adev->adm_data);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305067 qahwi_deinit(device);
Kiran Kandi910e1862013-10-29 13:29:42 -07005068 free(device);
5069 adev = NULL;
5070 }
5071 pthread_mutex_unlock(&adev_init_lock);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005072
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005073 return 0;
5074}
5075
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07005076/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
5077 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
5078 * just that it _might_ work.
5079 */
5080static int period_size_is_plausible_for_low_latency(int period_size)
5081{
5082 switch (period_size) {
5083 case 160:
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -07005084 case 192:
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07005085 case 240:
5086 case 320:
5087 case 480:
5088 return 1;
5089 default:
5090 return 0;
5091 }
5092}
5093
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005094static int adev_open(const hw_module_t *module, const char *name,
5095 hw_device_t **device)
5096{
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05305097 int ret;
5098
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08005099 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005100 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
5101
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07005102 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -07005103 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07005104 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -07005105 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07005106 ALOGD("%s: returning existing instance of adev", __func__);
5107 ALOGD("%s: exit", __func__);
5108 pthread_mutex_unlock(&adev_init_lock);
5109 return 0;
5110 }
5111
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005112 adev = calloc(1, sizeof(struct audio_device));
5113
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005114 if (!adev) {
5115 pthread_mutex_unlock(&adev_init_lock);
5116 return -ENOMEM;
5117 }
5118
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07005119 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
5120
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005121 adev->device.common.tag = HARDWARE_DEVICE_TAG;
5122 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
5123 adev->device.common.module = (struct hw_module_t *)module;
5124 adev->device.common.close = adev_close;
5125
5126 adev->device.init_check = adev_init_check;
5127 adev->device.set_voice_volume = adev_set_voice_volume;
5128 adev->device.set_master_volume = adev_set_master_volume;
5129 adev->device.get_master_volume = adev_get_master_volume;
5130 adev->device.set_master_mute = adev_set_master_mute;
5131 adev->device.get_master_mute = adev_get_master_mute;
5132 adev->device.set_mode = adev_set_mode;
5133 adev->device.set_mic_mute = adev_set_mic_mute;
5134 adev->device.get_mic_mute = adev_get_mic_mute;
5135 adev->device.set_parameters = adev_set_parameters;
5136 adev->device.get_parameters = adev_get_parameters;
5137 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
5138 adev->device.open_output_stream = adev_open_output_stream;
5139 adev->device.close_output_stream = adev_close_output_stream;
5140 adev->device.open_input_stream = adev_open_input_stream;
5141 adev->device.close_input_stream = adev_close_input_stream;
5142 adev->device.dump = adev_dump;
5143
5144 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005145 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08005146 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08005147 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005148 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005149 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08005150 adev->acdb_settings = TTY_MODE_OFF;
vivek mehta344576a2016-04-12 18:56:03 -07005151 adev->allow_afe_proxy_usage = true;
Eric Laurent07eeafd2013-10-06 12:52:49 -07005152 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07005153 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07005154 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08005155 list_init(&adev->usecase_list);
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -08005156 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005157 adev->offload_usecases_state = 0;
Ashish Jain81eb2a82015-05-13 10:52:34 +05305158 adev->is_channel_status_set = false;
Sudheer Papothifa9d2282015-09-17 01:53:25 +05305159 adev->perf_lock_opts[0] = 0x101;
5160 adev->perf_lock_opts[1] = 0x20E;
5161 adev->perf_lock_opts_size = 2;
Naresh Tanniru4c630392014-05-12 01:05:52 +05305162
5163 pthread_mutex_init(&adev->snd_card_status.lock, (const pthread_mutexattr_t *) NULL);
5164 adev->snd_card_status.state = SND_CARD_STATE_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005165 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07005166 adev->platform = platform_init(adev);
5167 if (!adev->platform) {
5168 free(adev->snd_dev_ref_cnt);
5169 free(adev);
5170 ALOGE("%s: Failed to init platform data, aborting.", __func__);
5171 *device = NULL;
Apoorv Raghuvanshi6e57d7e2013-12-16 16:02:45 -08005172 pthread_mutex_unlock(&adev_init_lock);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05305173 pthread_mutex_destroy(&adev->lock);
5174 pthread_mutex_destroy(&adev->snd_card_status.lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07005175 return -EINVAL;
5176 }
Eric Laurentc4aef752013-09-12 17:45:53 -07005177
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05305178 if (audio_extn_qaf_is_enabled()) {
5179 ret = audio_extn_qaf_init(adev);
5180 if (ret < 0) {
5181 free(adev);
5182 ALOGE("%s: Failed to init platform data, aborting.", __func__);
5183 *device = NULL;
5184 pthread_mutex_unlock(&adev_init_lock);
5185 pthread_mutex_destroy(&adev->lock);
5186 return ret;
5187 }
5188
5189 adev->device.open_output_stream = audio_extn_qaf_open_output_stream;
5190 adev->device.close_output_stream = audio_extn_qaf_close_output_stream;
5191 }
5192
Naresh Tanniru4c630392014-05-12 01:05:52 +05305193 adev->snd_card_status.state = SND_CARD_STATE_ONLINE;
5194
Eric Laurentc4aef752013-09-12 17:45:53 -07005195 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
5196 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
5197 if (adev->visualizer_lib == NULL) {
5198 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
5199 } else {
5200 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
5201 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08005202 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07005203 "visualizer_hal_start_output");
5204 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08005205 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07005206 "visualizer_hal_stop_output");
5207 }
5208 }
Dhanalakshmi Siddani21be3ac2016-12-29 14:31:08 +05305209 audio_extn_init(adev);
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08005210 audio_extn_listen_init(adev, adev->snd_card);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07005211 audio_extn_sound_trigger_init(adev);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08005212 audio_extn_gef_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -07005213
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08005214 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
5215 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
5216 if (adev->offload_effects_lib == NULL) {
5217 ALOGE("%s: DLOPEN failed for %s", __func__,
5218 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
5219 } else {
5220 ALOGV("%s: DLOPEN successful for %s", __func__,
5221 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
5222 adev->offload_effects_start_output =
Ashish Jain5106d362016-05-11 19:23:33 +05305223 (int (*)(audio_io_handle_t, int, struct mixer *))dlsym(adev->offload_effects_lib,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08005224 "offload_effects_bundle_hal_start_output");
5225 adev->offload_effects_stop_output =
5226 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
5227 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005228 adev->offload_effects_set_hpx_state =
5229 (int (*)(bool))dlsym(adev->offload_effects_lib,
5230 "offload_effects_bundle_set_hpx_state");
Dhananjay Kumard68883d2015-09-04 13:39:26 +05305231 adev->offload_effects_get_parameters =
5232 (void (*)(struct str_parms *, struct str_parms *))
5233 dlsym(adev->offload_effects_lib,
5234 "offload_effects_bundle_get_parameters");
5235 adev->offload_effects_set_parameters =
5236 (void (*)(struct str_parms *))dlsym(adev->offload_effects_lib,
5237 "offload_effects_bundle_set_parameters");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08005238 }
5239 }
5240
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005241 if (access(ADM_LIBRARY_PATH, R_OK) == 0) {
5242 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
5243 if (adev->adm_lib == NULL) {
5244 ALOGE("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
5245 } else {
5246 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
5247 adev->adm_init = (adm_init_t)
5248 dlsym(adev->adm_lib, "adm_init");
5249 adev->adm_deinit = (adm_deinit_t)
5250 dlsym(adev->adm_lib, "adm_deinit");
5251 adev->adm_register_input_stream = (adm_register_input_stream_t)
5252 dlsym(adev->adm_lib, "adm_register_input_stream");
5253 adev->adm_register_output_stream = (adm_register_output_stream_t)
5254 dlsym(adev->adm_lib, "adm_register_output_stream");
5255 adev->adm_deregister_stream = (adm_deregister_stream_t)
5256 dlsym(adev->adm_lib, "adm_deregister_stream");
5257 adev->adm_request_focus = (adm_request_focus_t)
5258 dlsym(adev->adm_lib, "adm_request_focus");
5259 adev->adm_abandon_focus = (adm_abandon_focus_t)
5260 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005261 adev->adm_set_config = (adm_set_config_t)
5262 dlsym(adev->adm_lib, "adm_set_config");
5263 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
5264 dlsym(adev->adm_lib, "adm_request_focus_v2");
5265 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
5266 dlsym(adev->adm_lib, "adm_is_noirq_avail");
5267 adev->adm_on_routing_change = (adm_on_routing_change_t)
5268 dlsym(adev->adm_lib, "adm_on_routing_change");
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005269 }
5270 }
5271
Mingming Yin514a8bc2014-07-29 15:22:21 -07005272 adev->bt_wb_speech_enabled = false;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08005273 //initialize this to false for now,
5274 //this will be set to true through set param
5275 adev->vr_audio_mode_enabled = false;
Mingming Yin514a8bc2014-07-29 15:22:21 -07005276
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07005277 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005278 *device = &adev->device.common;
5279
Dhananjay Kumard6d32152016-10-13 16:11:03 +05305280 audio_extn_utils_update_streams_cfg_lists(adev->platform, adev->mixer,
5281 &adev->streams_output_cfg_list,
5282 &adev->streams_input_cfg_list);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07005283
Kiran Kandi910e1862013-10-29 13:29:42 -07005284 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07005285
5286 char value[PROPERTY_VALUE_MAX];
5287 int trial;
5288 if (property_get("audio_hal.period_size", value, NULL) > 0) {
5289 trial = atoi(value);
5290 if (period_size_is_plausible_for_low_latency(trial)) {
5291 pcm_config_low_latency.period_size = trial;
5292 pcm_config_low_latency.start_threshold = trial / 4;
5293 pcm_config_low_latency.avail_min = trial / 4;
5294 configured_low_latency_capture_period_size = trial;
5295 }
5296 }
5297 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
5298 trial = atoi(value);
5299 if (period_size_is_plausible_for_low_latency(trial)) {
5300 configured_low_latency_capture_period_size = trial;
5301 }
5302 }
5303
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005304 if (property_get("audio_hal.period_multiplier", value, NULL) > 0) {
5305 af_period_multiplier = atoi(value);
5306 if (af_period_multiplier < 0)
5307 af_period_multiplier = 2;
5308 else if (af_period_multiplier > 4)
5309 af_period_multiplier = 4;
5310
5311 ALOGV("new period_multiplier = %d", af_period_multiplier);
5312 }
5313
vivek mehta446c3962015-09-14 10:57:35 -07005314 adev->multi_offload_enable = property_get_bool("audio.offload.multiple.enabled", false);
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07005315 pthread_mutex_unlock(&adev_init_lock);
5316
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005317 if (adev->adm_init)
5318 adev->adm_data = adev->adm_init();
5319
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305320 qahwi_init(*device);
Sudheer Papothifa9d2282015-09-17 01:53:25 +05305321 audio_extn_perf_lock_init();
Eric Laurent994a6932013-07-17 11:51:42 -07005322 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005323 return 0;
5324}
5325
5326static struct hw_module_methods_t hal_module_methods = {
5327 .open = adev_open,
5328};
5329
5330struct audio_module HAL_MODULE_INFO_SYM = {
5331 .common = {
5332 .tag = HARDWARE_MODULE_TAG,
5333 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
5334 .hal_api_version = HARDWARE_HAL_API_VERSION,
5335 .id = AUDIO_HARDWARE_MODULE_ID,
5336 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -08005337 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005338 .methods = &hal_module_methods,
5339 },
5340};